From ee604f445499591ff8c5252b248d1e269a791134 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Thu, 21 Jun 2018 23:17:39 +0200 Subject: [PATCH] -39in1: Split Intel XScale PXA255 peripherals into a separate device. [Ryan Holtz] note: will apply this change to any drivers using copy/pasted PXA255 code tomorrow. --- scripts/src/machine.lua | 13 + scripts/target/mame/arcade.lua | 1 + scripts/target/mame/mess.lua | 1 + src/devices/machine/pxa255.cpp | 1240 ++++++++++++++ src/devices/machine/pxa255.h | 235 +++ .../pxa255.h => devices/machine/pxa255defs.h} | 144 +- src/mame/drivers/39in1.cpp | 1425 +---------------- 7 files changed, 1546 insertions(+), 1513 deletions(-) create mode 100644 src/devices/machine/pxa255.cpp create mode 100644 src/devices/machine/pxa255.h rename src/{mame/machine/pxa255.h => devices/machine/pxa255defs.h} (91%) diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 204972c198e..15eae3e6f12 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -2254,6 +2254,19 @@ if (MACHINES["PLA"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/pla.h,MACHINES["PXA255"] = true +--------------------------------------------------- + +if (MACHINES["PXA255"]~=null) then + files { + MAME_DIR .. "src/devices/machine/pxa255.cpp", + MAME_DIR .. "src/devices/machine/pxa255.h", + MAME_DIR .. "src/devices/machine/pxa255defs.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/r10696.h,MACHINES["R10696"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 198fdee0fd3..d92c75cf8d7 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -536,6 +536,7 @@ MACHINES["PIT8253"] = true MACHINES["PLA"] = true --MACHINES["PROFILE"] = true --MACHINES["PROM82S129"] = true +MACHINES["PXA255"] = true MACHINES["R10696"] = true MACHINES["R10788"] = true MACHINES["RA17XX"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 6835d1960f9..c507a797bb1 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -534,6 +534,7 @@ MACHINES["PIT8253"] = true MACHINES["PLA"] = true --MACHINES["PROFILE"] = true MACHINES["PROM82S129"] = true +MACHINES["PXA255"] = true MACHINES["R64H156"] = true MACHINES["RF5C296"] = true MACHINES["RIOT6532"] = true diff --git a/src/devices/machine/pxa255.cpp b/src/devices/machine/pxa255.cpp new file mode 100644 index 00000000000..b4e8b3bcf8f --- /dev/null +++ b/src/devices/machine/pxa255.cpp @@ -0,0 +1,1240 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/************************************************************************** + * + * Intel XScale PXA255 peripheral emulation + * + * TODO: + * Most things + * + **************************************************************************/ + +#include "pxa255.h" + +#include "screen.h" +#include "speaker.h" + +#define VERBOSE_LEVEL (0) + +DEFINE_DEVICE_TYPE(PXA255_PERIPHERALS, pxa255_periphs_device, "pxa255_periphs", "Intel XScale PXA255 Peripherals") + +pxa255_periphs_device::pxa255_periphs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, PXA255_PERIPHERALS, tag, owner, clock) + , m_gpio0_set_func(*this) + , m_gpio0_clear_func(*this) + , m_gpio0_in_func(*this) + , m_maincpu(*this, finder_base::DUMMY_TAG) + , m_dmadac(*this, "dac%u", 1U) + , m_palette(*this, "palette") +{ +} + +inline void ATTR_PRINTF(3,4) pxa255_periphs_device::verboselog(int n_level, const char *s_fmt, ... ) +{ + if (VERBOSE_LEVEL >= n_level) + { + va_list v; + char buf[32768]; + va_start( v, s_fmt ); + vsprintf( buf, s_fmt, v ); + va_end( v ); + logerror( "%s: %s", machine().describe_context(), buf ); + } +} + +/* + + PXA255 Inter-Integrated-Circuit Sound (I2S) Controller + + pg. 489 to 504, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +READ32_MEMBER(pxa255_periphs_device::pxa255_i2s_r) +{ + switch(PXA255_I2S_BASE_ADDR | (offset << 2)) + { + case PXA255_SACR0: + verboselog(3, "pxa255_i2s_r: Serial Audio Controller Global Control Register: %08x & %08x\n", m_i2s_regs.sacr0, mem_mask); + return m_i2s_regs.sacr0; + case PXA255_SACR1: + verboselog(3, "pxa255_i2s_r: Serial Audio Controller I2S/MSB-Justified Control Register: %08x & %08x\n", m_i2s_regs.sacr1, mem_mask); + return m_i2s_regs.sacr1; + case PXA255_SASR0: + verboselog(3, "pxa255_i2s_r: Serial Audio Controller I2S/MSB-Justified Status Register: %08x & %08x\n", m_i2s_regs.sasr0, mem_mask); + return m_i2s_regs.sasr0; + case PXA255_SAIMR: + verboselog(3, "pxa255_i2s_r: Serial Audio Interrupt Mask Register: %08x & %08x\n", m_i2s_regs.saimr, mem_mask); + return m_i2s_regs.saimr; + case PXA255_SAICR: + verboselog(3, "pxa255_i2s_r: Serial Audio Interrupt Clear Register: %08x & %08x\n", m_i2s_regs.saicr, mem_mask); + return m_i2s_regs.saicr; + case PXA255_SADIV: + verboselog(3, "pxa255_i2s_r: Serial Audio Clock Divider Register: %08x & %08x\n", m_i2s_regs.sadiv, mem_mask); + return m_i2s_regs.sadiv; + case PXA255_SADR: + verboselog(5, "pxa255_i2s_r: Serial Audio Data Register: %08x & %08x\n", m_i2s_regs.sadr, mem_mask); + return m_i2s_regs.sadr; + default: + verboselog(0, "pxa255_i2s_r: Unknown address: %08x\n", PXA255_I2S_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +WRITE32_MEMBER(pxa255_periphs_device::pxa255_i2s_w) +{ + switch(PXA255_I2S_BASE_ADDR | (offset << 2)) + { + case PXA255_SACR0: + verboselog(3, "pxa255_i2s_w: Serial Audio Controller Global Control Register: %08x & %08x\n", data, mem_mask); + m_i2s_regs.sacr0 = data & 0x0000ff3d; + break; + case PXA255_SACR1: + verboselog(3, "pxa255_i2s_w: Serial Audio Controller I2S/MSB-Justified Control Register: %08x & %08x\n", data, mem_mask); + m_i2s_regs.sacr1 = data & 0x00000039; + break; + case PXA255_SASR0: + verboselog(3, "pxa255_i2s_w: Serial Audio Controller I2S/MSB-Justified Status Register: %08x & %08x\n", data, mem_mask); + m_i2s_regs.sasr0 = data & 0x0000ff7f; + break; + case PXA255_SAIMR: + verboselog(3, "pxa255_i2s_w: Serial Audio Interrupt Mask Register: %08x & %08x\n", data, mem_mask); + m_i2s_regs.saimr = data & 0x00000078; + break; + case PXA255_SAICR: + verboselog(3, "pxa255_i2s_w: Serial Audio Interrupt Clear Register: %08x & %08x\n", data, mem_mask); + if(m_i2s_regs.saicr & PXA255_SAICR_ROR) + { + m_i2s_regs.sasr0 &= ~PXA255_SASR0_ROR; + } + if(m_i2s_regs.saicr & PXA255_SAICR_TUR) + { + m_i2s_regs.sasr0 &= ~PXA255_SASR0_TUR; + } + break; + case PXA255_SADIV: + verboselog(3, "pxa255_i2s_w: Serial Audio Clock Divider Register: %08x & %08x\n", data, mem_mask); + m_i2s_regs.sadiv = data & 0x0000007f; + for (int i = 0; i < 2; i++) + { + m_dmadac[i]->set_frequency(((double)147600000 / (double)m_i2s_regs.sadiv) / 256.0); + m_dmadac[i]->enable(1); + } + break; + case PXA255_SADR: + verboselog(4, "pxa255_i2s_w: Serial Audio Data Register: %08x & %08x\n", data, mem_mask); + m_i2s_regs.sadr = data; + break; + default: + verboselog(0, "pxa255_i2s_w: Unknown address: %08x = %08x & %08x\n", PXA255_I2S_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + + PXA255 DMA controller + + pg. 151 to 182, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +void pxa255_periphs_device::pxa255_dma_irq_check() +{ + int set_irq = 0; + for (int channel = 0; channel < 16; channel++) + { + if (m_dma_regs.dcsr[channel] & (PXA255_DCSR_ENDINTR | PXA255_DCSR_STARTINTR | PXA255_DCSR_BUSERRINTR)) + { + m_dma_regs.dint |= 1 << channel; + set_irq = 1; + } + else + { + m_dma_regs.dint &= ~(1 << channel); + } + } + + pxa255_set_irq_line(PXA255_INT_DMA, set_irq); +} + +void pxa255_periphs_device::pxa255_dma_load_descriptor_and_start(int channel) +{ + // Shut down any transfers that are currently going on, software should be smart enough to check if a + // transfer is running before starting another one on the same channel. + if (m_dma_regs.timer[channel]->enabled()) + { + m_dma_regs.timer[channel]->adjust(attotime::never); + } + + // Load the next descriptor + + address_space &space = m_maincpu->space(AS_PROGRAM); + m_dma_regs.dsadr[channel] = space.read_dword(m_dma_regs.ddadr[channel] + 0x4); + m_dma_regs.dtadr[channel] = space.read_dword(m_dma_regs.ddadr[channel] + 0x8); + m_dma_regs.dcmd[channel] = space.read_dword(m_dma_regs.ddadr[channel] + 0xc); + m_dma_regs.ddadr[channel] = space.read_dword(m_dma_regs.ddadr[channel]); + + // Start our end-of-transfer timer + switch(channel) + { + case 3: + m_dma_regs.timer[channel]->adjust(attotime::from_hz((147600000 / m_i2s_regs.sadiv) / (4 * 64)) * (m_dma_regs.dcmd[channel] & 0x00001fff), channel); + break; + default: + m_dma_regs.timer[channel]->adjust(attotime::from_hz(100000000) * (m_dma_regs.dcmd[channel] & 0x00001fff), channel); + break; + } + + // Interrupt as necessary + if(m_dma_regs.dcmd[channel] & PXA255_DCMD_STARTIRQEN) + { + m_dma_regs.dcsr[channel] |= PXA255_DCSR_STARTINTR; + } + + m_dma_regs.dcsr[channel] &= ~PXA255_DCSR_STOPSTATE; +} + +TIMER_CALLBACK_MEMBER(pxa255_periphs_device::pxa255_dma_dma_end) +{ + uint32_t sadr = m_dma_regs.dsadr[param]; + uint32_t tadr = m_dma_regs.dtadr[param]; + uint32_t count = m_dma_regs.dcmd[param] & 0x00001fff; + + address_space &space = m_maincpu->space(AS_PROGRAM); + switch (param) + { + case 3: + for (uint32_t index = 0; index < count; index += 4) + { + m_words[index >> 2] = space.read_dword(sadr); + m_samples[(index >> 1) + 0] = (int16_t)(m_words[index >> 2] >> 16); + m_samples[(index >> 1) + 1] = (int16_t)(m_words[index >> 2] & 0xffff); + sadr += 4; + } + for (int index = 0; index < 2; index++) + { + m_dmadac[index]->flush(); + m_dmadac[index]->transfer(index, 2, 2, count/4, m_samples.get()); + } + break; + default: + for (uint32_t index = 0; index < count;) + { + switch (m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE) + { + case PXA255_DCMD_SIZE_8: + space.write_byte(tadr, space.read_byte(sadr)); + index++; + break; + case PXA255_DCMD_SIZE_16: + space.write_word(tadr, space.read_word(sadr)); + index += 2; + break; + case PXA255_DCMD_SIZE_32: + space.write_dword(tadr, space.read_dword(sadr)); + index += 4; + break; + default: + logerror( "pxa255_dma_dma_end: Unsupported DMA size\n" ); + break; + } + + if (m_dma_regs.dcmd[param] & PXA255_DCMD_INCSRCADDR) + { + switch(m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE) + { + case PXA255_DCMD_SIZE_8: + sadr++; + break; + case PXA255_DCMD_SIZE_16: + sadr += 2; + break; + case PXA255_DCMD_SIZE_32: + sadr += 4; + break; + default: + break; + } + } + if(m_dma_regs.dcmd[param] & PXA255_DCMD_INCTRGADDR) + { + switch(m_dma_regs.dcmd[param] & PXA255_DCMD_SIZE) + { + case PXA255_DCMD_SIZE_8: + tadr++; + break; + case PXA255_DCMD_SIZE_16: + tadr += 2; + break; + case PXA255_DCMD_SIZE_32: + tadr += 4; + break; + default: + break; + } + } + } + break; + } + + if (m_dma_regs.dcmd[param] & PXA255_DCMD_ENDIRQEN) + { + m_dma_regs.dcsr[param] |= PXA255_DCSR_ENDINTR; + } + + if (!(m_dma_regs.ddadr[param] & PXA255_DDADR_STOP) && (m_dma_regs.dcsr[param] & PXA255_DCSR_RUN)) + { + if (m_dma_regs.dcsr[param] & PXA255_DCSR_RUN) + { + pxa255_dma_load_descriptor_and_start(param); + } + else + { + m_dma_regs.dcsr[param] &= ~PXA255_DCSR_RUN; + m_dma_regs.dcsr[param] |= PXA255_DCSR_STOPSTATE; + } + } + else + { + m_dma_regs.dcsr[param] &= ~PXA255_DCSR_RUN; + m_dma_regs.dcsr[param] |= PXA255_DCSR_STOPSTATE; + } + + pxa255_dma_irq_check(); +} + +READ32_MEMBER(pxa255_periphs_device::pxa255_dma_r) +{ + switch(PXA255_DMA_BASE_ADDR | (offset << 2)) + { + case PXA255_DCSR0: case PXA255_DCSR1: case PXA255_DCSR2: case PXA255_DCSR3: + case PXA255_DCSR4: case PXA255_DCSR5: case PXA255_DCSR6: case PXA255_DCSR7: + case PXA255_DCSR8: case PXA255_DCSR9: case PXA255_DCSR10: case PXA255_DCSR11: + case PXA255_DCSR12: case PXA255_DCSR13: case PXA255_DCSR14: case PXA255_DCSR15: + verboselog(4, "pxa255_dma_r: DMA Channel Control/Status Register %d: %08x & %08x\n", offset, m_dma_regs.dcsr[offset], mem_mask); + return m_dma_regs.dcsr[offset]; + case PXA255_DINT: + if (0) verboselog(3, "pxa255_dma_r: DMA Interrupt Register: %08x & %08x\n", m_dma_regs.dint, mem_mask); + return m_dma_regs.dint; + case PXA255_DRCMR0: case PXA255_DRCMR1: case PXA255_DRCMR2: case PXA255_DRCMR3: + case PXA255_DRCMR4: case PXA255_DRCMR5: case PXA255_DRCMR6: case PXA255_DRCMR7: + case PXA255_DRCMR8: case PXA255_DRCMR9: case PXA255_DRCMR10: case PXA255_DRCMR11: + case PXA255_DRCMR12: case PXA255_DRCMR13: case PXA255_DRCMR14: case PXA255_DRCMR15: + case PXA255_DRCMR16: case PXA255_DRCMR17: case PXA255_DRCMR18: case PXA255_DRCMR19: + case PXA255_DRCMR20: case PXA255_DRCMR21: case PXA255_DRCMR22: case PXA255_DRCMR23: + case PXA255_DRCMR24: case PXA255_DRCMR25: case PXA255_DRCMR26: case PXA255_DRCMR27: + case PXA255_DRCMR28: case PXA255_DRCMR29: case PXA255_DRCMR30: case PXA255_DRCMR31: + case PXA255_DRCMR32: case PXA255_DRCMR33: case PXA255_DRCMR34: case PXA255_DRCMR35: + case PXA255_DRCMR36: case PXA255_DRCMR37: case PXA255_DRCMR38: case PXA255_DRCMR39: + verboselog(3, "pxa255_dma_r: DMA Request to Channel Map Register %d: %08x & %08x\n", offset - (0x100 >> 2), 0, mem_mask); + return m_dma_regs.drcmr[offset - (0x100 >> 2)]; + case PXA255_DDADR0: case PXA255_DDADR1: case PXA255_DDADR2: case PXA255_DDADR3: + case PXA255_DDADR4: case PXA255_DDADR5: case PXA255_DDADR6: case PXA255_DDADR7: + case PXA255_DDADR8: case PXA255_DDADR9: case PXA255_DDADR10: case PXA255_DDADR11: + case PXA255_DDADR12: case PXA255_DDADR13: case PXA255_DDADR14: case PXA255_DDADR15: + verboselog(3, "pxa255_dma_r: DMA Descriptor Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, 0, mem_mask); + return m_dma_regs.ddadr[(offset - (0x200 >> 2)) >> 2]; + case PXA255_DSADR0: case PXA255_DSADR1: case PXA255_DSADR2: case PXA255_DSADR3: + case PXA255_DSADR4: case PXA255_DSADR5: case PXA255_DSADR6: case PXA255_DSADR7: + case PXA255_DSADR8: case PXA255_DSADR9: case PXA255_DSADR10: case PXA255_DSADR11: + case PXA255_DSADR12: case PXA255_DSADR13: case PXA255_DSADR14: case PXA255_DSADR15: + verboselog(3, "pxa255_dma_r: DMA Source Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, 0, mem_mask); + return m_dma_regs.dsadr[(offset - (0x200 >> 2)) >> 2]; + case PXA255_DTADR0: case PXA255_DTADR1: case PXA255_DTADR2: case PXA255_DTADR3: + case PXA255_DTADR4: case PXA255_DTADR5: case PXA255_DTADR6: case PXA255_DTADR7: + case PXA255_DTADR8: case PXA255_DTADR9: case PXA255_DTADR10: case PXA255_DTADR11: + case PXA255_DTADR12: case PXA255_DTADR13: case PXA255_DTADR14: case PXA255_DTADR15: + verboselog(3, "pxa255_dma_r: DMA Target Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, 0, mem_mask); + return m_dma_regs.dtadr[(offset - (0x200 >> 2)) >> 2]; + case PXA255_DCMD0: case PXA255_DCMD1: case PXA255_DCMD2: case PXA255_DCMD3: + case PXA255_DCMD4: case PXA255_DCMD5: case PXA255_DCMD6: case PXA255_DCMD7: + case PXA255_DCMD8: case PXA255_DCMD9: case PXA255_DCMD10: case PXA255_DCMD11: + case PXA255_DCMD12: case PXA255_DCMD13: case PXA255_DCMD14: case PXA255_DCMD15: + verboselog(3, "pxa255_dma_r: DMA Command Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, 0, mem_mask); + return m_dma_regs.dcmd[(offset - (0x200 >> 2)) >> 2]; + default: + verboselog(0, "pxa255_dma_r: Unknown address: %08x\n", PXA255_DMA_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +WRITE32_MEMBER(pxa255_periphs_device::pxa255_dma_w) +{ + switch (PXA255_DMA_BASE_ADDR | (offset << 2)) + { + case PXA255_DCSR0: case PXA255_DCSR1: case PXA255_DCSR2: case PXA255_DCSR3: + case PXA255_DCSR4: case PXA255_DCSR5: case PXA255_DCSR6: case PXA255_DCSR7: + case PXA255_DCSR8: case PXA255_DCSR9: case PXA255_DCSR10: case PXA255_DCSR11: + case PXA255_DCSR12: case PXA255_DCSR13: case PXA255_DCSR14: case PXA255_DCSR15: + if (0) verboselog(3, "pxa255_dma_w: DMA Channel Control/Status Register %d: %08x & %08x\n", offset, data, mem_mask); + m_dma_regs.dcsr[offset] &= ~(data & 0x00000007); + m_dma_regs.dcsr[offset] &= ~0x60000000; + m_dma_regs.dcsr[offset] |= data & 0x60000000; + if ((data & PXA255_DCSR_RUN) && !(m_dma_regs.dcsr[offset] & PXA255_DCSR_RUN)) + { + m_dma_regs.dcsr[offset] |= PXA255_DCSR_RUN; + if (data & PXA255_DCSR_NODESCFETCH) + { + verboselog(0, " No-Descriptor-Fetch mode is not supported.\n"); + break; + } + + pxa255_dma_load_descriptor_and_start(offset); + } + else if(!(data & PXA255_DCSR_RUN)) + { + m_dma_regs.dcsr[offset] &= ~PXA255_DCSR_RUN; + } + + pxa255_dma_irq_check(); + break; + case PXA255_DINT: + verboselog(3, "pxa255_dma_w: DMA Interrupt Register: %08x & %08x\n", data, mem_mask); + m_dma_regs.dint &= ~data; + break; + case PXA255_DRCMR0: case PXA255_DRCMR1: case PXA255_DRCMR2: case PXA255_DRCMR3: + case PXA255_DRCMR4: case PXA255_DRCMR5: case PXA255_DRCMR6: case PXA255_DRCMR7: + case PXA255_DRCMR8: case PXA255_DRCMR9: case PXA255_DRCMR10: case PXA255_DRCMR11: + case PXA255_DRCMR12: case PXA255_DRCMR13: case PXA255_DRCMR14: case PXA255_DRCMR15: + case PXA255_DRCMR16: case PXA255_DRCMR17: case PXA255_DRCMR18: case PXA255_DRCMR19: + case PXA255_DRCMR20: case PXA255_DRCMR21: case PXA255_DRCMR22: case PXA255_DRCMR23: + case PXA255_DRCMR24: case PXA255_DRCMR25: case PXA255_DRCMR26: case PXA255_DRCMR27: + case PXA255_DRCMR28: case PXA255_DRCMR29: case PXA255_DRCMR30: case PXA255_DRCMR31: + case PXA255_DRCMR32: case PXA255_DRCMR33: case PXA255_DRCMR34: case PXA255_DRCMR35: + case PXA255_DRCMR36: case PXA255_DRCMR37: case PXA255_DRCMR38: case PXA255_DRCMR39: + verboselog(3, "pxa255_dma_w: DMA Request to Channel Map Register %d: %08x & %08x\n", offset - (0x100 >> 2), data, mem_mask); + m_dma_regs.drcmr[offset - (0x100 >> 2)] = data & 0x0000008f; + break; + case PXA255_DDADR0: case PXA255_DDADR1: case PXA255_DDADR2: case PXA255_DDADR3: + case PXA255_DDADR4: case PXA255_DDADR5: case PXA255_DDADR6: case PXA255_DDADR7: + case PXA255_DDADR8: case PXA255_DDADR9: case PXA255_DDADR10: case PXA255_DDADR11: + case PXA255_DDADR12: case PXA255_DDADR13: case PXA255_DDADR14: case PXA255_DDADR15: + verboselog(3, "pxa255_dma_w: DMA Descriptor Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, data, mem_mask); + m_dma_regs.ddadr[(offset - (0x200 >> 2)) >> 2] = data & 0xfffffff1; + break; + case PXA255_DSADR0: case PXA255_DSADR1: case PXA255_DSADR2: case PXA255_DSADR3: + case PXA255_DSADR4: case PXA255_DSADR5: case PXA255_DSADR6: case PXA255_DSADR7: + case PXA255_DSADR8: case PXA255_DSADR9: case PXA255_DSADR10: case PXA255_DSADR11: + case PXA255_DSADR12: case PXA255_DSADR13: case PXA255_DSADR14: case PXA255_DSADR15: + verboselog(3, "pxa255_dma_w: DMA Source Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, data, mem_mask); + m_dma_regs.dsadr[(offset - (0x200 >> 2)) >> 2] = data & 0xfffffffc; + break; + case PXA255_DTADR0: case PXA255_DTADR1: case PXA255_DTADR2: case PXA255_DTADR3: + case PXA255_DTADR4: case PXA255_DTADR5: case PXA255_DTADR6: case PXA255_DTADR7: + case PXA255_DTADR8: case PXA255_DTADR9: case PXA255_DTADR10: case PXA255_DTADR11: + case PXA255_DTADR12: case PXA255_DTADR13: case PXA255_DTADR14: case PXA255_DTADR15: + verboselog(3, "pxa255_dma_w: DMA Target Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, data, mem_mask); + m_dma_regs.dtadr[(offset - (0x200 >> 2)) >> 2] = data & 0xfffffffc; + break; + case PXA255_DCMD0: case PXA255_DCMD1: case PXA255_DCMD2: case PXA255_DCMD3: + case PXA255_DCMD4: case PXA255_DCMD5: case PXA255_DCMD6: case PXA255_DCMD7: + case PXA255_DCMD8: case PXA255_DCMD9: case PXA255_DCMD10: case PXA255_DCMD11: + case PXA255_DCMD12: case PXA255_DCMD13: case PXA255_DCMD14: case PXA255_DCMD15: + verboselog(3, "pxa255_dma_w: DMA Command Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, data, mem_mask); + m_dma_regs.dcmd[(offset - (0x200 >> 2)) >> 2] = data & 0xf067dfff; + break; + default: + verboselog(0, "pxa255_dma_w: Unknown address: %08x = %08x & %08x\n", PXA255_DMA_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + + PXA255 OS Timer register + + pg. 138 to 142, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +void pxa255_periphs_device::pxa255_ostimer_irq_check() +{ + pxa255_set_irq_line(PXA255_INT_OSTIMER0, (m_ostimer_regs.oier & PXA255_OIER_E0) ? ((m_ostimer_regs.ossr & PXA255_OSSR_M0) ? 1 : 0) : 0); + //pxa255_set_irq_line(PXA255_INT_OSTIMER1, (m_ostimer_regs.oier & PXA255_OIER_E1) ? ((m_ostimer_regs.ossr & PXA255_OSSR_M1) ? 1 : 0) : 0); + //pxa255_set_irq_line(PXA255_INT_OSTIMER2, (m_ostimer_regs.oier & PXA255_OIER_E2) ? ((m_ostimer_regs.ossr & PXA255_OSSR_M2) ? 1 : 0) : 0); + //pxa255_set_irq_line(PXA255_INT_OSTIMER3, (m_ostimer_regs.oier & PXA255_OIER_E3) ? ((m_ostimer_regs.ossr & PXA255_OSSR_M3) ? 1 : 0) : 0); +} + +TIMER_CALLBACK_MEMBER(pxa255_periphs_device::pxa255_ostimer_match) +{ + if (0) verboselog(3, "pxa255_ostimer_match channel %d\n", param); + m_ostimer_regs.ossr |= (1 << param); + m_ostimer_regs.oscr = m_ostimer_regs.osmr[param]; + pxa255_ostimer_irq_check(); +} + +READ32_MEMBER(pxa255_periphs_device::pxa255_ostimer_r) +{ + switch(PXA255_OSTMR_BASE_ADDR | (offset << 2)) + { + case PXA255_OSMR0: + if (0) verboselog(3, "pxa255_ostimer_r: OS Timer Match Register 0: %08x & %08x\n", m_ostimer_regs.osmr[0], mem_mask); + return m_ostimer_regs.osmr[0]; + case PXA255_OSMR1: + if (0) verboselog(3, "pxa255_ostimer_r: OS Timer Match Register 1: %08x & %08x\n", m_ostimer_regs.osmr[1], mem_mask); + return m_ostimer_regs.osmr[1]; + case PXA255_OSMR2: + if (0) verboselog(3, "pxa255_ostimer_r: OS Timer Match Register 2: %08x & %08x\n", m_ostimer_regs.osmr[2], mem_mask); + return m_ostimer_regs.osmr[2]; + case PXA255_OSMR3: + if (0) verboselog(3, "pxa255_ostimer_r: OS Timer Match Register 3: %08x & %08x\n", m_ostimer_regs.osmr[3], mem_mask); + return m_ostimer_regs.osmr[3]; + case PXA255_OSCR: + if (0) verboselog(4, "pxa255_ostimer_r: OS Timer Count Register: %08x & %08x\n", m_ostimer_regs.oscr, mem_mask); + // free-running 3.something MHz counter. this is a complete hack. + m_ostimer_regs.oscr += 0x300; + return m_ostimer_regs.oscr; + case PXA255_OSSR: + if (0) verboselog(3, "pxa255_ostimer_r: OS Timer Status Register: %08x & %08x\n", m_ostimer_regs.ossr, mem_mask); + return m_ostimer_regs.ossr; + case PXA255_OWER: + if (0) verboselog(3, "pxa255_ostimer_r: OS Timer Watchdog Match Enable Register: %08x & %08x\n", m_ostimer_regs.ower, mem_mask); + return m_ostimer_regs.ower; + case PXA255_OIER: + if (0) verboselog(3, "pxa255_ostimer_r: OS Timer Interrupt Enable Register: %08x & %08x\n", m_ostimer_regs.oier, mem_mask); + return m_ostimer_regs.oier; + default: + if (0) verboselog(0, "pxa255_ostimer_r: Unknown address: %08x\n", PXA255_OSTMR_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +WRITE32_MEMBER(pxa255_periphs_device::pxa255_ostimer_w) +{ + switch(PXA255_OSTMR_BASE_ADDR | (offset << 2)) + { + case PXA255_OSMR0: + if (0) verboselog(3, "pxa255_ostimer_w: OS Timer Match Register 0: %08x & %08x\n", data, mem_mask); + m_ostimer_regs.osmr[0] = data; + if (m_ostimer_regs.oier & PXA255_OIER_E0) + { + m_ostimer_regs.timer[0]->adjust(attotime::from_hz(3846400) * (m_ostimer_regs.osmr[0] - m_ostimer_regs.oscr)); + } + break; + case PXA255_OSMR1: + if (0) verboselog(3, "pxa255_ostimer_w: OS Timer Match Register 1: %08x & %08x\n", data, mem_mask); + m_ostimer_regs.osmr[1] = data; + if (m_ostimer_regs.oier & PXA255_OIER_E1) + { + m_ostimer_regs.timer[1]->adjust(attotime::from_hz(3846400) * (m_ostimer_regs.osmr[1] - m_ostimer_regs.oscr), 1); + } + break; + case PXA255_OSMR2: + if (0) verboselog(3, "pxa255_ostimer_w: OS Timer Match Register 2: %08x & %08x\n", data, mem_mask); + m_ostimer_regs.osmr[2] = data; + if (m_ostimer_regs.oier & PXA255_OIER_E2) + { + m_ostimer_regs.timer[2]->adjust(attotime::from_hz(3846400) * (m_ostimer_regs.osmr[2] - m_ostimer_regs.oscr), 2); + } + break; + case PXA255_OSMR3: + if (0) verboselog(3, "pxa255_ostimer_w: OS Timer Match Register 3: %08x & %08x\n", data, mem_mask); + m_ostimer_regs.osmr[3] = data; + if (m_ostimer_regs.oier & PXA255_OIER_E3) + { + //m_ostimer_regs.timer[3]->adjust(attotime::from_hz(3846400) * (m_ostimer_regs.osmr[3] - m_ostimer_regs.oscr), 3); + } + break; + case PXA255_OSCR: + if (0) verboselog(3, "pxa255_ostimer_w: OS Timer Count Register: %08x & %08x\n", data, mem_mask); + m_ostimer_regs.oscr = data; + break; + case PXA255_OSSR: + if (0) verboselog(3, "pxa255_ostimer_w: OS Timer Status Register: %08x & %08x\n", data, mem_mask); + m_ostimer_regs.ossr &= ~data; + pxa255_ostimer_irq_check(); + break; + case PXA255_OWER: + if (0) verboselog(3, "pxa255_ostimer_w: OS Timer Watchdog Enable Register: %08x & %08x\n", data, mem_mask); + m_ostimer_regs.ower = data & 0x00000001; + break; + case PXA255_OIER: + { + if (0) verboselog(3, "pxa255_ostimer_w: OS Timer Interrupt Enable Register: %08x & %08x\n", data, mem_mask); + m_ostimer_regs.oier = data & 0x0000000f; + for (int index = 0; index < 4; index++) + { + if (m_ostimer_regs.oier & (1 << index)) + { + //m_ostimer_regs.timer[index]->adjust(attotime::from_hz(200000000) * m_ostimer_regs.osmr[index], index); + } + } + break; + } + default: + verboselog(0, "pxa255_ostimer_w: Unknown address: %08x = %08x & %08x\n", PXA255_OSTMR_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + + PXA255 Interrupt registers + + pg. 124 to 132, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +void pxa255_periphs_device::pxa255_update_interrupts() +{ + m_intc_regs.icfp = (m_intc_regs.icpr & m_intc_regs.icmr) & m_intc_regs.iclr; + m_intc_regs.icip = (m_intc_regs.icpr & m_intc_regs.icmr) & (~m_intc_regs.iclr); + m_maincpu->set_input_line(ARM7_FIRQ_LINE, m_intc_regs.icfp ? ASSERT_LINE : CLEAR_LINE); + m_maincpu->set_input_line(ARM7_IRQ_LINE, m_intc_regs.icip ? ASSERT_LINE : CLEAR_LINE); +} + +void pxa255_periphs_device::pxa255_set_irq_line(uint32_t line, int irq_state) +{ + m_intc_regs.icpr &= ~line; + m_intc_regs.icpr |= irq_state ? line : 0; + pxa255_update_interrupts(); +} + +READ32_MEMBER(pxa255_periphs_device::pxa255_intc_r) +{ + switch (PXA255_INTC_BASE_ADDR | (offset << 2)) + { + case PXA255_ICIP: + if (0) verboselog(3, "pxa255_intc_r: Interrupt Controller IRQ Pending Register: %08x & %08x\n", m_intc_regs.icip, mem_mask); + return m_intc_regs.icip; + case PXA255_ICMR: + if (0) verboselog(3, "pxa255_intc_r: Interrupt Controller Mask Register: %08x & %08x\n", m_intc_regs.icmr, mem_mask); + return m_intc_regs.icmr; + case PXA255_ICLR: + if (0) verboselog(3, "pxa255_intc_r: Interrupt Controller Level Register: %08x & %08x\n", m_intc_regs.iclr, mem_mask); + return m_intc_regs.iclr; + case PXA255_ICFP: + if (0) verboselog(3, "pxa255_intc_r: Interrupt Controller FIQ Pending Register: %08x & %08x\n", m_intc_regs.icfp, mem_mask); + return m_intc_regs.icfp; + case PXA255_ICPR: + if (0) verboselog(3, "pxa255_intc_r: Interrupt Controller Pending Register: %08x & %08x\n", m_intc_regs.icpr, mem_mask); + return m_intc_regs.icpr; + case PXA255_ICCR: + if (0) verboselog(3, "pxa255_intc_r: Interrupt Controller Control Register: %08x & %08x\n", m_intc_regs.iccr, mem_mask); + return m_intc_regs.iccr; + default: + verboselog(0, "pxa255_intc_r: Unknown address: %08x\n", PXA255_INTC_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +WRITE32_MEMBER(pxa255_periphs_device::pxa255_intc_w) +{ + switch (PXA255_INTC_BASE_ADDR | (offset << 2)) + { + case PXA255_ICIP: + verboselog(3, "pxa255_intc_w: (Invalid Write) Interrupt Controller IRQ Pending Register: %08x & %08x\n", data, mem_mask); + break; + case PXA255_ICMR: + if (0) verboselog(3, "pxa255_intc_w: Interrupt Controller Mask Register: %08x & %08x\n", data, mem_mask); + m_intc_regs.icmr = data & 0xfffe7f00; + break; + case PXA255_ICLR: + if (0) verboselog(3, "pxa255_intc_w: Interrupt Controller Level Register: %08x & %08x\n", data, mem_mask); + m_intc_regs.iclr = data & 0xfffe7f00; + break; + case PXA255_ICFP: + if (0) verboselog(3, "pxa255_intc_w: (Invalid Write) Interrupt Controller FIQ Pending Register: %08x & %08x\n", data, mem_mask); + break; + case PXA255_ICPR: + if (0) verboselog(3, "pxa255_intc_w: (Invalid Write) Interrupt Controller Pending Register: %08x & %08x\n", data, mem_mask); + break; + case PXA255_ICCR: + if (0) verboselog(3, "pxa255_intc_w: Interrupt Controller Control Register: %08x & %08x\n", data, mem_mask); + m_intc_regs.iccr = data & 0x00000001; + break; + default: + verboselog(0, "pxa255_intc_w: Unknown address: %08x = %08x & %08x\n", PXA255_INTC_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + + PXA255 General-Purpose I/O registers + + pg. 105 to 124, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +READ32_MEMBER(pxa255_periphs_device::pxa255_gpio_r) +{ + switch(PXA255_GPIO_BASE_ADDR | (offset << 2)) + { + case PXA255_GPLR0: + { + uint32_t value = m_gpio_regs.gplr0; + if (!m_gpio0_in_func.isnull()) + { + value |= m_gpio0_in_func(space, 0); + } + verboselog(3, "pxa255_gpio_r: GPIO Pin-Level Register 0: %08x & %08x\n", m_gpio_regs.gplr0 | (1 << 1), mem_mask); + return value; + } + case PXA255_GPLR1: + verboselog(3, "pxa255_gpio_r: *Not Yet Implemented* GPIO Pin-Level Register 1: %08x & %08x\n", m_gpio_regs.gplr1, mem_mask); + return 0xff9fffff; + /* + 0x200000 = flip screen + */ + case PXA255_GPLR2: + verboselog(3, "pxa255_gpio_r: *Not Yet Implemented* GPIO Pin-Level Register 2: %08x & %08x\n", m_gpio_regs.gplr2, mem_mask); + return m_gpio_regs.gplr2; + case PXA255_GPDR0: + verboselog(3, "pxa255_gpio_r: GPIO Pin Direction Register 0: %08x & %08x\n", m_gpio_regs.gpdr0, mem_mask); + return m_gpio_regs.gpdr0; + case PXA255_GPDR1: + verboselog(3, "pxa255_gpio_r: GPIO Pin Direction Register 1: %08x & %08x\n", m_gpio_regs.gpdr1, mem_mask); + return m_gpio_regs.gpdr1; + case PXA255_GPDR2: + verboselog(3, "pxa255_gpio_r: GPIO Pin Direction Register 2: %08x & %08x\n", m_gpio_regs.gpdr2, mem_mask); + return m_gpio_regs.gpdr2; + case PXA255_GPSR0: + verboselog(3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 0: %08x & %08x\n", machine().rand(), mem_mask); + return machine().rand(); + case PXA255_GPSR1: + verboselog(3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 1: %08x & %08x\n", machine().rand(), mem_mask); + return machine().rand(); + case PXA255_GPSR2: + verboselog(3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 2: %08x & %08x\n", machine().rand(), mem_mask); + return machine().rand(); + case PXA255_GPCR0: + verboselog(3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 0: %08x & %08x\n", machine().rand(), mem_mask); + return machine().rand(); + case PXA255_GPCR1: + verboselog(3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 1: %08x & %08x\n", machine().rand(), mem_mask); + return machine().rand(); + case PXA255_GPCR2: + verboselog(3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 2: %08x & %08x\n", machine().rand(), mem_mask); + return machine().rand(); + case PXA255_GRER0: + verboselog(3, "pxa255_gpio_r: GPIO Rising Edge Detect Enable Register 0: %08x & %08x\n", m_gpio_regs.grer0, mem_mask); + return m_gpio_regs.grer0; + case PXA255_GRER1: + verboselog(3, "pxa255_gpio_r: GPIO Rising Edge Detect Enable Register 1: %08x & %08x\n", m_gpio_regs.grer1, mem_mask); + return m_gpio_regs.grer1; + case PXA255_GRER2: + verboselog(3, "pxa255_gpio_r: GPIO Rising Edge Detect Enable Register 2: %08x & %08x\n", m_gpio_regs.grer2, mem_mask); + return m_gpio_regs.grer2; + case PXA255_GFER0: + verboselog(3, "pxa255_gpio_r: GPIO Falling Edge Detect Enable Register 0: %08x & %08x\n", m_gpio_regs.gfer0, mem_mask); + return m_gpio_regs.gfer0; + case PXA255_GFER1: + verboselog(3, "pxa255_gpio_r: GPIO Falling Edge Detect Enable Register 1: %08x & %08x\n", m_gpio_regs.gfer1, mem_mask); + return m_gpio_regs.gfer1; + case PXA255_GFER2: + verboselog(3, "pxa255_gpio_r: GPIO Falling Edge Detect Enable Register 2: %08x & %08x\n", m_gpio_regs.gfer2, mem_mask); + return m_gpio_regs.gfer2; + case PXA255_GEDR0: + verboselog(3, "pxa255_gpio_r: GPIO Edge Detect Status Register 0: %08x & %08x\n", m_gpio_regs.gedr0, mem_mask); + return m_gpio_regs.gedr0; + case PXA255_GEDR1: + verboselog(3, "pxa255_gpio_r: GPIO Edge Detect Status Register 1: %08x & %08x\n", m_gpio_regs.gedr1, mem_mask); + return m_gpio_regs.gedr1; + case PXA255_GEDR2: + verboselog(3, "pxa255_gpio_r: GPIO Edge Detect Status Register 2: %08x & %08x\n", m_gpio_regs.gedr2, mem_mask); + return m_gpio_regs.gedr2; + case PXA255_GAFR0_L: + verboselog(3, "pxa255_gpio_r: GPIO Alternate Function Register 0 Lower: %08x & %08x\n", m_gpio_regs.gafr0l, mem_mask); + return m_gpio_regs.gafr0l; + case PXA255_GAFR0_U: + verboselog(3, "pxa255_gpio_r: GPIO Alternate Function Register 0 Upper: %08x & %08x\n", m_gpio_regs.gafr0u, mem_mask); + return m_gpio_regs.gafr0u; + case PXA255_GAFR1_L: + verboselog(3, "pxa255_gpio_r: GPIO Alternate Function Register 1 Lower: %08x & %08x\n", m_gpio_regs.gafr1l, mem_mask); + return m_gpio_regs.gafr1l; + case PXA255_GAFR1_U: + verboselog(3, "pxa255_gpio_r: GPIO Alternate Function Register 1 Upper: %08x & %08x\n", m_gpio_regs.gafr1u, mem_mask); + return m_gpio_regs.gafr1u; + case PXA255_GAFR2_L: + verboselog(3, "pxa255_gpio_r: GPIO Alternate Function Register 2 Lower: %08x & %08x\n", m_gpio_regs.gafr2l, mem_mask); + return m_gpio_regs.gafr2l; + case PXA255_GAFR2_U: + verboselog(3, "pxa255_gpio_r: GPIO Alternate Function Register 2 Upper: %08x & %08x\n", m_gpio_regs.gafr2u, mem_mask); + return m_gpio_regs.gafr2u; + default: + verboselog(0, "pxa255_gpio_r: Unknown address: %08x\n", PXA255_GPIO_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +WRITE32_MEMBER(pxa255_periphs_device::pxa255_gpio_w) +{ + switch(PXA255_GPIO_BASE_ADDR | (offset << 2)) + { + case PXA255_GPLR0: + verboselog(3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 0: %08x & %08x\n", data, mem_mask); + break; + case PXA255_GPLR1: + verboselog(3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 1: %08x & %08x\n", data, mem_mask); + break; + case PXA255_GPLR2: + verboselog(3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 2: %08x & %08x\n", data, mem_mask); + break; + case PXA255_GPDR0: + verboselog(3, "pxa255_gpio_w: GPIO Pin Direction Register 0: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpdr0 = data; + break; + case PXA255_GPDR1: + verboselog(3, "pxa255_gpio_w: GPIO Pin Direction Register 1: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpdr1 = data; + break; + case PXA255_GPDR2: + verboselog(3, "pxa255_gpio_w: GPIO Pin Direction Register 2: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpdr2 = data; + break; + case PXA255_GPSR0: + verboselog(3, "pxa255_gpio_w: GPIO Pin Output Set Register 0: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpsr0 |= data & m_gpio_regs.gpdr0; + if (!m_gpio0_set_func.isnull()) + { + m_gpio0_set_func(space, 0, data); + } + break; + case PXA255_GPSR1: + verboselog(3, "pxa255_gpio_w: GPIO Pin Output Set Register 1: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpsr1 |= data & m_gpio_regs.gpdr1; + break; + case PXA255_GPSR2: + verboselog(3, "pxa255_gpio_w: GPIO Pin Output Set Register 2: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpsr2 |= data & m_gpio_regs.gpdr2; + break; + case PXA255_GPCR0: + verboselog(3, "pxa255_gpio_w: GPIO Pin Output Clear Register 0: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpsr0 &= ~(data & m_gpio_regs.gpdr0); + if (!m_gpio0_clear_func.isnull()) + { + m_gpio0_clear_func(space, 0, data); + } + break; + case PXA255_GPCR1: + verboselog(3, "pxa255_gpio_w: GPIO Pin Output Clear Register 1: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpsr1 &= ~(data & m_gpio_regs.gpdr1); + break; + case PXA255_GPCR2: + verboselog(3, "pxa255_gpio_w: GPIO Pin Output Clear Register 2: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gpsr2 &= ~(data & m_gpio_regs.gpdr2); + break; + case PXA255_GRER0: + verboselog(3, "pxa255_gpio_w: GPIO Rising Edge Detect Enable Register 0: %08x & %08x\n", data, mem_mask); + m_gpio_regs.grer0 = data; + break; + case PXA255_GRER1: + verboselog(3, "pxa255_gpio_w: GPIO Rising Edge Detect Enable Register 1: %08x & %08x\n", data, mem_mask); + m_gpio_regs.grer1 = data; + break; + case PXA255_GRER2: + verboselog(3, "pxa255_gpio_w: GPIO Rising Edge Detect Enable Register 2: %08x & %08x\n", data, mem_mask); + m_gpio_regs.grer2 = data; + break; + case PXA255_GFER0: + verboselog(3, "pxa255_gpio_w: GPIO Falling Edge Detect Enable Register 0: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gfer0 = data; + break; + case PXA255_GFER1: + verboselog(3, "pxa255_gpio_w: GPIO Falling Edge Detect Enable Register 1: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gfer1 = data; + break; + case PXA255_GFER2: + verboselog(3, "pxa255_gpio_w: GPIO Falling Edge Detect Enable Register 2: %08x & %08x\n", data, mem_mask); + m_gpio_regs.gfer2 = data; + break; + case PXA255_GEDR0: + verboselog(3, "pxa255_gpio_w: GPIO Edge Detect Status Register 0: %08x & %08x\n", m_gpio_regs.gedr0, mem_mask); + m_gpio_regs.gedr0 &= ~data; + break; + case PXA255_GEDR1: + verboselog(3, "pxa255_gpio_w: GPIO Edge Detect Status Register 1: %08x & %08x\n", m_gpio_regs.gedr1, mem_mask); + m_gpio_regs.gedr1 &= ~data; + break; + case PXA255_GEDR2: + verboselog(3, "pxa255_gpio_w: GPIO Edge Detect Status Register 2: %08x & %08x\n", m_gpio_regs.gedr2, mem_mask); + m_gpio_regs.gedr2 &= ~data; + break; + case PXA255_GAFR0_L: + verboselog(3, "pxa255_gpio_w: GPIO Alternate Function Register 0 Lower: %08x & %08x\n", m_gpio_regs.gafr0l, mem_mask); + m_gpio_regs.gafr0l = data; + break; + case PXA255_GAFR0_U: + verboselog(3, "pxa255_gpio_w: GPIO Alternate Function Register 0 Upper: %08x & %08x\n", m_gpio_regs.gafr0u, mem_mask); + m_gpio_regs.gafr0u = data; + break; + case PXA255_GAFR1_L: + verboselog(3, "pxa255_gpio_w: GPIO Alternate Function Register 1 Lower: %08x & %08x\n", m_gpio_regs.gafr1l, mem_mask); + m_gpio_regs.gafr1l = data; + break; + case PXA255_GAFR1_U: + verboselog(3, "pxa255_gpio_w: GPIO Alternate Function Register 1 Upper: %08x & %08x\n", m_gpio_regs.gafr1u, mem_mask); + m_gpio_regs.gafr1u = data; + break; + case PXA255_GAFR2_L: + verboselog(3, "pxa255_gpio_w: GPIO Alternate Function Register 2 Lower: %08x & %08x\n", m_gpio_regs.gafr2l, mem_mask); + m_gpio_regs.gafr2l = data; + break; + case PXA255_GAFR2_U: + verboselog(3, "pxa255_gpio_w: GPIO Alternate Function Register 2 Upper: %08x & %08x\n", m_gpio_regs.gafr2u, mem_mask); + m_gpio_regs.gafr2u = data; + break; + default: + verboselog(0, "pxa255_gpio_w: Unknown address: %08x = %08x & %08x\n", PXA255_GPIO_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +/* + + PXA255 LCD Controller + + pg. 265 to 310, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +void pxa255_periphs_device::pxa255_lcd_load_dma_descriptor(address_space & space, uint32_t address, int channel) +{ + m_lcd_regs.dma[channel].fdadr = space.read_dword(address); + m_lcd_regs.dma[channel].fsadr = space.read_dword(address + 0x04); + m_lcd_regs.dma[channel].fidr = space.read_dword(address + 0x08); + m_lcd_regs.dma[channel].ldcmd = space.read_dword(address + 0x0c); + verboselog(4, "pxa255_lcd_load_dma_descriptor, address = %08x, channel = %d\n", address, channel); + verboselog(4, " DMA Frame Descriptor: %08x\n", m_lcd_regs.dma[channel].fdadr ); + verboselog(4, " DMA Frame Source Address: %08x\n", m_lcd_regs.dma[channel].fsadr ); + verboselog(4, " DMA Frame ID: %08x\n", m_lcd_regs.dma[channel].fidr ); + verboselog(4, " DMA Command: %08x\n", m_lcd_regs.dma[channel].ldcmd ); +} + +void pxa255_periphs_device::pxa255_lcd_irq_check() +{ + if(((m_lcd_regs.lcsr & PXA255_LCSR_BS) != 0 && (m_lcd_regs.lccr0 & PXA255_LCCR0_BM) == 0) || + ((m_lcd_regs.lcsr & PXA255_LCSR_EOF) != 0 && (m_lcd_regs.lccr0 & PXA255_LCCR0_EFM) == 0) || + ((m_lcd_regs.lcsr & PXA255_LCSR_SOF) != 0 && (m_lcd_regs.lccr0 & PXA255_LCCR0_SFM) == 0)) + { + pxa255_set_irq_line(PXA255_INT_LCD, 1); + } + else + { + pxa255_set_irq_line(PXA255_INT_LCD, 0); + } +} + +void pxa255_periphs_device::pxa255_lcd_dma_kickoff(int channel) +{ + if(m_lcd_regs.dma[channel].fdadr != 0) + { + attotime period = attotime::from_hz(20000000) * (m_lcd_regs.dma[channel].ldcmd & 0x000fffff); + + m_lcd_regs.dma[channel].eof->adjust(period, channel); + + if(m_lcd_regs.dma[channel].ldcmd & PXA255_LDCMD_SOFINT) + { + m_lcd_regs.liidr = m_lcd_regs.dma[channel].fidr; + m_lcd_regs.lcsr |= PXA255_LCSR_SOF; + pxa255_lcd_irq_check(); + } + + if(m_lcd_regs.dma[channel].ldcmd & PXA255_LDCMD_PAL) + { + address_space &space = m_maincpu->space(AS_PROGRAM); + int length = m_lcd_regs.dma[channel].ldcmd & 0x000fffff; + int index = 0; + for(index = 0; index < length; index += 2) + { + uint16_t color = space.read_word((m_lcd_regs.dma[channel].fsadr &~ 1) + index); + m_pxa255_lcd_palette[index >> 1] = (((((color >> 11) & 0x1f) << 3) | (color >> 13)) << 16) | (((((color >> 5) & 0x3f) << 2) | ((color >> 9) & 0x3)) << 8) | (((color & 0x1f) << 3) | ((color >> 2) & 0x7)); + m_palette->set_pen_color(index >> 1, (((color >> 11) & 0x1f) << 3) | (color >> 13), (((color >> 5) & 0x3f) << 2) | ((color >> 9) & 0x3), ((color & 0x1f) << 3) | ((color >> 2) & 0x7)); + } + } + else + { + address_space &space = m_maincpu->space(AS_PROGRAM); + int length = m_lcd_regs.dma[channel].ldcmd & 0x000fffff; + int index = 0; + for(index = 0; index < length; index++) + { + m_pxa255_lcd_framebuffer[index] = space.read_byte(m_lcd_regs.dma[channel].fsadr + index); + } + } + } +} + +void pxa255_periphs_device::pxa255_lcd_check_load_next_branch(int channel) +{ + if(m_lcd_regs.fbr[channel] & 1) + { + verboselog(4, "pxa255_lcd_check_load_next_branch: Taking branch\n" ); + m_lcd_regs.fbr[channel] &= ~1; + address_space &space = m_maincpu->space(AS_PROGRAM); + //m_lcd_regs.fbr[channel] = (space.read_dword(m_lcd_regs.fbr[channel] & 0xfffffff0) & 0xfffffff0) | (m_lcd_regs.fbr[channel] & 0x00000003); + //printf( "%08x\n", m_lcd_regs.fbr[channel] ); + pxa255_lcd_load_dma_descriptor(space, m_lcd_regs.fbr[channel] & 0xfffffff0, 0); + m_lcd_regs.fbr[channel] = (space.read_dword(m_lcd_regs.fbr[channel] & 0xfffffff0) & 0xfffffff0) | (m_lcd_regs.fbr[channel] & 0x00000003); + pxa255_lcd_dma_kickoff(0); + if(m_lcd_regs.fbr[channel] & 2) + { + m_lcd_regs.fbr[channel] &= ~2; + if(!(m_lcd_regs.lccr0 & PXA255_LCCR0_BM)) + { + m_lcd_regs.lcsr |= PXA255_LCSR_BS; + } + } + } + else + { + if (0) verboselog(3, "pxa255_lcd_check_load_next_branch: Not taking branch\n" ); + } +} + +TIMER_CALLBACK_MEMBER(pxa255_periphs_device::pxa255_lcd_dma_eof) +{ + if (0) verboselog(3, "End of frame callback\n" ); + if(m_lcd_regs.dma[param].ldcmd & PXA255_LDCMD_EOFINT) + { + m_lcd_regs.liidr = m_lcd_regs.dma[param].fidr; + m_lcd_regs.lcsr |= PXA255_LCSR_EOF; + } + pxa255_lcd_check_load_next_branch(param); + pxa255_lcd_irq_check(); +} + +READ32_MEMBER(pxa255_periphs_device::pxa255_lcd_r) +{ + switch(PXA255_LCD_BASE_ADDR | (offset << 2)) + { + case PXA255_LCCR0: // 0x44000000 + verboselog(3, "pxa255_lcd_r: LCD Control 0: %08x & %08x\n", m_lcd_regs.lccr0, mem_mask); + return m_lcd_regs.lccr0; + case PXA255_LCCR1: // 0x44000004 + verboselog(3, "pxa255_lcd_r: LCD Control 1: %08x & %08x\n", m_lcd_regs.lccr1, mem_mask); + return m_lcd_regs.lccr1; + case PXA255_LCCR2: // 0x44000008 + verboselog(3, "pxa255_lcd_r: LCD Control 2: %08x & %08x\n", m_lcd_regs.lccr2, mem_mask); + return m_lcd_regs.lccr2; + case PXA255_LCCR3: // 0x4400000c + verboselog(3, "pxa255_lcd_r: LCD Control 3: %08x & %08x\n", m_lcd_regs.lccr3, mem_mask); + return m_lcd_regs.lccr3; + case PXA255_FBR0: // 0x44000020 + verboselog(4, "pxa255_lcd_r: LCD Frame Branch Register 0: %08x & %08x\n", m_lcd_regs.fbr[0], mem_mask); + return m_lcd_regs.fbr[0]; + case PXA255_FBR1: // 0x44000024 + verboselog(3, "pxa255_lcd_r: LCD Frame Branch Register 1: %08x & %08x\n", m_lcd_regs.fbr[1], mem_mask); + return m_lcd_regs.fbr[1]; + case PXA255_LCSR: // 0x44000038 + verboselog(4, "pxa255_lcd_r: LCD Status Register: %08x & %08x\n", m_lcd_regs.lcsr, mem_mask); + return m_lcd_regs.lcsr; + case PXA255_LIIDR: // 0x4400003c + verboselog(3, "pxa255_lcd_r: LCD Interrupt ID Register: %08x & %08x\n", m_lcd_regs.liidr, mem_mask); + return m_lcd_regs.liidr; + case PXA255_TRGBR: // 0x44000040 + verboselog(3, "pxa255_lcd_r: TMED RGB Seed Register: %08x & %08x\n", m_lcd_regs.trgbr, mem_mask); + return m_lcd_regs.trgbr; + case PXA255_TCR: // 0x44000044 + verboselog(3, "pxa255_lcd_r: TMED RGB Seed Register: %08x & %08x\n", m_lcd_regs.tcr, mem_mask); + return m_lcd_regs.tcr; + case PXA255_FDADR0: // 0x44000200 + if (0) verboselog(3, "pxa255_lcd_r: LCD DMA Frame Descriptor Address Register 0: %08x & %08x\n", m_lcd_regs.dma[0].fdadr, mem_mask); + return m_lcd_regs.dma[0].fdadr; + case PXA255_FSADR0: // 0x44000204 + verboselog(3, "pxa255_lcd_r: LCD DMA Frame Source Address Register 0: %08x & %08x\n", m_lcd_regs.dma[0].fsadr, mem_mask); + return m_lcd_regs.dma[0].fsadr; + case PXA255_FIDR0: // 0x44000208 + verboselog(3, "pxa255_lcd_r: LCD DMA Frame ID Register 0: %08x & %08x\n", m_lcd_regs.dma[0].fidr, mem_mask); + return m_lcd_regs.dma[0].fidr; + case PXA255_LDCMD0: // 0x4400020c + if (0) verboselog(3, "pxa255_lcd_r: LCD DMA Command Register 0: %08x & %08x\n", m_lcd_regs.dma[0].ldcmd & 0xfff00000, mem_mask); + return m_lcd_regs.dma[0].ldcmd & 0xfff00000; + case PXA255_FDADR1: // 0x44000210 + verboselog(3, "pxa255_lcd_r: LCD DMA Frame Descriptor Address Register 1: %08x & %08x\n", m_lcd_regs.dma[1].fdadr, mem_mask); + return m_lcd_regs.dma[1].fdadr; + case PXA255_FSADR1: // 0x44000214 + verboselog(3, "pxa255_lcd_r: LCD DMA Frame Source Address Register 1: %08x & %08x\n", m_lcd_regs.dma[1].fsadr, mem_mask); + return m_lcd_regs.dma[1].fsadr; + case PXA255_FIDR1: // 0x44000218 + verboselog(3, "pxa255_lcd_r: LCD DMA Frame ID Register 1: %08x & %08x\n", m_lcd_regs.dma[1].fidr, mem_mask); + return m_lcd_regs.dma[1].fidr; + case PXA255_LDCMD1: // 0x4400021c + verboselog(3, "pxa255_lcd_r: LCD DMA Command Register 1: %08x & %08x\n", m_lcd_regs.dma[1].ldcmd & 0xfff00000, mem_mask); + return m_lcd_regs.dma[1].ldcmd & 0xfff00000; + default: + verboselog(0, "pxa255_lcd_r: Unknown address: %08x\n", PXA255_LCD_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +WRITE32_MEMBER(pxa255_periphs_device::pxa255_lcd_w) +{ + switch(PXA255_LCD_BASE_ADDR | (offset << 2)) + { + case PXA255_LCCR0: // 0x44000000 + verboselog(3, "pxa255_lcd_w: LCD Control 0: %08x & %08x\n", data, mem_mask); + m_lcd_regs.lccr0 = data & 0x00fffeff; + break; + case PXA255_LCCR1: // 0x44000004 + verboselog(3, "pxa255_lcd_w: LCD Control 1: %08x & %08x\n", data, mem_mask); + m_lcd_regs.lccr1 = data; + break; + case PXA255_LCCR2: // 0x44000008 + verboselog(3, "pxa255_lcd_w: LCD Control 2: %08x & %08x\n", data, mem_mask); + m_lcd_regs.lccr2 = data; + break; + case PXA255_LCCR3: // 0x4400000c + verboselog(3, "pxa255_lcd_w: LCD Control 3: %08x & %08x\n", data, mem_mask); + m_lcd_regs.lccr3 = data; + break; + case PXA255_FBR0: // 0x44000020 + verboselog(4l, "pxa255_lcd_w: LCD Frame Branch Register 0: %08x & %08x\n", data, mem_mask); + m_lcd_regs.fbr[0] = data & 0xfffffff3; + if(!m_lcd_regs.dma[0].eof->enabled()) + { + if (0) verboselog(3, "ch0 EOF timer is not enabled, taking branch now\n" ); + pxa255_lcd_check_load_next_branch(0); + pxa255_lcd_irq_check(); + } + break; + case PXA255_FBR1: // 0x44000024 + verboselog(3, "pxa255_lcd_w: LCD Frame Branch Register 1: %08x & %08x\n", data, mem_mask); + m_lcd_regs.fbr[1] = data & 0xfffffff3; + if(!m_lcd_regs.dma[1].eof->enabled()) + { + verboselog(3, "ch1 EOF timer is not enabled, taking branch now\n" ); + pxa255_lcd_check_load_next_branch(1); + pxa255_lcd_irq_check(); + } + break; + case PXA255_LCSR: // 0x44000038 + verboselog(4, "pxa255_lcd_w: LCD Controller Status Register: %08x & %08x\n", data, mem_mask); + m_lcd_regs.lcsr &= ~data; + pxa255_lcd_irq_check(); + break; + case PXA255_LIIDR: // 0x4400003c + verboselog(3, "pxa255_lcd_w: LCD Controller Interrupt ID Register: %08x & %08x\n", data, mem_mask); + break; + case PXA255_TRGBR: // 0x44000040 + verboselog(3, "pxa255_lcd_w: TMED RGB Seed Register: %08x & %08x\n", data, mem_mask); + m_lcd_regs.trgbr = data & 0x00ffffff; + break; + case PXA255_TCR: // 0x44000044 + verboselog(3, "pxa255_lcd_w: TMED Control Register: %08x & %08x\n", data, mem_mask); + m_lcd_regs.tcr = data & 0x00004fff; + break; + case PXA255_FDADR0: // 0x44000200 + verboselog(4, "pxa255_lcd_w: LCD DMA Frame Descriptor Address Register 0: %08x & %08x\n", data, mem_mask); + if(!m_lcd_regs.dma[0].eof->enabled()) + { + pxa255_lcd_load_dma_descriptor(space, data & 0xfffffff0, 0); + } + else + { + m_lcd_regs.fbr[0] &= 0x00000003; + m_lcd_regs.fbr[0] |= data & 0xfffffff0; + } + break; + case PXA255_FSADR0: // 0x44000204 + verboselog(4, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame Source Address Register 0: %08x & %08x\n", data, mem_mask); + break; + case PXA255_FIDR0: // 0x44000208 + verboselog(4, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame ID Register 0: %08x & %08x\n", data, mem_mask); + break; + case PXA255_LDCMD0: // 0x4400020c + verboselog(4, "pxa255_lcd_w: (Invalid Write) LCD DMA Command Register 0: %08x & %08x\n", data, mem_mask); + break; + case PXA255_FDADR1: // 0x44000210 + verboselog(4, "pxa255_lcd_w: LCD DMA Frame Descriptor Address Register 1: %08x & %08x\n", data, mem_mask); + if(!m_lcd_regs.dma[1].eof->enabled()) + { + pxa255_lcd_load_dma_descriptor(space, data & 0xfffffff0, 1); + } + else + { + m_lcd_regs.fbr[1] &= 0x00000003; + m_lcd_regs.fbr[1] |= data & 0xfffffff0; + } + break; + case PXA255_FSADR1: // 0x44000214 + verboselog(4, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame Source Address Register 1: %08x & %08x\n", data, mem_mask); + break; + case PXA255_FIDR1: // 0x44000218 + verboselog(4, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame ID Register 1: %08x & %08x\n", data, mem_mask); + break; + case PXA255_LDCMD1: // 0x4400021c + verboselog(4, "pxa255_lcd_w: (Invalid Write) LCD DMA Command Register 1: %08x & %08x\n", data, mem_mask); + break; + default: + verboselog(0, "pxa255_lcd_w: Unknown address: %08x = %08x & %08x\n", PXA255_LCD_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +void pxa255_periphs_device::device_start() +{ + for (int index = 0; index < 16; index++) + { + m_dma_regs.timer[index] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::pxa255_dma_dma_end),this)); + } + + for (int index = 0; index < 4; index++) + { + m_ostimer_regs.timer[index] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::pxa255_ostimer_match),this)); + } + + m_lcd_regs.dma[0].eof = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::pxa255_lcd_dma_eof),this)); + m_lcd_regs.dma[1].eof = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pxa255_periphs_device::pxa255_lcd_dma_eof),this)); + + m_pxa255_lcd_palette = make_unique_clear(0x100); + m_pxa255_lcd_framebuffer = make_unique_clear(0x100000); + m_words = make_unique_clear(0x800); + m_samples = make_unique_clear(0x1000); + + m_gpio0_set_func.resolve_safe(); + m_gpio0_clear_func.resolve_safe(); + m_gpio0_in_func.resolve_safe(0xffffffff); +} + +void pxa255_periphs_device::device_reset() +{ + for (int index = 0; index < 16; index++) + { + m_dma_regs.dcsr[index] = 0x00000008; + } + + memset(&m_intc_regs, 0, sizeof(m_intc_regs)); + + m_lcd_regs.trgbr = 0x00aa5500; + m_lcd_regs.tcr = 0x0000754f; +} + +uint32_t pxa255_periphs_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + for (int y = 0; y <= (m_lcd_regs.lccr2 & PXA255_LCCR2_LPP); y++) + { + uint32_t *dst = &bitmap.pix32(y); + for (int x = 0; x <= (m_lcd_regs.lccr1 & PXA255_LCCR1_PPL); x++) + { + *dst++ = m_pxa255_lcd_palette[m_pxa255_lcd_framebuffer[y * ((m_lcd_regs.lccr1 & PXA255_LCCR1_PPL) + 1) + x]]; + } + } + return 0; +} + +MACHINE_CONFIG_START(pxa255_periphs_device::device_add_mconfig) + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(60) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) + MCFG_SCREEN_SIZE(1024, 1024) + MCFG_SCREEN_VISIBLE_AREA(0, 295, 0, 479) + MCFG_SCREEN_UPDATE_DEVICE(DEVICE_SELF, pxa255_periphs_device, screen_update) + MCFG_PALETTE_ADD(m_palette, 256) + + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + MCFG_DEVICE_ADD(m_dmadac[0], DMADAC) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0) + MCFG_DEVICE_ADD(m_dmadac[1], DMADAC) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0) +MACHINE_CONFIG_END \ No newline at end of file diff --git a/src/devices/machine/pxa255.h b/src/devices/machine/pxa255.h new file mode 100644 index 00000000000..b06235a29ba --- /dev/null +++ b/src/devices/machine/pxa255.h @@ -0,0 +1,235 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/************************************************************************** + * + * Intel XScale PXA255 peripheral emulation + * + * TODO: + * Most things + * + **************************************************************************/ + +#ifndef DEVICES_MACHINE_PXA255 +#define DEVICES_MACHINE_PXA255 + +#pragma once + +#include "emu.h" +#include "cpu/arm7/arm7.h" +#include "cpu/arm7/arm7core.h" +#include "sound/dmadac.h" +#include "emupal.h" + +#include "pxa255defs.h" + +#define MCFG_PXA255_GPIO0_SET_CALLBACK(_devcb) \ + devcb = &downcast(*device).set_gpio0_set_cb(DEVCB_##_devcb); + +#define MCFG_PXA255_GPIO0_CLEAR_CALLBACK(_devcb) \ + devcb = &downcast(*device).set_gpio0_clear_cb(DEVCB_##_devcb); + +#define MCFG_PXA255_GPIO0_IN_CALLBACK(_devcb) \ + devcb = &downcast(*device).set_gpio0_in_cb(DEVCB_##_devcb); + +class pxa255_periphs_device : public device_t +{ +public: + template + pxa255_periphs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag) + : pxa255_periphs_device(mconfig, tag, owner, clock) + { + m_maincpu.set_tag(std::forward(cpu_tag)); + } + + pxa255_periphs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template devcb_base &set_gpio0_set_cb(Object &&cb) { return m_gpio0_set_func.set_callback(std::forward(cb)); } + template devcb_base &set_gpio0_clear_cb(Object &&cb) { return m_gpio0_clear_func.set_callback(std::forward(cb)); } + template devcb_base &set_gpio0_in_cb(Object &&cb) { return m_gpio0_in_func.set_callback(std::forward(cb)); } + + DECLARE_READ32_MEMBER(pxa255_i2s_r); + DECLARE_WRITE32_MEMBER(pxa255_i2s_w); + DECLARE_READ32_MEMBER(pxa255_dma_r); + DECLARE_WRITE32_MEMBER(pxa255_dma_w); + DECLARE_READ32_MEMBER(pxa255_ostimer_r); + DECLARE_WRITE32_MEMBER(pxa255_ostimer_w); + DECLARE_READ32_MEMBER(pxa255_intc_r); + DECLARE_WRITE32_MEMBER(pxa255_intc_w); + DECLARE_READ32_MEMBER(pxa255_gpio_r); + DECLARE_WRITE32_MEMBER(pxa255_gpio_w); + DECLARE_READ32_MEMBER(pxa255_lcd_r); + DECLARE_WRITE32_MEMBER(pxa255_lcd_w); + +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + + void pxa255_dma_irq_check(); + void pxa255_dma_load_descriptor_and_start(int channel); + void pxa255_ostimer_irq_check(); + void pxa255_update_interrupts(); + void pxa255_set_irq_line(uint32_t line, int state); + void pxa255_lcd_load_dma_descriptor(address_space & space, uint32_t address, int channel); + void pxa255_lcd_irq_check(); + void pxa255_lcd_dma_kickoff(int channel); + void pxa255_lcd_check_load_next_branch(int channel); + + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + TIMER_CALLBACK_MEMBER(pxa255_dma_dma_end); + TIMER_CALLBACK_MEMBER(pxa255_ostimer_match); + TIMER_CALLBACK_MEMBER(pxa255_lcd_dma_eof); + + struct dma_regs_t + { + uint32_t dcsr[16]; + uint32_t pad0[44]; + + uint32_t dint; + uint32_t pad1[3]; + + uint32_t drcmr[40]; + uint32_t pad2[24]; + + uint32_t ddadr[16]; + uint32_t dsadr[16]; + uint32_t dtadr[16]; + uint32_t dcmd[16]; + + emu_timer* timer[16]; + }; + + struct i2s_regs_t + { + uint32_t sacr0; + uint32_t sacr1; + uint32_t pad0; + + uint32_t sasr0; + uint32_t pad1; + + uint32_t saimr; + uint32_t saicr; + uint32_t pad2[17]; + + uint32_t sadiv; + uint32_t pad3[6]; + + uint32_t sadr; + }; + + struct ostmr_regs_t + { + uint32_t osmr[4]; + uint32_t oscr; + uint32_t ossr; + uint32_t ower; + uint32_t oier; + + emu_timer* timer[4]; + }; + + struct intc_regs_t + { + uint32_t icip; + uint32_t icmr; + uint32_t iclr; + uint32_t icfp; + uint32_t icpr; + uint32_t iccr; + }; + + struct gpio_regs_t + { + uint32_t gplr0; // GPIO Pin-Level + uint32_t gplr1; + uint32_t gplr2; + + uint32_t gpdr0; + uint32_t gpdr1; + uint32_t gpdr2; + + uint32_t gpsr0; + uint32_t gpsr1; + uint32_t gpsr2; + + uint32_t gpcr0; + uint32_t gpcr1; + uint32_t gpcr2; + + uint32_t grer0; + uint32_t grer1; + uint32_t grer2; + + uint32_t gfer0; + uint32_t gfer1; + uint32_t gfer2; + + uint32_t gedr0; + uint32_t gedr1; + uint32_t gedr2; + + uint32_t gafr0l; + uint32_t gafr0u; + uint32_t gafr1l; + uint32_t gafr1u; + uint32_t gafr2l; + uint32_t gafr2u; + }; + + struct lcd_dma_regs_t + { + uint32_t fdadr; + uint32_t fsadr; + uint32_t fidr; + uint32_t ldcmd; + emu_timer *eof; + }; + + struct lcd_regs_t + { + uint32_t lccr0; + uint32_t lccr1; + uint32_t lccr2; + uint32_t lccr3; + uint32_t pad0[4]; + + uint32_t fbr[2]; + uint32_t pad1[4]; + + uint32_t lcsr; + uint32_t liidr; + uint32_t trgbr; + uint32_t tcr; + uint32_t pad2[110]; + + lcd_dma_regs_t dma[2]; + }; + + dma_regs_t m_dma_regs; + i2s_regs_t m_i2s_regs; + ostmr_regs_t m_ostimer_regs; + intc_regs_t m_intc_regs; + gpio_regs_t m_gpio_regs; + lcd_regs_t m_lcd_regs; + + devcb_write32 m_gpio0_set_func; + devcb_write32 m_gpio0_clear_func; + devcb_read32 m_gpio0_in_func; + + required_device m_maincpu; + required_device_array m_dmadac; + required_device m_palette; + + std::unique_ptr m_pxa255_lcd_palette; // 0x100 + std::unique_ptr m_pxa255_lcd_framebuffer; // 0x100000 + std::unique_ptr m_words; // 0x800 + std::unique_ptr m_samples; // 0x1000 + + inline void ATTR_PRINTF(3,4) verboselog(int n_level, const char *s_fmt, ... ); +}; + +DECLARE_DEVICE_TYPE(PXA255_PERIPHERALS, pxa255_periphs_device) + +#endif // DEVICES_MACHINE_PXA255 \ No newline at end of file diff --git a/src/mame/machine/pxa255.h b/src/devices/machine/pxa255defs.h similarity index 91% rename from src/mame/machine/pxa255.h rename to src/devices/machine/pxa255defs.h index 75f20c103a6..89e3aedef7d 100644 --- a/src/mame/machine/pxa255.h +++ b/src/devices/machine/pxa255defs.h @@ -2,12 +2,14 @@ // copyright-holders:Ryan Holtz /************************************************************************** * - * Intel PXA255 on-chip peripheral emulation - * - * Mostly-incomplete implementation by Ryan Holtz + * Intel XScale PXA255 peripheral emulation defines * **************************************************************************/ +#ifndef DEVICES_MACHINE_PXA255DEFS +#define DEVICES_MACHINE_PXA255DEFS + +#pragma once /* PXA255 DMA controller @@ -165,28 +167,6 @@ #define PXA255_DCMD_WIDTH_2 (0x00008000) #define PXA255_DCMD_WIDTH_4 (0x0000c000) -struct PXA255_DMA_Regs -{ - uint32_t dcsr[16]; - - uint32_t pad0[44]; - - uint32_t dint; - - uint32_t pad1[3]; - - uint32_t drcmr[40]; - - uint32_t pad2[24]; - - uint32_t ddadr[16]; - uint32_t dsadr[16]; - uint32_t dtadr[16]; - uint32_t dcmd[16]; - - emu_timer* timer[16]; -}; - /* PXA255 Inter-Integrated-Circuit Sound (I2S) Controller @@ -232,29 +212,6 @@ struct PXA255_DMA_Regs #define PXA255_SADIV (PXA255_I2S_BASE_ADDR + 0x00000060) #define PXA255_SADR (PXA255_I2S_BASE_ADDR + 0x00000080) -struct PXA255_I2S_Regs -{ - uint32_t sacr0; - uint32_t sacr1; - - uint32_t pad0; - - uint32_t sasr0; - - uint32_t pad1; - - uint32_t saimr; - uint32_t saicr; - - uint32_t pad2[17]; - - uint32_t sadiv; - - uint32_t pad3[6]; - - uint32_t sadr; -}; - /* PXA255 OS Timer register @@ -281,17 +238,6 @@ struct PXA255_I2S_Regs #define PXA255_OIER_E2 (0x00000004) #define PXA255_OIER_E3 (0x00000008) -struct PXA255_OSTMR_Regs -{ - uint32_t osmr[4]; - uint32_t oscr; - uint32_t ossr; - uint32_t ower; - uint32_t oier; - - emu_timer* timer[4]; -}; - /* PXA255 Interrupt registers @@ -333,16 +279,6 @@ struct PXA255_OSTMR_Regs #define PXA255_INT_RTC_HZ (1 << 30) #define PXA255_INT_RTC_ALARM (1 << 31) -struct PXA255_INTC_Regs -{ - uint32_t icip; - uint32_t icmr; - uint32_t iclr; - uint32_t icfp; - uint32_t icpr; - uint32_t iccr; -}; - /* PXA255 General-Purpose I/O registers @@ -380,44 +316,6 @@ struct PXA255_INTC_Regs #define PXA255_GAFR2_L (PXA255_GPIO_BASE_ADDR + 0x00000064) #define PXA255_GAFR2_U (PXA255_GPIO_BASE_ADDR + 0x00000068) -struct PXA255_GPIO_Regs -{ - uint32_t gplr0; // GPIO Pin-Leve - uint32_t gplr1; - uint32_t gplr2; - - uint32_t gpdr0; - uint32_t gpdr1; - uint32_t gpdr2; - - uint32_t gpsr0; - uint32_t gpsr1; - uint32_t gpsr2; - - uint32_t gpcr0; - uint32_t gpcr1; - uint32_t gpcr2; - - uint32_t grer0; - uint32_t grer1; - uint32_t grer2; - - uint32_t gfer0; - uint32_t gfer1; - uint32_t gfer2; - - uint32_t gedr0; - uint32_t gedr1; - uint32_t gedr2; - - uint32_t gafr0l; - uint32_t gafr0u; - uint32_t gafr1l; - uint32_t gafr1u; - uint32_t gafr2l; - uint32_t gafr2u; -}; - /* PXA255 LCD Controller @@ -478,34 +376,4 @@ struct PXA255_GPIO_Regs #define PXA255_FIDR1 (PXA255_LCD_BASE_ADDR + 0x00000218) #define PXA255_LDCMD1 (PXA255_LCD_BASE_ADDR + 0x0000021c) -struct PXA255_LCD_DMA_Regs -{ - uint32_t fdadr; - uint32_t fsadr; - uint32_t fidr; - uint32_t ldcmd; - emu_timer *eof; -}; - -struct PXA255_LCD_Regs -{ - uint32_t lccr0; - uint32_t lccr1; - uint32_t lccr2; - uint32_t lccr3; - - uint32_t pad0[4]; - - uint32_t fbr[2]; - - uint32_t pad1[4]; - - uint32_t lcsr; - uint32_t liidr; - uint32_t trgbr; - uint32_t tcr; - - uint32_t pad2[110]; - - PXA255_LCD_DMA_Regs dma[2]; -}; +#endif // DEVICES_MACHINE_PXA255DEFS \ No newline at end of file diff --git a/src/mame/drivers/39in1.cpp b/src/mame/drivers/39in1.cpp index 4aed92d891e..9ad3688eefa 100644 --- a/src/mame/drivers/39in1.cpp +++ b/src/mame/drivers/39in1.cpp @@ -2,7 +2,7 @@ // copyright-holders:R. Belmont, Ryan Holtz, Andreas Naive /************************************************************************** * - * 39in1.c - bootleg MAME-based "39-in-1" arcade PCB + * 39in1.cpp - bootleg MAME-based "39-in-1" arcade PCB * Skeleton by R. Belmont, thanks to the Guru * PXA255 Peripheral hookup by Ryan Holtz * Decrypt by Andreas Naive @@ -27,1346 +27,87 @@ #include "cpu/arm7/arm7core.h" #include "machine/eepromser.h" #include "machine/pxa255.h" -#include "sound/dmadac.h" -#include "emupal.h" -#include "screen.h" -#include "speaker.h" class _39in1_state : public driver_device { public: _39in1_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) + , m_pxa_periphs(*this, "pxa_periphs") , m_ram(*this, "ram") - , m_dmadac(*this, "dac%u", 1U) , m_eeprom(*this, "eeprom") , m_maincpu(*this, "maincpu") - , m_palette(*this, "palette") { } void _60in1(machine_config &config); void _39in1(machine_config &config); - void init_39in1(); + void driver_init() override; private: uint32_t m_seed; uint32_t m_magic; uint32_t m_state; + required_device m_pxa_periphs; required_shared_ptr m_ram; - - PXA255_DMA_Regs m_dma_regs; - PXA255_I2S_Regs m_i2s_regs; - PXA255_OSTMR_Regs m_ostimer_regs; - PXA255_INTC_Regs m_intc_regs; - PXA255_GPIO_Regs m_gpio_regs; - PXA255_LCD_Regs m_lcd_regs; - - required_device_array m_dmadac; required_device m_eeprom; - uint32_t m_pxa255_lcd_palette[0x100]; - uint8_t m_pxa255_lcd_framebuffer[0x100000]; + DECLARE_READ32_MEMBER(eeprom_r); + DECLARE_WRITE32_MEMBER(eeprom_set_w); + DECLARE_WRITE32_MEMBER(eeprom_clear_w); - //FILE* audio_dump; - uint32_t m_words[0x800]; - int16_t m_samples[0x1000]; - DECLARE_READ32_MEMBER(pxa255_i2s_r); - DECLARE_WRITE32_MEMBER(pxa255_i2s_w); - DECLARE_READ32_MEMBER(pxa255_dma_r); - DECLARE_WRITE32_MEMBER(pxa255_dma_w); - DECLARE_READ32_MEMBER(pxa255_ostimer_r); - DECLARE_WRITE32_MEMBER(pxa255_ostimer_w); - DECLARE_READ32_MEMBER(pxa255_intc_r); - DECLARE_WRITE32_MEMBER(pxa255_intc_w); - DECLARE_READ32_MEMBER(pxa255_gpio_r); - DECLARE_WRITE32_MEMBER(pxa255_gpio_w); - DECLARE_READ32_MEMBER(pxa255_lcd_r); - DECLARE_WRITE32_MEMBER(pxa255_lcd_w); DECLARE_READ32_MEMBER(cpld_r); DECLARE_WRITE32_MEMBER(cpld_w); DECLARE_READ32_MEMBER(prot_cheater_r); DECLARE_MACHINE_START(60in1); virtual void machine_start() override; - uint32_t screen_update_39in1(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - INTERRUPT_GEN_MEMBER(pxa255_vblank_start); - TIMER_CALLBACK_MEMBER(pxa255_dma_dma_end); - TIMER_CALLBACK_MEMBER(pxa255_ostimer_match); - TIMER_CALLBACK_MEMBER(pxa255_lcd_dma_eof); - void pxa255_dma_irq_check(); - void pxa255_dma_load_descriptor_and_start(int channel); - void pxa255_ostimer_irq_check(); - void pxa255_update_interrupts(); - void pxa255_set_irq_line(uint32_t line, int state); - void pxa255_lcd_load_dma_descriptor(address_space & space, uint32_t address, int channel); - void pxa255_lcd_irq_check(); - void pxa255_lcd_dma_kickoff(int channel); - void pxa255_lcd_check_load_next_branch(int channel); - void pxa255_start(); required_device m_maincpu; - required_device m_palette; void _39in1_map(address_map &map); + + inline void ATTR_PRINTF(3,4) verboselog(int n_level, const char *s_fmt, ... ); }; #define VERBOSE_LEVEL (0) -static inline void ATTR_PRINTF(3,4) verboselog( device_t& device, int n_level, const char* s_fmt, ... ) +inline void ATTR_PRINTF(3,4) _39in1_state::verboselog(int n_level, const char *s_fmt, ... ) { - if( VERBOSE_LEVEL >= n_level ) + if (VERBOSE_LEVEL >= n_level) { va_list v; char buf[32768]; va_start( v, s_fmt ); vsprintf( buf, s_fmt, v ); va_end( v ); - device.logerror( "%s: %s", device.machine().describe_context(), buf ); - //printf( "%s: %s", device.machine().describe_context().c_str(), buf ); + logerror("%s: %s", machine().describe_context(), buf); } } -/* - - PXA255 Inter-Integrated-Circuit Sound (I2S) Controller - - pg. 489 to 504, PXA255 Processor Developers Manual [278693-002].pdf - -*/ - -READ32_MEMBER(_39in1_state::pxa255_i2s_r) +READ32_MEMBER(_39in1_state::eeprom_r) { - PXA255_I2S_Regs *i2s_regs = &m_i2s_regs; - - switch(PXA255_I2S_BASE_ADDR | (offset << 2)) - { - case PXA255_SACR0: - verboselog(*this, 3, "pxa255_i2s_r: Serial Audio Controller Global Control Register: %08x & %08x\n", i2s_regs->sacr0, mem_mask ); - return i2s_regs->sacr0; - case PXA255_SACR1: - verboselog(*this, 3, "pxa255_i2s_r: Serial Audio Controller I2S/MSB-Justified Control Register: %08x & %08x\n", i2s_regs->sacr1, mem_mask ); - return i2s_regs->sacr1; - case PXA255_SASR0: - verboselog(*this, 3, "pxa255_i2s_r: Serial Audio Controller I2S/MSB-Justified Status Register: %08x & %08x\n", i2s_regs->sasr0, mem_mask ); - return i2s_regs->sasr0; - case PXA255_SAIMR: - verboselog(*this, 3, "pxa255_i2s_r: Serial Audio Interrupt Mask Register: %08x & %08x\n", i2s_regs->saimr, mem_mask ); - return i2s_regs->saimr; - case PXA255_SAICR: - verboselog(*this, 3, "pxa255_i2s_r: Serial Audio Interrupt Clear Register: %08x & %08x\n", i2s_regs->saicr, mem_mask ); - return i2s_regs->saicr; - case PXA255_SADIV: - verboselog(*this, 3, "pxa255_i2s_r: Serial Audio Clock Divider Register: %08x & %08x\n", i2s_regs->sadiv, mem_mask ); - return i2s_regs->sadiv; - case PXA255_SADR: - verboselog(*this, 5, "pxa255_i2s_r: Serial Audio Data Register: %08x & %08x\n", i2s_regs->sadr, mem_mask ); - return i2s_regs->sadr; - default: - verboselog(*this, 0, "pxa255_i2s_r: Unknown address: %08x\n", PXA255_I2S_BASE_ADDR | (offset << 2)); - break; - } - return 0; + return (m_eeprom->do_read() << 5) | (1 << 1); // Must be on. Probably a DIP switch. } -WRITE32_MEMBER(_39in1_state::pxa255_i2s_w) +WRITE32_MEMBER(_39in1_state::eeprom_set_w) { - PXA255_I2S_Regs *i2s_regs = &m_i2s_regs; - -#if 0 - if(!audio_dump) - { - int count = 0; - char filename[256]; - do - { - sprintf(filename, "39in1_%04d.raw", count++); - audio_dump = fopen(filename, "rb"); - }while(audio_dump != nullptr); - count--; - sprintf(filename, "39in1_%04d.raw", count); - audio_dump = fopen(filename, "wb"); - } -#endif - switch(PXA255_I2S_BASE_ADDR | (offset << 2)) - { - case PXA255_SACR0: - verboselog(*this, 3, "pxa255_i2s_w: Serial Audio Controller Global Control Register: %08x & %08x\n", data, mem_mask ); - i2s_regs->sacr0 = data & 0x0000ff3d; - break; - case PXA255_SACR1: - verboselog(*this, 3, "pxa255_i2s_w: Serial Audio Controller I2S/MSB-Justified Control Register: %08x & %08x\n", data, mem_mask ); - i2s_regs->sacr1 = data & 0x00000039; - break; - case PXA255_SASR0: - verboselog(*this, 3, "pxa255_i2s_w: Serial Audio Controller I2S/MSB-Justified Status Register: %08x & %08x\n", data, mem_mask ); - i2s_regs->sasr0 = data & 0x0000ff7f; - break; - case PXA255_SAIMR: - verboselog(*this, 3, "pxa255_i2s_w: Serial Audio Interrupt Mask Register: %08x & %08x\n", data, mem_mask ); - i2s_regs->saimr = data & 0x00000078; - break; - case PXA255_SAICR: - verboselog(*this, 3, "pxa255_i2s_w: Serial Audio Interrupt Clear Register: %08x & %08x\n", data, mem_mask ); - if(i2s_regs->saicr & PXA255_SAICR_ROR) - { - i2s_regs->sasr0 &= ~PXA255_SASR0_ROR; - } - if(i2s_regs->saicr & PXA255_SAICR_TUR) - { - i2s_regs->sasr0 &= ~PXA255_SASR0_TUR; - } - break; - case PXA255_SADIV: - verboselog(*this, 3, "pxa255_i2s_w: Serial Audio Clock Divider Register: %08x & %08x\n", data, mem_mask ); - i2s_regs->sadiv = data & 0x0000007f; - for (auto &dac : m_dmadac) - { - dac->set_frequency(((double)147600000 / (double)i2s_regs->sadiv) / 256.0); - dac->enable(1); - } - break; - case PXA255_SADR: - verboselog(*this, 4, "pxa255_i2s_w: Serial Audio Data Register: %08x & %08x\n", data, mem_mask ); - i2s_regs->sadr = data; -#if 0 - if(audio_dump) - { - fwrite(&data, 4, 1, audio_dump); - } -#endif - break; - default: - verboselog(*this, 0, "pxa255_i2s_w: Unknown address: %08x = %08x & %08x\n", PXA255_I2S_BASE_ADDR | (offset << 2), data, mem_mask); - break; - } + if (BIT(data, 2)) + m_eeprom->cs_write(ASSERT_LINE); + if (BIT(data, 3)) + m_eeprom->clk_write(ASSERT_LINE); + if (BIT(data, 4)) + m_eeprom->di_write(1); } -/* - - PXA255 DMA controller (placeholder) - - pg. 151 to 182, PXA255 Processor Developers Manual [278693-002].pdf - -*/ - -void _39in1_state::pxa255_dma_irq_check() +WRITE32_MEMBER(_39in1_state::eeprom_clear_w) { - PXA255_DMA_Regs *dma_regs = &m_dma_regs; - int channel = 0; - int set_intr = 0; - - for(channel = 0; channel < 16; channel++) - { - if (dma_regs->dcsr[channel] & (PXA255_DCSR_ENDINTR | PXA255_DCSR_STARTINTR | PXA255_DCSR_BUSERRINTR)) - { - dma_regs->dint |= 1 << channel; - set_intr = 1; - } - else - { - dma_regs->dint &= ~(1 << channel); - } - } - - pxa255_set_irq_line(PXA255_INT_DMA, set_intr); + if (BIT(data, 2)) + m_eeprom->cs_write(ASSERT_LINE); + if (BIT(data, 3)) + m_eeprom->clk_write(CLEAR_LINE); + if (BIT(data, 4)) + m_eeprom->di_write(0); } -void _39in1_state::pxa255_dma_load_descriptor_and_start(int channel) -{ - PXA255_DMA_Regs *dma_regs = &m_dma_regs; - attotime period; - - // Shut down any transfers that are currently going on, software should be smart enough to check if a - // transfer is running before starting another one on the same channel. - if (dma_regs->timer[channel]->enabled()) - { - dma_regs->timer[channel]->adjust(attotime::never); - } - - // Load the next descriptor - - address_space &space = m_maincpu->space(AS_PROGRAM); - dma_regs->dsadr[channel] = space.read_dword(dma_regs->ddadr[channel] + 0x4); - dma_regs->dtadr[channel] = space.read_dword(dma_regs->ddadr[channel] + 0x8); - dma_regs->dcmd[channel] = space.read_dword(dma_regs->ddadr[channel] + 0xc); - dma_regs->ddadr[channel] = space.read_dword(dma_regs->ddadr[channel]); - - // Start our end-of-transfer timer - switch(channel) - { - case 3: - period = attotime::from_hz((147600000 / m_i2s_regs.sadiv) / (4 * 64)) * (dma_regs->dcmd[channel] & 0x00001fff); - break; - default: - period = attotime::from_hz(100000000) * (dma_regs->dcmd[channel] & 0x00001fff); - break; - } - - dma_regs->timer[channel]->adjust(period, channel); - - // Interrupt as necessary - if(dma_regs->dcmd[channel] & PXA255_DCMD_STARTIRQEN) - { - dma_regs->dcsr[channel] |= PXA255_DCSR_STARTINTR; - } - - dma_regs->dcsr[channel] &= ~PXA255_DCSR_STOPSTATE; -} - -TIMER_CALLBACK_MEMBER(_39in1_state::pxa255_dma_dma_end) -{ - PXA255_DMA_Regs *dma_regs = &m_dma_regs; - uint32_t sadr = dma_regs->dsadr[param]; - uint32_t tadr = dma_regs->dtadr[param]; - uint32_t count = dma_regs->dcmd[param] & 0x00001fff; - uint32_t index = 0; - uint8_t temp8; - uint16_t temp16; - uint32_t temp32; - - address_space &space = m_maincpu->space(AS_PROGRAM); - switch(param) - { - case 3: - for(index = 0; index < count; index += 4) - { - m_words[index >> 2] = space.read_dword(sadr); - m_samples[(index >> 1) + 0] = (int16_t)(m_words[index >> 2] >> 16); - m_samples[(index >> 1) + 1] = (int16_t)(m_words[index >> 2] & 0xffff); - sadr += 4; - } - for (auto &dac : m_dmadac) - dac->flush(); - m_dmadac[0]->transfer(0, 2, 2, count/4, m_samples); - m_dmadac[1]->transfer(1, 2, 2, count/4, m_samples); - break; - default: - for(index = 0; index < count;) - { - switch(dma_regs->dcmd[param] & PXA255_DCMD_SIZE) - { - case PXA255_DCMD_SIZE_8: - temp8 = space.read_byte(sadr); - space.write_byte(tadr, temp8); - index++; - break; - case PXA255_DCMD_SIZE_16: - temp16 = space.read_word(sadr); - space.write_word(tadr, temp16); - index += 2; - break; - case PXA255_DCMD_SIZE_32: - temp32 = space.read_dword(sadr); - space.write_dword(tadr, temp32); - index += 4; - break; - default: - printf( "pxa255_dma_dma_end: Unsupported DMA size\n" ); - break; - } - if(dma_regs->dcmd[param] & PXA255_DCMD_INCSRCADDR) - { - switch(dma_regs->dcmd[param] & PXA255_DCMD_SIZE) - { - case PXA255_DCMD_SIZE_8: - sadr++; - break; - case PXA255_DCMD_SIZE_16: - sadr += 2; - break; - case PXA255_DCMD_SIZE_32: - sadr += 4; - break; - default: - break; - } - } - if(dma_regs->dcmd[param] & PXA255_DCMD_INCTRGADDR) - { - switch(dma_regs->dcmd[param] & PXA255_DCMD_SIZE) - { - case PXA255_DCMD_SIZE_8: - tadr++; - break; - case PXA255_DCMD_SIZE_16: - tadr += 2; - break; - case PXA255_DCMD_SIZE_32: - tadr += 4; - break; - default: - break; - } - } - } - break; - } - if(dma_regs->dcmd[param] & PXA255_DCMD_ENDIRQEN) - { - dma_regs->dcsr[param] |= PXA255_DCSR_ENDINTR; - } - if(!(dma_regs->ddadr[param] & PXA255_DDADR_STOP) && - (dma_regs->dcsr[param] & PXA255_DCSR_RUN)) - { - if(dma_regs->dcsr[param] & PXA255_DCSR_RUN) - { - pxa255_dma_load_descriptor_and_start(param); - } - else - { - dma_regs->dcsr[param] &= ~PXA255_DCSR_RUN; - dma_regs->dcsr[param] |= PXA255_DCSR_STOPSTATE; - } - } - else - { - dma_regs->dcsr[param] &= ~PXA255_DCSR_RUN; - dma_regs->dcsr[param] |= PXA255_DCSR_STOPSTATE; - } - pxa255_dma_irq_check(); -} - -READ32_MEMBER(_39in1_state::pxa255_dma_r) -{ - PXA255_DMA_Regs *dma_regs = &m_dma_regs; - - switch(PXA255_DMA_BASE_ADDR | (offset << 2)) - { - case PXA255_DCSR0: case PXA255_DCSR1: case PXA255_DCSR2: case PXA255_DCSR3: - case PXA255_DCSR4: case PXA255_DCSR5: case PXA255_DCSR6: case PXA255_DCSR7: - case PXA255_DCSR8: case PXA255_DCSR9: case PXA255_DCSR10: case PXA255_DCSR11: - case PXA255_DCSR12: case PXA255_DCSR13: case PXA255_DCSR14: case PXA255_DCSR15: - verboselog(*this, 4, "pxa255_dma_r: DMA Channel Control/Status Register %d: %08x & %08x\n", offset, dma_regs->dcsr[offset], mem_mask ); - return dma_regs->dcsr[offset]; - case PXA255_DINT: - if (0) verboselog(*this, 3, "pxa255_dma_r: DMA Interrupt Register: %08x & %08x\n", dma_regs->dint, mem_mask ); - return dma_regs->dint; - case PXA255_DRCMR0: case PXA255_DRCMR1: case PXA255_DRCMR2: case PXA255_DRCMR3: - case PXA255_DRCMR4: case PXA255_DRCMR5: case PXA255_DRCMR6: case PXA255_DRCMR7: - case PXA255_DRCMR8: case PXA255_DRCMR9: case PXA255_DRCMR10: case PXA255_DRCMR11: - case PXA255_DRCMR12: case PXA255_DRCMR13: case PXA255_DRCMR14: case PXA255_DRCMR15: - case PXA255_DRCMR16: case PXA255_DRCMR17: case PXA255_DRCMR18: case PXA255_DRCMR19: - case PXA255_DRCMR20: case PXA255_DRCMR21: case PXA255_DRCMR22: case PXA255_DRCMR23: - case PXA255_DRCMR24: case PXA255_DRCMR25: case PXA255_DRCMR26: case PXA255_DRCMR27: - case PXA255_DRCMR28: case PXA255_DRCMR29: case PXA255_DRCMR30: case PXA255_DRCMR31: - case PXA255_DRCMR32: case PXA255_DRCMR33: case PXA255_DRCMR34: case PXA255_DRCMR35: - case PXA255_DRCMR36: case PXA255_DRCMR37: case PXA255_DRCMR38: case PXA255_DRCMR39: - verboselog(*this, 3, "pxa255_dma_r: DMA Request to Channel Map Register %d: %08x & %08x\n", offset - (0x100 >> 2), 0, mem_mask ); - return dma_regs->drcmr[offset - (0x100 >> 2)]; - case PXA255_DDADR0: case PXA255_DDADR1: case PXA255_DDADR2: case PXA255_DDADR3: - case PXA255_DDADR4: case PXA255_DDADR5: case PXA255_DDADR6: case PXA255_DDADR7: - case PXA255_DDADR8: case PXA255_DDADR9: case PXA255_DDADR10: case PXA255_DDADR11: - case PXA255_DDADR12: case PXA255_DDADR13: case PXA255_DDADR14: case PXA255_DDADR15: - verboselog(*this, 3, "pxa255_dma_r: DMA Descriptor Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, 0, mem_mask ); - return dma_regs->ddadr[(offset - (0x200 >> 2)) >> 2]; - case PXA255_DSADR0: case PXA255_DSADR1: case PXA255_DSADR2: case PXA255_DSADR3: - case PXA255_DSADR4: case PXA255_DSADR5: case PXA255_DSADR6: case PXA255_DSADR7: - case PXA255_DSADR8: case PXA255_DSADR9: case PXA255_DSADR10: case PXA255_DSADR11: - case PXA255_DSADR12: case PXA255_DSADR13: case PXA255_DSADR14: case PXA255_DSADR15: - verboselog(*this, 3, "pxa255_dma_r: DMA Source Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, 0, mem_mask ); - return dma_regs->dsadr[(offset - (0x200 >> 2)) >> 2]; - case PXA255_DTADR0: case PXA255_DTADR1: case PXA255_DTADR2: case PXA255_DTADR3: - case PXA255_DTADR4: case PXA255_DTADR5: case PXA255_DTADR6: case PXA255_DTADR7: - case PXA255_DTADR8: case PXA255_DTADR9: case PXA255_DTADR10: case PXA255_DTADR11: - case PXA255_DTADR12: case PXA255_DTADR13: case PXA255_DTADR14: case PXA255_DTADR15: - verboselog(*this, 3, "pxa255_dma_r: DMA Target Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, 0, mem_mask ); - return dma_regs->dtadr[(offset - (0x200 >> 2)) >> 2]; - case PXA255_DCMD0: case PXA255_DCMD1: case PXA255_DCMD2: case PXA255_DCMD3: - case PXA255_DCMD4: case PXA255_DCMD5: case PXA255_DCMD6: case PXA255_DCMD7: - case PXA255_DCMD8: case PXA255_DCMD9: case PXA255_DCMD10: case PXA255_DCMD11: - case PXA255_DCMD12: case PXA255_DCMD13: case PXA255_DCMD14: case PXA255_DCMD15: - verboselog(*this, 3, "pxa255_dma_r: DMA Command Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, 0, mem_mask ); - return dma_regs->dcmd[(offset - (0x200 >> 2)) >> 2]; - default: - verboselog(*this, 0, "pxa255_dma_r: Unknown address: %08x\n", PXA255_DMA_BASE_ADDR | (offset << 2)); - break; - } - return 0; -} - -WRITE32_MEMBER(_39in1_state::pxa255_dma_w) -{ - PXA255_DMA_Regs *dma_regs = &m_dma_regs; - - switch(PXA255_DMA_BASE_ADDR | (offset << 2)) - { - case PXA255_DCSR0: case PXA255_DCSR1: case PXA255_DCSR2: case PXA255_DCSR3: - case PXA255_DCSR4: case PXA255_DCSR5: case PXA255_DCSR6: case PXA255_DCSR7: - case PXA255_DCSR8: case PXA255_DCSR9: case PXA255_DCSR10: case PXA255_DCSR11: - case PXA255_DCSR12: case PXA255_DCSR13: case PXA255_DCSR14: case PXA255_DCSR15: - if (0) verboselog(*this, 3, "pxa255_dma_w: DMA Channel Control/Status Register %d: %08x & %08x\n", offset, data, mem_mask ); - dma_regs->dcsr[offset] &= ~(data & 0x00000007); - dma_regs->dcsr[offset] &= ~0x60000000; - dma_regs->dcsr[offset] |= data & 0x60000000; - if((data & PXA255_DCSR_RUN) && !(dma_regs->dcsr[offset] & PXA255_DCSR_RUN)) - { - dma_regs->dcsr[offset] |= PXA255_DCSR_RUN; - if(data & PXA255_DCSR_NODESCFETCH) - { - verboselog(*this, 0, " No-Descriptor-Fetch mode is not supported.\n" ); - break; - } - - pxa255_dma_load_descriptor_and_start(offset); - } - else if(!(data & PXA255_DCSR_RUN)) - { - dma_regs->dcsr[offset] &= ~PXA255_DCSR_RUN; - } - - pxa255_dma_irq_check(); - break; - case PXA255_DINT: - verboselog(*this, 3, "pxa255_dma_w: DMA Interrupt Register: %08x & %08x\n", data, mem_mask ); - dma_regs->dint &= ~data; - break; - case PXA255_DRCMR0: case PXA255_DRCMR1: case PXA255_DRCMR2: case PXA255_DRCMR3: - case PXA255_DRCMR4: case PXA255_DRCMR5: case PXA255_DRCMR6: case PXA255_DRCMR7: - case PXA255_DRCMR8: case PXA255_DRCMR9: case PXA255_DRCMR10: case PXA255_DRCMR11: - case PXA255_DRCMR12: case PXA255_DRCMR13: case PXA255_DRCMR14: case PXA255_DRCMR15: - case PXA255_DRCMR16: case PXA255_DRCMR17: case PXA255_DRCMR18: case PXA255_DRCMR19: - case PXA255_DRCMR20: case PXA255_DRCMR21: case PXA255_DRCMR22: case PXA255_DRCMR23: - case PXA255_DRCMR24: case PXA255_DRCMR25: case PXA255_DRCMR26: case PXA255_DRCMR27: - case PXA255_DRCMR28: case PXA255_DRCMR29: case PXA255_DRCMR30: case PXA255_DRCMR31: - case PXA255_DRCMR32: case PXA255_DRCMR33: case PXA255_DRCMR34: case PXA255_DRCMR35: - case PXA255_DRCMR36: case PXA255_DRCMR37: case PXA255_DRCMR38: case PXA255_DRCMR39: - verboselog(*this, 3, "pxa255_dma_w: DMA Request to Channel Map Register %d: %08x & %08x\n", offset - (0x100 >> 2), data, mem_mask ); - dma_regs->drcmr[offset - (0x100 >> 2)] = data & 0x0000008f; - break; - case PXA255_DDADR0: case PXA255_DDADR1: case PXA255_DDADR2: case PXA255_DDADR3: - case PXA255_DDADR4: case PXA255_DDADR5: case PXA255_DDADR6: case PXA255_DDADR7: - case PXA255_DDADR8: case PXA255_DDADR9: case PXA255_DDADR10: case PXA255_DDADR11: - case PXA255_DDADR12: case PXA255_DDADR13: case PXA255_DDADR14: case PXA255_DDADR15: - verboselog(*this, 3, "pxa255_dma_w: DMA Descriptor Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, data, mem_mask ); - dma_regs->ddadr[(offset - (0x200 >> 2)) >> 2] = data & 0xfffffff1; - break; - case PXA255_DSADR0: case PXA255_DSADR1: case PXA255_DSADR2: case PXA255_DSADR3: - case PXA255_DSADR4: case PXA255_DSADR5: case PXA255_DSADR6: case PXA255_DSADR7: - case PXA255_DSADR8: case PXA255_DSADR9: case PXA255_DSADR10: case PXA255_DSADR11: - case PXA255_DSADR12: case PXA255_DSADR13: case PXA255_DSADR14: case PXA255_DSADR15: - verboselog(*this, 3, "pxa255_dma_w: DMA Source Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, data, mem_mask ); - dma_regs->dsadr[(offset - (0x200 >> 2)) >> 2] = data & 0xfffffffc; - break; - case PXA255_DTADR0: case PXA255_DTADR1: case PXA255_DTADR2: case PXA255_DTADR3: - case PXA255_DTADR4: case PXA255_DTADR5: case PXA255_DTADR6: case PXA255_DTADR7: - case PXA255_DTADR8: case PXA255_DTADR9: case PXA255_DTADR10: case PXA255_DTADR11: - case PXA255_DTADR12: case PXA255_DTADR13: case PXA255_DTADR14: case PXA255_DTADR15: - verboselog(*this, 3, "pxa255_dma_w: DMA Target Address Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, data, mem_mask ); - dma_regs->dtadr[(offset - (0x200 >> 2)) >> 2] = data & 0xfffffffc; - break; - case PXA255_DCMD0: case PXA255_DCMD1: case PXA255_DCMD2: case PXA255_DCMD3: - case PXA255_DCMD4: case PXA255_DCMD5: case PXA255_DCMD6: case PXA255_DCMD7: - case PXA255_DCMD8: case PXA255_DCMD9: case PXA255_DCMD10: case PXA255_DCMD11: - case PXA255_DCMD12: case PXA255_DCMD13: case PXA255_DCMD14: case PXA255_DCMD15: - verboselog(*this, 3, "pxa255_dma_w: DMA Command Register %d: %08x & %08x\n", (offset - (0x200 >> 2)) >> 2, data, mem_mask ); - dma_regs->dcmd[(offset - (0x200 >> 2)) >> 2] = data & 0xf067dfff; - break; - default: - verboselog(*this, 0, "pxa255_dma_w: Unknown address: %08x = %08x & %08x\n", PXA255_DMA_BASE_ADDR | (offset << 2), data, mem_mask); - break; - } -} - -/* - - PXA255 OS Timer register - - pg. 138 to 142, PXA255 Processor Developers Manual [278693-002].pdf - -*/ - -void _39in1_state::pxa255_ostimer_irq_check() -{ - PXA255_OSTMR_Regs *ostimer_regs = &m_ostimer_regs; - - pxa255_set_irq_line(PXA255_INT_OSTIMER0, (ostimer_regs->oier & PXA255_OIER_E0) ? ((ostimer_regs->ossr & PXA255_OSSR_M0) ? 1 : 0) : 0); - //pxa255_set_irq_line(PXA255_INT_OSTIMER1, (ostimer_regs->oier & PXA255_OIER_E1) ? ((ostimer_regs->ossr & PXA255_OSSR_M1) ? 1 : 0) : 0); - //pxa255_set_irq_line(PXA255_INT_OSTIMER2, (ostimer_regs->oier & PXA255_OIER_E2) ? ((ostimer_regs->ossr & PXA255_OSSR_M2) ? 1 : 0) : 0); - //pxa255_set_irq_line(PXA255_INT_OSTIMER3, (ostimer_regs->oier & PXA255_OIER_E3) ? ((ostimer_regs->ossr & PXA255_OSSR_M3) ? 1 : 0) : 0); -} - -TIMER_CALLBACK_MEMBER(_39in1_state::pxa255_ostimer_match) -{ - PXA255_OSTMR_Regs *ostimer_regs = &m_ostimer_regs; - - if (0) verboselog(*this, 3, "pxa255_ostimer_match channel %d\n", param); - ostimer_regs->ossr |= (1 << param); - ostimer_regs->oscr = ostimer_regs->osmr[param]; - pxa255_ostimer_irq_check(); -} - -READ32_MEMBER(_39in1_state::pxa255_ostimer_r) -{ - PXA255_OSTMR_Regs *ostimer_regs = &m_ostimer_regs; - - switch(PXA255_OSTMR_BASE_ADDR | (offset << 2)) - { - case PXA255_OSMR0: - if (0) verboselog(*this, 3, "pxa255_ostimer_r: OS Timer Match Register 0: %08x & %08x\n", ostimer_regs->osmr[0], mem_mask ); - return ostimer_regs->osmr[0]; - case PXA255_OSMR1: - if (0) verboselog(*this, 3, "pxa255_ostimer_r: OS Timer Match Register 1: %08x & %08x\n", ostimer_regs->osmr[1], mem_mask ); - return ostimer_regs->osmr[1]; - case PXA255_OSMR2: - if (0) verboselog(*this, 3, "pxa255_ostimer_r: OS Timer Match Register 2: %08x & %08x\n", ostimer_regs->osmr[2], mem_mask ); - return ostimer_regs->osmr[2]; - case PXA255_OSMR3: - if (0) verboselog(*this, 3, "pxa255_ostimer_r: OS Timer Match Register 3: %08x & %08x\n", ostimer_regs->osmr[3], mem_mask ); - return ostimer_regs->osmr[3]; - case PXA255_OSCR: - if (0) verboselog(*this, 4, "pxa255_ostimer_r: OS Timer Count Register: %08x & %08x\n", ostimer_regs->oscr, mem_mask ); - // free-running 3.something MHz counter. this is a complete hack. - ostimer_regs->oscr += 0x300; - return ostimer_regs->oscr; - case PXA255_OSSR: - if (0) verboselog(*this, 3, "pxa255_ostimer_r: OS Timer Status Register: %08x & %08x\n", ostimer_regs->ossr, mem_mask ); - return ostimer_regs->ossr; - case PXA255_OWER: - if (0) verboselog(*this, 3, "pxa255_ostimer_r: OS Timer Watchdog Match Enable Register: %08x & %08x\n", ostimer_regs->ower, mem_mask ); - return ostimer_regs->ower; - case PXA255_OIER: - if (0) verboselog(*this, 3, "pxa255_ostimer_r: OS Timer Interrupt Enable Register: %08x & %08x\n", ostimer_regs->oier, mem_mask ); - return ostimer_regs->oier; - default: - if (0) verboselog(*this, 0, "pxa255_ostimer_r: Unknown address: %08x\n", PXA255_OSTMR_BASE_ADDR | (offset << 2)); - break; - } - return 0; -} - -WRITE32_MEMBER(_39in1_state::pxa255_ostimer_w) -{ - PXA255_OSTMR_Regs *ostimer_regs = &m_ostimer_regs; - - switch(PXA255_OSTMR_BASE_ADDR | (offset << 2)) - { - case PXA255_OSMR0: - if (0) verboselog(*this, 3, "pxa255_ostimer_w: OS Timer Match Register 0: %08x & %08x\n", data, mem_mask ); - ostimer_regs->osmr[0] = data; - if(ostimer_regs->oier & PXA255_OIER_E0) - { - attotime period = attotime::from_hz(3846400) * (ostimer_regs->osmr[0] - ostimer_regs->oscr); - - //printf( "Adjusting one-shot timer to 200MHz * %08x\n", ostimer_regs->osmr[0]); - ostimer_regs->timer[0]->adjust(period); - } - break; - case PXA255_OSMR1: - if (0) verboselog(*this, 3, "pxa255_ostimer_w: OS Timer Match Register 1: %08x & %08x\n", data, mem_mask ); - ostimer_regs->osmr[1] = data; - if(ostimer_regs->oier & PXA255_OIER_E1) - { - attotime period = attotime::from_hz(3846400) * (ostimer_regs->osmr[1] - ostimer_regs->oscr); - - ostimer_regs->timer[1]->adjust(period, 1); - } - break; - case PXA255_OSMR2: - if (0) verboselog(*this, 3, "pxa255_ostimer_w: OS Timer Match Register 2: %08x & %08x\n", data, mem_mask ); - ostimer_regs->osmr[2] = data; - if(ostimer_regs->oier & PXA255_OIER_E2) - { - attotime period = attotime::from_hz(3846400) * (ostimer_regs->osmr[2] - ostimer_regs->oscr); - - ostimer_regs->timer[2]->adjust(period, 2); - } - break; - case PXA255_OSMR3: - if (0) verboselog(*this, 3, "pxa255_ostimer_w: OS Timer Match Register 3: %08x & %08x\n", data, mem_mask ); - ostimer_regs->osmr[3] = data; - if(ostimer_regs->oier & PXA255_OIER_E3) - { - //attotime period = attotime::from_hz(3846400) * (ostimer_regs->osmr[3] - ostimer_regs->oscr); - - //ostimer_regs->timer[3]->adjust(period, 3); - } - break; - case PXA255_OSCR: - if (0) verboselog(*this, 3, "pxa255_ostimer_w: OS Timer Count Register: %08x & %08x\n", data, mem_mask ); - ostimer_regs->oscr = data; - break; - case PXA255_OSSR: - if (0) verboselog(*this, 3, "pxa255_ostimer_w: OS Timer Status Register: %08x & %08x\n", data, mem_mask ); - ostimer_regs->ossr &= ~data; - pxa255_ostimer_irq_check(); - break; - case PXA255_OWER: - if (0) verboselog(*this, 3, "pxa255_ostimer_w: OS Timer Watchdog Enable Register: %08x & %08x\n", data, mem_mask ); - ostimer_regs->ower = data & 0x00000001; - break; - case PXA255_OIER: - { - int index = 0; - if (0) verboselog(*this, 3, "pxa255_ostimer_w: OS Timer Interrupt Enable Register: %08x & %08x\n", data, mem_mask ); - ostimer_regs->oier = data & 0x0000000f; - for(index = 0; index < 4; index++) - { - if(ostimer_regs->oier & (1 << index)) - { - //attotime period = attotime::from_hz(200000000) * ostimer_regs->osmr[index]; - - //ostimer_regs->timer[index]->adjust(period, index); - } - } - - break; - } - default: - verboselog(*this, 0, "pxa255_ostimer_w: Unknown address: %08x = %08x & %08x\n", PXA255_OSTMR_BASE_ADDR | (offset << 2), data, mem_mask); - break; - } -} - -/* - - PXA255 Interrupt registers - - pg. 124 to 132, PXA255 Processor Developers Manual [278693-002].pdf - -*/ - -void _39in1_state::pxa255_update_interrupts() -{ - PXA255_INTC_Regs *intc_regs = &m_intc_regs; - - intc_regs->icfp = (intc_regs->icpr & intc_regs->icmr) & intc_regs->iclr; - intc_regs->icip = (intc_regs->icpr & intc_regs->icmr) & (~intc_regs->iclr); - m_maincpu->set_input_line(ARM7_FIRQ_LINE, intc_regs->icfp ? ASSERT_LINE : CLEAR_LINE); - m_maincpu->set_input_line(ARM7_IRQ_LINE, intc_regs->icip ? ASSERT_LINE : CLEAR_LINE); -} - -void _39in1_state::pxa255_set_irq_line(uint32_t line, int irq_state) -{ - PXA255_INTC_Regs *intc_regs = &m_intc_regs; - - intc_regs->icpr &= ~line; - intc_regs->icpr |= irq_state ? line : 0; - //printf( "Setting IRQ line %08x to %d\n", line, irq_state ); - pxa255_update_interrupts(); -} - -READ32_MEMBER(_39in1_state::pxa255_intc_r) -{ - PXA255_INTC_Regs *intc_regs = &m_intc_regs; - - switch(PXA255_INTC_BASE_ADDR | (offset << 2)) - { - case PXA255_ICIP: - if (0) verboselog(*this, 3, "pxa255_intc_r: Interrupt Controller IRQ Pending Register: %08x & %08x\n", intc_regs->icip, mem_mask ); - return intc_regs->icip; - case PXA255_ICMR: - if (0) verboselog(*this, 3, "pxa255_intc_r: Interrupt Controller Mask Register: %08x & %08x\n", intc_regs->icmr, mem_mask ); - return intc_regs->icmr; - case PXA255_ICLR: - if (0) verboselog(*this, 3, "pxa255_intc_r: Interrupt Controller Level Register: %08x & %08x\n", intc_regs->iclr, mem_mask ); - return intc_regs->iclr; - case PXA255_ICFP: - if (0) verboselog(*this, 3, "pxa255_intc_r: Interrupt Controller FIQ Pending Register: %08x & %08x\n", intc_regs->icfp, mem_mask ); - return intc_regs->icfp; - case PXA255_ICPR: - if (0) verboselog(*this, 3, "pxa255_intc_r: Interrupt Controller Pending Register: %08x & %08x\n", intc_regs->icpr, mem_mask ); - return intc_regs->icpr; - case PXA255_ICCR: - if (0) verboselog(*this, 3, "pxa255_intc_r: Interrupt Controller Control Register: %08x & %08x\n", intc_regs->iccr, mem_mask ); - return intc_regs->iccr; - default: - verboselog(*this, 0, "pxa255_intc_r: Unknown address: %08x\n", PXA255_INTC_BASE_ADDR | (offset << 2)); - break; - } - return 0; -} - -WRITE32_MEMBER(_39in1_state::pxa255_intc_w) -{ - PXA255_INTC_Regs *intc_regs = &m_intc_regs; - - switch(PXA255_INTC_BASE_ADDR | (offset << 2)) - { - case PXA255_ICIP: - verboselog(*this, 3, "pxa255_intc_w: (Invalid Write) Interrupt Controller IRQ Pending Register: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_ICMR: - if (0) verboselog(*this, 3, "pxa255_intc_w: Interrupt Controller Mask Register: %08x & %08x\n", data, mem_mask ); - intc_regs->icmr = data & 0xfffe7f00; - break; - case PXA255_ICLR: - if (0) verboselog(*this, 3, "pxa255_intc_w: Interrupt Controller Level Register: %08x & %08x\n", data, mem_mask ); - intc_regs->iclr = data & 0xfffe7f00; - break; - case PXA255_ICFP: - if (0) verboselog(*this, 3, "pxa255_intc_w: (Invalid Write) Interrupt Controller FIQ Pending Register: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_ICPR: - if (0) verboselog(*this, 3, "pxa255_intc_w: (Invalid Write) Interrupt Controller Pending Register: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_ICCR: - if (0) verboselog(*this, 3, "pxa255_intc_w: Interrupt Controller Control Register: %08x & %08x\n", data, mem_mask ); - intc_regs->iccr = data & 0x00000001; - break; - default: - verboselog(*this, 0, "pxa255_intc_w: Unknown address: %08x = %08x & %08x\n", PXA255_INTC_BASE_ADDR | (offset << 2), data, mem_mask); - break; - } -} - -/* - - PXA255 General-Purpose I/O registers - - pg. 105 to 124, PXA255 Processor Developers Manual [278693-002].pdf - -*/ - -READ32_MEMBER(_39in1_state::pxa255_gpio_r) -{ - PXA255_GPIO_Regs *gpio_regs = &m_gpio_regs; - - switch(PXA255_GPIO_BASE_ADDR | (offset << 2)) - { - case PXA255_GPLR0: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Pin-Level Register 0: %08x & %08x\n", gpio_regs->gplr0 | (1 << 1), mem_mask ); - return gpio_regs->gplr0 | (1 << 1) | (m_eeprom->do_read() << 5); // Must be on. Probably a DIP switch. - case PXA255_GPLR1: - verboselog(*this, 3, "pxa255_gpio_r: *Not Yet Implemented* GPIO Pin-Level Register 1: %08x & %08x\n", gpio_regs->gplr1, mem_mask ); - return 0xff9fffff; - /* - 0x200000 = flip screen - */ - case PXA255_GPLR2: - verboselog(*this, 3, "pxa255_gpio_r: *Not Yet Implemented* GPIO Pin-Level Register 2: %08x & %08x\n", gpio_regs->gplr2, mem_mask ); - return gpio_regs->gplr2; - case PXA255_GPDR0: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Pin Direction Register 0: %08x & %08x\n", gpio_regs->gpdr0, mem_mask ); - return gpio_regs->gpdr0; - case PXA255_GPDR1: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Pin Direction Register 1: %08x & %08x\n", gpio_regs->gpdr1, mem_mask ); - return gpio_regs->gpdr1; - case PXA255_GPDR2: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Pin Direction Register 2: %08x & %08x\n", gpio_regs->gpdr2, mem_mask ); - return gpio_regs->gpdr2; - case PXA255_GPSR0: - verboselog(*this, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 0: %08x & %08x\n", machine().rand(), mem_mask ); - return machine().rand(); - case PXA255_GPSR1: - verboselog(*this, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 1: %08x & %08x\n", machine().rand(), mem_mask ); - return machine().rand(); - case PXA255_GPSR2: - verboselog(*this, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 2: %08x & %08x\n", machine().rand(), mem_mask ); - return machine().rand(); - case PXA255_GPCR0: - verboselog(*this, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 0: %08x & %08x\n", machine().rand(), mem_mask ); - return machine().rand(); - case PXA255_GPCR1: - verboselog(*this, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 1: %08x & %08x\n", machine().rand(), mem_mask ); - return machine().rand(); - case PXA255_GPCR2: - verboselog(*this, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 2: %08x & %08x\n", machine().rand(), mem_mask ); - return machine().rand(); - case PXA255_GRER0: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Rising Edge Detect Enable Register 0: %08x & %08x\n", gpio_regs->grer0, mem_mask ); - return gpio_regs->grer0; - case PXA255_GRER1: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Rising Edge Detect Enable Register 1: %08x & %08x\n", gpio_regs->grer1, mem_mask ); - return gpio_regs->grer1; - case PXA255_GRER2: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Rising Edge Detect Enable Register 2: %08x & %08x\n", gpio_regs->grer2, mem_mask ); - return gpio_regs->grer2; - case PXA255_GFER0: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Falling Edge Detect Enable Register 0: %08x & %08x\n", gpio_regs->gfer0, mem_mask ); - return gpio_regs->gfer0; - case PXA255_GFER1: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Falling Edge Detect Enable Register 1: %08x & %08x\n", gpio_regs->gfer1, mem_mask ); - return gpio_regs->gfer1; - case PXA255_GFER2: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Falling Edge Detect Enable Register 2: %08x & %08x\n", gpio_regs->gfer2, mem_mask ); - return gpio_regs->gfer2; - case PXA255_GEDR0: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Edge Detect Status Register 0: %08x & %08x\n", gpio_regs->gedr0, mem_mask ); - return gpio_regs->gedr0; - case PXA255_GEDR1: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Edge Detect Status Register 1: %08x & %08x\n", gpio_regs->gedr1, mem_mask ); - return gpio_regs->gedr1; - case PXA255_GEDR2: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Edge Detect Status Register 2: %08x & %08x\n", gpio_regs->gedr2, mem_mask ); - return gpio_regs->gedr2; - case PXA255_GAFR0_L: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Alternate Function Register 0 Lower: %08x & %08x\n", gpio_regs->gafr0l, mem_mask ); - return gpio_regs->gafr0l; - case PXA255_GAFR0_U: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Alternate Function Register 0 Upper: %08x & %08x\n", gpio_regs->gafr0u, mem_mask ); - return gpio_regs->gafr0u; - case PXA255_GAFR1_L: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Alternate Function Register 1 Lower: %08x & %08x\n", gpio_regs->gafr1l, mem_mask ); - return gpio_regs->gafr1l; - case PXA255_GAFR1_U: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Alternate Function Register 1 Upper: %08x & %08x\n", gpio_regs->gafr1u, mem_mask ); - return gpio_regs->gafr1u; - case PXA255_GAFR2_L: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Alternate Function Register 2 Lower: %08x & %08x\n", gpio_regs->gafr2l, mem_mask ); - return gpio_regs->gafr2l; - case PXA255_GAFR2_U: - verboselog(*this, 3, "pxa255_gpio_r: GPIO Alternate Function Register 2 Upper: %08x & %08x\n", gpio_regs->gafr2u, mem_mask ); - return gpio_regs->gafr2u; - default: - verboselog(*this, 0, "pxa255_gpio_r: Unknown address: %08x\n", PXA255_GPIO_BASE_ADDR | (offset << 2)); - break; - } - return 0; -} - -WRITE32_MEMBER(_39in1_state::pxa255_gpio_w) -{ - PXA255_GPIO_Regs *gpio_regs = &m_gpio_regs; - - switch(PXA255_GPIO_BASE_ADDR | (offset << 2)) - { - case PXA255_GPLR0: - verboselog(*this, 3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 0: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_GPLR1: - verboselog(*this, 3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 1: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_GPLR2: - verboselog(*this, 3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 2: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_GPDR0: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Direction Register 0: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpdr0 = data; - break; - case PXA255_GPDR1: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Direction Register 1: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpdr1 = data; - break; - case PXA255_GPDR2: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Direction Register 2: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpdr2 = data; - break; - case PXA255_GPSR0: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Output Set Register 0: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpsr0 |= data & gpio_regs->gpdr0; - if(data & 0x00000004) - { - m_eeprom->cs_write(ASSERT_LINE); - } - if(data & 0x00000008) - { - m_eeprom->clk_write(ASSERT_LINE); - } - if(data & 0x00000010) - { - m_eeprom->di_write(1); - } - break; - case PXA255_GPSR1: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Output Set Register 1: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpsr1 |= data & gpio_regs->gpdr1; - break; - case PXA255_GPSR2: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Output Set Register 2: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpsr2 |= data & gpio_regs->gpdr2; - break; - case PXA255_GPCR0: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Output Clear Register 0: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpsr0 &= ~(data & gpio_regs->gpdr0); - if(data & 0x00000004) - { - m_eeprom->cs_write(ASSERT_LINE); - } - if(data & 0x00000008) - { - m_eeprom->clk_write(CLEAR_LINE); - } - if(data & 0x00000010) - { - m_eeprom->di_write(0); - } - break; - case PXA255_GPCR1: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Output Clear Register 1: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpsr1 &= ~(data & gpio_regs->gpdr1); - break; - case PXA255_GPCR2: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Pin Output Clear Register 2: %08x & %08x\n", data, mem_mask ); - gpio_regs->gpsr2 &= ~(data & gpio_regs->gpdr2); - break; - case PXA255_GRER0: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Rising Edge Detect Enable Register 0: %08x & %08x\n", data, mem_mask ); - gpio_regs->grer0 = data; - break; - case PXA255_GRER1: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Rising Edge Detect Enable Register 1: %08x & %08x\n", data, mem_mask ); - gpio_regs->grer1 = data; - break; - case PXA255_GRER2: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Rising Edge Detect Enable Register 2: %08x & %08x\n", data, mem_mask ); - gpio_regs->grer2 = data; - break; - case PXA255_GFER0: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Falling Edge Detect Enable Register 0: %08x & %08x\n", data, mem_mask ); - gpio_regs->gfer0 = data; - break; - case PXA255_GFER1: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Falling Edge Detect Enable Register 1: %08x & %08x\n", data, mem_mask ); - gpio_regs->gfer1 = data; - break; - case PXA255_GFER2: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Falling Edge Detect Enable Register 2: %08x & %08x\n", data, mem_mask ); - gpio_regs->gfer2 = data; - break; - case PXA255_GEDR0: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Edge Detect Status Register 0: %08x & %08x\n", gpio_regs->gedr0, mem_mask ); - gpio_regs->gedr0 &= ~data; - break; - case PXA255_GEDR1: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Edge Detect Status Register 1: %08x & %08x\n", gpio_regs->gedr1, mem_mask ); - gpio_regs->gedr1 &= ~data; - break; - case PXA255_GEDR2: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Edge Detect Status Register 2: %08x & %08x\n", gpio_regs->gedr2, mem_mask ); - gpio_regs->gedr2 &= ~data; - break; - case PXA255_GAFR0_L: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Alternate Function Register 0 Lower: %08x & %08x\n", gpio_regs->gafr0l, mem_mask ); - gpio_regs->gafr0l = data; - break; - case PXA255_GAFR0_U: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Alternate Function Register 0 Upper: %08x & %08x\n", gpio_regs->gafr0u, mem_mask ); - gpio_regs->gafr0u = data; - break; - case PXA255_GAFR1_L: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Alternate Function Register 1 Lower: %08x & %08x\n", gpio_regs->gafr1l, mem_mask ); - gpio_regs->gafr1l = data; - break; - case PXA255_GAFR1_U: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Alternate Function Register 1 Upper: %08x & %08x\n", gpio_regs->gafr1u, mem_mask ); - gpio_regs->gafr1u = data; - break; - case PXA255_GAFR2_L: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Alternate Function Register 2 Lower: %08x & %08x\n", gpio_regs->gafr2l, mem_mask ); - gpio_regs->gafr2l = data; - break; - case PXA255_GAFR2_U: - verboselog(*this, 3, "pxa255_gpio_w: GPIO Alternate Function Register 2 Upper: %08x & %08x\n", gpio_regs->gafr2u, mem_mask ); - gpio_regs->gafr2u = data; - break; - default: - verboselog(*this, 0, "pxa255_gpio_w: Unknown address: %08x = %08x & %08x\n", PXA255_GPIO_BASE_ADDR | (offset << 2), data, mem_mask); - break; - } -} - -/* - - PXA255 LCD Controller - - pg. 265 to 310, PXA255 Processor Developers Manual [278693-002].pdf - -*/ - -void _39in1_state::pxa255_lcd_load_dma_descriptor(address_space & space, uint32_t address, int channel) -{ - PXA255_LCD_Regs *lcd_regs = &m_lcd_regs; - - lcd_regs->dma[channel].fdadr = space.read_dword(address); - lcd_regs->dma[channel].fsadr = space.read_dword(address + 0x04); - lcd_regs->dma[channel].fidr = space.read_dword(address + 0x08); - lcd_regs->dma[channel].ldcmd = space.read_dword(address + 0x0c); - verboselog(*this, 4, "pxa255_lcd_load_dma_descriptor, address = %08x, channel = %d\n", address, channel); - verboselog(*this, 4, " DMA Frame Descriptor: %08x\n", lcd_regs->dma[channel].fdadr ); - verboselog(*this, 4, " DMA Frame Source Address: %08x\n", lcd_regs->dma[channel].fsadr ); - verboselog(*this, 4, " DMA Frame ID: %08x\n", lcd_regs->dma[channel].fidr ); - verboselog(*this, 4, " DMA Command: %08x\n", lcd_regs->dma[channel].ldcmd ); -} - -void _39in1_state::pxa255_lcd_irq_check() -{ - PXA255_LCD_Regs *lcd_regs = &m_lcd_regs; - - if(((lcd_regs->lcsr & PXA255_LCSR_BS) != 0 && (lcd_regs->lccr0 & PXA255_LCCR0_BM) == 0) || - ((lcd_regs->lcsr & PXA255_LCSR_EOF) != 0 && (lcd_regs->lccr0 & PXA255_LCCR0_EFM) == 0) || - ((lcd_regs->lcsr & PXA255_LCSR_SOF) != 0 && (lcd_regs->lccr0 & PXA255_LCCR0_SFM) == 0)) - { - pxa255_set_irq_line(PXA255_INT_LCD, 1); - } - else - { - pxa255_set_irq_line(PXA255_INT_LCD, 0); - } -} - -void _39in1_state::pxa255_lcd_dma_kickoff(int channel) -{ - PXA255_LCD_Regs *lcd_regs = &m_lcd_regs; - - if(lcd_regs->dma[channel].fdadr != 0) - { - attotime period = attotime::from_hz(20000000) * (lcd_regs->dma[channel].ldcmd & 0x000fffff); - - lcd_regs->dma[channel].eof->adjust(period, channel); - - if(lcd_regs->dma[channel].ldcmd & PXA255_LDCMD_SOFINT) - { - lcd_regs->liidr = lcd_regs->dma[channel].fidr; - lcd_regs->lcsr |= PXA255_LCSR_SOF; - pxa255_lcd_irq_check(); - } - - if(lcd_regs->dma[channel].ldcmd & PXA255_LDCMD_PAL) - { - address_space &space = m_maincpu->space(AS_PROGRAM); - int length = lcd_regs->dma[channel].ldcmd & 0x000fffff; - int index = 0; - for(index = 0; index < length; index += 2) - { - uint16_t color = space.read_word((lcd_regs->dma[channel].fsadr &~ 1) + index); - m_pxa255_lcd_palette[index >> 1] = (((((color >> 11) & 0x1f) << 3) | (color >> 13)) << 16) | (((((color >> 5) & 0x3f) << 2) | ((color >> 9) & 0x3)) << 8) | (((color & 0x1f) << 3) | ((color >> 2) & 0x7)); - m_palette->set_pen_color(index >> 1, (((color >> 11) & 0x1f) << 3) | (color >> 13), (((color >> 5) & 0x3f) << 2) | ((color >> 9) & 0x3), ((color & 0x1f) << 3) | ((color >> 2) & 0x7)); - } - } - else - { - address_space &space = m_maincpu->space(AS_PROGRAM); - int length = lcd_regs->dma[channel].ldcmd & 0x000fffff; - int index = 0; - for(index = 0; index < length; index++) - { - m_pxa255_lcd_framebuffer[index] = space.read_byte(lcd_regs->dma[channel].fsadr + index); - } - } - } -} - -void _39in1_state::pxa255_lcd_check_load_next_branch(int channel) -{ - PXA255_LCD_Regs *lcd_regs = &m_lcd_regs; - - if(lcd_regs->fbr[channel] & 1) - { - verboselog(*this, 4, "pxa255_lcd_check_load_next_branch: Taking branch\n" ); - lcd_regs->fbr[channel] &= ~1; - address_space &space = m_maincpu->space(AS_PROGRAM); - //lcd_regs->fbr[channel] = (space.read_dword(lcd_regs->fbr[channel] & 0xfffffff0) & 0xfffffff0) | (lcd_regs->fbr[channel] & 0x00000003); - //printf( "%08x\n", lcd_regs->fbr[channel] ); - pxa255_lcd_load_dma_descriptor(space, lcd_regs->fbr[channel] & 0xfffffff0, 0); - lcd_regs->fbr[channel] = (space.read_dword(lcd_regs->fbr[channel] & 0xfffffff0) & 0xfffffff0) | (lcd_regs->fbr[channel] & 0x00000003); - pxa255_lcd_dma_kickoff(0); - if(lcd_regs->fbr[channel] & 2) - { - lcd_regs->fbr[channel] &= ~2; - if(!(lcd_regs->lccr0 & PXA255_LCCR0_BM)) - { - lcd_regs->lcsr |= PXA255_LCSR_BS; - } - } - } - else - { - if (0) verboselog(*this, 3, "pxa255_lcd_check_load_next_branch: Not taking branch\n" ); - } -} - -TIMER_CALLBACK_MEMBER(_39in1_state::pxa255_lcd_dma_eof) -{ - PXA255_LCD_Regs *lcd_regs = &m_lcd_regs; - - if (0) verboselog(*this, 3, "End of frame callback\n" ); - if(lcd_regs->dma[param].ldcmd & PXA255_LDCMD_EOFINT) - { - lcd_regs->liidr = lcd_regs->dma[param].fidr; - lcd_regs->lcsr |= PXA255_LCSR_EOF; - } - pxa255_lcd_check_load_next_branch(param); - pxa255_lcd_irq_check(); -} - -READ32_MEMBER(_39in1_state::pxa255_lcd_r) -{ - PXA255_LCD_Regs *lcd_regs = &m_lcd_regs; - - switch(PXA255_LCD_BASE_ADDR | (offset << 2)) - { - case PXA255_LCCR0: // 0x44000000 - verboselog(*this, 3, "pxa255_lcd_r: LCD Control 0: %08x & %08x\n", lcd_regs->lccr0, mem_mask ); - return lcd_regs->lccr0; - case PXA255_LCCR1: // 0x44000004 - verboselog(*this, 3, "pxa255_lcd_r: LCD Control 1: %08x & %08x\n", lcd_regs->lccr1, mem_mask ); - return lcd_regs->lccr1; - case PXA255_LCCR2: // 0x44000008 - verboselog(*this, 3, "pxa255_lcd_r: LCD Control 2: %08x & %08x\n", lcd_regs->lccr2, mem_mask ); - return lcd_regs->lccr2; - case PXA255_LCCR3: // 0x4400000c - verboselog(*this, 3, "pxa255_lcd_r: LCD Control 3: %08x & %08x\n", lcd_regs->lccr3, mem_mask ); - return lcd_regs->lccr3; - case PXA255_FBR0: // 0x44000020 - verboselog(*this, 4, "pxa255_lcd_r: LCD Frame Branch Register 0: %08x & %08x\n", lcd_regs->fbr[0], mem_mask ); - return lcd_regs->fbr[0]; - case PXA255_FBR1: // 0x44000024 - verboselog(*this, 3, "pxa255_lcd_r: LCD Frame Branch Register 1: %08x & %08x\n", lcd_regs->fbr[1], mem_mask ); - return lcd_regs->fbr[1]; - case PXA255_LCSR: // 0x44000038 - verboselog(*this, 4, "pxa255_lcd_r: LCD Status Register: %08x & %08x\n", lcd_regs->lcsr, mem_mask ); - return lcd_regs->lcsr; - case PXA255_LIIDR: // 0x4400003c - verboselog(*this, 3, "pxa255_lcd_r: LCD Interrupt ID Register: %08x & %08x\n", lcd_regs->liidr, mem_mask ); - return lcd_regs->liidr; - case PXA255_TRGBR: // 0x44000040 - verboselog(*this, 3, "pxa255_lcd_r: TMED RGB Seed Register: %08x & %08x\n", lcd_regs->trgbr, mem_mask ); - return lcd_regs->trgbr; - case PXA255_TCR: // 0x44000044 - verboselog(*this, 3, "pxa255_lcd_r: TMED RGB Seed Register: %08x & %08x\n", lcd_regs->tcr, mem_mask ); - return lcd_regs->tcr; - case PXA255_FDADR0: // 0x44000200 - if (0) verboselog(*this, 3, "pxa255_lcd_r: LCD DMA Frame Descriptor Address Register 0: %08x & %08x\n", lcd_regs->dma[0].fdadr, mem_mask ); - return lcd_regs->dma[0].fdadr; - case PXA255_FSADR0: // 0x44000204 - verboselog(*this, 3, "pxa255_lcd_r: LCD DMA Frame Source Address Register 0: %08x & %08x\n", lcd_regs->dma[0].fsadr, mem_mask ); - return lcd_regs->dma[0].fsadr; - case PXA255_FIDR0: // 0x44000208 - verboselog(*this, 3, "pxa255_lcd_r: LCD DMA Frame ID Register 0: %08x & %08x\n", lcd_regs->dma[0].fidr, mem_mask ); - return lcd_regs->dma[0].fidr; - case PXA255_LDCMD0: // 0x4400020c - if (0) verboselog(*this, 3, "pxa255_lcd_r: LCD DMA Command Register 0: %08x & %08x\n", lcd_regs->dma[0].ldcmd & 0xfff00000, mem_mask ); - return lcd_regs->dma[0].ldcmd & 0xfff00000; - case PXA255_FDADR1: // 0x44000210 - verboselog(*this, 3, "pxa255_lcd_r: LCD DMA Frame Descriptor Address Register 1: %08x & %08x\n", lcd_regs->dma[1].fdadr, mem_mask ); - return lcd_regs->dma[1].fdadr; - case PXA255_FSADR1: // 0x44000214 - verboselog(*this, 3, "pxa255_lcd_r: LCD DMA Frame Source Address Register 1: %08x & %08x\n", lcd_regs->dma[1].fsadr, mem_mask ); - return lcd_regs->dma[1].fsadr; - case PXA255_FIDR1: // 0x44000218 - verboselog(*this, 3, "pxa255_lcd_r: LCD DMA Frame ID Register 1: %08x & %08x\n", lcd_regs->dma[1].fidr, mem_mask ); - return lcd_regs->dma[1].fidr; - case PXA255_LDCMD1: // 0x4400021c - verboselog(*this, 3, "pxa255_lcd_r: LCD DMA Command Register 1: %08x & %08x\n", lcd_regs->dma[1].ldcmd & 0xfff00000, mem_mask ); - return lcd_regs->dma[1].ldcmd & 0xfff00000; - default: - verboselog(*this, 0, "pxa255_lcd_r: Unknown address: %08x\n", PXA255_LCD_BASE_ADDR | (offset << 2)); - break; - } - return 0; -} - -WRITE32_MEMBER(_39in1_state::pxa255_lcd_w) -{ - PXA255_LCD_Regs *lcd_regs = &m_lcd_regs; - - switch(PXA255_LCD_BASE_ADDR | (offset << 2)) - { - case PXA255_LCCR0: // 0x44000000 - verboselog(*this, 3, "pxa255_lcd_w: LCD Control 0: %08x & %08x\n", data, mem_mask ); - lcd_regs->lccr0 = data & 0x00fffeff; - break; - case PXA255_LCCR1: // 0x44000004 - verboselog(*this, 3, "pxa255_lcd_w: LCD Control 1: %08x & %08x\n", data, mem_mask ); - lcd_regs->lccr1 = data; - break; - case PXA255_LCCR2: // 0x44000008 - verboselog(*this, 3, "pxa255_lcd_w: LCD Control 2: %08x & %08x\n", data, mem_mask ); - lcd_regs->lccr2 = data; - break; - case PXA255_LCCR3: // 0x4400000c - verboselog(*this, 3, "pxa255_lcd_w: LCD Control 3: %08x & %08x\n", data, mem_mask ); - lcd_regs->lccr3 = data; - break; - case PXA255_FBR0: // 0x44000020 - verboselog(*this, 4l, "pxa255_lcd_w: LCD Frame Branch Register 0: %08x & %08x\n", data, mem_mask ); - lcd_regs->fbr[0] = data & 0xfffffff3; - if(!lcd_regs->dma[0].eof->enabled()) - { - if (0) verboselog(*this, 3, "ch0 EOF timer is not enabled, taking branch now\n" ); - pxa255_lcd_check_load_next_branch(0); - pxa255_lcd_irq_check(); - } - break; - case PXA255_FBR1: // 0x44000024 - verboselog(*this, 3, "pxa255_lcd_w: LCD Frame Branch Register 1: %08x & %08x\n", data, mem_mask ); - lcd_regs->fbr[1] = data & 0xfffffff3; - if(!lcd_regs->dma[1].eof->enabled()) - { - verboselog(*this, 3, "ch1 EOF timer is not enabled, taking branch now\n" ); - pxa255_lcd_check_load_next_branch(1); - pxa255_lcd_irq_check(); - } - break; - case PXA255_LCSR: // 0x44000038 - verboselog(*this, 4, "pxa255_lcd_w: LCD Controller Status Register: %08x & %08x\n", data, mem_mask ); - lcd_regs->lcsr &= ~data; - pxa255_lcd_irq_check(); - break; - case PXA255_LIIDR: // 0x4400003c - verboselog(*this, 3, "pxa255_lcd_w: LCD Controller Interrupt ID Register: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_TRGBR: // 0x44000040 - verboselog(*this, 3, "pxa255_lcd_w: TMED RGB Seed Register: %08x & %08x\n", data, mem_mask ); - lcd_regs->trgbr = data & 0x00ffffff; - break; - case PXA255_TCR: // 0x44000044 - verboselog(*this, 3, "pxa255_lcd_w: TMED Control Register: %08x & %08x\n", data, mem_mask ); - lcd_regs->tcr = data & 0x00004fff; - break; - case PXA255_FDADR0: // 0x44000200 - verboselog(*this, 4, "pxa255_lcd_w: LCD DMA Frame Descriptor Address Register 0: %08x & %08x\n", data, mem_mask ); - if(!lcd_regs->dma[0].eof->enabled()) - { - pxa255_lcd_load_dma_descriptor(space, data & 0xfffffff0, 0); - } - else - { - lcd_regs->fbr[0] &= 0x00000003; - lcd_regs->fbr[0] |= data & 0xfffffff0; - } - break; - case PXA255_FSADR0: // 0x44000204 - verboselog(*this, 4, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame Source Address Register 0: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_FIDR0: // 0x44000208 - verboselog(*this, 4, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame ID Register 0: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_LDCMD0: // 0x4400020c - verboselog(*this, 4, "pxa255_lcd_w: (Invalid Write) LCD DMA Command Register 0: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_FDADR1: // 0x44000210 - verboselog(*this, 4, "pxa255_lcd_w: LCD DMA Frame Descriptor Address Register 1: %08x & %08x\n", data, mem_mask ); - if(!lcd_regs->dma[1].eof->enabled()) - { - pxa255_lcd_load_dma_descriptor(space, data & 0xfffffff0, 1); - } - else - { - lcd_regs->fbr[1] &= 0x00000003; - lcd_regs->fbr[1] |= data & 0xfffffff0; - } - break; - case PXA255_FSADR1: // 0x44000214 - verboselog(*this, 4, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame Source Address Register 1: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_FIDR1: // 0x44000218 - verboselog(*this, 4, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame ID Register 1: %08x & %08x\n", data, mem_mask ); - break; - case PXA255_LDCMD1: // 0x4400021c - verboselog(*this, 4, "pxa255_lcd_w: (Invalid Write) LCD DMA Command Register 1: %08x & %08x\n", data, mem_mask ); - break; - default: - verboselog(*this, 0, "pxa255_lcd_w: Unknown address: %08x = %08x & %08x\n", PXA255_LCD_BASE_ADDR | (offset << 2), data, mem_mask); - break; - } -} - -INTERRUPT_GEN_MEMBER(_39in1_state::pxa255_vblank_start) -{ -} - -#ifdef UNUSED_FUNCTION -READ32_MEMBER(_39in1_state::return_zero) -{ - return 0; -} - -READ32_MEMBER(_39in1_state::unknown_r) -{ - return 0x00008000; -} -#endif - READ32_MEMBER(_39in1_state::cpld_r) { //if (m_maincpu->pc() != 0xe3af4) printf("CPLD read @ %x (PC %x state %d)\n", offset, m_maincpu->pc(), state); @@ -1454,25 +195,23 @@ READ32_MEMBER(_39in1_state::prot_cheater_r) return 0x37; } -void _39in1_state::init_39in1() +void _39in1_state::driver_init() { address_space &space = m_maincpu->space(AS_PROGRAM); space.install_read_handler (0xa0151648, 0xa015164b, read32_delegate(FUNC(_39in1_state::prot_cheater_r), this)); } - - void _39in1_state::_39in1_map(address_map &map) { map(0x00000000, 0x0007ffff).rom(); map(0x00400000, 0x005fffff).rom().region("data", 0); map(0x04000000, 0x047fffff).rw(FUNC(_39in1_state::cpld_r), FUNC(_39in1_state::cpld_w)); - map(0x40000000, 0x400002ff).rw(FUNC(_39in1_state::pxa255_dma_r), FUNC(_39in1_state::pxa255_dma_w)); - map(0x40400000, 0x40400083).rw(FUNC(_39in1_state::pxa255_i2s_r), FUNC(_39in1_state::pxa255_i2s_w)); - map(0x40a00000, 0x40a0001f).rw(FUNC(_39in1_state::pxa255_ostimer_r), FUNC(_39in1_state::pxa255_ostimer_w)); - map(0x40d00000, 0x40d00017).rw(FUNC(_39in1_state::pxa255_intc_r), FUNC(_39in1_state::pxa255_intc_w)); - map(0x40e00000, 0x40e0006b).rw(FUNC(_39in1_state::pxa255_gpio_r), FUNC(_39in1_state::pxa255_gpio_w)); - map(0x44000000, 0x4400021f).rw(FUNC(_39in1_state::pxa255_lcd_r), FUNC(_39in1_state::pxa255_lcd_w)); + map(0x40000000, 0x400002ff).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::pxa255_dma_r), FUNC(pxa255_periphs_device::pxa255_dma_w)); + map(0x40400000, 0x40400083).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::pxa255_i2s_r), FUNC(pxa255_periphs_device::pxa255_i2s_w)); + map(0x40a00000, 0x40a0001f).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::pxa255_ostimer_r), FUNC(pxa255_periphs_device::pxa255_ostimer_w)); + map(0x40d00000, 0x40d00017).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::pxa255_intc_r), FUNC(pxa255_periphs_device::pxa255_intc_w)); + map(0x40e00000, 0x40e0006b).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::pxa255_gpio_r), FUNC(pxa255_periphs_device::pxa255_gpio_w)); + map(0x44000000, 0x4400021f).rw(m_pxa_periphs, FUNC(pxa255_periphs_device::pxa255_lcd_r), FUNC(pxa255_periphs_device::pxa255_lcd_w)); map(0xa0000000, 0xa07fffff).ram().share("ram"); } @@ -1512,102 +251,38 @@ static INPUT_PORTS_START( 39in1 ) PORT_SERVICE_NO_TOGGLE( 0x80000000, IP_ACTIVE_LOW ) INPUT_PORTS_END -uint32_t _39in1_state::screen_update_39in1(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int x = 0; - int y = 0; - - for(y = 0; y <= (m_lcd_regs.lccr2 & PXA255_LCCR2_LPP); y++) - { - uint32_t *d = &bitmap.pix32(y); - for(x = 0; x <= (m_lcd_regs.lccr1 & PXA255_LCCR1_PPL); x++) - { - d[x] = m_pxa255_lcd_palette[m_pxa255_lcd_framebuffer[y*((m_lcd_regs.lccr1 & PXA255_LCCR1_PPL) + 1) + x]]; - } - } - return 0; -} - -/* To be moved to device start of pxa255 upon completion */ -void _39in1_state::pxa255_start() -{ - int index = 0; - - for(index = 0; index < 16; index++) - { - m_dma_regs.dcsr[index] = 0x00000008; - m_dma_regs.timer[index] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(_39in1_state::pxa255_dma_dma_end),this)); - } - - memset(&m_ostimer_regs, 0, sizeof(m_ostimer_regs)); - for(index = 0; index < 4; index++) - { - m_ostimer_regs.osmr[index] = 0; - m_ostimer_regs.timer[index] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(_39in1_state::pxa255_ostimer_match),this)); - } - - memset(&m_intc_regs, 0, sizeof(m_intc_regs)); - - memset(&m_lcd_regs, 0, sizeof(m_lcd_regs)); - m_lcd_regs.dma[0].eof = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(_39in1_state::pxa255_lcd_dma_eof),this)); - m_lcd_regs.dma[1].eof = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(_39in1_state::pxa255_lcd_dma_eof),this)); - m_lcd_regs.trgbr = 0x00aa5500; - m_lcd_regs.tcr = 0x0000754f; -} - void _39in1_state::machine_start() { uint8_t *ROM = memregion("maincpu")->base(); - int i; - - for (i = 0; i < 0x80000; i += 2) + for (int i = 0; i < 0x80000; i += 2) { ROM[i] = bitswap<8>(ROM[i],7,2,5,6,0,3,1,4) ^ bitswap<8>((i>>3)&0xf, 3,2,4,1,4,4,0,4) ^ 0x90; } - - pxa255_start(); } MACHINE_START_MEMBER(_39in1_state,60in1) { + // TODO: Machine is marked as MNW; is this decrypt correct? uint8_t *ROM = memregion("maincpu")->base(); - int i; - - for (i = 0; i < 0x80000; i += 2) + for (int i = 0; i < 0x80000; i += 2) { if ((i%2)==0) { ROM[i] = bitswap<8>(ROM[i],5,1,4,2,0,7,6,3)^bitswap<8>(i, 6,0,4,13,0,5,3,11); } } - - pxa255_start(); } MACHINE_CONFIG_START(_39in1_state::_39in1) - MCFG_DEVICE_ADD("maincpu", PXA255, 200000000) MCFG_DEVICE_PROGRAM_MAP(_39in1_map) - MCFG_DEVICE_VBLANK_INT_DRIVER("screen", _39in1_state, pxa255_vblank_start) - - MCFG_SCREEN_ADD("screen", RASTER) - MCFG_SCREEN_REFRESH_RATE(60) - MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) - MCFG_SCREEN_SIZE(1024, 1024) - MCFG_SCREEN_VISIBLE_AREA(0, 295, 0, 479) - MCFG_SCREEN_UPDATE_DRIVER(_39in1_state, screen_update_39in1) - - MCFG_PALETTE_ADD("palette", 256) MCFG_DEVICE_ADD("eeprom", EEPROM_SERIAL_93C66_16BIT) - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - MCFG_DEVICE_ADD("dac1", DMADAC) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0) - MCFG_DEVICE_ADD("dac2", DMADAC) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0) + MCFG_DEVICE_ADD("pxa_periphs", PXA255_PERIPHERALS, 200000000, "maincpu") + MCFG_PXA255_GPIO0_SET_CALLBACK(WRITE32(*this, _39in1_state, eeprom_set_w)) + MCFG_PXA255_GPIO0_CLEAR_CALLBACK(WRITE32(*this, _39in1_state, eeprom_clear_w)) + MCFG_PXA255_GPIO0_IN_CALLBACK(READ32(*this, _39in1_state, eeprom_r)) MACHINE_CONFIG_END MACHINE_CONFIG_START(_39in1_state::_60in1) @@ -1732,11 +407,11 @@ ROM_START( 19in1 ) ROM_LOAD16_WORD_SWAP( "19in1_eeprom.bin", 0x000, 0x200, NO_DUMP ) ROM_END -GAME(2004, 4in1a, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "4 in 1 MAME bootleg (set 1, ver 3.00)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) -GAME(2004, 4in1b, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "4 in 1 MAME bootleg (set 2)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) -GAME(2004, 19in1, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "19 in 1 MAME bootleg", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) -GAME(2004, 39in1, 0, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "39 in 1 MAME bootleg", MACHINE_IMPERFECT_SOUND) -GAME(2004, 48in1, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "48 in 1 MAME bootleg (set 1, ver 3.09)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) -GAME(2004, 48in1b, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "48 in 1 MAME bootleg (set 2, ver 3.09, alt flash)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) -GAME(2004, 48in1a, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "48 in 1 MAME bootleg (set 3, ver 3.02)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) -GAME(2004, 60in1, 39in1, _60in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "60 in 1 MAME bootleg (ver 3.00)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) +GAME(2004, 4in1a, 39in1, _39in1, 39in1, _39in1_state, driver_init, ROT270, "bootleg", "4 in 1 MAME bootleg (set 1, ver 3.00)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) +GAME(2004, 4in1b, 39in1, _39in1, 39in1, _39in1_state, driver_init, ROT270, "bootleg", "4 in 1 MAME bootleg (set 2)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) +GAME(2004, 19in1, 39in1, _39in1, 39in1, _39in1_state, driver_init, ROT270, "bootleg", "19 in 1 MAME bootleg", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) +GAME(2004, 39in1, 0, _39in1, 39in1, _39in1_state, driver_init, ROT270, "bootleg", "39 in 1 MAME bootleg", MACHINE_IMPERFECT_SOUND) +GAME(2004, 48in1, 39in1, _39in1, 39in1, _39in1_state, driver_init, ROT270, "bootleg", "48 in 1 MAME bootleg (set 1, ver 3.09)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) +GAME(2004, 48in1b, 39in1, _39in1, 39in1, _39in1_state, driver_init, ROT270, "bootleg", "48 in 1 MAME bootleg (set 2, ver 3.09, alt flash)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) +GAME(2004, 48in1a, 39in1, _39in1, 39in1, _39in1_state, driver_init, ROT270, "bootleg", "48 in 1 MAME bootleg (set 3, ver 3.02)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND) +GAME(2004, 60in1, 39in1, _60in1, 39in1, _39in1_state, driver_init, ROT270, "bootleg", "60 in 1 MAME bootleg (ver 3.00)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)