mirror of https://github.com/PCSX2/pcsx2.git
Start actually using tDMA_TAG. (IPU.h now uses it, and all the transfer code got moved to it.)
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2291 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
8d5caa300d
commit
6d99798fad
109
pcsx2/Dmac.h
109
pcsx2/Dmac.h
|
@ -19,6 +19,29 @@
|
|||
|
||||
extern u8 *psH; // hw mem
|
||||
|
||||
// Useful enums for some of the fields.
|
||||
enum pce_values
|
||||
{
|
||||
PCE_NOTHING = 0,
|
||||
PCE_RESERVED,
|
||||
PCE_DISABLED,
|
||||
PCE_ENABLED
|
||||
};
|
||||
|
||||
|
||||
enum tag_id
|
||||
{
|
||||
TAG_CNTS = 0,
|
||||
TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end
|
||||
TAG_CNT, // Transfer QWC following the tag.
|
||||
TAG_NEXT, // Transfer QWC following tag. TADR = ADDR
|
||||
TAG_REF, // Transfer QWC from ADDR field
|
||||
TAG_REFS, // Transfer QWC from ADDR field (Stall Control)
|
||||
TAG_CALL, // Transfer QWC following the tag, save succeeding tag
|
||||
TAG_RET, // Transfer QWC following the tag, load next tag
|
||||
TAG_END // Transfer QWC following the tag
|
||||
};
|
||||
|
||||
enum mfd_type
|
||||
{
|
||||
NO_MFD = 0,
|
||||
|
@ -55,15 +78,38 @@ enum TransferMode
|
|||
// --- DMA ---
|
||||
//
|
||||
|
||||
// Doing double duty as both the top 32 bits *and* the lower 32 bits of a chain tag.
|
||||
// Theoretically should probably both be in a u64 together, but with the way the
|
||||
// code is layed out, this is easier for the moment.
|
||||
|
||||
union tDMA_TAG {
|
||||
struct {
|
||||
u32 QWC : 16;
|
||||
u32 reserved2 : 10;
|
||||
u32 PCE : 2;
|
||||
u32 ID : 3;
|
||||
u32 IRQ : 1;
|
||||
};
|
||||
struct {
|
||||
u32 ADDR : 31;
|
||||
u32 SPR : 1;
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMA_TAG(u32 val) { _u32 = val; }
|
||||
u16 upper() { return (_u32 >> 16); }
|
||||
u16 lower() { return (u16)_u32; }
|
||||
};
|
||||
|
||||
union tDMA_CHCR {
|
||||
struct {
|
||||
u32 DIR : 1;
|
||||
u32 DIR : 1; // Direction: 0 - to memory, 1 - from memory. VIF1 & SIF2 only.
|
||||
u32 reserved1 : 1;
|
||||
u32 MOD : 2;
|
||||
u32 ASP : 2;
|
||||
u32 TTE : 1;
|
||||
u32 TIE : 1;
|
||||
u32 STR : 1;
|
||||
u32 ASP : 2; // ASP1 & ASP2; Address stack pointer. 0, 1, or 2 addresses.
|
||||
u32 TTE : 1; // Tag Transfer Enable. 0 - Disable / 1 - Enable.
|
||||
u32 TIE : 1; // Tag Interrupt Enable. 0 - Disable / 1 - Enable.
|
||||
u32 STR : 1; // Start. 0 while stopping DMA, 1 while it's running.
|
||||
u32 reserved2 : 7;
|
||||
u32 TAG : 16;
|
||||
};
|
||||
|
@ -143,6 +189,8 @@ union tDMA_QWC {
|
|||
wxString desc() { return wxsFormat(L"QWC: 0x%x", _u32); }
|
||||
};
|
||||
|
||||
static __forceinline void throwBusError(const char *s);
|
||||
|
||||
struct DMACh {
|
||||
tDMA_CHCR chcr;
|
||||
u32 null0[3];
|
||||
|
@ -157,9 +205,39 @@ struct DMACh {
|
|||
u32 asr1;
|
||||
u32 null5[11];
|
||||
u32 sadr;
|
||||
|
||||
void chcrTransfer(tDMA_TAG* ptag)
|
||||
{
|
||||
chcr.TAG = ptag[0].upper();
|
||||
}
|
||||
|
||||
void qwcTransfer(tDMA_TAG* ptag)
|
||||
{
|
||||
qwc = ptag[0].QWC;
|
||||
}
|
||||
|
||||
bool transfer(const char *s, tDMA_TAG* ptag)
|
||||
{
|
||||
//chcrTransfer(ptag);
|
||||
|
||||
if (ptag == NULL) // Is ptag empty?
|
||||
{
|
||||
throwBusError(s);
|
||||
return false;
|
||||
}
|
||||
chcrTransfer(ptag);
|
||||
|
||||
qwcTransfer(ptag);
|
||||
return true;
|
||||
}
|
||||
|
||||
void unsafeTransfer(tDMA_TAG* ptag)
|
||||
{
|
||||
chcrTransfer(ptag);
|
||||
qwcTransfer(ptag);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
enum INTCIrqs
|
||||
{
|
||||
INTC_GS = 0,
|
||||
|
@ -227,12 +305,12 @@ enum DMAInter
|
|||
|
||||
union tDMAC_CTRL {
|
||||
struct {
|
||||
u32 DMAE : 1;
|
||||
u32 RELE : 1;
|
||||
u32 MFD : 2;
|
||||
u32 STS : 2;
|
||||
u32 STD : 2;
|
||||
u32 RCYC : 3;
|
||||
u32 DMAE : 1; // 0/1 - disables/enables all DMAs
|
||||
u32 RELE : 1; // 0/1 - cycle stealing off/on
|
||||
u32 MFD : 2; // Memory FIFO drain channel (mfd_type)
|
||||
u32 STS : 2; // Stall Control source channel (sts type)
|
||||
u32 STD : 2; // Stall Control drain channel (std_type)
|
||||
u32 RCYC : 3; // Release cycle (8/16/32/64/128/256)
|
||||
u32 reserved1 : 21;
|
||||
};
|
||||
u32 _u32;
|
||||
|
@ -346,6 +424,7 @@ union tDMAC_STADR {
|
|||
wxString desc() { return wxsFormat(L"Stadr: 0x%x", _u32); }
|
||||
};
|
||||
|
||||
|
||||
struct DMACregisters
|
||||
{
|
||||
tDMAC_CTRL ctrl;
|
||||
|
@ -407,6 +486,12 @@ struct INTCregisters
|
|||
#define dmacRegs ((DMACregisters*)(PS2MEM_HW+0xE000))
|
||||
#define intcRegs ((INTCregisters*)(PS2MEM_HW+0xF000))
|
||||
|
||||
static __forceinline void throwBusError(const char *s)
|
||||
{
|
||||
Console.Error("%s BUSERR", s);
|
||||
dmacRegs->stat.BEIS = true;
|
||||
}
|
||||
|
||||
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
|
||||
static __forceinline void *dmaGetAddr(u32 addr) {
|
||||
u8 *ptr;
|
||||
|
|
|
@ -1351,9 +1351,9 @@ static __forceinline bool IPU1chain(int &totalqwc)
|
|||
if (ipu1dma->qwc > 0)
|
||||
{
|
||||
int qwc = ipu1dma->qwc;
|
||||
u32 *pMem;
|
||||
tDMA_TAG *pMem;
|
||||
|
||||
pMem = (u32*)dmaGetAddr(ipu1dma->madr);
|
||||
pMem = (tDMA_TAG*)dmaGetAddr(ipu1dma->madr);
|
||||
|
||||
if (pMem == NULL)
|
||||
{
|
||||
|
@ -1361,7 +1361,7 @@ static __forceinline bool IPU1chain(int &totalqwc)
|
|||
return true;
|
||||
}
|
||||
|
||||
qwc = FIFOto_write(pMem, qwc);
|
||||
qwc = FIFOto_write((u32*)pMem, qwc);
|
||||
ipu1dma->madr += qwc<< 4;
|
||||
ipu1dma->qwc -= qwc;
|
||||
totalqwc += qwc;
|
||||
|
@ -1375,10 +1375,9 @@ static __forceinline bool IPU1chain(int &totalqwc)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Remind me to give this a better name. --arcum42
|
||||
static __forceinline bool IncreaseTadr(u32 tag)
|
||||
static __forceinline bool ipuDmacPartialChain(tDMA_TAG tag)
|
||||
{
|
||||
switch (Tag::Id(tag))
|
||||
switch (tag.ID)
|
||||
{
|
||||
case TAG_REFE: // refe
|
||||
ipu1dma->tadr += 16;
|
||||
|
@ -1393,13 +1392,13 @@ static __forceinline bool IncreaseTadr(u32 tag)
|
|||
|
||||
extern void gsInterrupt();
|
||||
|
||||
static __forceinline bool ipuDmacSrcChain(DMACh *tag, u32 *ptag)
|
||||
static __forceinline bool ipuDmacSrcChain(DMACh *tag, tDMA_TAG *ptag)
|
||||
{
|
||||
switch (Tag::Id(ptag))
|
||||
switch (ptag->ID)
|
||||
{
|
||||
case TAG_REFE: // refe
|
||||
// do not change tadr
|
||||
tag->madr = ptag[1];
|
||||
tag->madr = ptag[1].ADDR;
|
||||
return true;
|
||||
break;
|
||||
|
||||
|
@ -1411,11 +1410,11 @@ static __forceinline bool ipuDmacSrcChain(DMACh *tag, u32 *ptag)
|
|||
|
||||
case TAG_NEXT: // next
|
||||
tag->madr = tag->tadr + 16;
|
||||
tag->tadr = ptag[1];
|
||||
tag->tadr = ptag[1].ADDR;
|
||||
break;
|
||||
|
||||
case TAG_REF: // ref
|
||||
tag->madr = ptag[1];
|
||||
tag->madr = ptag[1].ADDR;
|
||||
tag->tadr += 16;
|
||||
break;
|
||||
|
||||
|
@ -1444,7 +1443,7 @@ static __forceinline void flushGIF()
|
|||
|
||||
int IPU1dma()
|
||||
{
|
||||
u32 *ptag;
|
||||
tDMA_TAG *ptag;
|
||||
bool done = false;
|
||||
int ipu1cycles = 0, totalqwc = 0;
|
||||
|
||||
|
@ -1483,15 +1482,15 @@ int IPU1dma()
|
|||
else
|
||||
{
|
||||
// Chain mode.
|
||||
u32 tag = ipu1dma->chcr._u32; // upper bits describe current tag
|
||||
tDMA_TAG tag = ipu1dma->chcr._u32; // upper bits describe current tag
|
||||
|
||||
if (ipu1dma->chcr.TIE && Tag::IRQ(tag))
|
||||
if (ipu1dma->chcr.TIE && tag.IRQ)
|
||||
{
|
||||
ptag = (u32*)dmaGetAddr(ipu1dma->tadr);
|
||||
ptag = (tDMA_TAG*)dmaGetAddr(ipu1dma->tadr);
|
||||
|
||||
IncreaseTadr(tag);
|
||||
ipuDmacPartialChain(tag);
|
||||
|
||||
Tag::UpperTransfer(ipu1dma, ptag);
|
||||
ipu1dma->chcrTransfer(ptag);
|
||||
|
||||
IPU_LOG("IPU dmaIrq Set");
|
||||
IPU_INT_TO(totalqwc * BIAS);
|
||||
|
@ -1499,7 +1498,7 @@ int IPU1dma()
|
|||
return totalqwc;
|
||||
}
|
||||
|
||||
if (IncreaseTadr(tag))
|
||||
if (ipuDmacPartialChain(tag))
|
||||
{
|
||||
IPU_INT_TO((1 + totalqwc)*BIAS);
|
||||
return totalqwc;
|
||||
|
@ -1530,19 +1529,19 @@ int IPU1dma()
|
|||
else
|
||||
{
|
||||
// Chain Mode & ipu1dma->qwc is 0
|
||||
ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR
|
||||
ptag = (tDMA_TAG*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR
|
||||
|
||||
// Transfer the tag.
|
||||
if (!(Tag::Transfer("IPU1", ipu1dma, ptag))) return totalqwc;
|
||||
if (!ipu1dma->transfer("IPU1", ptag)) return totalqwc;
|
||||
|
||||
ipu1cycles += 1; // Add 1 cycles from the QW read for the tag
|
||||
|
||||
done = ipuDmacSrcChain(ipu1dma, ptag);
|
||||
|
||||
IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x",
|
||||
ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC);
|
||||
ptag[1]._u32, ptag[0]._u32, ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC);
|
||||
|
||||
g_nDMATransfer.DOTIE1 = (ipu1dma->chcr.TIE && Tag::IRQ(ptag));
|
||||
g_nDMATransfer.DOTIE1 = (ipu1dma->chcr.TIE && ptag->IRQ);
|
||||
|
||||
if (ipu1dma->qwc == 0)
|
||||
{
|
||||
|
@ -1555,12 +1554,12 @@ int IPU1dma()
|
|||
|
||||
if (done)
|
||||
{
|
||||
ptag = (u32*)dmaGetAddr(ipu1dma->tadr);
|
||||
ptag = (tDMA_TAG*)dmaGetAddr(ipu1dma->tadr);
|
||||
|
||||
IncreaseTadr(ptag[0]);
|
||||
ipuDmacPartialChain(ptag[0]);
|
||||
|
||||
// Transfer the last of ptag into chcr.
|
||||
Tag::UpperTransfer(ipu1dma, ptag);
|
||||
ipu1dma->chcrTransfer(ptag);
|
||||
}
|
||||
|
||||
IPU_INT_TO(ipu1cycles + totalqwc * BIAS); // Should it be (ipu1cycles + totalqwc) * BIAS?
|
||||
|
@ -1574,7 +1573,7 @@ int IPU1dma()
|
|||
if (IPU1chain(totalqwc)) return totalqwc;
|
||||
}
|
||||
|
||||
IncreaseTadr(ptag[0]);
|
||||
ipuDmacPartialChain(ptag[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1655,7 +1654,7 @@ int IPU0dma()
|
|||
{
|
||||
int readsize;
|
||||
static int totalsize = 0;
|
||||
void* pMem;
|
||||
tDMA_TAG* pMem;
|
||||
|
||||
if ((!(ipu0dma->chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0))
|
||||
return 0;
|
||||
|
@ -1665,8 +1664,9 @@ int IPU0dma()
|
|||
IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx",
|
||||
ipu0dma->chcr._u32, ipu0dma->madr, ipu0dma->qwc);
|
||||
|
||||
pxAssert((ipu0dma->chcr._u32 & 0xC) == 0);
|
||||
pMem = (u32*)dmaGetAddr(ipu0dma->madr);
|
||||
pxAssert(ipu0dma->chcr.MOD == NORMAL_MODE);
|
||||
|
||||
pMem = (tDMA_TAG*)dmaGetAddr(ipu0dma->madr);
|
||||
|
||||
readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC);
|
||||
totalsize+=readsize;
|
||||
|
@ -1700,7 +1700,7 @@ int IPU0dma()
|
|||
//This broke vids in Digital Devil Saga
|
||||
//Note that interrupting based on totalsize is just guessing..
|
||||
IPU_INT_FROM(totalsize*BIAS );
|
||||
totalsize=0;
|
||||
totalsize = 0;
|
||||
}
|
||||
|
||||
return readsize;
|
||||
|
|
115
pcsx2/Tags.h
115
pcsx2/Tags.h
|
@ -14,139 +14,54 @@
|
|||
*/
|
||||
|
||||
// This is meant to be a collection of generic functions dealing with tags.
|
||||
// It's now going to be mostly depreciated for Dmac.h.
|
||||
|
||||
#include "Dmac.h"
|
||||
|
||||
enum pce_values
|
||||
{
|
||||
PCE_NOTHING = 0,
|
||||
PCE_RESERVED,
|
||||
PCE_DISABLED,
|
||||
PCE_ENABLED
|
||||
};
|
||||
|
||||
|
||||
enum tag_id
|
||||
{
|
||||
TAG_CNTS = 0,
|
||||
TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end
|
||||
TAG_CNT, // Transfer QWC following the tag.
|
||||
TAG_NEXT, // Transfer QWC following tag. TADR = ADDR
|
||||
TAG_REF, // Transfer QWC from ADDR field
|
||||
TAG_REFS, // Transfer QWC from ADDR field (Stall Control)
|
||||
TAG_CALL, // Transfer QWC following the tag, save succeeding tag
|
||||
TAG_RET, // Transfer QWC following the tag, load next tag
|
||||
TAG_END // Transfer QWC following the tag
|
||||
};
|
||||
|
||||
enum d_ctrl_flags
|
||||
{
|
||||
CTRL_DMAE = 0x1, // 0/1 - disables/enables all DMAs
|
||||
CTRL_RELE = 0x2, // 0/1 - cycle stealing off/on
|
||||
CTRL_MFD = 0xC, // Memory FIFO drain channel (mfd_type)
|
||||
CTRL_STS = 0x30, // Stall Control source channel (sts type)
|
||||
CTRL_STD = 0xC0, // Stall Control drain channel (std_type)
|
||||
CTRL_RCYC = 0x100 // Release cycle (8/16/32/64/128/256)
|
||||
// When cycle stealing is on, the release cycle sets the period to release
|
||||
// the bus to EE.
|
||||
};
|
||||
|
||||
enum chcr_flags
|
||||
{
|
||||
CHCR_DIR = 0x1, // Direction: 0 - to memory, 1 - from memory. VIF1 & SIF2 only.
|
||||
CHCR_MOD1 = 0x4,
|
||||
CHCR_MOD2 = 0x8,
|
||||
CHCR_MOD = 0xC, // MOD1 & MOD2; Holds which of the Transfer modes above is used.
|
||||
CHCR_ASP1 = 0x10,
|
||||
CHCR_ASP2 = 0x20,
|
||||
CHCR_ASP = 0x30, // ASP1 & ASP2; Address stack pointer. 0, 1, or 2 addresses.
|
||||
CHCR_TTE = 0x40, // Tag Transfer Enable. 0 - Diable / 1 - Enable.
|
||||
CHCR_TIE = 0x80, // Tag Interrupt Enable. 0 - Diable / 1 - Enable.
|
||||
CHCR_STR = 0x100 // Start. 0 while stopping DMA, 1 while it's running.
|
||||
};
|
||||
|
||||
// Doing double duty as both the top 32 bits *and* the lower 32 bits of a chain tag.
|
||||
// Theoretically should probably both be in a u64 together, but with the way the
|
||||
// code is layed out, this is easier for the moment.
|
||||
union tDMA_TAG {
|
||||
struct {
|
||||
u32 QWC : 16;
|
||||
u32 reserved2 : 10;
|
||||
u32 PCE : 2;
|
||||
u32 ID : 3;
|
||||
u32 IRQ : 1;
|
||||
};
|
||||
struct {
|
||||
u32 ADDR : 31;
|
||||
u32 SPR : 1;
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMA_TAG(u32 val) { _u32 = val; }
|
||||
};
|
||||
|
||||
// Transfer functions using u32. Eventually should be phased out for the tDMA_TAG functions.
|
||||
namespace Tag
|
||||
{
|
||||
// Transfer functions,
|
||||
static __forceinline void UpperTransfer(DMACh *tag, u32* ptag)
|
||||
{
|
||||
// Transfer upper part of tag to CHCR bits 31-15
|
||||
tag->chcr.TAG = ((*ptag) >> 16);
|
||||
tag->chcrTransfer((tDMA_TAG*)ptag);
|
||||
}
|
||||
|
||||
static __forceinline void LowerTransfer(DMACh *tag, u32* ptag)
|
||||
{
|
||||
//QWC set to lower 16bits of the tag
|
||||
tag->qwc = (u16)ptag[0];
|
||||
tag->qwcTransfer((tDMA_TAG*)ptag);
|
||||
}
|
||||
|
||||
static __forceinline bool Transfer(const char *s, DMACh *tag, u32* ptag)
|
||||
{
|
||||
if (ptag == NULL) // Is ptag empty?
|
||||
{
|
||||
Console.Error("%s BUSERR", s);
|
||||
UpperTransfer(tag, ptag);
|
||||
|
||||
// Set BEIS (BUSERR) in DMAC_STAT register
|
||||
dmacRegs->stat.BEIS = true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpperTransfer(tag, ptag);
|
||||
LowerTransfer(tag, ptag);
|
||||
return true;
|
||||
}
|
||||
tag->transfer(s, (tDMA_TAG*)ptag);
|
||||
}
|
||||
|
||||
static __forceinline void UnsafeTransfer(DMACh *tag, u32* ptag)
|
||||
{
|
||||
UpperTransfer(tag, ptag);
|
||||
LowerTransfer(tag, ptag);
|
||||
}
|
||||
|
||||
// Untested
|
||||
static __forceinline pce_values PCE(u32 *tag)
|
||||
{
|
||||
return (pce_values)((tag[0] >> 22) & 0x3);
|
||||
tag->unsafeTransfer((tDMA_TAG*)ptag);
|
||||
}
|
||||
}
|
||||
|
||||
// Misc Tag functions, soon to be obsolete.
|
||||
namespace Tag
|
||||
{
|
||||
static __forceinline tag_id Id(u32* tag)
|
||||
{
|
||||
return (tag_id)((tag[0] >> 28) & 0x7);
|
||||
return (tag_id)(((tDMA_TAG)tag[0]).ID);
|
||||
}
|
||||
|
||||
static __forceinline tag_id Id(u32 tag)
|
||||
{
|
||||
return (tag_id)((tag >> 28) & 0x7);
|
||||
return (tag_id)(((tDMA_TAG)tag).ID);
|
||||
}
|
||||
|
||||
static __forceinline bool IRQ(u32 *tag)
|
||||
{
|
||||
return !!(tag[0] >> 31);
|
||||
return !!((tDMA_TAG)tag[0]).IRQ;
|
||||
}
|
||||
|
||||
static __forceinline bool IRQ(u32 tag)
|
||||
{
|
||||
return !!(tag >> 31);
|
||||
return !!((tDMA_TAG)tag).IRQ;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue