From b5aacf68ce507f41f71e7456dc24ca508edc0c06 Mon Sep 17 00:00:00 2001 From: Ryan Holtz Date: Sat, 25 Jul 2009 09:48:51 +0000 Subject: [PATCH] Fleshed out some Intel PXA255 peripherals. 39in1 now kicks off a palette DMA and a framebuffer DMA, services the resulting interrupts, and repeats, but does not yet write any palette data or framebuffer data other than 0. [MooglyGuy] --- src/mame/drivers/39in1.c | 959 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 944 insertions(+), 15 deletions(-) diff --git a/src/mame/drivers/39in1.c b/src/mame/drivers/39in1.c index 0df0954e271..30a286e0b84 100644 --- a/src/mame/drivers/39in1.c +++ b/src/mame/drivers/39in1.c @@ -22,30 +22,932 @@ #include "driver.h" #include "video/generic.h" #include "cpu/arm7/arm7.h" +#include "cpu/arm7/arm7core.h" -static UINT32 counter_timer; +#define VERBOSE_LEVEL ( 3 ) -// free-running 3.something MHz counter. this is a complete hack. -static READ32_HANDLER( os_timer_counter_r ) +INLINE void ATTR_PRINTF(3,4) verboselog( running_machine *machine, int n_level, const char *s_fmt, ... ) { - UINT32 ret; - - ret = counter_timer; - counter_timer += 0x300; - - return ret; + 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", cpuexec_describe_context(machine), buf ); + } } -// intel docs says nothing's here, but code at e4010 begs to differ -static READ32_HANDLER( unknown_r ) +/* + + PXA255 DMA registers (placeholder) + + pg. 151 to 182, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +#define PXA255_DMA_BASE_ADDR (0x40000000) +#define PXA255_DCSR0 (PXA255_DMA_BASE_ADDR + 0x00000000) +#define PXA255_DCSR1 (PXA255_DMA_BASE_ADDR + 0x00000004) +#define PXA255_DCSR2 (PXA255_DMA_BASE_ADDR + 0x00000008) +#define PXA255_DCSR3 (PXA255_DMA_BASE_ADDR + 0x0000000c) +#define PXA255_DCSR4 (PXA255_DMA_BASE_ADDR + 0x00000010) +#define PXA255_DCSR5 (PXA255_DMA_BASE_ADDR + 0x00000014) +#define PXA255_DCSR6 (PXA255_DMA_BASE_ADDR + 0x00000018) +#define PXA255_DCSR7 (PXA255_DMA_BASE_ADDR + 0x0000001c) +#define PXA255_DCSR8 (PXA255_DMA_BASE_ADDR + 0x00000020) +#define PXA255_DCSR9 (PXA255_DMA_BASE_ADDR + 0x00000024) +#define PXA255_DCSR10 (PXA255_DMA_BASE_ADDR + 0x00000028) +#define PXA255_DCSR11 (PXA255_DMA_BASE_ADDR + 0x0000002c) +#define PXA255_DCSR12 (PXA255_DMA_BASE_ADDR + 0x00000030) +#define PXA255_DCSR13 (PXA255_DMA_BASE_ADDR + 0x00000034) +#define PXA255_DCSR14 (PXA255_DMA_BASE_ADDR + 0x00000038) +#define PXA255_DCSR15 (PXA255_DMA_BASE_ADDR + 0x0000003c) +/* More DMA registers TODO */ + +static READ32_HANDLER( pxa255_dma_r ) { - return 2; // TST #$2 + verboselog( space->machine, 0, "pxa255_dma_r: Placeholder functionality. Read: %08x & %08x\n", PXA255_DMA_BASE_ADDR | (offset << 2), mem_mask ); + /* TODO: Everything placeholder, DCSR3 just needs to flag that it's ready to accept data so everything boots. */ + 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: + return 0x00000008; // Report channel as stopped + default: + break; + } + return 0; +} + +/* + + PXA255 OS Timer registers + + pg. 138 to 142, PXA255 Processor Developers Manual [278693-002].pdf + +*/ + +#define PXA255_OSTMR_BASE_ADDR (0x40a00000) +#define PXA255_OSMR0 (PXA255_OSTMR_BASE_ADDR + 0x00000000) +#define PXA255_OSMR1 (PXA255_OSTMR_BASE_ADDR + 0x00000004) +#define PXA255_OSMR2 (PXA255_OSTMR_BASE_ADDR + 0x00000008) +#define PXA255_OSMR3 (PXA255_OSTMR_BASE_ADDR + 0x0000000c) +#define PXA255_OSCR (PXA255_OSTMR_BASE_ADDR + 0x00000010) +#define PXA255_OSSR (PXA255_OSTMR_BASE_ADDR + 0x00000014) + #define PXA255_OSSR_M0 (0x00000001) + #define PXA255_OSSR_M1 (0x00000002) + #define PXA255_OSSR_M2 (0x00000004) + #define PXA255_OSSR_M3 (0x00000008) +#define PXA255_OWER (PXA255_OSTMR_BASE_ADDR + 0x00000018) +#define PXA255_OIER (PXA255_OSTMR_BASE_ADDR + 0x0000001c) + #define PXA255_OIER_E0 (0x00000001) + #define PXA255_OIER_E1 (0x00000002) + #define PXA255_OIER_E2 (0x00000004) + #define PXA255_OIER_E3 (0x00000008) + +typedef struct +{ + UINT32 osmr0; + UINT32 osmr1; + UINT32 osmr2; + UINT32 osmr3; + UINT32 oscr; + UINT32 ossr; + UINT32 ower; + UINT32 oier; +} PXA255_OSTMR_Regs; + +static PXA255_OSTMR_Regs ostimer_regs; + +static READ32_HANDLER( pxa255_ostimer_r ) +{ + switch(PXA255_OSTMR_BASE_ADDR | (offset << 2)) + { + case PXA255_OSMR0: + verboselog( space->machine, 3, "pxa255_ostimer_r: OS Timer Match Register 0: %08x & %08x\n", ostimer_regs.osmr0, mem_mask ); + return ostimer_regs.osmr0; + case PXA255_OSMR1: + verboselog( space->machine, 3, "pxa255_ostimer_r: OS Timer Match Register 1: %08x & %08x\n", ostimer_regs.osmr1, mem_mask ); + return ostimer_regs.osmr1; + case PXA255_OSMR2: + verboselog( space->machine, 3, "pxa255_ostimer_r: OS Timer Match Register 2: %08x & %08x\n", ostimer_regs.osmr2, mem_mask ); + return ostimer_regs.osmr2; + case PXA255_OSMR3: + verboselog( space->machine, 3, "pxa255_ostimer_r: OS Timer Match Register 3: %08x & %08x\n", ostimer_regs.osmr3, mem_mask ); + return ostimer_regs.osmr3; + case PXA255_OSCR: + verboselog( space->machine, 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: + verboselog( space->machine, 3, "pxa255_ostimer_r: OS Timer Status Register: %08x & %08x\n", ostimer_regs.ossr, mem_mask ); + return ostimer_regs.ossr; + case PXA255_OWER: + verboselog( space->machine, 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: + verboselog( space->machine, 3, "pxa255_ostimer_r: OS Timer Interrupt Enable Register: %08x & %08x\n", ostimer_regs.oier, mem_mask ); + return ostimer_regs.oier; + default: + verboselog( space->machine, 0, "pxa255_ostimer_r: Unknown address: %08x\n", PXA255_OSTMR_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + + +static WRITE32_HANDLER( pxa255_ostimer_w ) +{ + switch(PXA255_OSTMR_BASE_ADDR | (offset << 2)) + { + case PXA255_OSMR0: + verboselog( space->machine, 3, "pxa255_ostimer_w: OS Timer Match Register 0: %08x & %08x\n", data, mem_mask ); + ostimer_regs.osmr0 = data; + break; + case PXA255_OSMR1: + verboselog( space->machine, 3, "pxa255_ostimer_w: OS Timer Match Register 1: %08x & %08x\n", data, mem_mask ); + ostimer_regs.osmr1 = data; + break; + case PXA255_OSMR2: + verboselog( space->machine, 3, "pxa255_ostimer_w: OS Timer Match Register 2: %08x & %08x\n", data, mem_mask ); + ostimer_regs.osmr2 = data; + break; + case PXA255_OSMR3: + verboselog( space->machine, 3, "pxa255_ostimer_w: OS Timer Match Register 3: %08x & %08x\n", data, mem_mask ); + ostimer_regs.osmr3 = data; + break; + case PXA255_OSCR: + verboselog( space->machine, 3, "pxa255_ostimer_w: OS Timer Count Register: %08x & %08x\n", data, mem_mask ); + ostimer_regs.oscr = data; + break; + case PXA255_OSSR: + verboselog( space->machine, 3, "pxa255_ostimer_w: OS Timer Status Register: %08x & %08x\n", data, mem_mask ); + ostimer_regs.ossr &= ~data; + break; + case PXA255_OWER: + verboselog( space->machine, 3, "pxa255_ostimer_w: OS Timer Watchdog Enable Register: %08x & %08x\n", data, mem_mask ); + ostimer_regs.ower = data & 0x00000001; + break; + case PXA255_OIER: + verboselog( space->machine, 3, "pxa255_ostimer_w: OS Timer Interrupt Enable Register: %08x & %08x\n", data, mem_mask ); + ostimer_regs.oier = data & 0x0000000f; + break; + default: + verboselog( space->machine, 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 + +*/ + +#define PXA255_INTC_BASE_ADDR (0x40d00000) +#define PXA255_ICIP (PXA255_INTC_BASE_ADDR + 0x00000000) +#define PXA255_ICMR (PXA255_INTC_BASE_ADDR + 0x00000004) +#define PXA255_ICLR (PXA255_INTC_BASE_ADDR + 0x00000008) +#define PXA255_ICFP (PXA255_INTC_BASE_ADDR + 0x0000000c) +#define PXA255_ICPR (PXA255_INTC_BASE_ADDR + 0x00000010) +#define PXA255_ICCR (PXA255_INTC_BASE_ADDR + 0x00000014) + +#define PXA255_INT_HUART (1 << 7) +#define PXA255_INT_GPIO0 (1 << 8) +#define PXA255_INT_GPIO1 (1 << 9) +#define PXA255_INT_GPIO84_2 (1 << 10) +#define PXA255_INT_USB (1 << 11) +#define PXA255_INT_PMU (1 << 12) +#define PXA255_INT_I2S (1 << 13) +#define PXA255_INT_AC97 (1 << 14) +#define PXA255_INT_NETWORK (1 << 16) +#define PXA255_INT_LCD (1 << 17) +#define PXA255_INT_I2C (1 << 18) +#define PXA255_INT_ICP (1 << 19) +#define PXA255_INT_STUART (1 << 20) +#define PXA255_INT_BTUART (1 << 21) +#define PXA255_INT_FFUART (1 << 22) +#define PXA255_INT_MMC (1 << 23) +#define PXA255_INT_SSP (1 << 24) +#define PXA255_INT_DMA (1 << 25) +#define PXA255_INT_OSTIMER0 (1 << 26) +#define PXA255_INT_OSTIMER1 (1 << 27) +#define PXA255_INT_OSTIMER2 (1 << 28) +#define PXA255_INT_OSTIMER3 (1 << 29) +#define PXA255_INT_RTC_HZ (1 << 30) +#define PXA255_INT_RTC_ALARM (1 << 31) + +typedef struct +{ + UINT32 icip; + UINT32 icmr; + UINT32 iclr; + UINT32 icfp; + UINT32 icpr; + UINT32 iccr; +} PXA255_INTC_Regs; + +static PXA255_INTC_Regs intc_regs; + +static void pxa255_update_interrupts(running_machine *machine) +{ + intc_regs.icfp = (intc_regs.icpr & intc_regs.icmr) & intc_regs.iclr; + intc_regs.icip = (intc_regs.icpr & intc_regs.icmr) & (~intc_regs.iclr); + cputag_set_input_line(machine, "maincpu", ARM7_FIRQ_LINE, intc_regs.icfp ? ASSERT_LINE : CLEAR_LINE); + cputag_set_input_line(machine, "maincpu", ARM7_IRQ_LINE, intc_regs.icip ? ASSERT_LINE : CLEAR_LINE); +} + +static void pxa255_set_irq_line(running_machine *machine, UINT32 line, int state) +{ + intc_regs.icpr &= ~line; + intc_regs.icpr |= state ? line : 0; + pxa255_update_interrupts(machine); +} + +static READ32_HANDLER( pxa255_intc_r ) +{ + switch(PXA255_INTC_BASE_ADDR | (offset << 2)) + { + case PXA255_ICIP: + verboselog( space->machine, 3, "pxa255_intc_r: Interrupt Controller IRQ Pending Register: %08x & %08x\n", intc_regs.icip, mem_mask ); + return intc_regs.icip; + case PXA255_ICMR: + verboselog( space->machine, 3, "pxa255_intc_r: Interrupt Controller Mask Register: %08x & %08x\n", intc_regs.icmr, mem_mask ); + return intc_regs.icmr; + case PXA255_ICLR: + verboselog( space->machine, 3, "pxa255_intc_r: Interrupt Controller Level Register: %08x & %08x\n", intc_regs.iclr, mem_mask ); + return intc_regs.iclr; + case PXA255_ICFP: + verboselog( space->machine, 3, "pxa255_intc_r: Interrupt Controller FIQ Pending Register: %08x & %08x\n", intc_regs.icfp, mem_mask ); + return intc_regs.icfp; + case PXA255_ICPR: + verboselog( space->machine, 3, "pxa255_intc_r: Interrupt Controller Pending Register: %08x & %08x\n", intc_regs.icpr, mem_mask ); + return intc_regs.icpr; + case PXA255_ICCR: + verboselog( space->machine, 3, "pxa255_intc_r: Interrupt Controller Control Register: %08x & %08x\n", intc_regs.iccr, mem_mask ); + return intc_regs.iccr; + default: + verboselog( space->machine, 0, "pxa255_intc_r: Unknown address: %08x\n", PXA255_INTC_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +static WRITE32_HANDLER( pxa255_intc_w ) +{ + switch(PXA255_INTC_BASE_ADDR | (offset << 2)) + { + case PXA255_ICIP: + verboselog( space->machine, 3, "pxa255_intc_w: (Invalid Write) Interrupt Controller IRQ Pending Register: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_ICMR: + verboselog( space->machine, 3, "pxa255_intc_w: Interrupt Controller Mask Register: %08x & %08x\n", data, mem_mask ); + intc_regs.icmr = data & 0xfffe7f00; + break; + case PXA255_ICLR: + verboselog( space->machine, 3, "pxa255_intc_w: Interrupt Controller Level Register: %08x & %08x\n", data, mem_mask ); + intc_regs.iclr = data & 0xfffe7f00; + break; + case PXA255_ICFP: + verboselog( space->machine, 3, "pxa255_intc_w: (Invalid Write) Interrupt Controller FIQ Pending Register: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_ICPR: + verboselog( space->machine, 3, "pxa255_intc_w: (Invalid Write) Interrupt Controller Pending Register: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_ICCR: + verboselog( space->machine, 3, "pxa255_intc_w: Interrupt Controller Control Register: %08x & %08x\n", data, mem_mask ); + intc_regs.iccr = data & 0x00000001; + break; + default: + verboselog( space->machine, 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 + +*/ + +#define PXA255_GPIO_BASE_ADDR (0x40E00000) +#define PXA255_GPLR0 (PXA255_GPIO_BASE_ADDR + 0x00000000) +#define PXA255_GPLR1 (PXA255_GPIO_BASE_ADDR + 0x00000004) +#define PXA255_GPLR2 (PXA255_GPIO_BASE_ADDR + 0x00000008) +#define PXA255_GPDR0 (PXA255_GPIO_BASE_ADDR + 0x0000000c) +#define PXA255_GPDR1 (PXA255_GPIO_BASE_ADDR + 0x00000010) +#define PXA255_GPDR2 (PXA255_GPIO_BASE_ADDR + 0x00000014) +#define PXA255_GPSR0 (PXA255_GPIO_BASE_ADDR + 0x00000018) +#define PXA255_GPSR1 (PXA255_GPIO_BASE_ADDR + 0x0000001c) +#define PXA255_GPSR2 (PXA255_GPIO_BASE_ADDR + 0x00000020) +#define PXA255_GPCR0 (PXA255_GPIO_BASE_ADDR + 0x00000024) +#define PXA255_GPCR1 (PXA255_GPIO_BASE_ADDR + 0x00000028) +#define PXA255_GPCR2 (PXA255_GPIO_BASE_ADDR + 0x0000002c) +#define PXA255_GRER0 (PXA255_GPIO_BASE_ADDR + 0x00000030) +#define PXA255_GRER1 (PXA255_GPIO_BASE_ADDR + 0x00000034) +#define PXA255_GRER2 (PXA255_GPIO_BASE_ADDR + 0x00000038) +#define PXA255_GFER0 (PXA255_GPIO_BASE_ADDR + 0x0000003c) +#define PXA255_GFER1 (PXA255_GPIO_BASE_ADDR + 0x00000040) +#define PXA255_GFER2 (PXA255_GPIO_BASE_ADDR + 0x00000044) +#define PXA255_GEDR0 (PXA255_GPIO_BASE_ADDR + 0x00000048) +#define PXA255_GEDR1 (PXA255_GPIO_BASE_ADDR + 0x0000004c) +#define PXA255_GEDR2 (PXA255_GPIO_BASE_ADDR + 0x00000050) +#define PXA255_GAFR0_L (PXA255_GPIO_BASE_ADDR + 0x00000054) +#define PXA255_GAFR0_U (PXA255_GPIO_BASE_ADDR + 0x00000058) +#define PXA255_GAFR1_L (PXA255_GPIO_BASE_ADDR + 0x0000005c) +#define PXA255_GAFR1_U (PXA255_GPIO_BASE_ADDR + 0x00000060) +#define PXA255_GAFR2_L (PXA255_GPIO_BASE_ADDR + 0x00000064) +#define PXA255_GAFR2_U (PXA255_GPIO_BASE_ADDR + 0x00000068) + +typedef struct +{ + UINT32 gplr0; // GPIO Pin-Leve + UINT32 gplr1; + UINT32 gplr2; + + UINT32 gpdr0; + UINT32 gpdr1; + UINT32 gpdr2; + + UINT32 gpsr0; + UINT32 gpsr1; + UINT32 gpsr2; + + UINT32 gpcr0; + UINT32 gpcr1; + UINT32 gpcr2; + + UINT32 grer0; + UINT32 grer1; + UINT32 grer2; + + UINT32 gfer0; + UINT32 gfer1; + UINT32 gfer2; + + UINT32 gedr0; + UINT32 gedr1; + UINT32 gedr2; + + UINT32 gafr0l; + UINT32 gafr0u; + UINT32 gafr1l; + UINT32 gafr1u; + UINT32 gafr2l; + UINT32 gafr2u; +} PXA255_GPIO_Regs; + +static PXA255_GPIO_Regs gpio_regs; + +static READ32_HANDLER( pxa255_gpio_r ) +{ + switch(PXA255_GPIO_BASE_ADDR | (offset << 2)) + { + case PXA255_GPLR0: + verboselog( space->machine, 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); // Must be on. Probably a DIP switch. + case PXA255_GPLR1: + verboselog( space->machine, 3, "pxa255_gpio_r: *Not Yet Implemented* GPIO Pin-Level Register 1: %08x & %08x\n", gpio_regs.gplr1, mem_mask ); + return gpio_regs.gplr1; + case PXA255_GPLR2: + verboselog( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 0: %08x & %08x\n", mame_rand(space->machine), mem_mask ); + return mame_rand(space->machine); + case PXA255_GPSR1: + verboselog( space->machine, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 1: %08x & %08x\n", mame_rand(space->machine), mem_mask ); + return mame_rand(space->machine); + case PXA255_GPSR2: + verboselog( space->machine, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Set Register 2: %08x & %08x\n", mame_rand(space->machine), mem_mask ); + return mame_rand(space->machine); + case PXA255_GPCR0: + verboselog( space->machine, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 0: %08x & %08x\n", mame_rand(space->machine), mem_mask ); + return mame_rand(space->machine); + case PXA255_GPCR1: + verboselog( space->machine, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 1: %08x & %08x\n", mame_rand(space->machine), mem_mask ); + return mame_rand(space->machine); + case PXA255_GPCR2: + verboselog( space->machine, 3, "pxa255_gpio_r: (Invalid Read) GPIO Pin Output Clear Register 2: %08x & %08x\n", mame_rand(space->machine), mem_mask ); + return mame_rand(space->machine); + case PXA255_GRER0: + verboselog( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 3, "pxa255_gpio_r: GPIO Alternate Function Register 2 Upper: %08x & %08x\n", gpio_regs.gafr2u, mem_mask ); + return gpio_regs.gafr2u; + default: + verboselog( space->machine, 0, "pxa255_gpio_r: Unknown address: %08x\n", PXA255_GPIO_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +static WRITE32_HANDLER( pxa255_gpio_w ) +{ + switch(PXA255_GPIO_BASE_ADDR | (offset << 2)) + { + case PXA255_GPLR0: + verboselog( space->machine, 3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 0: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_GPLR1: + verboselog( space->machine, 3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 1: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_GPLR2: + verboselog( space->machine, 3, "pxa255_gpio_w: (Invalid Write) GPIO Pin-Level Register 2: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_GPDR0: + verboselog( space->machine, 3, "pxa255_gpio_w: GPIO Pin Direction Register 0: %08x & %08x\n", data, mem_mask ); + gpio_regs.gpdr0 = data; + break; + case PXA255_GPDR1: + verboselog( space->machine, 3, "pxa255_gpio_w: GPIO Pin Direction Register 1: %08x & %08x\n", data, mem_mask ); + gpio_regs.gpdr1 = data; + break; + case PXA255_GPDR2: + verboselog( space->machine, 3, "pxa255_gpio_w: GPIO Pin Direction Register 2: %08x & %08x\n", data, mem_mask ); + gpio_regs.gpdr2 = data; + break; + case PXA255_GPSR0: + verboselog( space->machine, 3, "pxa255_gpio_w: GPIO Pin Output Set Register 0: %08x & %08x\n", data, mem_mask ); + gpio_regs.gpsr0 |= data & gpio_regs.gpdr0; + break; + case PXA255_GPSR1: + verboselog( space->machine, 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( space->machine, 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( space->machine, 3, "pxa255_gpio_w: GPIO Pin Output Clear Register 0: %08x & %08x\n", data, mem_mask ); + gpio_regs.gpsr0 &= ~(data & gpio_regs.gpdr0); + break; + case PXA255_GPCR1: + verboselog( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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 + +*/ + +#define PXA255_LCD_BASE_ADDR (0x44000000) +#define PXA255_LCCR0 (PXA255_LCD_BASE_ADDR + 0x00000000) + #define PXA255_LCCR0_OUM (0x00200000) + #define PXA255_LCCR0_BM (0x00100000) + #define PXA255_LCCR0_PDD (0x000ff000) + #define PXA255_LCCR0_QDM (0x00000800) + #define PXA255_LCCR0_DIS (0x00000400) + #define PXA255_LCCR0_DPD (0x00000200) + #define PXA255_LCCR0_PAS (0x00000080) + #define PXA255_LCCR0_EFM (0x00000040) + #define PXA255_LCCR0_IUM (0x00000020) + #define PXA255_LCCR0_SFM (0x00000010) + #define PXA255_LCCR0_LDM (0x00000008) + #define PXA255_LCCR0_SDS (0x00000004) + #define PXA255_LCCR0_CMS (0x00000002) + #define PXA255_LCCR0_ENB (0x00000001) +#define PXA255_LCCR1 (PXA255_LCD_BASE_ADDR + 0x00000004) +#define PXA255_LCCR2 (PXA255_LCD_BASE_ADDR + 0x00000008) +#define PXA255_LCCR3 (PXA255_LCD_BASE_ADDR + 0x0000000c) +#define PXA255_FBR0 (PXA255_LCD_BASE_ADDR + 0x00000020) +#define PXA255_FBR1 (PXA255_LCD_BASE_ADDR + 0x00000024) +#define PXA255_LCSR (PXA255_LCD_BASE_ADDR + 0x00000038) + #define PXA255_LCSR_LDD (0x00000001) + #define PXA255_LCSR_SOF (0x00000002) + #define PXA255_LCSR_BER (0x00000004) + #define PXA255_LCSR_ABC (0x00000008) + #define PXA255_LCSR_IUL (0x00000010) + #define PXA255_LCSR_IUU (0x00000020) + #define PXA255_LCSR_OU (0x00000040) + #define PXA255_LCSR_QD (0x00000080) + #define PXA255_LCSR_EOF (0x00000100) + #define PXA255_LCSR_BS (0x00000200) + #define PXA255_LCSR_SINT (0x00000400) +#define PXA255_LIIDR (PXA255_LCD_BASE_ADDR + 0x0000003c) +#define PXA255_TRGBR (PXA255_LCD_BASE_ADDR + 0x00000040) +#define PXA255_TCR (PXA255_LCD_BASE_ADDR + 0x00000044) +#define PXA255_FDADR0 (PXA255_LCD_BASE_ADDR + 0x00000200) +#define PXA255_FSADR0 (PXA255_LCD_BASE_ADDR + 0x00000204) +#define PXA255_FIDR0 (PXA255_LCD_BASE_ADDR + 0x00000208) +#define PXA255_LDCMD0 (PXA255_LCD_BASE_ADDR + 0x0000020c) + #define PXA255_LDCMD_SOFINT (0x00400000) + #define PXA255_LDCMD_EOFINT (0x00200000) +#define PXA255_FDADR1 (PXA255_LCD_BASE_ADDR + 0x00000210) +#define PXA255_FSADR1 (PXA255_LCD_BASE_ADDR + 0x00000214) +#define PXA255_FIDR1 (PXA255_LCD_BASE_ADDR + 0x00000218) +#define PXA255_LDCMD1 (PXA255_LCD_BASE_ADDR + 0x0000021c) + +typedef struct +{ + UINT32 fdadr; + UINT32 fsadr; + UINT32 fidr; + UINT32 ldcmd; + emu_timer *eof; +} PXA255_LCD_DMA_Regs; + +typedef struct +{ + UINT32 lccr0; + UINT32 lccr1; + UINT32 lccr2; + UINT32 lccr3; + + UINT32 pad0[4]; + + UINT32 fbr0; + UINT32 fbr1; + + UINT32 pad1[4]; + + UINT32 lcsr; + UINT32 liidr; + UINT32 trgbr; + UINT32 tcr; + + UINT32 pad2[110]; + + PXA255_LCD_DMA_Regs dma[2]; +} PXA255_LCD_Regs; + +static PXA255_LCD_Regs lcd_regs; + +static void pxa255_lcd_initiate_dma(const address_space* space, UINT32 address, int channel) +{ + lcd_regs.dma[channel].fdadr = memory_read_dword_32le(space, address); + lcd_regs.dma[channel].fsadr = memory_read_dword_32le(space, address + 0x04); + lcd_regs.dma[channel].fidr = memory_read_dword_32le(space, address + 0x08); + lcd_regs.dma[channel].ldcmd = memory_read_dword_32le(space, address + 0x0c); + verboselog( space->machine, 3, "pxa255_lcd_initiate_dma, address = %08x, channel = %d\n", address, channel); + verboselog( space->machine, 3, " DMA Frame Descriptor: %08x\n", lcd_regs.dma[channel].fdadr ); + verboselog( space->machine, 3, " DMA Frame Source Address: %08x\n", lcd_regs.dma[channel].fsadr ); + verboselog( space->machine, 3, " DMA Frame ID: %08x\n", lcd_regs.dma[channel].fidr ); + verboselog( space->machine, 3, " DMA Command: %08x\n", lcd_regs.dma[channel].ldcmd ); +} + +static void pxa255_lcd_irq_check(running_machine *machine) +{ + 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(machine, PXA255_INT_LCD, 1); + } + else + { + pxa255_set_irq_line(machine, PXA255_INT_LCD, 0); + } +} + +static READ32_HANDLER( pxa255_lcd_r ) +{ + switch(PXA255_LCD_BASE_ADDR | (offset << 2)) + { + case PXA255_LCCR0: // 0x44000000 + verboselog( space->machine, 3, "pxa255_lcd_r: LCD Control 0: %08x & %08x\n", lcd_regs.lccr0, mem_mask ); + return lcd_regs.lccr0; + case PXA255_LCCR1: // 0x44000004 + verboselog( space->machine, 3, "pxa255_lcd_r: LCD Control 1: %08x & %08x\n", lcd_regs.lccr1, mem_mask ); + return lcd_regs.lccr1; + case PXA255_LCCR2: // 0x44000008 + verboselog( space->machine, 3, "pxa255_lcd_r: LCD Control 2: %08x & %08x\n", lcd_regs.lccr2, mem_mask ); + return lcd_regs.lccr2; + case PXA255_LCCR3: // 0x4400000c + verboselog( space->machine, 3, "pxa255_lcd_r: LCD Control 3: %08x & %08x\n", lcd_regs.lccr3, mem_mask ); + return lcd_regs.lccr3; + case PXA255_FBR0: // 0x44000020 + verboselog( space->machine, 3, "pxa255_lcd_r: LCD Frame Branch Register 0: %08x & %08x\n", lcd_regs.fbr0, mem_mask ); + return lcd_regs.fbr0; + case PXA255_FBR1: // 0x44000024 + verboselog( space->machine, 3, "pxa255_lcd_r: LCD Frame Branch Register 1: %08x & %08x\n", lcd_regs.fbr1, mem_mask ); + return lcd_regs.fbr1; + case PXA255_LCSR: // 0x44000038 + verboselog( space->machine, 3, "pxa255_lcd_r: LCD Status Register: %08x & %08x\n", lcd_regs.lcsr, mem_mask ); + return lcd_regs.lcsr; + case PXA255_LIIDR: // 0x4400003c + verboselog( space->machine, 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( space->machine, 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( space->machine, 3, "pxa255_lcd_r: TMED RGB Seed Register: %08x & %08x\n", lcd_regs.tcr, mem_mask ); + return lcd_regs.tcr; + case PXA255_FDADR0: // 0x44000200 + verboselog( space->machine, 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( space->machine, 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( space->machine, 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 + verboselog( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 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( space->machine, 0, "pxa255_lcd_r: Unknown address: %08x\n", PXA255_LCD_BASE_ADDR | (offset << 2)); + break; + } + return 0; +} + +static WRITE32_HANDLER( pxa255_lcd_w ) +{ + switch(PXA255_LCD_BASE_ADDR | (offset << 2)) + { + case PXA255_LCCR0: // 0x44000000 + verboselog( space->machine, 3, "pxa255_lcd_w: LCD Control 0: %08x & %08x\n", data, mem_mask ); + lcd_regs.lccr0 = data & 0x00fffeff; + break; + case PXA255_LCCR1: // 0x44000004 + verboselog( space->machine, 3, "pxa255_lcd_w: LCD Control 1: %08x & %08x\n", data, mem_mask ); + lcd_regs.lccr1 = data; + break; + case PXA255_LCCR2: // 0x44000008 + verboselog( space->machine, 3, "pxa255_lcd_w: LCD Control 2: %08x & %08x\n", data, mem_mask ); + lcd_regs.lccr2 = data; + break; + case PXA255_LCCR3: // 0x4400000c + verboselog( space->machine, 3, "pxa255_lcd_w: LCD Control 3: %08x & %08x\n", data, mem_mask ); + lcd_regs.lccr3 = data; + break; + case PXA255_FBR0: // 0x44000020 + verboselog( space->machine, 3, "pxa255_lcd_w: LCD Frame Branch Register 0: %08x & %08x\n", data, mem_mask ); + lcd_regs.fbr0 = data & 2; + if(data & 1) + { + pxa255_lcd_initiate_dma(space, data & 0xfffffff0, 0); + lcd_regs.fbr0 |= memory_read_dword_32le(space, data & 0xfffffff0) & 0xfffffff0; + if(!(lcd_regs.lccr0 & PXA255_LCCR0_BM)) + { + lcd_regs.lcsr |= PXA255_LCSR_BS; + pxa255_lcd_irq_check(space->machine); + } + } + break; + case PXA255_FBR1: // 0x44000024 + verboselog( space->machine, 3, "pxa255_lcd_w: LCD Frame Branch Register 1: %08x & %08x\n", data, mem_mask ); + lcd_regs.fbr1 = data & 2; + if(data & 1) + { + pxa255_lcd_initiate_dma(space, data & 0xfffffff0, 1); + lcd_regs.fbr1 |= memory_read_dword_32le(space, data & 0xfffffff0) & 0xfffffff0; + if(!(lcd_regs.lccr0 & PXA255_LCCR0_BM)) + { + lcd_regs.lcsr |= PXA255_LCSR_BS; + pxa255_lcd_irq_check(space->machine); + } + } + break; + case PXA255_LCSR: // 0x44000038 + verboselog( space->machine, 3, "pxa255_lcd_w: LCD Controller Status Register: %08x & %08x\n", data, mem_mask ); + lcd_regs.lcsr &= ~data; + pxa255_lcd_irq_check(space->machine); + break; + case PXA255_LIIDR: // 0x4400003c + verboselog( space->machine, 3, "pxa255_lcd_w: LCD Controller Interrupt ID Register: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_TRGBR: // 0x44000040 + verboselog( space->machine, 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( space->machine, 3, "pxa255_lcd_w: TMED Control Register: %08x & %08x\n", data, mem_mask ); + lcd_regs.tcr = data & 0x00004fff; + break; + case PXA255_FDADR0: // 0x44000200 + verboselog( space->machine, 3, "pxa255_lcd_w: LCD DMA Frame Descriptor Address Register 0: %08x & %08x\n", data, mem_mask ); + pxa255_lcd_initiate_dma(space, data & 0xfffffff0, 0); + break; + case PXA255_FSADR0: // 0x44000204 + verboselog( space->machine, 3, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame Source Address Register 0: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_FIDR0: // 0x44000208 + verboselog( space->machine, 3, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame ID Register 0: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_LDCMD0: // 0x4400020c + verboselog( space->machine, 3, "pxa255_lcd_w: (Invalid Write) LCD DMA Command Register 0: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_FDADR1: // 0x44000210 + verboselog( space->machine, 3, "pxa255_lcd_w: LCD DMA Frame Descriptor Address Register 1: %08x & %08x\n", data, mem_mask ); + pxa255_lcd_initiate_dma(space, data & 0xfffffff0, 1); + break; + case PXA255_FSADR1: // 0x44000214 + verboselog( space->machine, 3, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame Source Address Register 1: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_FIDR1: // 0x44000218 + verboselog( space->machine, 3, "pxa255_lcd_w: (Invalid Write) LCD DMA Frame ID Register 1: %08x & %08x\n", data, mem_mask ); + break; + case PXA255_LDCMD1: // 0x4400021c + verboselog( space->machine, 3, "pxa255_lcd_w: (Invalid Write) LCD DMA Command Register 1: %08x & %08x\n", data, mem_mask ); + break; + default: + verboselog( space->machine, 0, "pxa255_lcd_w: Unknown address: %08x = %08x & %08x\n", PXA255_LCD_BASE_ADDR | (offset << 2), data, mem_mask); + break; + } +} + +static TIMER_CALLBACK( pxa255_lcd_dma_eof ) +{ + printf( "LCD EOF: %d\n", param ); + lcd_regs.liidr = lcd_regs.dma[param].fidr; + lcd_regs.lcsr |= PXA255_LCSR_EOF; + pxa255_lcd_irq_check(machine); +} + +static INTERRUPT_GEN( pxa255_vblank_start ) +{ + if(lcd_regs.lccr0 & PXA255_LCCR0_ENB) + { + // Mark the start of the current DMA frame as appropriate + int channel = 0; + for(channel = 0; channel < 2; channel++) + { + if(lcd_regs.dma[channel].fdadr != 0) + { + if(lcd_regs.dma[channel].ldcmd & PXA255_LDCMD_SOFINT) + { + printf( "LCD SOF: %d\n", channel ); + lcd_regs.liidr = lcd_regs.dma[channel].fidr; + lcd_regs.lcsr |= PXA255_LCSR_SOF; + pxa255_lcd_irq_check(device->machine); + } + if(lcd_regs.dma[channel].ldcmd & PXA255_LDCMD_EOFINT) + { + attotime period = attotime_mul(ATTOTIME_IN_HZ(200000000), lcd_regs.dma[channel].ldcmd & 0x000fffff); + + timer_adjust_oneshot(lcd_regs.dma[channel].eof, period, channel); + } + } + } + } } static ADDRESS_MAP_START( 39in1_map, ADDRESS_SPACE_PROGRAM, 32 ) AM_RANGE(0x00000000, 0x0007ffff) AM_ROM - AM_RANGE(0x40a00010, 0x40a00013) AM_READ( os_timer_counter_r ) - AM_RANGE(0x40e00000, 0x40e00003) AM_READ( unknown_r ) + AM_RANGE(0x40000000, 0x400002ff) AM_READ( pxa255_dma_r ) + AM_RANGE(0x40a00000, 0x40a0001f) AM_READWRITE( pxa255_ostimer_r, pxa255_ostimer_w ) + AM_RANGE(0x40d00000, 0x40d00017) AM_READWRITE( pxa255_intc_r, pxa255_intc_w ) + AM_RANGE(0x40e00000, 0x40e0006b) AM_READWRITE( pxa255_gpio_r, pxa255_gpio_w ) + AM_RANGE(0x44000000, 0x4400021f) AM_READWRITE( pxa255_lcd_r, pxa255_lcd_w ) AM_RANGE(0xa0000000, 0xa3ffffff) AM_RAM ADDRESS_MAP_END @@ -57,6 +959,32 @@ static VIDEO_UPDATE( 39in1 ) return 0; } +/* To be moved to DEVICE_START( pxa255 ) upon completion */ +static void pxa255_start(running_machine *machine) +{ + //pxa255_t* pxa255 = pxa255_get_safe_token( device ); + + //pxa255->iface = device->static_config; + + ostimer_regs.osmr0 = ostimer_regs.osmr1 = ostimer_regs.osmr2 = ostimer_regs.osmr3 = 0; + ostimer_regs.oscr = ostimer_regs.ossr = ostimer_regs.ower = ostimer_regs.oier = 0; + + intc_regs.icmr = intc_regs.iclr = intc_regs.iccr = intc_regs.icip = intc_regs.icfp = intc_regs.icpr = 0; + + lcd_regs.lccr0 = lcd_regs.lccr1 = lcd_regs.lccr2 = lcd_regs.lccr3 = 0; + lcd_regs.dma[0].fdadr = lcd_regs.dma[1].fdadr = 0; + lcd_regs.dma[0].fsadr = lcd_regs.dma[1].fsadr = 0; + lcd_regs.dma[0].fidr = lcd_regs.dma[1].fidr = 0; + lcd_regs.dma[0].ldcmd = lcd_regs.dma[1].ldcmd = 0; + lcd_regs.dma[0].eof = timer_alloc(machine, pxa255_lcd_dma_eof, 0); + lcd_regs.dma[1].eof = timer_alloc(machine, pxa255_lcd_dma_eof, 0); + lcd_regs.fbr0 = lcd_regs.fbr1 = lcd_regs.lcsr = lcd_regs.liidr = 0; + lcd_regs.trgbr = 0x00aa5500; + lcd_regs.tcr = 0x0000754f; + + //pxa255_register_state_save(device); +} + static MACHINE_START(39in1) { UINT8 *ROM = memory_region(machine, "maincpu"); @@ -67,12 +995,13 @@ static MACHINE_START(39in1) ROM[i] = BITSWAP8(ROM[i],7,2,5,6,0,3,1,4) ^ BITSWAP8((i>>3)&0xf, 3,2,4,1,4,4,0,4) ^ 0x90; } - counter_timer = 0x300; + pxa255_start(machine); } static MACHINE_DRIVER_START( 39in1 ) MDRV_CPU_ADD("maincpu", PXA255, 200000000) MDRV_CPU_PROGRAM_MAP(39in1_map) + MDRV_CPU_VBLANK_INT("screen", pxa255_vblank_start) MDRV_PALETTE_LENGTH(32768)