summaryrefslogtreecommitdiff
path: root/arm9/lib/src
diff options
context:
space:
mode:
authorred031000 <rubenru09@aol.com>2020-06-29 22:37:12 +0100
committerred031000 <rubenru09@aol.com>2020-06-29 22:37:12 +0100
commit32fee85569e5dbae8d26512e15fc16017f293d37 (patch)
tree7b6c5fa308c13af3fef81d63563dc765b1b0c537 /arm9/lib/src
parenta0d97c85151a1a1750176f29edaad02355887c06 (diff)
arm9 MI_dma
Diffstat (limited to 'arm9/lib/src')
-rw-r--r--arm9/lib/src/MI_dma.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/arm9/lib/src/MI_dma.c b/arm9/lib/src/MI_dma.c
new file mode 100644
index 00000000..565b1ef6
--- /dev/null
+++ b/arm9/lib/src/MI_dma.c
@@ -0,0 +1,307 @@
+#include "MI_dma.h"
+#include "function_target.h"
+#include "OS_interrupt.h"
+#include "OS_terminate_proc.h"
+#include "sections.h"
+
+#pragma section ITCM begin
+ARM_FUNC void MIi_DmaSetParams(u32 dmaNo, u32 src, u32 dest, u32 ctrl)
+{
+ OSIntrMode lastIntrMode = OS_DisableInterrupts();
+ vu32 *p = (vu32 *)((u32)REG_ADDR_DMA0SAD + dmaNo * 12);
+ *p = (vu32)src;
+ *(p + 1) = (vu32)dest;
+ *(p + 2) = (vu32)ctrl;
+ (void)OS_RestoreInterrupts(lastIntrMode);
+}
+
+ARM_FUNC void MIi_DmaSetParams_wait(u32 dmaNo, u32 src, u32 dest, u32 ctrl)
+{
+ OSIntrMode enabled = OS_DisableInterrupts();
+ vu32 *p = (vu32 *)((u32)REG_ADDR_DMA0SAD + dmaNo * 12);
+ *p = (vu32)src;
+ *(p + 1) = (vu32)dest;
+ *(p + 2) = (vu32)ctrl;
+
+ //delay cycles
+ {
+ u32 delay = reg_MI_DMA0SAD;
+ }
+ {
+ u32 delay = reg_MI_DMA0SAD;
+ }
+
+ if (!dmaNo)
+ {
+ *p = (vu32)0;
+ *(p + 1) = (vu32)0;
+ *(p + 2) = (vu32)0x81400001;
+ }
+
+ (void)OS_RestoreInterrupts(enabled);
+}
+
+ARM_FUNC void MIi_DmaSetParams_noInt(u32 dmaNo, u32 src, u32 dest, u32 ctrl)
+{
+ vu32 *p = (vu32 *)((u32)REG_ADDR_DMA0SAD + dmaNo * 12);
+ *p = (vu32)src;
+ *(p + 1) = (vu32)dest;
+ *(p + 2) = (vu32)ctrl;
+}
+
+ARM_FUNC void MIi_DmaSetParams_wait_noInt(u32 dmaNo, u32 src, u32 dest, u32 ctrl)
+{
+ vu32 *p = (vu32 *)((u32)REG_ADDR_DMA0SAD + dmaNo * 12);
+ *p = (vu32)src;
+ *(p + 1) = (vu32)dest;
+ *(p + 2) = (vu32)ctrl;
+
+ //delay cycles
+ {
+ u32 delay = reg_MI_DMA0SAD;
+ }
+ {
+ u32 delay = reg_MI_DMA0SAD;
+ }
+
+ if (!dmaNo)
+ {
+ *p = (vu32)0;
+ *(p + 1) = (vu32)0;
+ *(p + 2) = (vu32)0x81400001;
+ }
+
+ //delay cycles
+ {
+ u32 delay = reg_MI_DMA0SAD;
+ }
+ {
+ u32 delay = reg_MI_DMA0SAD;
+ }
+}
+#pragma section ITCM end
+
+ARM_FUNC void MI_DmaFill32(u32 dmaNo, void *dest, u32 data, u32 size)
+{
+ vu32 *dmaCntp;
+ if (!size)
+ {
+ return;
+ }
+
+ do
+ {
+ dmaCntp = &((vu32 *)REG_ADDR_DMA0SAD)[dmaNo * 3 + 2];
+ while (*dmaCntp & 0x80000000) {}
+ } while(0);
+
+ MIi_DmaSetParams_wait_src32(dmaNo, data, (u32)dest, MI_CNT_CLEAR32(size));
+
+ do
+ {
+ while (*dmaCntp & 0x80000000) {}
+ } while(0);
+}
+
+ARM_FUNC void MI_DmaCopy32(u32 dmaNo, const void *src, void *dest, u32 size)
+{
+ vu32 *dmaCntp;
+ MIi_CheckDma0SourceAddress(dmaNo, (u32)src, size, DMA_SRC_INC);
+
+ if (!size)
+ {
+ return;
+ }
+
+ do
+ {
+ dmaCntp = &((vu32 *)REG_ADDR_DMA0SAD)[dmaNo * 3 + 2];
+ while (*dmaCntp & 0x80000000) {}
+ } while(0);
+
+ MIi_DmaSetParams_wait(dmaNo, (u32)src, (u32)dest, MI_CNT_COPY32(size));
+
+ do
+ {
+ while (*dmaCntp & 0x80000000) {}
+ } while(0);
+}
+
+ARM_FUNC void MI_DmaCopy16(u32 dmaNo, const void *src, void *dest, u32 size)
+{
+ vu32 *dmaCntp;
+
+ if (!size)
+ {
+ return;
+ }
+
+ MIi_CheckDma0SourceAddress(dmaNo, (u32)src, size, DMA_SRC_INC);
+
+ do
+ {
+ dmaCntp = &((vu32 *)REG_ADDR_DMA0SAD)[dmaNo * 3 + 2];
+ while (*dmaCntp & 0x80000000) {}
+ } while(0);
+
+ MIi_DmaSetParams_wait(dmaNo, (u32)src, (u32)dest, MI_CNT_COPY16(size));
+
+ do
+ {
+ while (*dmaCntp & 0x80000000) {}
+ } while(0);
+}
+
+ARM_FUNC void MI_DmaFill32Async(u32 dmaNo, void *dest, u32 data, u32 size, MIDmaCallback callback, void *arg)
+{
+ if (!size)
+ {
+ MIi_CallCallback(callback, arg);
+ }
+ else
+ {
+ MI_WaitDma(dmaNo);
+
+ if (callback)
+ {
+ OSi_EnterDmaCallback(dmaNo, callback, arg);
+ MIi_DmaSetParams_src32(dmaNo, data, (u32)dest, MI_CNT_CLEAR32_IF(size));
+ }
+ else
+ {
+ MIi_DmaSetParams_src32(dmaNo, data, (u32)dest, MI_CNT_CLEAR32(size));
+ }
+ }
+}
+
+ARM_FUNC void MI_DmaCopy32Async(u32 dmaNo, const void *src, void *dest, u32 size, MIDmaCallback callback, void *arg)
+{
+ MIi_CheckDma0SourceAddress(dmaNo, (u32)src, size, DMA_SRC_INC);
+
+ if (!size)
+ {
+ MIi_CallCallback(callback, arg);
+ }
+ else
+ {
+ MI_WaitDma(dmaNo);
+
+ if (callback)
+ {
+ OSi_EnterDmaCallback(dmaNo, callback, arg);
+ MIi_DmaSetParams(dmaNo, (u32)src, (u32)dest, MI_CNT_COPY32_IF(size));
+ }
+ else
+ {
+ MIi_DmaSetParams(dmaNo, (u32)src, (u32)dest, MI_CNT_COPY32(size));
+ }
+ }
+}
+
+ARM_FUNC void MI_WaitDma(u32 dmaNo)
+{
+ OSIntrMode lastIntrMode = OS_DisableInterrupts();
+ vu32 *dmaCntp = &((vu32 *)REG_ADDR_DMA0SAD)[dmaNo * 3 + 2];
+
+ while (*dmaCntp & 0x80000000) {}
+
+ if (!dmaNo)
+ {
+ vu32 *p = (vu32 *)((u32)REG_ADDR_DMA0SAD + dmaNo * 12);
+ *p = (vu32)0;
+ *(p + 1) = (vu32)0;
+ *(p + 2) = (vu32)0x81400001;
+ }
+
+ (void)OS_RestoreInterrupts(lastIntrMode);
+}
+
+ARM_FUNC void MI_StopDma(u32 dmaNo)
+{
+ OSIntrMode lastIntrMode = OS_DisableInterrupts();
+ vu16 *dmaCntp = &((vu16 *)REG_ADDR_DMA0SAD)[dmaNo * 6 + 5];
+
+ *dmaCntp &= ~0x3a00;
+ *dmaCntp &= ~0x8000;
+
+ //delay cycles
+ {
+ s32 delay = dmaCntp[0];
+ }
+ {
+ s32 delay = dmaCntp[0];
+ }
+
+ if (!dmaNo)
+ {
+ vu32 *p = (vu32 *)((u32)REG_ADDR_DMA0SAD + dmaNo * 12);
+ *p = (vu32)0;
+ *(p + 1) = (vu32)0;
+ *(p + 2) = (vu32)0x81400001;
+ }
+
+ (void)OS_RestoreInterrupts(lastIntrMode);
+}
+
+ARM_FUNC void MIi_CheckAnotherAutoDMA(u32 dmaNo, u32 dmaType)
+{
+ u32 dmaCnt;
+ u32 timing;
+ for (int i = 0; i < 3; i++)
+ {
+ if (i == dmaNo) continue;
+
+ dmaCnt = *(REGType32v *)(REG_ADDR_DMA0CNT + i * 12);
+
+ if (!(dmaCnt & 0x80000000)) continue;
+
+ timing = dmaCnt & 0x38000000;
+
+ if (timing == dmaType
+ || (timing == 0x8000000 && dmaType == 0x10000000)
+ || (timing == 0x10000000 && dmaType == 0x8000000))
+ {
+ continue;
+ }
+
+ if (timing == 0x18000000
+ || timing == 0x20000000
+ || timing == 0x28000000
+ || timing == 0x30000000
+ || timing == 0x38000000
+ || timing == 0x8000000
+ || timing == 0x10000000)
+ {
+ OS_Terminate();
+ }
+ }
+}
+
+ARM_FUNC void MIi_CheckDma0SourceAddress(u32 dmaNo, u32 src, u32 size, u32 dir)
+{
+ if (!dmaNo)
+ {
+ u32 addStart = src & 0xff000000;
+ u32 addEnd;
+
+ switch (dir)
+ {
+ case 0: //dma_src_inc
+ addEnd = src + size;
+ break;
+ case 0x800000: //dma_src_dec
+ addEnd = src - size;
+ break;
+ default:
+ addEnd = src;
+ break;
+ }
+ addEnd &= 0xff000000;
+
+ if (addStart == 0x04000000 || addStart >= 0x08000000 ||
+ addEnd == 0x04000000 || addEnd >= 0x08000000)
+ {
+ OS_Terminate();
+ }
+ }
+}