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:
arcum42 2009-12-03 13:01:17 +00:00
parent 8d5caa300d
commit 6d99798fad
3 changed files with 142 additions and 142 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}