mirror of https://github.com/PCSX2/pcsx2.git
DMAC: Improve DMA Stall handling (#3701)
SIF: Implemented SIF0 and SIF1 DMA Stall handling Cleaned up some of the handling of DMA Stalls on the other channels
This commit is contained in:
parent
a5cc8efb10
commit
40d02400ca
|
@ -400,12 +400,12 @@ void GIFdma()
|
||||||
{
|
{
|
||||||
// stalled.
|
// stalled.
|
||||||
// We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
|
// We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
|
||||||
//Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gifch.madr, psHu32(DMAC_STADR));
|
//DevCon.Warning("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gifch.madr, psHu32(DMAC_STADR));
|
||||||
gif.prevcycles = gif.gscycles;
|
gif.prevcycles = gif.gscycles;
|
||||||
gifch.tadr -= 16;
|
gifch.tadr -= 16;
|
||||||
gifch.qwc = 0;
|
gifch.qwc = 0;
|
||||||
hwDmacIrq(DMAC_STALL_SIS);
|
hwDmacIrq(DMAC_STALL_SIS);
|
||||||
GifDMAInt(gif.gscycles);
|
GifDMAInt(128);
|
||||||
gif.gscycles = 0;
|
gif.gscycles = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,8 +226,9 @@ void IPU0dma()
|
||||||
ipu0ch.qwc -= readsize; // note: qwc is u16
|
ipu0ch.qwc -= readsize; // note: qwc is u16
|
||||||
|
|
||||||
|
|
||||||
if (dmacRegs.ctrl.STS == STS_fromIPU) // STS == fromIPU
|
if (dmacRegs.ctrl.STS == STS_fromIPU && ipu0ch.qwc == 0) // STS == fromIPU
|
||||||
{
|
{
|
||||||
|
//DevCon.Warning("fromIPU Stall Control");
|
||||||
dmacRegs.stadr.ADDR = ipu0ch.madr;
|
dmacRegs.stadr.ADDR = ipu0ch.madr;
|
||||||
switch (dmacRegs.ctrl.STD)
|
switch (dmacRegs.ctrl.STD)
|
||||||
{
|
{
|
||||||
|
@ -271,6 +272,10 @@ __fi void dmaIPU0() // fromIPU
|
||||||
hwDmacIrq(DMAC_FROM_IPU);
|
hwDmacIrq(DMAC_FROM_IPU);
|
||||||
}
|
}
|
||||||
//if (dmacRegs.ctrl.STS == STS_fromIPU) DevCon.Warning("DMA Stall enabled on IPU0");
|
//if (dmacRegs.ctrl.STS == STS_fromIPU) DevCon.Warning("DMA Stall enabled on IPU0");
|
||||||
|
|
||||||
|
if (dmacRegs.ctrl.STS == STS_fromIPU) // STS == fromIPU - Initial settings
|
||||||
|
dmacRegs.stadr.ADDR = ipu0ch.madr;
|
||||||
|
|
||||||
IPU_INT_FROM( 64 );
|
IPU_INT_FROM( 64 );
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,14 @@ int _SPR0chain()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spr0ch.qwc == 0 && dmacRegs.ctrl.STS == STS_fromSPR)
|
||||||
|
{
|
||||||
|
if (spr0ch.chcr.MOD == NORMAL_MODE || ((spr0ch.chcr.TAG >> 28) & 0x7) == TAG_CNTS)
|
||||||
|
{
|
||||||
|
//DevCon.Warning("SPR0 %s Stall Control", spr0ch.chcr.MOD == NORMAL_MODE ? "Normal" : "Chain");
|
||||||
|
dmacRegs.stadr.ADDR = spr0ch.madr; // Copy MADR to DMAC_STADR stall addr register
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (partialqwc); // Bus is 1/2 the ee speed
|
return (partialqwc); // Bus is 1/2 the ee speed
|
||||||
}
|
}
|
||||||
|
@ -188,17 +195,16 @@ void _SPR0interleave()
|
||||||
spr0ch.sadr &= 0x3FFF; // Limited to 16K
|
spr0ch.sadr &= 0x3FFF; // Limited to 16K
|
||||||
spr0ch.madr += (sqwc + spr0ch.qwc) * 16;
|
spr0ch.madr += (sqwc + spr0ch.qwc) * 16;
|
||||||
}
|
}
|
||||||
|
if (dmacRegs.ctrl.STS == STS_fromSPR)
|
||||||
|
{
|
||||||
|
//DevCon.Warning("SPR0 Interleave Stall Control");
|
||||||
|
dmacRegs.stadr.ADDR = spr0ch.madr; // Copy MADR to DMAC_STADR stall addr register
|
||||||
|
}
|
||||||
spr0ch.qwc = 0;
|
spr0ch.qwc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __fi void _dmaSPR0()
|
static __fi void _dmaSPR0()
|
||||||
{
|
{
|
||||||
if (dmacRegs.ctrl.STS == STS_fromSPR)
|
|
||||||
{
|
|
||||||
DevCon.Warning("SPR0 stall %d", dmacRegs.ctrl.STS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer Dn_QWC from SPR to Dn_MADR
|
// Transfer Dn_QWC from SPR to Dn_MADR
|
||||||
switch(spr0ch.chcr.MOD)
|
switch(spr0ch.chcr.MOD)
|
||||||
{
|
{
|
||||||
|
@ -206,7 +212,7 @@ static __fi void _dmaSPR0()
|
||||||
{
|
{
|
||||||
if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
|
if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
|
||||||
{
|
{
|
||||||
DevCon.Warning("SPR stall control Normal not implemented");
|
dmacRegs.stadr.ADDR = spr0ch.madr;
|
||||||
}
|
}
|
||||||
SPR0chain();
|
SPR0chain();
|
||||||
spr0finished = true;
|
spr0finished = true;
|
||||||
|
@ -234,15 +240,13 @@ static __fi void _dmaSPR0()
|
||||||
SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
|
SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
|
||||||
ptag[1]._u32, ptag[0]._u32, spr0ch.qwc, ptag->ID, spr0ch.madr, spr0ch.sadr);
|
ptag[1]._u32, ptag[0]._u32, spr0ch.qwc, ptag->ID, spr0ch.madr, spr0ch.sadr);
|
||||||
|
|
||||||
if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
|
|
||||||
{
|
|
||||||
Console.WriteLn("SPR stall control");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ptag->ID)
|
switch (ptag->ID)
|
||||||
{
|
{
|
||||||
case TAG_CNTS: // CNTS - Transfer QWC following the tag (Stall Control)
|
case TAG_CNTS: // CNTS - Transfer QWC following the tag (Stall Control)
|
||||||
if (dmacRegs.ctrl.STS == STS_fromSPR) dmacRegs.stadr.ADDR = spr0ch.madr + (spr0ch.qwc * 16); // Copy MADR to DMAC_STADR stall addr register
|
if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR - Initial Value
|
||||||
|
{
|
||||||
|
dmacRegs.stadr.ADDR = spr0ch.madr;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAG_CNT: // CNT - Transfer QWC following the tag.
|
case TAG_CNT: // CNT - Transfer QWC following the tag.
|
||||||
|
@ -270,10 +274,6 @@ static __fi void _dmaSPR0()
|
||||||
//case INTERLEAVE_MODE:
|
//case INTERLEAVE_MODE:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
|
|
||||||
{
|
|
||||||
Console.WriteLn("SPR stall control interleave not implemented");
|
|
||||||
}
|
|
||||||
_SPR0interleave();
|
_SPR0interleave();
|
||||||
spr0finished = true;
|
spr0finished = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -58,6 +58,13 @@ static __fi bool WriteFifoToEE()
|
||||||
sif0.ee.cycles += readSize; // fixme : BIAS is factored in above
|
sif0.ee.cycles += readSize; // fixme : BIAS is factored in above
|
||||||
sif0ch.qwc -= readSize;
|
sif0ch.qwc -= readSize;
|
||||||
|
|
||||||
|
if (sif0ch.qwc == 0 && dmacRegs.ctrl.STS == STS_SIF0)
|
||||||
|
{
|
||||||
|
//DevCon.Warning("SIF0 Stall Control");
|
||||||
|
if ((sif0ch.chcr.MOD == NORMAL_MODE) || ((sif0ch.chcr.TAG >> 28) & 0x7) == TAG_CNTS)
|
||||||
|
dmacRegs.stadr.ADDR = sif0ch.madr;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,8 +112,8 @@ static __fi bool ProcessEETag()
|
||||||
case TAG_CNT: break;
|
case TAG_CNT: break;
|
||||||
|
|
||||||
case TAG_CNTS:
|
case TAG_CNTS:
|
||||||
if (dmacRegs.ctrl.STS == STS_SIF0)
|
if (dmacRegs.ctrl.STS == STS_SIF0) // STS == SIF0 - Initial Value
|
||||||
dmacRegs.stadr.ADDR = sif0ch.madr + (sif0ch.qwc * 16);
|
dmacRegs.stadr.ADDR = sif0ch.madr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAG_END:
|
case TAG_END:
|
||||||
|
@ -190,11 +197,6 @@ static __fi void HandleEETransfer()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dmacRegs.ctrl.STS == STS_SIF0)
|
|
||||||
{
|
|
||||||
DevCon.Warning("SIF0 stall control not properly implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (sif0ch.qwc == 0)
|
/*if (sif0ch.qwc == 0)
|
||||||
if (sif0ch.chcr.MOD == NORMAL_MODE)
|
if (sif0ch.chcr.MOD == NORMAL_MODE)
|
||||||
if (!sif0.ee.end){
|
if (!sif0.ee.end){
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
_sif sif1;
|
_sif sif1;
|
||||||
|
|
||||||
static bool done = false;
|
static bool done = false;
|
||||||
|
static bool sif1_dma_stall = false;
|
||||||
|
|
||||||
static __fi void Sif1Init()
|
static __fi void Sif1Init()
|
||||||
{
|
{
|
||||||
|
@ -186,10 +187,6 @@ static __fi void HandleEETransfer()
|
||||||
sif1.ee.busy = false;
|
sif1.ee.busy = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dmacRegs.ctrl.STD == STD_SIF1)
|
|
||||||
{
|
|
||||||
DevCon.Warning("SIF1 stall control Not Implemented"); // STD == fromSIF1
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (sif1ch.qwc == 0)
|
/*if (sif1ch.qwc == 0)
|
||||||
if (sif1ch.chcr.MOD == NORMAL_MODE)
|
if (sif1ch.chcr.MOD == NORMAL_MODE)
|
||||||
|
@ -216,6 +213,21 @@ static __fi void HandleEETransfer()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (dmacRegs.ctrl.STD == STD_SIF1)
|
||||||
|
{
|
||||||
|
if ((sif1ch.chcr.MOD == NORMAL_MODE) || ((sif1ch.chcr.TAG >> 28) & 0x7) == TAG_REFS)
|
||||||
|
{
|
||||||
|
//DevCon.Warning("SIF1 Stall Control");
|
||||||
|
const int writeSize = std::min((s32)sif1ch.qwc, sif1.fifo.sif_free() >> 2);
|
||||||
|
if ((sif1ch.madr + (writeSize * 16)) > dmacRegs.stadr.ADDR)
|
||||||
|
{
|
||||||
|
hwDmacIrq(DMAC_STALL_SIS);
|
||||||
|
sif1_dma_stall = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//DevCon.Warning("SIF1 stall control Not Implemented"); // STD == fromSIF1
|
||||||
|
}
|
||||||
if (sif1.fifo.sif_free() > 0)
|
if (sif1.fifo.sif_free() > 0)
|
||||||
{
|
{
|
||||||
WriteEEtoFifo();
|
WriteEEtoFifo();
|
||||||
|
@ -262,6 +274,15 @@ static __fi void Sif1End()
|
||||||
__fi void SIF1Dma()
|
__fi void SIF1Dma()
|
||||||
{
|
{
|
||||||
int BusyCheck = 0;
|
int BusyCheck = 0;
|
||||||
|
|
||||||
|
if (sif1_dma_stall)
|
||||||
|
{
|
||||||
|
const int writeSize = std::min((s32)sif1ch.qwc, sif1.fifo.sif_free() >> 2);
|
||||||
|
if ((sif1ch.madr + (writeSize * 16)) > dmacRegs.stadr.ADDR)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sif1_dma_stall = false;
|
||||||
Sif1Init();
|
Sif1Init();
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -269,7 +290,7 @@ __fi void SIF1Dma()
|
||||||
//I realise this is very hacky in a way but its an easy way of checking if both are doing something
|
//I realise this is very hacky in a way but its an easy way of checking if both are doing something
|
||||||
BusyCheck = 0;
|
BusyCheck = 0;
|
||||||
|
|
||||||
if (sif1.ee.busy)
|
if (sif1.ee.busy && !sif1_dma_stall)
|
||||||
{
|
{
|
||||||
if(sif1.fifo.sif_free() > 0 || (sif1.ee.end && sif1ch.qwc == 0))
|
if(sif1.fifo.sif_free() > 0 || (sif1.ee.end && sif1ch.qwc == 0))
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,7 +164,7 @@ __fi void vif1SetupTransfer()
|
||||||
if (!vif1.done && ((dmacRegs.ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
|
if (!vif1.done && ((dmacRegs.ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
|
||||||
{
|
{
|
||||||
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
|
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
|
||||||
if ((vif1ch.madr + vif1ch.qwc * 16) >= dmacRegs.stadr.ADDR)
|
if ((vif1ch.madr + vif1ch.qwc * 16) > dmacRegs.stadr.ADDR)
|
||||||
{
|
{
|
||||||
//DevCon.Warning("VIF1 DMA Stall");
|
//DevCon.Warning("VIF1 DMA Stall");
|
||||||
// stalled
|
// stalled
|
||||||
|
@ -437,13 +437,6 @@ void dmaVIF1()
|
||||||
|
|
||||||
g_vif1Cycles = 0;
|
g_vif1Cycles = 0;
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
|
||||||
if (dmacRegs.ctrl.STD == STD_VIF1)
|
|
||||||
{
|
|
||||||
//DevCon.WriteLn("VIF Stall Control Source = %x, Drain = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (vif1ch.qwc > 0) // Normal Mode
|
if (vif1ch.qwc > 0) // Normal Mode
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -421,14 +421,50 @@ __fi bool dmacWrite32( u32 mem, mem32_t& value )
|
||||||
{
|
{
|
||||||
if (!QueuedDMA.empty()) StartQueuedDMA();
|
if (!QueuedDMA.empty()) StartQueuedDMA();
|
||||||
}
|
}
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
if ((oldvalue & 0x30) != (value & 0x30))
|
if ((oldvalue & 0x30) != (value & 0x30))
|
||||||
{
|
{
|
||||||
DevCon.Warning("32bit Stall Source Changed to %x", (value & 0x30) >> 4);
|
std::string new_source;
|
||||||
|
|
||||||
|
switch ((value & 0x30) >> 4)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
new_source = "SIF0";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
new_source = "fromSPR";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
new_source = "fromIPU";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
new_source = "None";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DevCon.Warning("32bit Stall Source Changed to %s", new_source.c_str());
|
||||||
}
|
}
|
||||||
if ((oldvalue & 0xC0) != (value & 0xC0))
|
if ((oldvalue & 0xC0) != (value & 0xC0))
|
||||||
{
|
{
|
||||||
DevCon.Warning("32bit Stall Destination Changed to %x", (value & 0xC0) >> 4);
|
std::string new_dest;
|
||||||
|
|
||||||
|
switch ((value & 0xC0) >> 6)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
new_dest = "VIF1";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
new_dest = "GIF";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
new_dest = "SIF1";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
new_dest = "None";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DevCon.Warning("32bit Stall Destination Changed to %s", new_dest.c_str());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue