Preliminary hook up of sh3 dma from Haze + flash access code from Luca. (nw)

This commit is contained in:
Scott Stone 2011-10-09 23:09:13 +00:00
parent f8aba531d3
commit 6d00689c35
11 changed files with 1230 additions and 679 deletions

2
.gitattributes vendored
View File

@ -451,6 +451,8 @@ src/emu/cpu/sh4/sh4.h svneol=native#text/plain
src/emu/cpu/sh4/sh4comn.c svneol=native#text/plain
src/emu/cpu/sh4/sh4comn.h svneol=native#text/plain
src/emu/cpu/sh4/sh4dasm.c svneol=native#text/plain
src/emu/cpu/sh4/sh4dmac.c svneol=native#text/plain
src/emu/cpu/sh4/sh4dmac.h svneol=native#text/plain
src/emu/cpu/sh4/sh4regs.h svneol=native#text/plain
src/emu/cpu/sh4/sh4tmu.c svneol=native#text/plain
src/emu/cpu/sh4/sh4tmu.h svneol=native#text/plain

View File

@ -532,7 +532,7 @@ $(CPUOBJ)/sh2/sh2fe.o: $(CPUSRC)/sh2/sh2fe.c \
ifneq ($(filter SH4,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/sh4
CPUOBJS += $(CPUOBJ)/sh4/sh4.o $(CPUOBJ)/sh4/sh4comn.o $(CPUOBJ)/sh4/sh3comn.o $(CPUOBJ)/sh4/sh4tmu.o
CPUOBJS += $(CPUOBJ)/sh4/sh4.o $(CPUOBJ)/sh4/sh4comn.o $(CPUOBJ)/sh4/sh3comn.o $(CPUOBJ)/sh4/sh4tmu.o $(CPUOBJ)/sh4/sh4dmac.o
DASMOBJS += $(CPUOBJ)/sh4/sh4dasm.o
endif
@ -560,6 +560,16 @@ $(CPUOBJ)/sh4/sh4tmu.o: $(CPUSRC)/sh4/sh4tmu.c \
$(CPUSRC)/sh4/sh4comn.h \
$(CPUSRC)/sh4/sh3comn.h
$(CPUOBJ)/sh4/sh4dmac.o: $(CPUSRC)/sh4/sh4dmac.c \
$(CPUSRC)/sh4/sh4dmac.h \
$(CPUSRC)/sh4/sh3comn.c \
$(CPUSRC)/sh4/sh3comn.h \
$(CPUSRC)/sh4/sh4.c \
$(CPUSRC)/sh4/sh4.h \
$(CPUSRC)/sh4/sh4regs.h \
$(CPUSRC)/sh4/sh4comn.h \
$(CPUSRC)/sh4/sh3comn.h
#-------------------------------------------------
# Hudsonsoft 6280
#-------------------------------------------------

View File

@ -6,6 +6,8 @@
#include "sh4comn.h"
#include "sh3comn.h"
#include "sh4tmu.h"
#include "sh4dmac.h"
/* High internal area (ffffxxxx) */
WRITE32_HANDLER( sh3_internal_high_w )
@ -145,6 +147,26 @@ READ32_HANDLER( sh3_internal_r )
switch (offset)
{
case SH3_SAR0_ADDR: return sh4_handle_sar0_addr_r(sh4,mem_mask);
case SH3_SAR1_ADDR: return sh4_handle_sar1_addr_r(sh4,mem_mask);
case SH3_SAR2_ADDR: return sh4_handle_sar2_addr_r(sh4,mem_mask);
case SH3_SAR3_ADDR: return sh4_handle_sar3_addr_r(sh4,mem_mask);
case SH3_DAR0_ADDR: return sh4_handle_dar0_addr_r(sh4,mem_mask);
case SH3_DAR1_ADDR: return sh4_handle_dar1_addr_r(sh4,mem_mask);
case SH3_DAR2_ADDR: return sh4_handle_dar2_addr_r(sh4,mem_mask);
case SH3_DAR3_ADDR: return sh4_handle_dar3_addr_r(sh4,mem_mask);
case SH3_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(sh4,mem_mask);
case SH3_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(sh4,mem_mask);
case SH3_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(sh4,mem_mask);
case SH3_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(sh4,mem_mask);
case SH3_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(sh4,mem_mask);
case SH3_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(sh4,mem_mask);
case SH3_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(sh4,mem_mask);
case SH3_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(sh4,mem_mask);
case SH3_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(sh4,mem_mask)<<16;
case INTEVT2:
{
// logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (INTEVT2)\n",sh4->device->tag(), sh4->pc & AM,(offset *4)+0x4000000,mem_mask);
@ -248,6 +270,25 @@ WRITE32_HANDLER( sh3_internal_w )
switch (offset)
{
case SH3_SAR0_ADDR: sh4_handle_sar0_addr_w(sh4,data,mem_mask); break;
case SH3_SAR1_ADDR: sh4_handle_sar1_addr_w(sh4,data,mem_mask); break;
case SH3_SAR2_ADDR: sh4_handle_sar2_addr_w(sh4,data,mem_mask); break;
case SH3_SAR3_ADDR: sh4_handle_sar3_addr_w(sh4,data,mem_mask); break;
case SH3_DAR0_ADDR: sh4_handle_dar0_addr_w(sh4,data,mem_mask); break;
case SH3_DAR1_ADDR: sh4_handle_dar1_addr_w(sh4,data,mem_mask); break;
case SH3_DAR2_ADDR: sh4_handle_dar2_addr_w(sh4,data,mem_mask); break;
case SH3_DAR3_ADDR: sh4_handle_dar3_addr_w(sh4,data,mem_mask); break;
case SH3_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(sh4,data,mem_mask); break;
case SH3_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(sh4,data,mem_mask); break;
case SH3_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(sh4,data,mem_mask); break;
case SH3_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(sh4,data,mem_mask); break;
case SH3_CHCR0_ADDR: sh4_handle_chcr0_addr_w(sh4,data,mem_mask); break;
case SH3_CHCR1_ADDR: sh4_handle_chcr1_addr_w(sh4,data,mem_mask); break;
case SH3_CHCR2_ADDR: sh4_handle_chcr2_addr_w(sh4,data,mem_mask); break;
case SH3_CHCR3_ADDR: sh4_handle_chcr3_addr_w(sh4,data,mem_mask); break;
case SH3_DMAOR_ADDR: sh4_handle_dmaor_addr_w(sh4,data>>16,mem_mask>>16); break;
case IRR0_IRR1:
{
{

View File

@ -11,6 +11,26 @@
#define INTEVT2 ((0x4000000 - SH3_LOWER_REGBASE)/4)
#define IRR0_IRR1 ((0x4000004 - SH3_LOWER_REGBASE)/4)
#define PINTER_IPRC ((0x4000014 - SH3_LOWER_REGBASE)/4)
#define SH3_SAR0_ADDR ((0x4000020 - SH3_LOWER_REGBASE)/4)
#define SH3_DAR0_ADDR ((0x4000024 - SH3_LOWER_REGBASE)/4)
#define SH3_DMATCR0_ADDR ((0x4000028 - SH3_LOWER_REGBASE)/4)
#define SH3_CHCR0_ADDR ((0x400002c - SH3_LOWER_REGBASE)/4)
#define SH3_SAR1_ADDR ((0x4000030 - SH3_LOWER_REGBASE)/4)
#define SH3_DAR1_ADDR ((0x4000034 - SH3_LOWER_REGBASE)/4)
#define SH3_DMATCR1_ADDR ((0x4000038 - SH3_LOWER_REGBASE)/4)
#define SH3_CHCR1_ADDR ((0x400003c - SH3_LOWER_REGBASE)/4)
#define SH3_SAR2_ADDR ((0x4000040 - SH3_LOWER_REGBASE)/4)
#define SH3_DAR2_ADDR ((0x4000044 - SH3_LOWER_REGBASE)/4)
#define SH3_DMATCR2_ADDR ((0x4000048 - SH3_LOWER_REGBASE)/4)
#define SH3_CHCR2_ADDR ((0x400004c - SH3_LOWER_REGBASE)/4)
#define SH3_SAR3_ADDR ((0x4000050 - SH3_LOWER_REGBASE)/4)
#define SH3_DAR3_ADDR ((0x4000054 - SH3_LOWER_REGBASE)/4)
#define SH3_DMATCR3_ADDR ((0x4000058 - SH3_LOWER_REGBASE)/4)
#define SH3_CHCR3_ADDR ((0x400005c - SH3_LOWER_REGBASE)/4)
#define SH3_DMAOR_ADDR ((0x4000060 - SH3_LOWER_REGBASE)/4)
#define PCCR_PDCR ((0x4000104 - SH3_LOWER_REGBASE)/4)
#define PECR_PFCR ((0x4000108 - SH3_LOWER_REGBASE)/4)
#define PGCR_PHCR ((0x400010c - SH3_LOWER_REGBASE)/4)

View File

@ -3313,7 +3313,14 @@ static CPU_RESET( sh3 )
CPU_RESET_CALL(common_sh4_reset);
sh4->cpu_type = CPU_TYPE_SH3;
sh4->SH4_TCOR0 = 0xffffffff;
sh4->SH4_TCNT0 = 0xffffffff;
sh4->SH4_TCOR1 = 0xffffffff;
sh4->SH4_TCNT1 = 0xffffffff;
sh4->SH4_TCOR2 = 0xffffffff;
sh4->SH4_TCNT2 = 0xffffffff;
}
static CPU_RESET( sh4 )

View File

@ -13,11 +13,11 @@
#include "sh4comn.h"
#include "sh3comn.h"
#include "sh4tmu.h"
#include "sh4dmac.h"
static const int rtcnt_div[8] = { 0, 4, 16, 64, 256, 1024, 2048, 4096 };
static const int daysmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 };
static const UINT32 exception_priority_default[] = {
@ -627,280 +627,11 @@ static TIMER_CALLBACK( sh4_rtc_timer_callback )
}
static TIMER_CALLBACK( sh4_dmac_callback )
{
sh4_state *sh4 = (sh4_state *)ptr;
int channel = param;
if (sh4->cpu_type != CPU_TYPE_SH4)
fatalerror("sh4_dmac_callback uses sh4->m[] with SH3\n");
LOG(("SH4 '%s': DMA %d complete\n", sh4->device->tag(), channel));
sh4->dma_timer_active[channel] = 0;
switch (channel)
{
case 0:
sh4->m[DMATCR0] = 0;
sh4->m[CHCR0] |= CHCR_TE;
if (sh4->m[CHCR0] & CHCR_IE)
sh4_exception_request(sh4, SH4_INTC_DMTE0);
break;
case 1:
sh4->m[DMATCR1] = 0;
sh4->m[CHCR1] |= CHCR_TE;
if (sh4->m[CHCR1] & CHCR_IE)
sh4_exception_request(sh4, SH4_INTC_DMTE1);
break;
case 2:
sh4->m[DMATCR2] = 0;
sh4->m[CHCR2] |= CHCR_TE;
if (sh4->m[CHCR2] & CHCR_IE)
sh4_exception_request(sh4, SH4_INTC_DMTE2);
break;
case 3:
sh4->m[DMATCR3] = 0;
sh4->m[CHCR3] |= CHCR_TE;
if (sh4->m[CHCR3] & CHCR_IE)
sh4_exception_request(sh4, SH4_INTC_DMTE3);
break;
}
}
static int sh4_dma_transfer(sh4_state *sh4, int channel, int timermode, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
{
int incs, incd, size;
UINT32 src, dst, count;
incd = (chcr & CHCR_DM) >> 14;
incs = (chcr & CHCR_SM) >> 12;
size = dmasize[(chcr & CHCR_TS) >> 4];
if(incd == 3 || incs == 3)
{
logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
return 0;
}
src = *sar;
dst = *dar;
count = *dmatcr;
if (!count)
count = 0x1000000;
LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
if (timermode == 1) // timer actvated after a time based on the number of words to transfer
{
sh4->dma_timer_active[channel] = 1;
sh4->dma_timer[channel]->adjust(sh4->device->cycles_to_attotime(2*count+1), channel);
}
else if (timermode == 2) // timer activated immediately
{
sh4->dma_timer_active[channel] = 1;
sh4->dma_timer[channel]->adjust(attotime::zero, channel);
}
src &= AM;
dst &= AM;
switch(size)
{
case 1: // 8 bit
for(;count > 0; count --)
{
if(incs == 2)
src --;
if(incd == 2)
dst --;
sh4->program->write_byte(dst, sh4->program->read_byte(src));
if(incs == 1)
src ++;
if(incd == 1)
dst ++;
}
break;
case 2: // 16 bit
src &= ~1;
dst &= ~1;
for(;count > 0; count --)
{
if(incs == 2)
src -= 2;
if(incd == 2)
dst -= 2;
sh4->program->write_word(dst, sh4->program->read_word(src));
if(incs == 1)
src += 2;
if(incd == 1)
dst += 2;
}
break;
case 8: // 64 bit
src &= ~7;
dst &= ~7;
for(;count > 0; count --)
{
if(incs == 2)
src -= 8;
if(incd == 2)
dst -= 8;
sh4->program->write_qword(dst, sh4->program->read_qword(src));
if(incs == 1)
src += 8;
if(incd == 1)
dst += 8;
}
break;
case 4: // 32 bit
src &= ~3;
dst &= ~3;
for(;count > 0; count --)
{
if(incs == 2)
src -= 4;
if(incd == 2)
dst -= 4;
sh4->program->write_dword(dst, sh4->program->read_dword(src));
if(incs == 1)
src += 4;
if(incd == 1)
dst += 4;
}
break;
case 32:
src &= ~31;
dst &= ~31;
for(;count > 0; count --)
{
if(incs == 2)
src -= 32;
if(incd == 2)
dst -= 32;
sh4->program->write_qword(dst, sh4->program->read_qword(src));
sh4->program->write_qword(dst+8, sh4->program->read_qword(src+8));
sh4->program->write_qword(dst+16, sh4->program->read_qword(src+16));
sh4->program->write_qword(dst+24, sh4->program->read_qword(src+24));
if(incs == 1)
src += 32;
if(incd == 1)
dst += 32;
}
break;
}
*sar = (*sar & !AM) | src;
*dar = (*dar & !AM) | dst;
*dmatcr = count;
return 1;
}
static int sh4_dma_transfer_device(sh4_state *sh4, int channel, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
{
int incs, incd, size, mod;
UINT32 src, dst, count;
incd = (chcr & CHCR_DM) >> 14;
incs = (chcr & CHCR_SM) >> 12;
size = dmasize[(chcr & CHCR_TS) >> 4];
mod = ((chcr & CHCR_RS) >> 8);
if (incd == 3 || incs == 3)
{
logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
return 0;
}
src = *sar;
dst = *dar;
count = *dmatcr;
if (!count)
count = 0x1000000;
LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
sh4->dma_timer_active[channel] = 1;
src &= AM;
dst &= AM;
// remember parameters
sh4->dma_source[channel]=src;
sh4->dma_destination[channel]=dst;
sh4->dma_count[channel]=count;
sh4->dma_wordsize[channel]=size;
sh4->dma_source_increment[channel]=incs;
sh4->dma_destination_increment[channel]=incd;
sh4->dma_mode[channel]=mod;
// inform device its ready to transfer
sh4->io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16));
return 1;
}
static void sh4_dmac_check(sh4_state *sh4, int channel)
{
UINT32 dmatcr, chcr, sar, dar;
if (sh4->cpu_type != CPU_TYPE_SH4)
fatalerror("sh4_dmac_check uses sh4->m[] with SH3\n");
switch (channel)
{
case 0:
sar = sh4->m[SAR0];
dar = sh4->m[DAR0];
chcr = sh4->m[CHCR0];
dmatcr = sh4->m[DMATCR0];
break;
case 1:
sar = sh4->m[SAR1];
dar = sh4->m[DAR1];
chcr = sh4->m[CHCR1];
dmatcr = sh4->m[DMATCR1];
break;
case 2:
sar = sh4->m[SAR2];
dar = sh4->m[DAR2];
chcr = sh4->m[CHCR2];
dmatcr = sh4->m[DMATCR2];
break;
case 3:
sar = sh4->m[SAR3];
dar = sh4->m[DAR3];
chcr = sh4->m[CHCR3];
dmatcr = sh4->m[DMATCR3];
break;
default:
return;
}
if (chcr & sh4->m[DMAOR] & DMAOR_DME)
{
if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6))
return;
if (!sh4->dma_timer_active[channel] && !(chcr & CHCR_TE) && !(sh4->m[DMAOR] & (DMAOR_AE | DMAOR_NMIF)))
{
if (((chcr & CHCR_RS) >> 8) > 3)
sh4_dma_transfer(sh4, channel, 1, chcr, &sar, &dar, &dmatcr);
else if ((sh4->m[DMAOR] & DMAOR_DDT) == 0)
sh4_dma_transfer_device(sh4, channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer
}
}
else
{
if (sh4->dma_timer_active[channel])
{
logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel);
sh4->dma_timer[channel]->adjust(attotime::never, channel);
sh4->dma_timer_active[channel] = 0;
}
}
}
static void sh4_dmac_nmi(sh4_state *sh4) // manage dma when nmi gets asserted
{
int s;
int s;
if (sh4->cpu_type != CPU_TYPE_SH4)
fatalerror("sh4_dmac_nmi uses sh4->m[] with SH3\n");
sh4->m[DMAOR] |= DMAOR_NMIF;
sh4->SH4_DMAOR |= DMAOR_NMIF;
for (s = 0;s < 4;s++)
{
if (sh4->dma_timer_active[s])
@ -935,6 +666,7 @@ void sh4_handler_ipra_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
sh4_exception_recompute(sh4);
}
WRITE32_HANDLER( sh4_internal_w )
{
sh4_state *sh4 = get_safe_token(&space->device());
@ -1089,50 +821,35 @@ WRITE32_HANDLER( sh4_internal_w )
sh4->exception_priority[SH4_INTC_GPOI] = INTPRI((sh4->m[IPRC] & 0xf000) >> 12, SH4_INTC_GPOI);
sh4_exception_recompute(sh4);
break;
// DMA
case SAR0:
case SAR1:
case SAR2:
case SAR3:
case DAR0:
case DAR1:
case DAR2:
case DAR3:
case DMATCR0:
case DMATCR1:
case DMATCR2:
case DMATCR3:
break;
case CHCR0:
sh4_dmac_check(sh4, 0);
break;
case CHCR1:
sh4_dmac_check(sh4, 1);
break;
case CHCR2:
sh4_dmac_check(sh4, 2);
break;
case CHCR3:
sh4_dmac_check(sh4, 3);
break;
case DMAOR:
if ((sh4->m[DMAOR] & DMAOR_AE) && (~old & DMAOR_AE))
sh4->m[DMAOR] &= ~DMAOR_AE;
if ((sh4->m[DMAOR] & DMAOR_NMIF) && (~old & DMAOR_NMIF))
sh4->m[DMAOR] &= ~DMAOR_NMIF;
sh4_dmac_check(sh4, 0);
sh4_dmac_check(sh4, 1);
sh4_dmac_check(sh4, 2);
sh4_dmac_check(sh4, 3);
break;
// Store Queues
/*********************************************************************************************************************
DMAC (DMA Controller)
*********************************************************************************************************************/
case SH4_SAR0_ADDR: sh4_handle_sar0_addr_w(sh4,data,mem_mask); break;
case SH4_SAR1_ADDR: sh4_handle_sar1_addr_w(sh4,data,mem_mask); break;
case SH4_SAR2_ADDR: sh4_handle_sar2_addr_w(sh4,data,mem_mask); break;
case SH4_SAR3_ADDR: sh4_handle_sar3_addr_w(sh4,data,mem_mask); break;
case SH4_DAR0_ADDR: sh4_handle_dar0_addr_w(sh4,data,mem_mask); break;
case SH4_DAR1_ADDR: sh4_handle_dar1_addr_w(sh4,data,mem_mask); break;
case SH4_DAR2_ADDR: sh4_handle_dar2_addr_w(sh4,data,mem_mask); break;
case SH4_DAR3_ADDR: sh4_handle_dar3_addr_w(sh4,data,mem_mask); break;
case SH4_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(sh4,data,mem_mask); break;
case SH4_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(sh4,data,mem_mask); break;
case SH4_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(sh4,data,mem_mask); break;
case SH4_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(sh4,data,mem_mask); break;
case SH4_CHCR0_ADDR: sh4_handle_chcr0_addr_w(sh4,data,mem_mask); break;
case SH4_CHCR1_ADDR: sh4_handle_chcr1_addr_w(sh4,data,mem_mask); break;
case SH4_CHCR2_ADDR: sh4_handle_chcr2_addr_w(sh4,data,mem_mask); break;
case SH4_CHCR3_ADDR: sh4_handle_chcr3_addr_w(sh4,data,mem_mask); break;
case SH4_DMAOR_ADDR: sh4_handle_dmaor_addr_w(sh4,data,mem_mask); break;
/*********************************************************************************************************************
Store Queues
*********************************************************************************************************************/
case QACR0:
case QACR1:
break;
// I/O ports
/*********************************************************************************************************************
I/O
*********************************************************************************************************************/
case PCTRA:
sh4->ioport16_pullup = 0;
sh4->ioport16_direction = 0;
@ -1234,6 +951,26 @@ READ32_HANDLER( sh4_internal_r )
case SH4_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(sh4, mem_mask);
case SH4_TOCR_ADDR: return sh4_handle_tocr_addr_r(sh4, mem_mask); // not supported
case SH4_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(sh4, mem_mask); // not supported
/*********************************************************************************************************************
DMAC (DMA Controller)
*********************************************************************************************************************/
case SH4_SAR0_ADDR: return sh4_handle_sar0_addr_r(sh4,mem_mask);
case SH4_SAR1_ADDR: return sh4_handle_sar1_addr_r(sh4,mem_mask);
case SH4_SAR2_ADDR: return sh4_handle_sar2_addr_r(sh4,mem_mask);
case SH4_SAR3_ADDR: return sh4_handle_sar3_addr_r(sh4,mem_mask);
case SH4_DAR0_ADDR: return sh4_handle_dar0_addr_r(sh4,mem_mask);
case SH4_DAR1_ADDR: return sh4_handle_dar1_addr_r(sh4,mem_mask);
case SH4_DAR2_ADDR: return sh4_handle_dar2_addr_r(sh4,mem_mask);
case SH4_DAR3_ADDR: return sh4_handle_dar3_addr_r(sh4,mem_mask);
case SH4_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(sh4,mem_mask);
case SH4_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(sh4,mem_mask);
case SH4_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(sh4,mem_mask);
case SH4_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(sh4,mem_mask);
case SH4_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(sh4,mem_mask);
case SH4_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(sh4,mem_mask);
case SH4_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(sh4,mem_mask);
case SH4_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(sh4,mem_mask);
case SH4_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(sh4,mem_mask);
/*********************************************************************************************************************
I/O Ports
*********************************************************************************************************************/
@ -1491,270 +1228,6 @@ void sh4_common_init(device_t *device)
sh4->m = auto_alloc_array(device->machine(), UINT32, 16384);
}
// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu
int sh4_dma_data(device_t *device, struct sh4_device_dma *s)
{
UINT32 pos, len, siz;
int channel = s->channel;
void *data = s->buffer;
sh4_state *sh4 = get_safe_token(device);
if (!sh4->dma_timer_active[channel])
return 0;
if (sh4->dma_mode[channel] == 2)
{
// device receives data
len = sh4->dma_count[channel];
if (s->length < len)
len = s->length;
siz = sh4->dma_wordsize[channel];
for (pos = 0;pos < len;pos++) {
switch (siz)
{
case 8:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel] -= 8;
*(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~7);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel] += 8;
break;
case 1:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel]--;
*(UINT8 *)data = sh4->program->read_byte(sh4->dma_source[channel]);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel]++;
break;
case 2:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel] -= 2;
*(UINT16 *)data = sh4->program->read_word(sh4->dma_source[channel] & ~1);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel] += 2;
break;
case 4:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel] -= 4;
*(UINT32 *)data = sh4->program->read_dword(sh4->dma_source[channel] & ~3);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel] += 4;
break;
case 32:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel] -= 32;
*(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~31);
*((UINT64 *)data+1) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+8);
*((UINT64 *)data+2) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+16);
*((UINT64 *)data+3) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+24);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel] += 32;
break;
}
sh4->dma_count[channel]--;
}
if (sh4->dma_count[channel] == 0) // all data transferred ?
{
sh4->dma_timer[channel]->adjust(attotime::zero, channel);
return 2;
}
return 1;
}
else if (sh4->dma_mode[channel] == 3)
{
// device sends data
len = sh4->dma_count[channel];
if (s->length < len)
len = s->length;
siz = sh4->dma_wordsize[channel];
for (pos = 0;pos < len;pos++) {
switch (siz)
{
case 8:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]-=8;
sh4->program->write_qword(sh4->dma_destination[channel] & ~7, *(UINT64 *)data);
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]+=8;
break;
case 1:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]--;
sh4->program->write_byte(sh4->dma_destination[channel], *(UINT8 *)data);
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]++;
break;
case 2:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]-=2;
sh4->program->write_word(sh4->dma_destination[channel] & ~1, *(UINT16 *)data);
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]+=2;
break;
case 4:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]-=4;
sh4->program->write_dword(sh4->dma_destination[channel] & ~3, *(UINT32 *)data);
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]+=4;
break;
case 32:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]-=32;
sh4->program->write_qword(sh4->dma_destination[channel] & ~31, *(UINT64 *)data);
sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+8, *((UINT64 *)data+1));
sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+16, *((UINT64 *)data+2));
sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+24, *((UINT64 *)data+3));
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]+=32;
break;
}
sh4->dma_count[channel]--;
}
if (sh4->dma_count[channel] == 0) // all data transferred ?
{
sh4->dma_timer[channel]->adjust(attotime::zero, channel);
return 2;
}
return 1;
}
else
return 0;
}
// called by drivers to transfer data in a DDT dma. 'device' must be a SH4 cpu
void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s)
{
sh4_state *sh4 = get_safe_token(device);
UINT32 chcr;
UINT32 *p32bits;
UINT64 *p32bytes;
UINT32 pos,len,siz;
if (sh4->cpu_type != CPU_TYPE_SH4)
fatalerror("sh4_dma_ddt uses sh4->m[] with SH3\n");
if (sh4->dma_timer_active[s->channel])
return;
if (s->mode >= 0) {
switch (s->channel)
{
case 0:
if (s->mode & 1)
s->source = sh4->m[SAR0];
if (s->mode & 2)
sh4->m[SAR0] = s->source;
if (s->mode & 4)
s->destination = sh4->m[DAR0];
if (s->mode & 8)
sh4->m[DAR0] = s->destination;
break;
case 1:
if (s->mode & 1)
s->source = sh4->m[SAR1];
if (s->mode & 2)
sh4->m[SAR1] = s->source;
if (s->mode & 4)
s->destination = sh4->m[DAR1];
if (s->mode & 8)
sh4->m[DAR1] = s->destination;
break;
case 2:
if (s->mode & 1)
s->source = sh4->m[SAR2];
if (s->mode & 2)
sh4->m[SAR2] = s->source;
if (s->mode & 4)
s->destination = sh4->m[DAR2];
if (s->mode & 8)
sh4->m[DAR2] = s->destination;
break;
case 3:
default:
if (s->mode & 1)
s->source = sh4->m[SAR3];
if (s->mode & 2)
sh4->m[SAR3] = s->source;
if (s->mode & 4)
s->destination = sh4->m[DAR3];
if (s->mode & 8)
sh4->m[DAR3] = s->destination;
break;
}
switch (s->channel)
{
case 0:
chcr = sh4->m[CHCR0];
len = sh4->m[DMATCR0];
break;
case 1:
chcr = sh4->m[CHCR1];
len = sh4->m[DMATCR1];
break;
case 2:
chcr = sh4->m[CHCR2];
len = sh4->m[DMATCR2];
break;
case 3:
default:
chcr = sh4->m[CHCR3];
len = sh4->m[DMATCR3];
break;
}
if ((s->direction) == 0) {
chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10);
} else {
chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8);
}
siz = dmasize[(chcr >> 4) & 7];
if (siz && (s->size))
if ((len * siz) != (s->length * s->size))
return;
sh4_dma_transfer(sh4, s->channel, 0, chcr, &s->source, &s->destination, &len);
} else {
if (s->size == 4) {
if ((s->direction) == 0) {
len = s->length;
p32bits = (UINT32 *)(s->buffer);
for (pos = 0;pos < len;pos++) {
*p32bits = sh4->program->read_dword(s->source);
p32bits++;
s->source = s->source + 4;
}
} else {
len = s->length;
p32bits = (UINT32 *)(s->buffer);
for (pos = 0;pos < len;pos++) {
sh4->program->write_dword(s->destination, *p32bits);
p32bits++;
s->destination = s->destination + 4;
}
}
}
if (s->size == 32) {
if ((s->direction) == 0) {
len = s->length * 4;
p32bytes = (UINT64 *)(s->buffer);
for (pos = 0;pos < len;pos++) {
*p32bytes = sh4->program->read_qword(s->source);
p32bytes++;
s->destination = s->destination + 8;
}
} else {
len = s->length * 4;
p32bytes = (UINT64 *)(s->buffer);
for (pos = 0;pos < len;pos++) {
sh4->program->write_qword(s->destination, *p32bytes);
p32bytes++;
s->destination = s->destination + 8;
}
}
}
}
}
UINT32 sh4_getsqremap(sh4_state *sh4, UINT32 address)
{
if (!sh4->sh4_mmu_enabled)

View File

@ -101,6 +101,29 @@ typedef struct
UINT32 SH4_IPRC;
// DMAC regs
UINT32 SH4_SAR0;
UINT32 SH4_SAR1;
UINT32 SH4_SAR2;
UINT32 SH4_SAR3;
UINT32 SH4_DAR0;
UINT32 SH4_DAR1;
UINT32 SH4_DAR2;
UINT32 SH4_DAR3;
UINT32 SH4_CHCR0;
UINT32 SH4_CHCR1;
UINT32 SH4_CHCR2;
UINT32 SH4_CHCR3;
UINT32 SH4_DMATCR0;
UINT32 SH4_DMATCR1;
UINT32 SH4_DMATCR2;
UINT32 SH4_DMATCR3;
UINT32 SH4_DMAOR;
// sh3 internal
UINT32 m_sh3internal_upper[0x3000/4];

686
src/emu/cpu/sh4/sh4dmac.c Normal file
View File

@ -0,0 +1,686 @@
/* SHA3/4 DMA Controller */
#include "emu.h"
#include "debugger.h"
#include "sh4.h"
#include "sh4comn.h"
#include "sh3comn.h"
#include "sh4dmac.h"
static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 };
static const int sh3_dmasize[4] = { 1, 2, 4, 16 };
TIMER_CALLBACK( sh4_dmac_callback )
{
sh4_state *sh4 = (sh4_state *)ptr;
int channel = param;
LOG(("SH4 '%s': DMA %d complete\n", sh4->device->tag(), channel));
sh4->dma_timer_active[channel] = 0;
switch (channel)
{
case 0:
sh4->SH4_DMATCR0 = 0;
sh4->SH4_CHCR0 |= CHCR_TE;
if (sh4->SH4_CHCR0 & CHCR_IE)
sh4_exception_request(sh4, SH4_INTC_DMTE0);
break;
case 1:
sh4->SH4_DMATCR1 = 0;
sh4->SH4_CHCR1 |= CHCR_TE;
if (sh4->SH4_CHCR1 & CHCR_IE)
sh4_exception_request(sh4, SH4_INTC_DMTE1);
break;
case 2:
sh4->SH4_DMATCR2 = 0;
sh4->SH4_CHCR2 |= CHCR_TE;
if (sh4->SH4_CHCR2 & CHCR_IE)
sh4_exception_request(sh4, SH4_INTC_DMTE2);
break;
case 3:
sh4->SH4_DMATCR3 = 0;
sh4->SH4_CHCR3 |= CHCR_TE;
if (sh4->SH4_CHCR3 & CHCR_IE)
sh4_exception_request(sh4, SH4_INTC_DMTE3);
break;
}
}
static int sh4_dma_transfer(sh4_state *sh4, int channel, int timermode, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
{
int incs, incd, size;
UINT32 src, dst, count;
incd = (chcr & CHCR_DM) >> 14;
incs = (chcr & CHCR_SM) >> 12;
if (sh4->cpu_type == CPU_TYPE_SH4)
{
size = dmasize[(chcr & CHCR_TS) >> 4];
}
else
{
size = sh3_dmasize[(chcr >> 3) & 3];
}
if(incd == 3 || incs == 3)
{
logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
return 0;
}
src = *sar;
dst = *dar;
count = *dmatcr;
if (!count)
count = 0x1000000;
LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
if (timermode == 1) // timer actvated after a time based on the number of words to transfer
{
sh4->dma_timer_active[channel] = 1;
sh4->dma_timer[channel]->adjust(sh4->device->cycles_to_attotime(2*count+1), channel);
}
else if (timermode == 2) // timer activated immediately
{
sh4->dma_timer_active[channel] = 1;
sh4->dma_timer[channel]->adjust(attotime::zero, channel);
}
src &= AM;
dst &= AM;
switch(size)
{
case 1: // 8 bit
for(;count > 0; count --)
{
if(incs == 2)
src --;
if(incd == 2)
dst --;
sh4->program->write_byte(dst, sh4->program->read_byte(src));
if(incs == 1)
src ++;
if(incd == 1)
dst ++;
}
break;
case 2: // 16 bit
src &= ~1;
dst &= ~1;
for(;count > 0; count --)
{
if(incs == 2)
src -= 2;
if(incd == 2)
dst -= 2;
sh4->program->write_word(dst, sh4->program->read_word(src));
if(incs == 1)
src += 2;
if(incd == 1)
dst += 2;
}
break;
case 8: // 64 bit
src &= ~7;
dst &= ~7;
for(;count > 0; count --)
{
if(incs == 2)
src -= 8;
if(incd == 2)
dst -= 8;
sh4->program->write_qword(dst, sh4->program->read_qword(src));
if(incs == 1)
src += 8;
if(incd == 1)
dst += 8;
}
break;
case 4: // 32 bit
src &= ~3;
dst &= ~3;
for(;count > 0; count --)
{
if(incs == 2)
src -= 4;
if(incd == 2)
dst -= 4;
sh4->program->write_dword(dst, sh4->program->read_dword(src));
if(incs == 1)
src += 4;
if(incd == 1)
dst += 4;
}
break;
case 32:
src &= ~31;
dst &= ~31;
for(;count > 0; count --)
{
if(incs == 2)
src -= 32;
if(incd == 2)
dst -= 32;
sh4->program->write_qword(dst, sh4->program->read_qword(src));
sh4->program->write_qword(dst+8, sh4->program->read_qword(src+8));
sh4->program->write_qword(dst+16, sh4->program->read_qword(src+16));
sh4->program->write_qword(dst+24, sh4->program->read_qword(src+24));
if(incs == 1)
src += 32;
if(incd == 1)
dst += 32;
}
break;
}
*sar = (*sar & !AM) | src;
*dar = (*dar & !AM) | dst;
*dmatcr = count;
return 1;
}
static int sh4_dma_transfer_device(sh4_state *sh4, int channel, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
{
int incs, incd, size, mod;
UINT32 src, dst, count;
incd = (chcr & CHCR_DM) >> 14;
incs = (chcr & CHCR_SM) >> 12;
if (sh4->cpu_type == CPU_TYPE_SH4)
{
size = dmasize[(chcr & CHCR_TS) >> 4];
}
else
{
size = sh3_dmasize[(chcr >> 3) & 3];
}
mod = ((chcr & CHCR_RS) >> 8);
if (incd == 3 || incs == 3)
{
logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
return 0;
}
src = *sar;
dst = *dar;
count = *dmatcr;
if (!count)
count = 0x1000000;
LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
sh4->dma_timer_active[channel] = 1;
src &= AM;
dst &= AM;
// remember parameters
sh4->dma_source[channel]=src;
sh4->dma_destination[channel]=dst;
sh4->dma_count[channel]=count;
sh4->dma_wordsize[channel]=size;
sh4->dma_source_increment[channel]=incs;
sh4->dma_destination_increment[channel]=incd;
sh4->dma_mode[channel]=mod;
// inform device its ready to transfer
sh4->io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16));
return 1;
}
static void sh4_dmac_check(sh4_state *sh4, int channel)
{
UINT32 dmatcr, chcr, sar, dar;
switch (channel)
{
case 0:
sar = sh4->SH4_SAR0;
dar = sh4->SH4_DAR0;
chcr = sh4->SH4_CHCR0;
dmatcr = sh4->SH4_DMATCR0;
break;
case 1:
sar = sh4->SH4_SAR1;
dar = sh4->SH4_DAR1;
chcr = sh4->SH4_CHCR1;
dmatcr = sh4->SH4_DMATCR1;
break;
case 2:
sar = sh4->SH4_SAR2;
dar = sh4->SH4_DAR2;
chcr = sh4->SH4_CHCR2;
dmatcr = sh4->SH4_DMATCR2;
break;
case 3:
sar = sh4->SH4_SAR3;
dar = sh4->SH4_DAR3;
chcr = sh4->SH4_CHCR3;
dmatcr = sh4->SH4_DMATCR3;
break;
default:
return;
}
if (chcr & sh4->SH4_DMAOR & DMAOR_DME)
{
if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6))
return;
if (!sh4->dma_timer_active[channel] && !(chcr & CHCR_TE) && !(sh4->SH4_DMAOR & (DMAOR_AE | DMAOR_NMIF)))
{
if (((chcr & CHCR_RS) >> 8) > 3)
sh4_dma_transfer(sh4, channel, 1, chcr, &sar, &dar, &dmatcr);
else if ((sh4->SH4_DMAOR & DMAOR_DDT) == 0)
sh4_dma_transfer_device(sh4, channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer
}
}
else
{
if (sh4->dma_timer_active[channel])
{
logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel);
sh4->dma_timer[channel]->adjust(attotime::never, channel);
sh4->dma_timer_active[channel] = 0;
}
}
}
// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu
int sh4_dma_data(device_t *device, struct sh4_device_dma *s)
{
UINT32 pos, len, siz;
int channel = s->channel;
void *data = s->buffer;
sh4_state *sh4 = get_safe_token(device);
if (!sh4->dma_timer_active[channel])
return 0;
if (sh4->dma_mode[channel] == 2)
{
// device receives data
len = sh4->dma_count[channel];
if (s->length < len)
len = s->length;
siz = sh4->dma_wordsize[channel];
for (pos = 0;pos < len;pos++) {
switch (siz)
{
case 8:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel] -= 8;
*(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~7);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel] += 8;
break;
case 1:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel]--;
*(UINT8 *)data = sh4->program->read_byte(sh4->dma_source[channel]);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel]++;
break;
case 2:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel] -= 2;
*(UINT16 *)data = sh4->program->read_word(sh4->dma_source[channel] & ~1);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel] += 2;
break;
case 4:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel] -= 4;
*(UINT32 *)data = sh4->program->read_dword(sh4->dma_source[channel] & ~3);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel] += 4;
break;
case 32:
if (sh4->dma_source_increment[channel] == 2)
sh4->dma_source[channel] -= 32;
*(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~31);
*((UINT64 *)data+1) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+8);
*((UINT64 *)data+2) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+16);
*((UINT64 *)data+3) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+24);
if (sh4->dma_source_increment[channel] == 1)
sh4->dma_source[channel] += 32;
break;
}
sh4->dma_count[channel]--;
}
if (sh4->dma_count[channel] == 0) // all data transferred ?
{
sh4->dma_timer[channel]->adjust(attotime::zero, channel);
return 2;
}
return 1;
}
else if (sh4->dma_mode[channel] == 3)
{
// device sends data
len = sh4->dma_count[channel];
if (s->length < len)
len = s->length;
siz = sh4->dma_wordsize[channel];
for (pos = 0;pos < len;pos++) {
switch (siz)
{
case 8:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]-=8;
sh4->program->write_qword(sh4->dma_destination[channel] & ~7, *(UINT64 *)data);
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]+=8;
break;
case 1:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]--;
sh4->program->write_byte(sh4->dma_destination[channel], *(UINT8 *)data);
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]++;
break;
case 2:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]-=2;
sh4->program->write_word(sh4->dma_destination[channel] & ~1, *(UINT16 *)data);
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]+=2;
break;
case 4:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]-=4;
sh4->program->write_dword(sh4->dma_destination[channel] & ~3, *(UINT32 *)data);
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]+=4;
break;
case 32:
if (sh4->dma_destination_increment[channel] == 2)
sh4->dma_destination[channel]-=32;
sh4->program->write_qword(sh4->dma_destination[channel] & ~31, *(UINT64 *)data);
sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+8, *((UINT64 *)data+1));
sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+16, *((UINT64 *)data+2));
sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+24, *((UINT64 *)data+3));
if (sh4->dma_destination_increment[channel] == 1)
sh4->dma_destination[channel]+=32;
break;
}
sh4->dma_count[channel]--;
}
if (sh4->dma_count[channel] == 0) // all data transferred ?
{
sh4->dma_timer[channel]->adjust(attotime::zero, channel);
return 2;
}
return 1;
}
else
return 0;
}
// called by drivers to transfer data in a DDT dma. 'device' must be a SH4 cpu
void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s)
{
sh4_state *sh4 = get_safe_token(device);
UINT32 chcr;
UINT32 *p32bits;
UINT64 *p32bytes;
UINT32 pos,len,siz;
if (sh4->cpu_type != CPU_TYPE_SH4)
fatalerror("sh4_dma_ddt uses sh4->m[] with SH3\n");
if (sh4->dma_timer_active[s->channel])
return;
if (s->mode >= 0) {
switch (s->channel)
{
case 0:
if (s->mode & 1)
s->source = sh4->SH4_SAR0;
if (s->mode & 2)
sh4->SH4_SAR0 = s->source;
if (s->mode & 4)
s->destination = sh4->SH4_DAR0;
if (s->mode & 8)
sh4->SH4_DAR0 = s->destination;
break;
case 1:
if (s->mode & 1)
s->source = sh4->SH4_SAR1;
if (s->mode & 2)
sh4->SH4_SAR1 = s->source;
if (s->mode & 4)
s->destination = sh4->SH4_DAR1;
if (s->mode & 8)
sh4->SH4_DAR1 = s->destination;
break;
case 2:
if (s->mode & 1)
s->source = sh4->SH4_SAR2;
if (s->mode & 2)
sh4->SH4_SAR2 = s->source;
if (s->mode & 4)
s->destination = sh4->SH4_DAR2;
if (s->mode & 8)
sh4->SH4_DAR2 = s->destination;
break;
case 3:
default:
if (s->mode & 1)
s->source = sh4->SH4_SAR3;
if (s->mode & 2)
sh4->SH4_SAR3 = s->source;
if (s->mode & 4)
s->destination = sh4->SH4_DAR3;
if (s->mode & 8)
sh4->SH4_DAR3 = s->destination;
break;
}
switch (s->channel)
{
case 0:
chcr = sh4->SH4_CHCR0;
len = sh4->SH4_DMATCR0;
break;
case 1:
chcr = sh4->SH4_CHCR1;
len = sh4->SH4_DMATCR1;
break;
case 2:
chcr = sh4->SH4_CHCR2;
len = sh4->SH4_DMATCR2;
break;
case 3:
default:
chcr = sh4->SH4_CHCR3;
len = sh4->SH4_DMATCR3;
break;
}
if ((s->direction) == 0) {
chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10);
} else {
chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8);
}
if (sh4->cpu_type == CPU_TYPE_SH4)
{
//siz = dmasize[(chcr & CHCR_TS) >> 4];
siz = dmasize[(chcr >> 4) & 7];
}
else
{
siz = sh3_dmasize[(chcr >> 3) & 3];
}
if (siz && (s->size))
if ((len * siz) != (s->length * s->size))
return;
sh4_dma_transfer(sh4, s->channel, 0, chcr, &s->source, &s->destination, &len);
} else {
if (s->size == 4) {
if ((s->direction) == 0) {
len = s->length;
p32bits = (UINT32 *)(s->buffer);
for (pos = 0;pos < len;pos++) {
*p32bits = sh4->program->read_dword(s->source);
p32bits++;
s->source = s->source + 4;
}
} else {
len = s->length;
p32bits = (UINT32 *)(s->buffer);
for (pos = 0;pos < len;pos++) {
sh4->program->write_dword(s->destination, *p32bits);
p32bits++;
s->destination = s->destination + 4;
}
}
}
if (s->size == 32) {
if ((s->direction) == 0) {
len = s->length * 4;
p32bytes = (UINT64 *)(s->buffer);
for (pos = 0;pos < len;pos++) {
*p32bytes = sh4->program->read_qword(s->source);
p32bytes++;
s->destination = s->destination + 8;
}
} else {
len = s->length * 4;
p32bytes = (UINT64 *)(s->buffer);
for (pos = 0;pos < len;pos++) {
sh4->program->write_qword(s->destination, *p32bytes);
p32bytes++;
s->destination = s->destination + 8;
}
}
}
}
}
void sh4_handle_sar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_SAR0);
}
void sh4_handle_sar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_SAR1);
}
void sh4_handle_sar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_SAR2);
}
void sh4_handle_sar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_SAR3);
}
void sh4_handle_dar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_DAR0);
}
void sh4_handle_dar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_DAR1);
}
void sh4_handle_dar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_DAR2);
}
void sh4_handle_dar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_DAR3);
}
void sh4_handle_dmatcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_DMATCR0);
}
void sh4_handle_dmatcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_DMATCR1);
}
void sh4_handle_dmatcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_DMATCR2);
}
void sh4_handle_dmatcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_DMATCR3);
}
void sh4_handle_chcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_CHCR0);
sh4_dmac_check(sh4, 0);
}
void sh4_handle_chcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_CHCR1);
sh4_dmac_check(sh4, 1);
}
void sh4_handle_chcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_CHCR2);
sh4_dmac_check(sh4, 2);
}
void sh4_handle_chcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
COMBINE_DATA(&sh4->SH4_CHCR3);
sh4_dmac_check(sh4, 3);
}
void sh4_handle_dmaor_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
{
UINT32 old = sh4->SH4_DMAOR;
COMBINE_DATA(&sh4->SH4_DMAOR);
if ((sh4->SH4_DMAOR & DMAOR_AE) && (~old & DMAOR_AE))
sh4->SH4_DMAOR &= ~DMAOR_AE;
if ((sh4->SH4_DMAOR & DMAOR_NMIF) && (~old & DMAOR_NMIF))
sh4->SH4_DMAOR &= ~DMAOR_NMIF;
sh4_dmac_check(sh4, 0);
sh4_dmac_check(sh4, 1);
sh4_dmac_check(sh4, 2);
sh4_dmac_check(sh4, 3);
}
UINT32 sh4_handle_sar0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR0; }
UINT32 sh4_handle_sar1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR1; }
UINT32 sh4_handle_sar2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR2; }
UINT32 sh4_handle_sar3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR3; }
UINT32 sh4_handle_dar0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR0; }
UINT32 sh4_handle_dar1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR1; }
UINT32 sh4_handle_dar2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR2; }
UINT32 sh4_handle_dar3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR3; }
UINT32 sh4_handle_dmatcr0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR0; }
UINT32 sh4_handle_dmatcr1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR1; }
UINT32 sh4_handle_dmatcr2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR2; }
UINT32 sh4_handle_dmatcr3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR3; }
UINT32 sh4_handle_chcr0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR0; }
UINT32 sh4_handle_chcr1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR1; }
UINT32 sh4_handle_chcr2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR2; }
UINT32 sh4_handle_chcr3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR3; }
UINT32 sh4_handle_dmaor_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMAOR; }

63
src/emu/cpu/sh4/sh4dmac.h Normal file
View File

@ -0,0 +1,63 @@
/* SHA3/4 DMA Controller */
/* bit definitions */
#define CHCR_SSA 0xe0000000
#define CHCR_STC 0x10000000
#define CHCR_DSA 0x0e000000
#define CHCR_DTC 0x01000000
#define CHCR_DS 0x00080000
#define CHCR_RL 0x00040000
#define CHCR_AM 0x00020000
#define CHCR_AL 0x00010000
#define CHCR_DM 0x0000c000
#define CHCR_SM 0x00003000
#define CHCR_RS 0x00000f00
#define CHCR_TM 0x00000080
#define CHCR_TS 0x00000070
#define CHCR_IE 0x00000004
#define CHCR_TE 0x00000002
#define CHCR_DE 0x00000001
#define DMAOR_DDT 0x8000
#define DMAOR_PR 0x0300
#define DMAOR_COD 0x0010
#define DMAOR_AE 0x0004
#define DMAOR_NMIF 0x0002
#define DMAOR_DME 0x0001
TIMER_CALLBACK( sh4_dmac_callback );
void sh4_handle_sar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_sar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_sar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_sar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dmatcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dmatcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dmatcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dmatcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_chcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_chcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_chcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_chcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
void sh4_handle_dmaor_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
UINT32 sh4_handle_sar0_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_sar1_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_sar2_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_sar3_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dar0_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dar1_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dar2_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dar3_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dmatcr0_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dmatcr1_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dmatcr2_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dmatcr3_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_chcr0_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_chcr1_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_chcr2_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_chcr3_addr_r(sh4_state *sh4, UINT32 mem_mask);
UINT32 sh4_handle_dmaor_addr_r(sh4_state *sh4, UINT32 mem_mask);

View File

@ -49,23 +49,23 @@
#define GPIOIC 0x3012 /* FF800048 */
#define SDMR2 0x3200 /* FF900000 */
#define SDMR3 0x3280 /* FF940000 */
#define SAR0 0x3400 /* FFA00000 */
#define DAR0 0x3401 /* FFA00004 */
#define DMATCR0 0x3402 /* FFA00008 */
#define CHCR0 0x3403 /* FFA0000C */
#define SAR1 0x3404 /* FFA00010 */
#define DAR1 0x3405 /* FFA00014 */
#define DMATCR1 0x3406 /* FFA00018 */
#define CHCR1 0x3407 /* FFA0001C */
#define SAR2 0x3408 /* FFA00020 */
#define DAR2 0x3409 /* FFA00024 */
#define DMATCR2 0x340A /* FFA00028 */
#define CHCR2 0x340B /* FFA0002C */
#define SAR3 0x340C /* FFA00030 */
#define DAR3 0x340D /* FFA00034 */
#define DMATCR3 0x340E /* FFA00038 */
#define CHCR3 0x340F /* FFA0003C */
#define DMAOR 0x3410 /* FFA00040 */
#define SH4_SAR0_ADDR 0x3400 /* FFA00000 */
#define SH4_DAR0_ADDR 0x3401 /* FFA00004 */
#define SH4_DMATCR0_ADDR 0x3402 /* FFA00008 */
#define SH4_CHCR0_ADDR 0x3403 /* FFA0000C */
#define SH4_SAR1_ADDR 0x3404 /* FFA00010 */
#define SH4_DAR1_ADDR 0x3405 /* FFA00014 */
#define SH4_DMATCR1_ADDR 0x3406 /* FFA00018 */
#define SH4_CHCR1_ADDR 0x3407 /* FFA0001C */
#define SH4_SAR2_ADDR 0x3408 /* FFA00020 */
#define SH4_DAR2_ADDR 0x3409 /* FFA00024 */
#define SH4_DMATCR2_ADDR 0x340A /* FFA00028 */
#define SH4_CHCR2_ADDR 0x340B /* FFA0002C */
#define SH4_SAR3_ADDR 0x340C /* FFA00030 */
#define SH4_DAR3_ADDR 0x340D /* FFA00034 */
#define SH4_DMATCR3_ADDR 0x340E /* FFA00038 */
#define SH4_CHCR3_ADDR 0x340F /* FFA0003C */
#define SH4_DMAOR_ADDR 0x3410 /* FFA00040 */
#define SAR4 0x3414 /* FFA00050 */
#define DAR4 0x3415 /* FFA00054 */
#define DMATCR4 0x3416 /* FFA00058 */
@ -158,30 +158,7 @@
#define SDINT 0x3E05 /* FFF00014 */
#define SIZEREGS 15878
/* bit definitions */
#define CHCR_SSA 0xe0000000
#define CHCR_STC 0x10000000
#define CHCR_DSA 0x0e000000
#define CHCR_DTC 0x01000000
#define CHCR_DS 0x00080000
#define CHCR_RL 0x00040000
#define CHCR_AM 0x00020000
#define CHCR_AL 0x00010000
#define CHCR_DM 0x0000c000
#define CHCR_SM 0x00003000
#define CHCR_RS 0x00000f00
#define CHCR_TM 0x00000080
#define CHCR_TS 0x00000070
#define CHCR_IE 0x00000004
#define CHCR_TE 0x00000002
#define CHCR_DE 0x00000001
#define DMAOR_DDT 0x8000
#define DMAOR_PR 0x0300
#define DMAOR_COD 0x0010
#define DMAOR_AE 0x0004
#define DMAOR_NMIF 0x0002
#define DMAOR_DME 0x0001
#define MMUCR_LRUI 0xfc000000
#define MMUCR_URB 0x00fc0000

View File

@ -6,12 +6,12 @@
#include "cpu/sh4/sh4.h"
class cavesh3_state : public driver_device
{
public:
cavesh3_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) { }
};
@ -26,37 +26,22 @@ SCREEN_UPDATE(cavesh3)
static READ64_HANDLER( serial_rtc_eeprom_r )
static READ32_HANDLER( cavesh3_blitter_r )
{
if (mem_mask & U64(0xff00ffffffffffff))
{
logerror("unknown serial_rtc_eeprom_r access %08x%08x\n",(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
}
// UINT64 ret = space->machine().rand();
static UINT32 i = 0;
i^=0xffffffff;
return (UINT64)(space->machine().rand()&0xff)<<(32+16);
}
static WRITE64_HANDLER( serial_rtc_eeprom_w )
{
if (mem_mask & U64(0xff000000ffffffff))
{
logerror("unknown serial_rtc_eeprom_w access %08x%08x\n",(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
}
}
static READ64_HANDLER( cavesh3_blitter_r )
{
UINT64 ret = space->machine().rand();
logerror("cavesh3_blitter_r access at %08x (%08x) - mem_mask %08x%08x\n",offset, offset*8, (UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
logerror("%08x cavesh3_blitter_r access at %08x (%08x) - mem_mask %08x\n",cpu_get_pc(&space->device()), offset, offset*4, mem_mask);
switch (offset)
{
case 0x2:
return ret ^ (ret<<32);
case 0x4:
return i;
case 0x9:
return 0;
default:
@ -71,9 +56,9 @@ static READ64_HANDLER( cavesh3_blitter_r )
}
static WRITE64_HANDLER( cavesh3_blitter_w )
static WRITE32_HANDLER( cavesh3_blitter_w )
{
logerror("cavesh3_blitter_w access at %08x (%08x) - %08x%08x %08x%08x\n",offset, offset*8, (UINT32)(data>>32),(UINT32)(data&0xffffffff),(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
logerror("%08x cavesh3_blitter_w access at %08x (%08x) - %08x %08x\n",cpu_get_pc(&space->device()),offset, offset*8, data,mem_mask);
}
static READ64_HANDLER( ymz2770c_z_r )
@ -88,32 +73,307 @@ static WRITE64_HANDLER( ymz2770c_z_w )
}
static READ64_HANDLER( cavesh3_nand_r )
// FLASH
#define FLASH_PAGE_SIZE (2048+64)
UINT8 flash_page_data[FLASH_PAGE_SIZE];
typedef enum { STATE_IDLE = 0, STATE_READ, STATE_READ_ID, STATE_READ_STATUS } flash_state_t;
static const char *flash_state_name[] = { "IDLE", "READ", "READ_ID", "READ_STATUS" };
static flash_state_t flash_state;
static UINT8 flash_enab;
static UINT8 flash_cmd_seq;
static UINT32 flash_cmd_prev;
static UINT8 flash_addr_seq;
static UINT8 flash_read_seq;
static UINT16 flash_row, flash_col;
static UINT16 flash_page_addr;
static UINT16 flash_page_index;
static void flash_hard_reset(running_machine &machine)
{
if (mem_mask & U64(0x00ffffffffffffff))
// logerror("%08x FLASH: RESET\n", cpuexec_describe_context(machine));
flash_state = STATE_READ;
flash_cmd_prev = -1;
flash_cmd_seq = 0;
flash_addr_seq = 0;
flash_read_seq = 0;
flash_row = 0;
flash_col = 0;
memset(flash_page_data, 0, FLASH_PAGE_SIZE);
flash_page_addr = 0;
flash_page_index = 0;
}
static WRITE8_HANDLER( flash_enab_w )
{
logerror("%08x FLASH: enab = %02X\n", cpu_get_pc(&space->device()), data);
//flash_enab = data;
flash_enab = 1; // todo, why does it get turned off again instantly?
}
static void flash_change_state(running_machine &machine, flash_state_t state)
{
flash_state = state;
flash_cmd_prev = -1;
flash_cmd_seq = 0;
flash_read_seq = 0;
flash_addr_seq = 0;
logerror("flash_change_state - FLASH: state = %s\n", flash_state_name[state]);
}
static WRITE8_HANDLER( flash_cmd_w )
{
if (!flash_enab)
return;
logerror("%08x FLASH: cmd = %02X (prev = %02X)\n", cpu_get_pc(&space->device()), data, flash_cmd_prev);
if (flash_cmd_prev == -1)
{
logerror("unknown cavesh3_nand_r access %08x%08x\n",(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
flash_cmd_prev = data;
switch (data)
{
case 0x00: // READ
flash_addr_seq = 0;
break;
case 0x70: // READ STATUS
flash_change_state( space->machine(), STATE_READ_STATUS );
break;
case 0x90: // READ ID
flash_change_state( space->machine(), STATE_READ_ID );
break;
case 0xff: // RESET
flash_change_state( space->machine(), STATE_IDLE );
break;
default:
{
logerror("%08x FLASH: unknown cmd1 = %02X\n", cpu_get_pc(&space->device()), data);
}
}
}
else
{
logerror("cavesh3_nand_r access %08x%08x\n",(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
}
switch (flash_cmd_prev)
{
case 0x00: // READ
if (data == 0x30)
{
UINT8 *region = space->machine().region( "game" )->base();
return 0;// (UINT64)(space->machine().rand()&0xff)<<(32+16+8);
memcpy(flash_page_data, region + flash_row * FLASH_PAGE_SIZE, FLASH_PAGE_SIZE);
flash_page_addr = flash_col;
flash_page_index = flash_row;
flash_change_state( space->machine(), STATE_READ );
logerror("%08x FLASH: caching page = %04X\n", cpu_get_pc(&space->device()), flash_row);
}
break;
default:
{
logerror("%08x FLASH: unknown cmd2 = %02X (cmd1 = %02X)\n", cpu_get_pc(&space->device()), data, flash_cmd_prev);
}
}
}
}
static WRITE64_HANDLER( cavesh3_nand_w )
static WRITE8_HANDLER( flash_addr_w )
{
if (mem_mask & U64(0xff0000ffffffffff))
if (!flash_enab)
return;
logerror("%08x FLASH: addr = %02X (seq = %02X)\n", cpu_get_pc(&space->device()), data, flash_addr_seq);
switch( flash_addr_seq++ )
{
logerror("unknown cavesh3_nand_w access %08x%08x %08x%08x\n",(UINT32)(data>>32),(UINT32)(data&0xffffffff),(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
}
else
{
logerror("cavesh3_nand_w access %08x%08x %08x%08x\n",(UINT32)(data>>32),(UINT32)(data&0xffffffff),(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
case 0:
flash_col = (flash_col & 0xff00) | data;
break;
case 1:
flash_col = (flash_col & 0x00ff) | (data << 8);
break;
case 2:
flash_row = (flash_row & 0xff00) | data;
break;
case 3:
flash_row = (flash_row & 0x00ff) | (data << 8);
flash_addr_seq = 0;
break;
}
}
static READ8_HANDLER( flash_io_r )
{
UINT8 data = 0x00;
UINT32 old;
if (!flash_enab)
return 0xff;
switch (flash_state)
{
case STATE_READ_ID:
old = flash_read_seq;
switch( flash_read_seq++ )
{
case 0:
data = 0xEC; // Manufacturer
break;
case 1:
data = 0xF1; // Device
break;
case 2:
data = 0x00; // XX
break;
case 3:
data = 0x15; // Flags
flash_read_seq = 0;
break;
}
logerror("%08x FLASH: read %02X from id(%02X)\n", cpu_get_pc(&space->device()), data, old);
break;
case STATE_READ:
if (flash_page_addr > FLASH_PAGE_SIZE-1)
flash_page_addr = FLASH_PAGE_SIZE-1;
old = flash_page_addr;
data = flash_page_data[flash_page_addr++];
// logerror("%08x FLASH: read data %02X from addr %03X (page %04X)\n", cpu_get_pc(&space->device()), data, old, flash_page_index);
break;
case STATE_READ_STATUS:
// bit 7 = writeable, bit 6 = ready, bit 5 = ready/true ready, bit 1 = fail(N-1), bit 0 = fail
data = 0xe0;
logerror("%08x FLASH: read status %02X\n", cpu_get_pc(&space->device()), data);
break;
default:
{
logerror("%08x FLASH: unknown read in state %s\n", cpu_get_pc(&space->device()), flash_state_name[flash_state]);
}
}
return data;
}
/*
static READ8_HANDLER( flash_ready_r )
{
return 1;
}
// FLASH interface
static READ32_HANDLER( ibara_flash_ready_r )
{
// 400012a contains test bit (shown in service mode)
return ((flash_ready_r(space, offset) ? 0x20 : 0x00) << 24) |
input_port_read(space->machine(), "PORT_EF");
}
*/
static READ8_HANDLER( ibara_flash_io_r )
{
switch (offset)
{
default:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
// logerror("ibara_flash_io_r offset %04x\n", offset);
return 0xff;
case 0x00:
return flash_io_r(space,offset);
}
}
static WRITE8_HANDLER( ibara_flash_io_w )
{
switch (offset)
{
default:
case 0x00:
case 0x03:
logerror("unknown ibara_flash_io_w offset %04x data %02x\n", offset, data); // 03 enable/disable fgpa access?
break;
case 0x01:
flash_cmd_w(space, offset, data);
break;
case 0x2:
flash_addr_w(space, offset, data);
break;
}
}
static READ8_HANDLER( serial_rtc_eeprom_r )
{
switch (offset)
{
default:
logerror("unknown serial_rtc_eeprom_r access offset %02x\n", offset);
return 0xff;
}
}
static WRITE8_HANDLER( serial_rtc_eeprom_w )
{
switch (offset)
{
case 0x01:
// data & 0x00010000 = DATA
// data & 0x00020000 = CLK
// data & 0x00040000 = CE
break;
case 0x03:
flash_enab_w(space,offset,data);
return;
default:
logerror("unknown serial_rtc_eeprom_w access offset %02x data %02x\n",offset, data);
break;
}
}
static ADDRESS_MAP_START( cavesh3_map, AS_PROGRAM, 64 )
AM_RANGE(0x00000000, 0x001fffff) AM_ROM AM_REGION("maincpu", 0)
@ -124,10 +384,10 @@ static ADDRESS_MAP_START( cavesh3_map, AS_PROGRAM, 64 )
AM_RANGE(0x0c000000, 0x0c7fffff) AM_RAM // work RAM
AM_RANGE(0x0c800000, 0x0cffffff) AM_RAM // mirror of above on type B boards, extra ram on type D
AM_RANGE(0x10000000, 0x10000007) AM_READWRITE(cavesh3_nand_r, cavesh3_nand_w)
AM_RANGE(0x10000000, 0x10000007) AM_READWRITE8(ibara_flash_io_r, ibara_flash_io_w, U64(0xffffffffffffffff))
AM_RANGE(0x10400000, 0x10400007) AM_READWRITE(ymz2770c_z_r, ymz2770c_z_w)
AM_RANGE(0x10C00000, 0x10C00007) AM_READWRITE(serial_rtc_eeprom_r, serial_rtc_eeprom_w)
AM_RANGE(0x18000000, 0x18000057) AM_READWRITE(cavesh3_blitter_r, cavesh3_blitter_w)
AM_RANGE(0x10C00000, 0x10C00007) AM_READWRITE8(serial_rtc_eeprom_r, serial_rtc_eeprom_w, U64(0xffffffffffffffff))
AM_RANGE(0x18000000, 0x18000057) AM_READWRITE32(cavesh3_blitter_r, cavesh3_blitter_w, U64(0xffffffffffffffff))
AM_RANGE(0xf0000000, 0xf0ffffff) AM_RAM // mem mapped cache (sh3 internal?)
/* 0xffffe000, 0xffffffff SH3 Internal Regs 2 */
@ -143,26 +403,12 @@ static INPUT_PORTS_START( cavesh3 )
INPUT_PORTS_END
#define CAVE_CPU_CLOCK 133333333
#define CAVE_CPU_CLOCK 12800000 * 8
static const struct sh4_config sh4cpu_config = { 1, 0, 1, 0, 0, 0, 1, 1, 0, CAVE_CPU_CLOCK };
static IRQ_CALLBACK(cavesh3_int_callback)
{
if (irqline == 4)
{
return 0;
}
else
{
logerror("irqline %02x\n",irqline);
return 0;
}
}
static INTERRUPT_GEN(cavesh3_interrupt)
{
@ -171,9 +417,11 @@ static INTERRUPT_GEN(cavesh3_interrupt)
static MACHINE_RESET( cavesh3 )
{
device_set_irq_callback(machine.device("maincpu"), cavesh3_int_callback);
flash_enab = 0;
flash_hard_reset(machine);
}
static MACHINE_CONFIG_START( cavesh3, cavesh3_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", SH3BE, CAVE_CPU_CLOCK)
@ -375,6 +623,7 @@ ROM_END
GAME( 2004, mushisam, 0, cavesh3, cavesh3, 0, ROT0, "Cave", "Mushihime Sama (2004/10/12 MASTER VER.)", GAME_NOT_WORKING | GAME_NO_SOUND )
GAME( 2004, mushisama, mushisam, cavesh3, cavesh3, 0, ROT0, "Cave", "Mushihime Sama (2004/10/12 MASTER VER)", GAME_NOT_WORKING | GAME_NO_SOUND )
GAME( 2005, espgal2, 0, cavesh3, cavesh3, 0, ROT0, "Cave", "EspGaluda II (2005/11/14 MASTER VER)", GAME_NOT_WORKING | GAME_NO_SOUND )