diff options
author | Revo <projectrevotpp@hotmail.com> | 2020-10-20 15:25:32 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-20 15:25:32 -0400 |
commit | 4fd265a65d78f9b9eb1ca0f0f5f99a6ff9f5c244 (patch) | |
tree | 67b2d04e437378b48d2615543f480d979aae16ce /arm9/lib/src | |
parent | af8cfa1d2d306916d89a92b089d1bfd4819601c8 (diff) | |
parent | 47cd56c94c0b01099bc37c3a1059af8bec724579 (diff) |
Merge pull request #294 from red031000/master
arm9 card_rom
Diffstat (limited to 'arm9/lib/src')
-rw-r--r-- | arm9/lib/src/CARD_rom.c | 280 | ||||
-rw-r--r-- | arm9/lib/src/OS_init.c | 2 |
2 files changed, 281 insertions, 1 deletions
diff --git a/arm9/lib/src/CARD_rom.c b/arm9/lib/src/CARD_rom.c new file mode 100644 index 00000000..6d6b1ff8 --- /dev/null +++ b/arm9/lib/src/CARD_rom.c @@ -0,0 +1,280 @@ +#include "function_target.h" +#include "nitro/types.h" +#include "CARD_pullOut.h" +#include "CARD_rom.h" +#include "MI_dma_card.h" +#include "MI_memory.h" +#include "OS_cache.h" +#include "OS_interrupt.h" + +extern u32 cardi_rom_base; +u32 cardi_rom_base; +u32 cardi_rom_header_addr = HW_ROM_HEADER_BUF; + +CARDRomStat rom_stat ALIGN(32); + +static BOOL CARDi_ReadFromCache(CARDRomStat *p); +static void CARDi_SetRomOp(u32 cmd1, u32 cmd2); +static void CARDi_SetCardDma(void); +static void CARDi_OnReadCard(void); +static void CARDi_ReadRomSyncCore(CARDiCommon *c); + +static inline BOOL CARDi_OnReadPageDirect(CARDRomStat *arg) +{ +#pragma unused(arg) + CARDiCommon *p = &cardi_common; + p->src += CARD_ROM_PAGE_SIZE; + p->dst += CARD_ROM_PAGE_SIZE; + p->len -= CARD_ROM_PAGE_SIZE; + return (p->len > 0); +} + +ARM_FUNC static BOOL CARDi_ReadFromCache(CARDRomStat *p) +{ + CARDiCommon *c = &cardi_common; + const u32 cur_page = CARD_ALIGN_HI_BIT(c->src); + if (cur_page == (u32)p->cache_page) + { + const u32 mod = c->src - cur_page; + u32 len = CARD_ROM_PAGE_SIZE - mod; + if (len > c->len) + { + len = c->len; + } + MI_CpuCopy8(p->cache_buf + mod, (void *)c->dst, len); + c->src += len; + c->dst += len; + c->len -= len; + } + return (c->len > 0); +} + +ARM_FUNC static void CARDi_SetRomOp(u32 cmd1, u32 cmd2) +{ + while ((reg_CARD_CNT & CARD_START) != 0) {} + + reg_CARD_MASTERCNT = CARDMST_SEL_ROM | CARDMST_ENABLE | CARDMST_IF_ENABLE; + { + vu8 *const p_cmd = ®_CARD_CMD; + p_cmd[0] = (u8)(cmd1 >> (8 * 3)); + p_cmd[1] = (u8)(cmd1 >> (8 * 2)); + p_cmd[2] = (u8)(cmd1 >> (8 * 1)); + p_cmd[3] = (u8)(cmd1 >> (8 * 0)); + p_cmd[4] = (u8)(cmd2 >> (8 * 3)); + p_cmd[5] = (u8)(cmd2 >> (8 * 2)); + p_cmd[6] = (u8)(cmd2 >> (8 * 1)); + p_cmd[7] = (u8)(cmd2 >> (8 * 0)); + } +} + +static inline void CARDi_SetRomOpReadPage1(u32 src) +{ + CARDi_SetRomOp((u32)(MROMOP_G_READ_PAGE | (src >> 8)), (u32)(src << 24)); +} + +ARM_FUNC static void CARDi_SetCardDma(void) +{ + CARDiCommon *const c = &cardi_common; + CARDRomStat *const p = &rom_stat; + MIi_CardDmaCopy32(c->dma, (const void *)®_CARD_DATA, (void *)c->dst, CARD_ROM_PAGE_SIZE); + CARDi_SetRomOpReadPage1(c->src); + reg_CARD_CNT = p->ctrl; +} + +ARM_FUNC static void CARDi_OnReadCard(void) +{ + CARDRomStat *const p = &rom_stat; + CARDiCommon *const c = &cardi_common; + MI_StopDma(c->dma); + if (!CARDi_OnReadPageDirect(p)) + { + (void)OS_DisableIrqMask(OS_IE_CARD_DATA); + (void)OS_ResetRequestIrqMask(OS_IE_CARD_DATA); + CARDi_ReadEnd(); + } + else + { + CARDi_SetCardDma(); + } +} + +ARM_FUNC BOOL CARDi_TryReadCardDma(CARDRomStat *p) +{ + CARDiCommon *const c = &cardi_common; + const u32 dst = c->dst; + u32 len = c->len; + const BOOL is_async = !(dst & 31) && + (c->dma <= MI_DMA_MAX_NUM) && + !CARDi_IsInTcm(dst, len) && + !CARD_ALIGN_LO_BIT(c->src | len) && + (len > 0); + p->ctrl = CARDi_GetRomFlag(CARD_COMMAND_PAGE); + if (is_async) + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + IC_InvalidateRange((void *)dst, len); + { + u32 pos = dst; + u32 mod = (dst & (HW_CACHE_LINE_SIZE - 1)); + if (mod) + { + pos -= mod; + DC_StoreRange((void *)(pos), HW_CACHE_LINE_SIZE); + DC_StoreRange((void *)(pos + len), HW_CACHE_LINE_SIZE); + len += HW_CACHE_LINE_SIZE; + } + DC_InvalidateRange((void *)pos, len); + DC_WaitWriteBufferEmpty(); + } + (void)OS_SetIrqFunction(OS_IE_CARD_DATA, CARDi_OnReadCard); + (void)OS_ResetRequestIrqMask(OS_IE_CARD_DATA); + (void)OS_EnableIrqMask(OS_IE_CARD_DATA); + (void)OS_RestoreInterrupts(bak_psr); + CARDi_SetCardDma(); + } + return is_async; +} + +ARM_FUNC void CARDi_ReadCard(CARDRomStat *p) +{ + CARDiCommon *const c = &cardi_common; + while (TRUE) + { + const u32 len = CARD_ROM_PAGE_SIZE; + u32 src = CARD_ALIGN_HI_BIT(c->src); + u32 dst; + if ((src != c->src) || ((c->dst & 3) != 0) || (c->len < len)) + { + dst = (u32)p->cache_buf; + p->cache_page = (void *)src; + } + else + { + dst = c->dst; + } + + CARDi_SetRomOpReadPage1(src); + { + u32 pos = 0; + reg_CARD_CNT = p->ctrl; + while (TRUE) + { + const u32 ctrl = reg_CARD_CNT; + if ((ctrl & CARD_DATA_READY) != 0) + { + u32 data = reg_CARD_DATA; + if (pos < len) + { + ((u32 *)dst)[pos++] = data; + } + } + if (!(ctrl & CARD_START)) + { + break; + } + } + } + if (dst == c->dst) + { + if (!CARDi_OnReadPageDirect(p)) + { + break; + } + } + else + { + if (!CARDi_ReadFromCache(p)) + { + break; + } + } + } +} + +ARM_FUNC u32 CARDi_ReadRomIDCore(void) +{ + CARDi_SetRomOp(MROMOP_G_READ_ID, 0); + reg_CARD_CNT = (u32)(CARDi_GetRomFlag(CARD_COMMAND_ID) & ~CARD_LATENCY1_MASK); + while (!(reg_CARD_CNT & CARD_DATA_READY)) {} + return reg_CARD_DATA; +} + +ARM_FUNC static void CARDi_ReadRomSyncCore(CARDiCommon *c) +{ +#pragma unused(c) + CARDRomStat *const p = &rom_stat; + + if (CARDi_ReadFromCache(p)) + { + (*p->read_func) (p); + } + CARDi_ReadEnd(); +} + +ARM_FUNC void CARDi_ReadRom(u32 dma, const void *src, void *dst, u32 len, MIDmaCallback callback, void *arg, BOOL is_async) +{ + CARDRomStat *const p = &rom_stat; + CARDiCommon *const c = &cardi_common; + + CARD_CheckEnabled(); + + CARDi_WaitTask(c, callback, arg); + + c->dma = dma; + c->src = (u32)((u32)src + cardi_rom_base); + c->dst = (u32)dst; + c->len = (u32)len; + if (dma <= MI_DMA_MAX_NUM) + { + MI_StopDma(dma); + } + + if (CARDi_TryReadCardDma(p)) + { + if (!is_async) + { + CARD_WaitRomAsync(); + } + } + else if (is_async) + { + CARDi_SetTask(CARDi_ReadRomSyncCore); + } + else + { + c->cur_th = OS_GetCurrentThread(); + CARDi_ReadRomSyncCore(c); + } +} + +ARM_FUNC void CARD_Init(void) +{ + CARDiCommon *const p = &cardi_common; + + if (!p->flag) + { + p->flag = CARD_STAT_INIT; + p->src = p->dst = p->len = 0; + p->dma = (u32)~0; + p->callback = NULL; + p->callback_arg = NULL; + + cardi_rom_base = 0; + + CARDi_InitCommon(); + + rom_stat.read_func = CARDi_GetRomAccessor(); + + CARD_InitPulledOutCallback(); + } +} + +ARM_FUNC void CARD_WaitRomAsync(void) +{ + (void)CARDi_WaitAsync(); +} + +ARM_FUNC void (*CARDi_GetRomAccessor(void)) (CARDRomStat *) +{ + return CARDi_ReadCard; +} diff --git a/arm9/lib/src/OS_init.c b/arm9/lib/src/OS_init.c index 83e8a7d9..d1465625 100644 --- a/arm9/lib/src/OS_init.c +++ b/arm9/lib/src/OS_init.c @@ -2,9 +2,9 @@ #include "OS_init.h" #include "MI_init.h" #include "PXI_init.h" +#include "CARD_rom.h" extern void CTRDG_Init(void); -extern void CARD_Init(void); extern void PM_Init(void); ARM_FUNC void OS_Init(void) { |