251 lines
No EOL
5.6 KiB
C
251 lines
No EOL
5.6 KiB
C
#include "dolphin/ar.h"
|
|
|
|
#include "dolphin/hw_regs.h"
|
|
#include "dolphin/os.h"
|
|
|
|
static ARCallback __AR_Callback;
|
|
static u32 __AR_Size;
|
|
static u32 __AR_InternalSize;
|
|
static u32 __AR_ExpansionSize;
|
|
|
|
static u32 __AR_StackPointer;
|
|
static u32 __AR_FreeBlocks;
|
|
static u32* __AR_BlockLength;
|
|
|
|
static volatile BOOL __AR_init_flag = FALSE;
|
|
|
|
static void __ARHandler(__OSInterrupt interrupt, OSContext* context);
|
|
static void __ARChecksize(void);
|
|
static void __ARClearArea(u32 start_addr, u32 length);
|
|
|
|
ARCallback ARRegisterDMACallback(ARCallback callback) {
|
|
ARCallback oldCb;
|
|
BOOL enabled;
|
|
oldCb = __AR_Callback;
|
|
enabled = OSDisableInterrupts();
|
|
__AR_Callback = callback;
|
|
OSRestoreInterrupts(enabled);
|
|
return oldCb;
|
|
}
|
|
|
|
u32 ARGetDMAStatus() {
|
|
BOOL enabled;
|
|
u32 val;
|
|
enabled = OSDisableInterrupts();
|
|
val = __DSPRegs[5] & 0x0200;
|
|
OSRestoreInterrupts(enabled);
|
|
return val;
|
|
}
|
|
|
|
void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length) {
|
|
BOOL enabled;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
|
|
__DSPRegs[16] = (u16)(__DSPRegs[16] & ~0x3ff) | (u16)(mainmem_addr >> 16);
|
|
__DSPRegs[17] = (u16)(__DSPRegs[17] & ~0xffe0) | (u16)(mainmem_addr & 0xffff);
|
|
__DSPRegs[18] = (u16)(__DSPRegs[18] & ~0x3ff) | (u16)(aram_addr >> 16);
|
|
__DSPRegs[19] = (u16)(__DSPRegs[19] & ~0xffe0) | (u16)(aram_addr & 0xffff);
|
|
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x8000) | (type << 15));
|
|
__DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x3ff) | (u16)(length >> 16);
|
|
__DSPRegs[21] = (u16)(__DSPRegs[21] & ~0xffe0) | (u16)(length & 0xffff);
|
|
OSRestoreInterrupts(enabled);
|
|
}
|
|
|
|
u32 ARAlloc(u32 length) {
|
|
u32 tmp;
|
|
BOOL enabled;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
tmp = __AR_StackPointer;
|
|
__AR_StackPointer += length;
|
|
*__AR_BlockLength = length;
|
|
__AR_BlockLength++;
|
|
__AR_FreeBlocks--;
|
|
OSRestoreInterrupts(enabled);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
#if NONMATCHING
|
|
u32 ARFree(u32* length) {
|
|
BOOL old;
|
|
|
|
old = OSDisableInterrupts();
|
|
|
|
__AR_BlockLength--;
|
|
|
|
if (length) {
|
|
*length = *__AR_BlockLength;
|
|
}
|
|
|
|
__AR_StackPointer -= *__AR_BlockLength;
|
|
|
|
__AR_FreeBlocks++;
|
|
|
|
OSRestoreInterrupts(old);
|
|
|
|
return __AR_StackPointer;
|
|
}
|
|
#else
|
|
/* clang-format off */
|
|
#pragma push
|
|
#pragma optimization_level 0
|
|
#pragma optimizewithasm off
|
|
asm u32 ARFree(u32* length) {
|
|
nofralloc
|
|
mflr r0
|
|
stw r0, 4(r1)
|
|
stwu r1, -0x18(r1)
|
|
stw r31, 0x14(r1)
|
|
mr r31, r3
|
|
bl OSDisableInterrupts
|
|
lwz r4, __AR_BlockLength
|
|
cmplwi r31, 0
|
|
addi r0, r4, -4
|
|
stw r0, __AR_BlockLength
|
|
beq lbl_8036DAB4
|
|
lwz r4, __AR_BlockLength
|
|
lwz r0, 0(r4)
|
|
stw r0, 0(r31)
|
|
lbl_8036DAB4:
|
|
lwz r5, __AR_BlockLength
|
|
lwz r4, __AR_FreeBlocks
|
|
lwz r6, 0(r5)
|
|
addi r0, r4, 1
|
|
lwz r5, __AR_StackPointer
|
|
stw r0, __AR_FreeBlocks
|
|
subf r0, r6, r5
|
|
stw r0, __AR_StackPointer
|
|
bl OSRestoreInterrupts
|
|
lwz r3, __AR_StackPointer
|
|
lwz r0, 0x1c(r1)
|
|
lwz r31, 0x14(r1)
|
|
addi r1, r1, 0x18
|
|
mtlr r0
|
|
blr
|
|
}
|
|
#pragma pop
|
|
/* clang-format on */
|
|
#endif
|
|
|
|
BOOL ARCheckInit() { return __AR_init_flag; }
|
|
|
|
u32 ARInit(u32* stack_index_addr, u32 num_entries) {
|
|
|
|
BOOL old;
|
|
u16 refresh;
|
|
|
|
if (__AR_init_flag == TRUE) {
|
|
return 0x4000;
|
|
}
|
|
|
|
old = OSDisableInterrupts();
|
|
|
|
__AR_Callback = NULL;
|
|
|
|
__OSSetInterruptHandler(__OS_INTERRUPT_DSP_ARAM, __ARHandler);
|
|
__OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_ARAM);
|
|
|
|
__AR_StackPointer = 0x4000;
|
|
__AR_FreeBlocks = num_entries;
|
|
__AR_BlockLength = stack_index_addr;
|
|
|
|
refresh = (u16)(__DSPRegs[13] & 0x000000ff);
|
|
|
|
__DSPRegs[13] = (u16)((__DSPRegs[13] & ~0x000000ff) | (refresh & 0x000000ff));
|
|
|
|
__ARChecksize();
|
|
|
|
__AR_init_flag = TRUE;
|
|
|
|
OSRestoreInterrupts(old);
|
|
|
|
return __AR_StackPointer;
|
|
}
|
|
|
|
u32 ARGetBaseAddress(void) { return 0x4000; }
|
|
|
|
void ARSetSize(void)
|
|
{
|
|
|
|
}
|
|
|
|
u32 ARGetSize() { return __AR_Size; }
|
|
|
|
static void __ARHandler(__OSInterrupt interrupt, OSContext* context) {
|
|
|
|
OSContext exceptionContext;
|
|
u16 tmp;
|
|
|
|
tmp = __DSPRegs[5];
|
|
tmp = (u16)((tmp & ~0x00000088) | 0x20);
|
|
__DSPRegs[5] = tmp;
|
|
|
|
OSClearContext(&exceptionContext);
|
|
OSSetCurrentContext(&exceptionContext);
|
|
|
|
if (__AR_Callback) {
|
|
(*__AR_Callback)();
|
|
}
|
|
|
|
OSClearContext(&exceptionContext);
|
|
OSSetCurrentContext(context);
|
|
}
|
|
|
|
#define RoundUP32(x) (((u32)(x) + 32 - 1) & ~(32 - 1))
|
|
|
|
void __ARClearInterrupt(void) {
|
|
|
|
u16 tmp;
|
|
tmp = __DSPRegs[5];
|
|
tmp = (u16)((tmp & ~(0x00000080 | 0x00000008)) | 0x00000020);
|
|
__DSPRegs[5] = tmp;
|
|
}
|
|
u16 __ARGetInterruptStatus(void) { return ((u16)(__DSPRegs[5] & 0x0200)); }
|
|
|
|
static void __ARWaitForDMA(void) {
|
|
|
|
while (__DSPRegs[5] & 0x0200) {
|
|
}
|
|
}
|
|
|
|
static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length) {
|
|
|
|
__DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16));
|
|
__DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff));
|
|
|
|
__DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16));
|
|
__DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff));
|
|
|
|
__DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x8000);
|
|
|
|
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16));
|
|
__DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff));
|
|
|
|
__ARWaitForDMA();
|
|
|
|
__ARClearInterrupt();
|
|
}
|
|
|
|
static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length) {
|
|
|
|
__DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16));
|
|
__DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff));
|
|
|
|
__DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16));
|
|
__DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff));
|
|
|
|
__DSPRegs[20] = (u16)(__DSPRegs[20] | 0x8000);
|
|
|
|
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16));
|
|
__DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff));
|
|
|
|
__ARWaitForDMA();
|
|
|
|
__ARClearInterrupt();
|
|
}
|
|
|
|
static void __ARChecksize(void) {
|
|
//TODO: Implement for this SDK version
|
|
} |