summaryrefslogtreecommitdiff
path: root/arm9/lib/src/CARD_common.c
diff options
context:
space:
mode:
authorred031000 <rubenru09@aol.com>2020-09-16 18:18:33 +0100
committerred031000 <rubenru09@aol.com>2020-09-16 18:21:28 +0100
commit1e3c383ff53842cd2fe2134278b448fffebb15e9 (patch)
tree3a0c1dc4ce85764c1a6761d2bde821752231a889 /arm9/lib/src/CARD_common.c
parenta013685f0bd75d8070971d96b79e4c146d5fbcaf (diff)
arm9 CARD_common
Diffstat (limited to 'arm9/lib/src/CARD_common.c')
-rw-r--r--arm9/lib/src/CARD_common.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/arm9/lib/src/CARD_common.c b/arm9/lib/src/CARD_common.c
new file mode 100644
index 00000000..f02d10e2
--- /dev/null
+++ b/arm9/lib/src/CARD_common.c
@@ -0,0 +1,184 @@
+#include "CARD_common.h"
+#include "consts.h"
+#include "function_target.h"
+#include "MI_memory.h"
+#include "OS_system.h"
+#include "OS_terminate_proc.h"
+#include "OS_spinLock.h"
+#include "OS_cache.h"
+#include "MB_mb.h"
+#include "PXI_fifo.h"
+
+CARDiCommon cardi_common ALIGN(32);
+static CARDiCommandArg cardi_arg ALIGN(32);
+
+u8 cardi_thread_stack[0x400] ALIGN(4);
+
+extern void CARDi_TaskThread(void *arg);
+extern void PXI_SetFifoRecvCallback(u32 param1, void* callback);
+extern void CARDi_OnFifoRecv(PXIFifoTag tag, u32 data, BOOL err);
+
+static void CARDi_LockResource(CARDiOwner owner, CARDTargetMode target);
+static void CARDi_UnlockResource(CARDiOwner owner, CARDTargetMode target);
+
+ARM_FUNC void CARDi_SetTask(void (*task) (CARDiCommon *))
+{
+ CARDiCommon *const p = &cardi_common;
+
+ (void)OS_SetThreadPriority(p->thread, p->priority);
+
+ p->cur_th = p->thread;
+ p->task_func = task;
+ p->flag |= CARD_STAT_TASK;
+ OS_WakeupThreadDirect(p->thread);
+}
+
+ARM_FUNC static void CARDi_LockResource(CARDiOwner owner, CARDTargetMode target)
+{
+ CARDiCommon *const p = &cardi_common;
+ OSIntrMode bak_psr = OS_DisableInterrupts();
+ if (p->lock_owner == owner)
+ {
+ if (p->lock_target != target)
+ {
+ OS_Terminate();
+ }
+ }
+ else
+ {
+ while (p->lock_owner != OS_LOCK_ID_ERROR)
+ {
+ OS_SleepThread(p->lock_queue);
+ }
+ p->lock_owner = owner;
+ p->lock_target = target;
+ }
+ ++p->lock_ref;
+ p->cmd->result = CARD_RESULT_SUCCESS;
+ (void)OS_RestoreInterrupts(bak_psr);
+}
+
+ARM_FUNC static void CARDi_UnlockResource(CARDiOwner owner, CARDTargetMode target)
+{
+ CARDiCommon *p = &cardi_common;
+ OSIntrMode bak_psr = OS_DisableInterrupts();
+ if ((p->lock_owner != owner) || !p->lock_ref)
+ {
+ OS_Terminate();
+ }
+ else
+ {
+ if (p->lock_target != target)
+ {
+ OS_Terminate();
+ }
+ if (!--p->lock_ref)
+ {
+ p->lock_owner = OS_LOCK_ID_ERROR;
+ p->lock_target = CARD_TARGET_NONE;
+ OS_WakeupThread(p->lock_queue);
+ }
+ }
+ p->cmd->result = CARD_RESULT_SUCCESS;
+ (void)OS_RestoreInterrupts(bak_psr);
+}
+
+ARM_FUNC void CARDi_InitCommon(void)
+{
+ CARDiCommon *p = &cardi_common;
+
+ p->lock_owner = OS_LOCK_ID_ERROR;
+ p->lock_ref = 0;
+ p->lock_target = CARD_TARGET_NONE;
+
+ p->cmd = &cardi_arg;
+ MI_CpuFillFast(&cardi_arg, 0x00, sizeof(cardi_arg));
+ DC_FlushRange(&cardi_arg, sizeof(cardi_arg));
+
+ if (!MB_IsMultiBootChild())
+ {
+ MI_CpuCopy8((const void *)HW_ROM_HEADER_BUF, (void *)HW_CARD_ROM_HEADER, HW_CARD_ROM_HEADER_SIZE);
+ }
+ OS_InitThreadQueue(p->lock_queue);
+ OS_InitThreadQueue(p->busy_q);
+ p->priority = CARD_THREAD_PRIORITY_DEFAULT;
+ OS_CreateThread(p->thread, CARDi_TaskThread, NULL, cardi_thread_stack + sizeof(cardi_thread_stack),
+ sizeof(cardi_thread_stack), p->priority);
+ OS_WakeupThreadDirect(p->thread);
+
+ PXI_SetFifoRecvCallback(PXI_FIFO_TAG_FS, CARDi_OnFifoRecv);
+
+ if (!MB_IsMultiBootChild())
+ {
+ CARD_Enable(TRUE);
+ }
+}
+
+static BOOL CARDi_EnableFlag = FALSE;
+
+ARM_FUNC BOOL CARD_IsEnabled(void)
+{
+ return CARDi_EnableFlag;
+}
+
+ARM_FUNC void CARD_CheckEnabled(void)
+{
+ if (!CARD_IsEnabled())
+ {
+ OS_Terminate();
+ }
+}
+
+ARM_FUNC void CARD_Enable(BOOL enable)
+{
+ CARDi_EnableFlag = enable;
+}
+
+ARM_FUNC BOOL CARDi_WaitAsync(void)
+{
+ CARDiCommon *const p = &cardi_common;
+
+ OSIntrMode bak_psr = OS_DisableInterrupts();
+ while ((p->flag & CARD_STAT_BUSY) != 0)
+ {
+ OS_SleepThread(p->busy_q);
+ }
+ (void)OS_RestoreInterrupts(bak_psr);
+ return (p->cmd->result == CARD_RESULT_SUCCESS);
+}
+
+ARM_FUNC BOOL CARDi_TryWaitAsync(void)
+{
+ CARDiCommon *const p = &cardi_common;
+
+ return !(p->flag & CARD_STAT_BUSY);
+}
+
+ARM_FUNC CARDResult CARD_GetResultCode(void)
+{
+ CARDiCommon *const p = &cardi_common;
+
+ return p->cmd->result;
+}
+
+ARM_FUNC void CARD_LockRom(u16 lock_id)
+{
+ CARDi_LockResource(lock_id, CARD_TARGET_ROM);
+ (void)OS_TryLockCard(lock_id);
+}
+
+ARM_FUNC void CARD_UnlockRom(u16 lock_id)
+{
+ (void)OS_UnlockCard(lock_id);
+ CARDi_UnlockResource(lock_id, CARD_TARGET_ROM);
+}
+
+ARM_FUNC void CARD_LockBackup(u16 lock_id)
+{
+ CARDi_LockResource(lock_id, CARD_TARGET_BACKUP);
+}
+
+ARM_FUNC void CARD_UnlockBackup(u16 lock_id)
+{
+ CARDi_UnlockResource(lock_id, CARD_TARGET_BACKUP);
+}