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 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 enum mfd_type
{ {
NO_MFD = 0, NO_MFD = 0,
@ -55,15 +78,38 @@ enum TransferMode
// --- DMA --- // --- 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 { union tDMA_CHCR {
struct { struct {
u32 DIR : 1; u32 DIR : 1; // Direction: 0 - to memory, 1 - from memory. VIF1 & SIF2 only.
u32 reserved1 : 1; u32 reserved1 : 1;
u32 MOD : 2; u32 MOD : 2;
u32 ASP : 2; u32 ASP : 2; // ASP1 & ASP2; Address stack pointer. 0, 1, or 2 addresses.
u32 TTE : 1; u32 TTE : 1; // Tag Transfer Enable. 0 - Disable / 1 - Enable.
u32 TIE : 1; u32 TIE : 1; // Tag Interrupt Enable. 0 - Disable / 1 - Enable.
u32 STR : 1; u32 STR : 1; // Start. 0 while stopping DMA, 1 while it's running.
u32 reserved2 : 7; u32 reserved2 : 7;
u32 TAG : 16; u32 TAG : 16;
}; };
@ -143,6 +189,8 @@ union tDMA_QWC {
wxString desc() { return wxsFormat(L"QWC: 0x%x", _u32); } wxString desc() { return wxsFormat(L"QWC: 0x%x", _u32); }
}; };
static __forceinline void throwBusError(const char *s);
struct DMACh { struct DMACh {
tDMA_CHCR chcr; tDMA_CHCR chcr;
u32 null0[3]; u32 null0[3];
@ -157,8 +205,38 @@ struct DMACh {
u32 asr1; u32 asr1;
u32 null5[11]; u32 null5[11];
u32 sadr; 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 enum INTCIrqs
{ {
@ -227,12 +305,12 @@ enum DMAInter
union tDMAC_CTRL { union tDMAC_CTRL {
struct { struct {
u32 DMAE : 1; u32 DMAE : 1; // 0/1 - disables/enables all DMAs
u32 RELE : 1; u32 RELE : 1; // 0/1 - cycle stealing off/on
u32 MFD : 2; u32 MFD : 2; // Memory FIFO drain channel (mfd_type)
u32 STS : 2; u32 STS : 2; // Stall Control source channel (sts type)
u32 STD : 2; u32 STD : 2; // Stall Control drain channel (std_type)
u32 RCYC : 3; u32 RCYC : 3; // Release cycle (8/16/32/64/128/256)
u32 reserved1 : 21; u32 reserved1 : 21;
}; };
u32 _u32; u32 _u32;
@ -346,6 +424,7 @@ union tDMAC_STADR {
wxString desc() { return wxsFormat(L"Stadr: 0x%x", _u32); } wxString desc() { return wxsFormat(L"Stadr: 0x%x", _u32); }
}; };
struct DMACregisters struct DMACregisters
{ {
tDMAC_CTRL ctrl; tDMAC_CTRL ctrl;
@ -407,6 +486,12 @@ struct INTCregisters
#define dmacRegs ((DMACregisters*)(PS2MEM_HW+0xE000)) #define dmacRegs ((DMACregisters*)(PS2MEM_HW+0xE000))
#define intcRegs ((INTCregisters*)(PS2MEM_HW+0xF000)) #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) // Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
static __forceinline void *dmaGetAddr(u32 addr) { static __forceinline void *dmaGetAddr(u32 addr) {
u8 *ptr; u8 *ptr;

View File

@ -1351,9 +1351,9 @@ static __forceinline bool IPU1chain(int &totalqwc)
if (ipu1dma->qwc > 0) if (ipu1dma->qwc > 0)
{ {
int qwc = ipu1dma->qwc; int qwc = ipu1dma->qwc;
u32 *pMem; tDMA_TAG *pMem;
pMem = (u32*)dmaGetAddr(ipu1dma->madr); pMem = (tDMA_TAG*)dmaGetAddr(ipu1dma->madr);
if (pMem == NULL) if (pMem == NULL)
{ {
@ -1361,7 +1361,7 @@ static __forceinline bool IPU1chain(int &totalqwc)
return true; return true;
} }
qwc = FIFOto_write(pMem, qwc); qwc = FIFOto_write((u32*)pMem, qwc);
ipu1dma->madr += qwc<< 4; ipu1dma->madr += qwc<< 4;
ipu1dma->qwc -= qwc; ipu1dma->qwc -= qwc;
totalqwc += qwc; totalqwc += qwc;
@ -1375,10 +1375,9 @@ static __forceinline bool IPU1chain(int &totalqwc)
return false; return false;
} }
// Remind me to give this a better name. --arcum42 static __forceinline bool ipuDmacPartialChain(tDMA_TAG tag)
static __forceinline bool IncreaseTadr(u32 tag)
{ {
switch (Tag::Id(tag)) switch (tag.ID)
{ {
case TAG_REFE: // refe case TAG_REFE: // refe
ipu1dma->tadr += 16; ipu1dma->tadr += 16;
@ -1393,13 +1392,13 @@ static __forceinline bool IncreaseTadr(u32 tag)
extern void gsInterrupt(); 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 case TAG_REFE: // refe
// do not change tadr // do not change tadr
tag->madr = ptag[1]; tag->madr = ptag[1].ADDR;
return true; return true;
break; break;
@ -1411,11 +1410,11 @@ static __forceinline bool ipuDmacSrcChain(DMACh *tag, u32 *ptag)
case TAG_NEXT: // next case TAG_NEXT: // next
tag->madr = tag->tadr + 16; tag->madr = tag->tadr + 16;
tag->tadr = ptag[1]; tag->tadr = ptag[1].ADDR;
break; break;
case TAG_REF: // ref case TAG_REF: // ref
tag->madr = ptag[1]; tag->madr = ptag[1].ADDR;
tag->tadr += 16; tag->tadr += 16;
break; break;
@ -1444,7 +1443,7 @@ static __forceinline void flushGIF()
int IPU1dma() int IPU1dma()
{ {
u32 *ptag; tDMA_TAG *ptag;
bool done = false; bool done = false;
int ipu1cycles = 0, totalqwc = 0; int ipu1cycles = 0, totalqwc = 0;
@ -1483,15 +1482,15 @@ int IPU1dma()
else else
{ {
// Chain mode. // 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_LOG("IPU dmaIrq Set");
IPU_INT_TO(totalqwc * BIAS); IPU_INT_TO(totalqwc * BIAS);
@ -1499,7 +1498,7 @@ int IPU1dma()
return totalqwc; return totalqwc;
} }
if (IncreaseTadr(tag)) if (ipuDmacPartialChain(tag))
{ {
IPU_INT_TO((1 + totalqwc)*BIAS); IPU_INT_TO((1 + totalqwc)*BIAS);
return totalqwc; return totalqwc;
@ -1530,19 +1529,19 @@ int IPU1dma()
else else
{ {
// Chain Mode & ipu1dma->qwc is 0 // 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. // 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 ipu1cycles += 1; // Add 1 cycles from the QW read for the tag
done = ipuDmacSrcChain(ipu1dma, ptag); done = ipuDmacSrcChain(ipu1dma, ptag);
IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x", 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) if (ipu1dma->qwc == 0)
{ {
@ -1555,12 +1554,12 @@ int IPU1dma()
if (done) 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. // 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? IPU_INT_TO(ipu1cycles + totalqwc * BIAS); // Should it be (ipu1cycles + totalqwc) * BIAS?
@ -1574,7 +1573,7 @@ int IPU1dma()
if (IPU1chain(totalqwc)) return totalqwc; if (IPU1chain(totalqwc)) return totalqwc;
} }
IncreaseTadr(ptag[0]); ipuDmacPartialChain(ptag[0]);
} }
else else
{ {
@ -1655,7 +1654,7 @@ int IPU0dma()
{ {
int readsize; int readsize;
static int totalsize = 0; static int totalsize = 0;
void* pMem; tDMA_TAG* pMem;
if ((!(ipu0dma->chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0)) if ((!(ipu0dma->chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0))
return 0; return 0;
@ -1665,8 +1664,9 @@ int IPU0dma()
IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx", IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx",
ipu0dma->chcr._u32, ipu0dma->madr, ipu0dma->qwc); ipu0dma->chcr._u32, ipu0dma->madr, ipu0dma->qwc);
pxAssert((ipu0dma->chcr._u32 & 0xC) == 0); pxAssert(ipu0dma->chcr.MOD == NORMAL_MODE);
pMem = (u32*)dmaGetAddr(ipu0dma->madr);
pMem = (tDMA_TAG*)dmaGetAddr(ipu0dma->madr);
readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC); readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC);
totalsize+=readsize; totalsize+=readsize;

View File

@ -14,139 +14,54 @@
*/ */
// This is meant to be a collection of generic functions dealing with tags. // 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" #include "Dmac.h"
enum pce_values // Transfer functions using u32. Eventually should be phased out for the tDMA_TAG functions.
{
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; }
};
namespace Tag namespace Tag
{ {
// Transfer functions,
static __forceinline void UpperTransfer(DMACh *tag, u32* ptag) static __forceinline void UpperTransfer(DMACh *tag, u32* ptag)
{ {
// Transfer upper part of tag to CHCR bits 31-15 tag->chcrTransfer((tDMA_TAG*)ptag);
tag->chcr.TAG = ((*ptag) >> 16);
} }
static __forceinline void LowerTransfer(DMACh *tag, u32* ptag) static __forceinline void LowerTransfer(DMACh *tag, u32* ptag)
{ {
//QWC set to lower 16bits of the tag tag->qwcTransfer((tDMA_TAG*)ptag);
tag->qwc = (u16)ptag[0];
} }
static __forceinline bool Transfer(const char *s, DMACh *tag, u32* ptag) static __forceinline bool Transfer(const char *s, DMACh *tag, u32* ptag)
{ {
if (ptag == NULL) // Is ptag empty? tag->transfer(s, (tDMA_TAG*)ptag);
{
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;
}
} }
static __forceinline void UnsafeTransfer(DMACh *tag, u32* ptag) static __forceinline void UnsafeTransfer(DMACh *tag, u32* ptag)
{ {
UpperTransfer(tag, ptag); tag->unsafeTransfer((tDMA_TAG*)ptag);
LowerTransfer(tag, ptag); }
} }
// Untested // Misc Tag functions, soon to be obsolete.
static __forceinline pce_values PCE(u32 *tag) namespace Tag
{ {
return (pce_values)((tag[0] >> 22) & 0x3);
}
static __forceinline tag_id Id(u32* 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) 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) static __forceinline bool IRQ(u32 *tag)
{ {
return !!(tag[0] >> 31); return !!((tDMA_TAG)tag[0]).IRQ;
} }
static __forceinline bool IRQ(u32 tag) static __forceinline bool IRQ(u32 tag)
{ {
return !!(tag >> 31); return !!((tDMA_TAG)tag).IRQ;
} }
} }