summaryrefslogtreecommitdiff
path: root/src/Dolphin/ar/arq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Dolphin/ar/arq.c')
-rw-r--r--src/Dolphin/ar/arq.c170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/Dolphin/ar/arq.c b/src/Dolphin/ar/arq.c
new file mode 100644
index 0000000..d157463
--- /dev/null
+++ b/src/Dolphin/ar/arq.c
@@ -0,0 +1,170 @@
+#include "dolphin/arq.h"
+#include "dolphin/os.h"
+
+const char* __ARQVersion = "<< Dolphin SDK - ARQ\trelease build: Sep 5 2002 05:34:29 (0x2301) >>";
+static ARQRequest* __ARQRequestQueueHi;
+static ARQRequest* __ARQRequestTailHi;
+static ARQRequest* __ARQRequestQueueLo;
+static ARQRequest* __ARQRequestTailLo;
+static ARQRequest* __ARQRequestPendingHi;
+static ARQRequest* __ARQRequestPendingLo;
+static ARQCallback __ARQCallbackHi;
+static ARQCallback __ARQCallbackLo;
+static u32 __ARQChunkSize;
+
+static volatile BOOL __ARQ_init_flag = FALSE;
+
+void __ARQPopTaskQueueHi(void);
+void __ARQServiceQueueLo(void);
+void __ARQCallbackHack(void);
+void __ARQInterruptServiceRoutine(void);
+void __ARQInitTempQueue(void);
+void __ARQPushTempQueue(ARQRequest* task);
+
+void __ARQPopTaskQueueHi(void) {
+
+ if (__ARQRequestQueueHi) {
+ if (__ARQRequestQueueHi->type == ARQ_TYPE_MRAM_TO_ARAM) {
+ ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->source, __ARQRequestQueueHi->dest,
+ __ARQRequestQueueHi->length);
+ } else {
+ ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->dest, __ARQRequestQueueHi->source,
+ __ARQRequestQueueHi->length);
+ }
+
+ __ARQCallbackHi = __ARQRequestQueueHi->callback;
+
+ __ARQRequestPendingHi = __ARQRequestQueueHi;
+
+ __ARQRequestQueueHi = __ARQRequestQueueHi->next;
+ }
+}
+
+void __ARQServiceQueueLo(void) {
+
+ if ((__ARQRequestPendingLo == NULL) && (__ARQRequestQueueLo)) {
+ __ARQRequestPendingLo = __ARQRequestQueueLo;
+
+ __ARQRequestQueueLo = __ARQRequestQueueLo->next;
+ }
+
+ if (__ARQRequestPendingLo) {
+ if (__ARQRequestPendingLo->length <= __ARQChunkSize) {
+ if (__ARQRequestPendingLo->type == ARQ_TYPE_MRAM_TO_ARAM)
+ ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->source,
+ __ARQRequestPendingLo->dest, __ARQRequestPendingLo->length);
+ else
+ ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->dest,
+ __ARQRequestPendingLo->source, __ARQRequestPendingLo->length);
+
+ __ARQCallbackLo = __ARQRequestPendingLo->callback;
+ } else {
+ if (__ARQRequestPendingLo->type == ARQ_TYPE_MRAM_TO_ARAM)
+ ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->source,
+ __ARQRequestPendingLo->dest, __ARQChunkSize);
+ else
+ ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->dest,
+ __ARQRequestPendingLo->source, __ARQChunkSize);
+ }
+
+ __ARQRequestPendingLo->length -= __ARQChunkSize;
+ __ARQRequestPendingLo->source += __ARQChunkSize;
+ __ARQRequestPendingLo->dest += __ARQChunkSize;
+ }
+}
+void __ARQCallbackHack(void) { return; }
+
+void __ARQInterruptServiceRoutine(void) {
+
+ if (__ARQCallbackHi) {
+ (*__ARQCallbackHi)((u32)__ARQRequestPendingHi);
+ __ARQRequestPendingHi = NULL;
+ __ARQCallbackHi = NULL;
+ }
+
+ else if (__ARQCallbackLo) {
+ (*__ARQCallbackLo)((u32)__ARQRequestPendingLo);
+ __ARQRequestPendingLo = NULL;
+ __ARQCallbackLo = NULL;
+ }
+
+ __ARQPopTaskQueueHi();
+
+ if (__ARQRequestPendingHi == NULL)
+ __ARQServiceQueueLo();
+}
+
+void ARQInit(void) {
+
+ if (TRUE == __ARQ_init_flag) {
+ return;
+ }
+
+ OSRegisterVersion(__ARQVersion);
+ __ARQRequestQueueHi = __ARQRequestQueueLo = NULL;
+ __ARQChunkSize = ARQ_CHUNK_SIZE_DEFAULT;
+ ARRegisterDMACallback(&__ARQInterruptServiceRoutine);
+ __ARQRequestPendingHi = NULL;
+ __ARQRequestPendingLo = NULL;
+ __ARQCallbackHi = NULL;
+ __ARQCallbackLo = NULL;
+ __ARQ_init_flag = TRUE;
+}
+
+void ARQPostRequest(ARQRequest* request, u32 owner, u32 type, u32 priority, u32 source, u32 dest,
+ u32 length, ARQCallback callback) {
+
+ BOOL enabled;
+
+ request->next = NULL;
+ request->owner = owner;
+ request->type = type;
+ request->source = source;
+ request->dest = dest;
+ request->length = length;
+
+ if (callback) {
+ request->callback = callback;
+ } else {
+ request->callback = (ARQCallback)&__ARQCallbackHack;
+ }
+
+ enabled = OSDisableInterrupts();
+
+ switch (priority) {
+ case ARQ_PRIORITY_LOW:
+
+ if (__ARQRequestQueueLo) {
+ __ARQRequestTailLo->next = request;
+ } else {
+ __ARQRequestQueueLo = request;
+ }
+ __ARQRequestTailLo = request;
+
+ break;
+
+ case ARQ_PRIORITY_HIGH:
+
+ if (__ARQRequestQueueHi) {
+ __ARQRequestTailHi->next = request;
+ } else {
+ __ARQRequestQueueHi = request;
+ }
+
+ __ARQRequestTailHi = request;
+
+ break;
+ }
+
+ if ((__ARQRequestPendingHi == NULL) && (__ARQRequestPendingLo == NULL)) {
+ __ARQPopTaskQueueHi();
+
+ if (__ARQRequestPendingHi == NULL) {
+ __ARQServiceQueueLo();
+ }
+ }
+
+ OSRestoreInterrupts(enabled);
+}
+
+u32 ARQGetChunkSize(void) { return __ARQChunkSize; }