* Match mtx and Padclamp.c * Match the rest of GX * Import TRK 2.6 * Import MSL headers and files * Merge some MSL headers into ours
559 lines
18 KiB
C
559 lines
18 KiB
C
#include <dolphin/PPCArch.h>
|
|
#include <dolphin/gx.h>
|
|
#include <dolphin/os.h>
|
|
#include <stddef.h>
|
|
|
|
|
|
#include <dolphin/gx/GXPriv.h>
|
|
|
|
static struct __GXFifoObj* CPUFifo;
|
|
static struct __GXFifoObj* GPFifo;
|
|
static OSThread* __GXCurrentThread;
|
|
static GXBool CPGPLinked;
|
|
static BOOL GXOverflowSuspendInProgress;
|
|
static GXBreakPtCallback BreakPointCB;
|
|
static u32 __GXOverflowCount;
|
|
|
|
void* __GXCurrentBP;
|
|
|
|
static void __GXFifoReadEnable(void);
|
|
static void __GXFifoReadDisable(void);
|
|
static void __GXFifoLink(u8 arg0);
|
|
static void __GXWriteFifoIntEnable(u8 arg0, u8 arg1);
|
|
static void __GXWriteFifoIntReset(u8 arg0, u8 arg1);
|
|
|
|
static void GXOverflowHandler(s16 interrupt, OSContext *context)
|
|
{
|
|
ASSERTLINE(0x179, !GXOverflowSuspendInProgress);
|
|
|
|
__GXOverflowCount++;
|
|
__GXWriteFifoIntEnable(0, 1);
|
|
__GXWriteFifoIntReset(1, 0);
|
|
GXOverflowSuspendInProgress = TRUE;
|
|
|
|
OSSuspendThread(__GXCurrentThread);
|
|
}
|
|
|
|
static void GXUnderflowHandler(s16 interrupt, OSContext *context)
|
|
{
|
|
ASSERTLINE(0x1A3, GXOverflowSuspendInProgress);
|
|
|
|
OSResumeThread(__GXCurrentThread);
|
|
GXOverflowSuspendInProgress = FALSE;
|
|
__GXWriteFifoIntReset(1U, 1U);
|
|
__GXWriteFifoIntEnable(1U, 0U);
|
|
}
|
|
|
|
#define SOME_SET_REG_MACRO(reg, size, shift, val) \
|
|
do { \
|
|
(reg) = (u32)__rlwimi((u32)(reg), (val), (shift), (32 - (shift) - (size)), (31 - (shift))); \
|
|
} while (0);
|
|
|
|
static void GXBreakPointHandler(s16 interrupt, OSContext *context)
|
|
{
|
|
OSContext exceptionContext;
|
|
|
|
gx->cpEnable = gx->cpEnable & 0xFFFFFFDF;
|
|
__cpReg[1] = gx->cpEnable;
|
|
if (BreakPointCB != NULL) {
|
|
OSClearContext(&exceptionContext);
|
|
OSSetCurrentContext(&exceptionContext);
|
|
BreakPointCB();
|
|
OSClearContext(&exceptionContext);
|
|
OSSetCurrentContext(context);
|
|
}
|
|
}
|
|
|
|
static void GXCPInterruptHandler(s16 interrupt, OSContext *context)
|
|
{
|
|
gx->cpStatus = GX_GET_CP_REG(0);
|
|
if (GET_REG_FIELD(gx->cpEnable, 1, 3) && GET_REG_FIELD(gx->cpStatus, 1, 1)) {
|
|
GXUnderflowHandler(interrupt, context);
|
|
}
|
|
if (GET_REG_FIELD(gx->cpEnable, 1, 2) && GET_REG_FIELD(gx->cpStatus, 1, 0)) {
|
|
GXOverflowHandler(interrupt, context);
|
|
}
|
|
if (GET_REG_FIELD(gx->cpEnable, 1, 5) && GET_REG_FIELD(gx->cpStatus, 1, 4)) {
|
|
GXBreakPointHandler(interrupt, context);
|
|
}
|
|
}
|
|
|
|
void GXInitFifoBase(GXFifoObj *fifo, void *base, u32 size)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
|
|
ASSERTMSGLINE(0x21E, realFifo != CPUFifo, "GXInitFifoBase: fifo is attached to CPU");
|
|
ASSERTMSGLINE(0x220, realFifo != GPFifo, "GXInitFifoBase: fifo is attached to GP");
|
|
ASSERTMSGLINE(0x222, ((u32)base & 0x1F) == 0, "GXInitFifoBase: base must be 32B aligned");
|
|
ASSERTMSGLINE(0x224, base != NULL, "GXInitFifoBase: base pointer is NULL");
|
|
ASSERTMSGLINE(0x226, (size & 0x1F) == 0, "GXInitFifoBase: size must be 32B aligned");
|
|
ASSERTMSGLINE(0x228, size >= 0x10000, "GXInitFifoBase: fifo is not large enough");
|
|
|
|
realFifo->base = base;
|
|
realFifo->top = (u8 *)base + size - 4;
|
|
realFifo->size = size;
|
|
realFifo->count = 0;
|
|
GXInitFifoLimits(fifo, size - 0x4000, (size >> 1) & ~0x1F);
|
|
GXInitFifoPtrs(fifo, base, base);
|
|
}
|
|
|
|
void GXInitFifoPtrs(GXFifoObj *fifo, void *readPtr, void *writePtr)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
BOOL enabled;
|
|
|
|
ASSERTMSGLINE(0x250, realFifo != CPUFifo, "GXInitFifoPtrs: fifo is attached to CPU");
|
|
ASSERTMSGLINE(0x252, realFifo != GPFifo, "GXInitFifoPtrs: fifo is attached to GP");
|
|
ASSERTMSGLINE(0x254, ((u32)readPtr & 0x1F) == 0, "GXInitFifoPtrs: readPtr not 32B aligned");
|
|
ASSERTMSGLINE(0x256, ((u32)writePtr & 0x1F) == 0, "GXInitFifoPtrs: writePtr not 32B aligned");
|
|
ASSERTMSGLINE(0x259, realFifo->base <= readPtr && readPtr < realFifo->top, "GXInitFifoPtrs: readPtr not in fifo range");
|
|
ASSERTMSGLINE(0x25C, realFifo->base <= writePtr && writePtr < realFifo->top, "GXInitFifoPtrs: writePtr not in fifo range");
|
|
|
|
enabled = OSDisableInterrupts();
|
|
realFifo->rdPtr = readPtr;
|
|
realFifo->wrPtr = writePtr;
|
|
realFifo->count = (u8 *)writePtr - (u8 *)readPtr;
|
|
if (realFifo->count < 0) {
|
|
realFifo->count += realFifo->size;
|
|
}
|
|
OSRestoreInterrupts(enabled);
|
|
}
|
|
|
|
void GXInitFifoLimits(GXFifoObj *fifo, u32 hiWatermark, u32 loWatermark)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
|
|
ASSERTMSGLINE(0x281, realFifo != GPFifo, "GXInitFifoLimits: fifo is attached to GP");
|
|
ASSERTMSGLINE(0x283, (hiWatermark & 0x1F) == 0, "GXInitFifoLimits: hiWatermark not 32B aligned");
|
|
ASSERTMSGLINE(0x285, (loWatermark & 0x1F) == 0, "GXInitFifoLimits: loWatermark not 32B aligned");
|
|
ASSERTMSGLINE(0x287, hiWatermark < realFifo->top - realFifo->base, "GXInitFifoLimits: hiWatermark too large");
|
|
ASSERTMSGLINE(0x289, loWatermark < hiWatermark, "GXInitFifoLimits: hiWatermark below lo watermark");
|
|
|
|
realFifo->hiWatermark = hiWatermark;
|
|
realFifo->loWatermark = loWatermark;
|
|
}
|
|
|
|
void GXSetCPUFifo(GXFifoObj *fifo)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
BOOL enabled = OSDisableInterrupts();
|
|
|
|
CPUFifo = realFifo;
|
|
if (CPUFifo == GPFifo)
|
|
{
|
|
u32 reg = 0;
|
|
|
|
__piReg[3] = (u32)realFifo->base & 0x3FFFFFFF;
|
|
__piReg[4] = (u32)realFifo->top & 0x3FFFFFFF;
|
|
SET_REG_FIELD(0x294, reg, 21, 5, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 5);
|
|
SET_REG_FIELD(0x295, reg, 1, 26, 0);
|
|
__piReg[5] = reg;
|
|
CPGPLinked = GX_TRUE;
|
|
__GXWriteFifoIntReset(1, 1);
|
|
__GXWriteFifoIntEnable(1, 0);
|
|
__GXFifoLink(1);
|
|
}
|
|
else
|
|
{
|
|
u32 reg;
|
|
|
|
if (CPGPLinked)
|
|
{
|
|
__GXFifoLink(0);
|
|
CPGPLinked = GX_FALSE;
|
|
}
|
|
__GXWriteFifoIntEnable(0, 0);
|
|
reg = 0;
|
|
__piReg[3] = (u32)realFifo->base & 0x3FFFFFFF;
|
|
__piReg[4] = (u32)realFifo->top & 0x3FFFFFFF;
|
|
SET_REG_FIELD(0x2B7, reg, 21, 5, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 5);
|
|
SET_REG_FIELD(0x2B8, reg, 1, 26, 0);
|
|
__piReg[5] = reg;
|
|
}
|
|
|
|
__sync();
|
|
|
|
OSRestoreInterrupts(enabled);
|
|
}
|
|
|
|
void GXSetGPFifo(GXFifoObj *fifo)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
BOOL enabled = OSDisableInterrupts();
|
|
|
|
__GXFifoReadDisable();
|
|
__GXWriteFifoIntEnable(0, 0);
|
|
GPFifo = realFifo;
|
|
|
|
GX_SET_CP_REG(16, (u32)realFifo->base & 0xFFFF);
|
|
GX_SET_CP_REG(18, (u32)realFifo->top & 0xFFFF);
|
|
GX_SET_CP_REG(24, realFifo->count & 0xFFFF);
|
|
GX_SET_CP_REG(26, (u32)realFifo->wrPtr & 0xFFFF);
|
|
GX_SET_CP_REG(28, (u32)realFifo->rdPtr & 0xFFFF);
|
|
GX_SET_CP_REG(20, (u32)realFifo->hiWatermark & 0xFFFF);
|
|
GX_SET_CP_REG(22, (u32)realFifo->loWatermark & 0xFFFF);
|
|
GX_SET_CP_REG(17, ((u32)realFifo->base & 0x3FFFFFFF) >> 16);
|
|
GX_SET_CP_REG(19, ((u32)realFifo->top & 0x3FFFFFFF) >> 16);
|
|
GX_SET_CP_REG(25, realFifo->count >> 16);
|
|
GX_SET_CP_REG(27, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 16);
|
|
GX_SET_CP_REG(29, ((u32)realFifo->rdPtr & 0x3FFFFFFF) >> 16);
|
|
GX_SET_CP_REG(21, (u32)realFifo->hiWatermark >> 16);
|
|
GX_SET_CP_REG(23, (u32)realFifo->loWatermark >> 16);
|
|
|
|
__sync();
|
|
|
|
if (CPUFifo == GPFifo) {
|
|
CPGPLinked = GX_TRUE;
|
|
__GXWriteFifoIntEnable(1, 0);
|
|
__GXFifoLink(1);
|
|
}
|
|
else {
|
|
CPGPLinked = GX_FALSE;
|
|
__GXWriteFifoIntEnable(0, 0);
|
|
__GXFifoLink(0);
|
|
}
|
|
__GXWriteFifoIntReset(1, 1);
|
|
__GXFifoReadEnable();
|
|
OSRestoreInterrupts(enabled);
|
|
}
|
|
|
|
void GXSaveCPUFifo(GXFifoObj *fifo)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
ASSERTMSGLINE(0x343, realFifo == CPUFifo, "GXSaveCPUFifo: fifo is not attached to CPU");
|
|
__GXSaveCPUFifoAux(realFifo);
|
|
}
|
|
|
|
#define SOME_MACRO1(fifo) \
|
|
do { \
|
|
u32 temp = GX_GET_CP_REG(29) << 16; \
|
|
temp |= GX_GET_CP_REG(28); \
|
|
fifo->rdPtr = OSPhysicalToCached(temp); \
|
|
} while (0)
|
|
|
|
#define SOME_MACRO2(fifo) \
|
|
do { \
|
|
u32 temp = GX_GET_CP_REG(25) << 16; \
|
|
temp |= GX_GET_CP_REG(24); \
|
|
fifo->count = temp; \
|
|
} while (0)
|
|
|
|
void __GXSaveCPUFifoAux(struct __GXFifoObj *realFifo)
|
|
{
|
|
BOOL enabled = OSDisableInterrupts();
|
|
|
|
GXFlush();
|
|
realFifo->base = OSPhysicalToCached(__piReg[3]);
|
|
realFifo->top = OSPhysicalToCached(__piReg[4]);
|
|
realFifo->wrPtr = OSPhysicalToCached(__piReg[5] & 0xFBFFFFFF);
|
|
if (CPGPLinked) {
|
|
SOME_MACRO1(realFifo);
|
|
SOME_MACRO2(realFifo);
|
|
} else {
|
|
realFifo->count = (u8 *)realFifo->wrPtr - (u8 *)realFifo->rdPtr;
|
|
if (realFifo->count < 0)
|
|
realFifo->count += realFifo->size;
|
|
}
|
|
OSRestoreInterrupts(enabled);
|
|
}
|
|
|
|
void GXSaveGPFifo(GXFifoObj *fifo)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
unsigned long cpStatus;
|
|
unsigned char readIdle;
|
|
unsigned long temp;
|
|
|
|
ASSERTMSGLINE(0x38C, realFifo == GPFifo, "GXSaveGPFifo: fifo is not attached to GP");
|
|
cpStatus = GX_GET_CP_REG(0);
|
|
readIdle = GET_REG_FIELD(cpStatus, 1, 2);
|
|
ASSERTMSGLINE(0x393, readIdle, "GXSaveGPFifo: GP is not idle");
|
|
|
|
SOME_MACRO1(realFifo);
|
|
SOME_MACRO2(realFifo);
|
|
}
|
|
|
|
void GXGetGPStatus(GXBool *overhi, GXBool *underlow, GXBool *readIdle, GXBool *cmdIdle, GXBool *brkpt)
|
|
{
|
|
gx->cpStatus = GX_GET_CP_REG(0);
|
|
*overhi = GET_REG_FIELD(gx->cpStatus, 1, 0);
|
|
*underlow = (int)GET_REG_FIELD(gx->cpStatus, 1, 1);
|
|
*readIdle = (int)GET_REG_FIELD(gx->cpStatus, 1, 2);
|
|
*cmdIdle = (int)GET_REG_FIELD(gx->cpStatus, 1, 3);
|
|
*brkpt = (int)GET_REG_FIELD(gx->cpStatus, 1, 4);
|
|
}
|
|
|
|
void GXGetFifoStatus(GXFifoObj *fifo, GXBool *overhi, GXBool *underflow, u32 *fifoCount, GXBool *cpuWrite, GXBool *gpRead, GXBool *fifowrap)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
|
|
*underflow = GX_FALSE;
|
|
*overhi = GX_FALSE;
|
|
*fifoCount = 0;
|
|
*fifowrap = GX_FALSE;
|
|
if (realFifo == GPFifo) {
|
|
SOME_MACRO1(realFifo);
|
|
SOME_MACRO2(realFifo);
|
|
}
|
|
if (realFifo == CPUFifo) {
|
|
GXFlush();
|
|
__GXSaveCPUFifoAux(realFifo);
|
|
*fifowrap = (int)GET_REG_FIELD(GX_GET_PI_REG(5), 1, 26);
|
|
}
|
|
*overhi = (realFifo->count > realFifo->hiWatermark);
|
|
*underflow = (realFifo->count < realFifo->loWatermark);
|
|
*fifoCount = (realFifo->count);
|
|
*cpuWrite = (CPUFifo == realFifo);
|
|
*gpRead = (GPFifo == realFifo);
|
|
}
|
|
|
|
void GXGetFifoPtrs(GXFifoObj *fifo, void **readPtr, void **writePtr)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
|
|
if (realFifo == CPUFifo) {
|
|
realFifo->wrPtr = OSPhysicalToCached(GX_GET_PI_REG(5) & 0xFBFFFFFF);
|
|
}
|
|
if (realFifo == GPFifo) {
|
|
SOME_MACRO1(realFifo);
|
|
SOME_MACRO2(realFifo);
|
|
}
|
|
else {
|
|
realFifo->count = (u8 *)realFifo->wrPtr - (u8 *)realFifo->rdPtr;
|
|
if (realFifo->count < 0) {
|
|
realFifo->count += realFifo->size;
|
|
}
|
|
}
|
|
*readPtr = realFifo->rdPtr;
|
|
*writePtr = realFifo->wrPtr;
|
|
}
|
|
|
|
void *GXGetFifoBase(const GXFifoObj *fifo)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
|
|
return realFifo->base;
|
|
}
|
|
|
|
u32 GXGetFifoSize(const GXFifoObj *fifo)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
|
|
return realFifo->size;
|
|
}
|
|
|
|
void GXGetFifoLimits(const GXFifoObj *fifo, u32 *hi, u32 *lo)
|
|
{
|
|
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
|
|
|
*hi = realFifo->hiWatermark;
|
|
*lo = realFifo->loWatermark;
|
|
}
|
|
|
|
GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb)
|
|
{
|
|
GXBreakPtCallback oldcb = BreakPointCB;
|
|
BOOL enabled = OSDisableInterrupts();
|
|
|
|
BreakPointCB = cb;
|
|
OSRestoreInterrupts(enabled);
|
|
return oldcb;
|
|
}
|
|
|
|
void *__GXCurrentBP;
|
|
|
|
void GXEnableBreakPt(void *break_pt)
|
|
{
|
|
BOOL enabled = OSDisableInterrupts();
|
|
|
|
__GXFifoReadDisable();
|
|
GX_SET_CP_REG(30, (u32)break_pt);
|
|
GX_SET_CP_REG(31, ((u32)break_pt >> 16) & 0x3FFF);
|
|
SOME_SET_REG_MACRO(gx->cpEnable, 1, 1, 1);
|
|
SOME_SET_REG_MACRO(gx->cpEnable, 1, 5, 1);
|
|
GX_SET_CP_REG(1, gx->cpEnable);
|
|
__GXCurrentBP = break_pt;
|
|
__GXFifoReadEnable();
|
|
OSRestoreInterrupts(enabled);
|
|
}
|
|
|
|
void GXDisableBreakPt(void)
|
|
{
|
|
BOOL enabled = OSDisableInterrupts();
|
|
|
|
SOME_SET_REG_MACRO(gx->cpEnable, 1, 1, 0);
|
|
SOME_SET_REG_MACRO(gx->cpEnable, 1, 5, 0);
|
|
GX_SET_CP_REG(1, gx->cpEnable);
|
|
__GXCurrentBP = NULL;
|
|
OSRestoreInterrupts(enabled);
|
|
}
|
|
|
|
void __GXFifoInit(void)
|
|
{
|
|
__OSSetInterruptHandler(0x11, GXCPInterruptHandler);
|
|
__OSUnmaskInterrupts(0x4000);
|
|
__GXCurrentThread = OSGetCurrentThread();
|
|
GXOverflowSuspendInProgress = FALSE;
|
|
CPUFifo = NULL;
|
|
GPFifo = NULL;
|
|
}
|
|
|
|
static void __GXFifoReadEnable(void)
|
|
{
|
|
SET_REG_FIELD(0, gx->cpEnable, 1, 0, 1);
|
|
GX_SET_CP_REG(1, gx->cpEnable);
|
|
}
|
|
|
|
static void __GXFifoReadDisable(void)
|
|
{
|
|
SET_REG_FIELD(0, gx->cpEnable, 1, 0, 0);
|
|
GX_SET_CP_REG(1, gx->cpEnable);
|
|
}
|
|
|
|
static void __GXFifoLink(u8 en)
|
|
{
|
|
SET_REG_FIELD(0x4DA, gx->cpEnable, 1, 4, (en != 0) ? 1 : 0);
|
|
GX_SET_CP_REG(1, gx->cpEnable);
|
|
}
|
|
|
|
static void __GXWriteFifoIntEnable(u8 hiWatermarkEn, u8 loWatermarkEn)
|
|
{
|
|
SET_REG_FIELD(0x4F0, gx->cpEnable, 1, 2, hiWatermarkEn);
|
|
SET_REG_FIELD(0x4F1, gx->cpEnable, 1, 3, loWatermarkEn);
|
|
GX_SET_CP_REG(1, gx->cpEnable);
|
|
}
|
|
|
|
static void __GXWriteFifoIntReset(u8 hiWatermarkClr, u8 loWatermarkClr)
|
|
{
|
|
SET_REG_FIELD(0x508, gx->cpClr, 1, 0, hiWatermarkClr);
|
|
SET_REG_FIELD(0x509, gx->cpClr, 1, 1, loWatermarkClr);
|
|
GX_SET_CP_REG(2, gx->cpClr);
|
|
}
|
|
|
|
void __GXInsaneWatermark(void)
|
|
{
|
|
struct __GXFifoObj *realFifo = GPFifo;
|
|
|
|
realFifo->hiWatermark = realFifo->loWatermark + 512;
|
|
GX_SET_CP_REG(20, (realFifo->hiWatermark & 0x3FFFFFFF) & 0xFFFF);
|
|
GX_SET_CP_REG(21, (realFifo->hiWatermark & 0x3FFFFFFF) >> 16);
|
|
}
|
|
|
|
void __GXCleanGPFifo(void)
|
|
{
|
|
GXFifoObj dummyFifo;
|
|
GXFifoObj *gpFifo = GXGetGPFifo();
|
|
GXFifoObj *cpuFifo = GXGetCPUFifo();
|
|
void *base = GXGetFifoBase(gpFifo);
|
|
|
|
dummyFifo = *gpFifo;
|
|
GXInitFifoPtrs(&dummyFifo, base, base);
|
|
GXSetGPFifo(&dummyFifo);
|
|
if (cpuFifo == gpFifo) {
|
|
GXSetCPUFifo(&dummyFifo);
|
|
}
|
|
GXInitFifoPtrs(gpFifo, base, base);
|
|
GXSetGPFifo(gpFifo);
|
|
if (cpuFifo == gpFifo) {
|
|
GXSetCPUFifo(cpuFifo);
|
|
}
|
|
}
|
|
|
|
OSThread *GXSetCurrentGXThread(void)
|
|
{
|
|
BOOL enabled;
|
|
struct OSThread *prev;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
prev = __GXCurrentThread;
|
|
ASSERTMSGLINE(0x561, !GXOverflowSuspendInProgress, "GXSetCurrentGXThread: Two threads cannot generate GX commands at the same time!");
|
|
__GXCurrentThread = OSGetCurrentThread();
|
|
OSRestoreInterrupts(enabled);
|
|
return prev;
|
|
}
|
|
|
|
OSThread *GXGetCurrentGXThread(void)
|
|
{
|
|
return __GXCurrentThread;
|
|
}
|
|
|
|
GXFifoObj *GXGetCPUFifo(void)
|
|
{
|
|
return (GXFifoObj *)CPUFifo;
|
|
}
|
|
|
|
GXFifoObj *GXGetGPFifo(void)
|
|
{
|
|
return (GXFifoObj *)GPFifo;
|
|
}
|
|
|
|
u32 GXGetOverflowCount(void)
|
|
{
|
|
return __GXOverflowCount;
|
|
}
|
|
|
|
u32 GXResetOverflowCount(void)
|
|
{
|
|
u32 oldcount;
|
|
|
|
oldcount = __GXOverflowCount;
|
|
__GXOverflowCount = 0;
|
|
return oldcount;
|
|
}
|
|
|
|
// NONMATCHING
|
|
volatile void *GXRedirectWriteGatherPipe(void *ptr)
|
|
{
|
|
u32 reg = 0;
|
|
BOOL enabled = OSDisableInterrupts();
|
|
|
|
CHECK_GXBEGIN(0x5D5, "GXRedirectWriteGatherPipe");
|
|
ASSERTLINE(0x5D6, OFFSET(ptr, 32) == 0);
|
|
ASSERTLINE(0x5D8, !IsWGPipeRedirected);
|
|
|
|
GXFlush();
|
|
while (PPCMfwpar() & 1) { }
|
|
PPCMtwpar((u32)OSUncachedToPhysical((void *)GXFIFO_ADDR));
|
|
if (CPGPLinked) {
|
|
__GXFifoLink(0);
|
|
__GXWriteFifoIntEnable(0, 0);
|
|
}
|
|
CPUFifo->wrPtr = OSPhysicalToCached(GX_GET_PI_REG(5) & 0xFBFFFFFF);
|
|
GX_SET_PI_REG(3, 0);
|
|
GX_SET_PI_REG(4, 0x04000000);
|
|
SET_REG_FIELD(0x5F7, reg, 21, 5, ((u32)ptr & 0x3FFFFFFF) >> 5);
|
|
reg &= 0xFBFFFFFF;
|
|
GX_SET_PI_REG(5, reg);
|
|
PPCSync();
|
|
OSRestoreInterrupts(enabled);
|
|
return (volatile void *)GXFIFO_ADDR;
|
|
}
|
|
|
|
// NONMATCHING
|
|
void GXRestoreWriteGatherPipe(void)
|
|
{
|
|
u32 reg = 0; // r31
|
|
u32 i; // r29
|
|
BOOL enabled; // r28
|
|
|
|
ASSERTLINE(0x610, IsWGPipeRedirected);
|
|
enabled = OSDisableInterrupts();
|
|
for (i = 0; i < 31; i++) {
|
|
GXWGFifo.u8 = 0;
|
|
}
|
|
PPCSync();
|
|
while (PPCMfwpar() & 1) { }
|
|
PPCMtwpar((u32)OSUncachedToPhysical((void *)GXFIFO_ADDR));
|
|
GX_SET_PI_REG(3, (u32)CPUFifo->base & 0x3FFFFFFF);
|
|
GX_SET_PI_REG(4, (u32)CPUFifo->top & 0x3FFFFFFF);
|
|
SET_REG_FIELD(0x62A, reg, 21, 5, ((u32)CPUFifo->wrPtr & 0x3FFFFFFF) >> 5);
|
|
reg &= 0xFBFFFFFF;
|
|
GX_SET_PI_REG(5, reg);
|
|
if (CPGPLinked) {
|
|
__GXWriteFifoIntReset(1, 1);
|
|
__GXWriteFifoIntEnable(1, 0);
|
|
__GXFifoLink(1);
|
|
}
|
|
PPCSync();
|
|
OSRestoreInterrupts(enabled);
|
|
}
|