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
|
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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
113
pcsx2/Tags.h
113
pcsx2/Tags.h
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue