diff options
author | Arisotura <thetotalworm@gmail.com> | 2019-06-17 13:24:37 +0200 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2019-06-17 13:24:37 +0200 |
commit | bedc0220fca7cb92ad37c3bac0e503372ea84ffc (patch) | |
tree | 0716a19a5b83ddd2051205532f375f40ac6d30e2 /src | |
parent | d4dd97638d1615f51bcadd256d390a895519d565 (diff) |
take this shit further
Diffstat (limited to 'src')
-rw-r--r-- | src/DSi.cpp | 8 | ||||
-rw-r--r-- | src/DSi_SD.cpp | 175 | ||||
-rw-r--r-- | src/DSi_SD.h | 55 |
3 files changed, 222 insertions, 16 deletions
diff --git a/src/DSi.cpp b/src/DSi.cpp index e30e3e1..8315fb8 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -57,16 +57,16 @@ u32 NWRAMStart[2][3]; u32 NWRAMEnd[2][3]; u32 NWRAMMask[2][3]; -DSi_SD* SDMMC; -DSi_SD* SDIO; +DSi_SDHost* SDMMC; +DSi_SDHost* SDIO; bool Init() { if (!DSi_I2C::Init()) return false; - SDMMC = new DSi_SD(0); - SDIO = new DSi_SD(1); + SDMMC = new DSi_SDHost(0); + SDIO = new DSi_SDHost(1); return true; } diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 58b733c..a821fe5 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -20,19 +20,27 @@ #include <string.h> #include "DSi.h" #include "DSi_SD.h" +#include "Platform.h" -DSi_SD::DSi_SD(u32 num) +#define SD_DESC (Num?"SDIO":"SD/MMC") + + +DSi_SDHost::DSi_SDHost(u32 num) { Num = num; + + Ports[0] = NULL; + Ports[1] = NULL; } -DSi_SD::~DSi_SD() +DSi_SDHost::~DSi_SDHost() { - // + if (Ports[0]) delete Ports[0]; + if (Ports[1]) delete Ports[1]; } -void DSi_SD::Reset() +void DSi_SDHost::Reset() { if (Num == 0) { @@ -42,31 +50,180 @@ void DSi_SD::Reset() { PortSelect = 0x0100; // CHECKME } + + SoftReset = 0x0007; // CHECKME + + Command = 0; + Param = 0; + memset(ResponseBuffer, 0, sizeof(ResponseBuffer)); + + IRQStatus = 0; + IRQMask = 0x8B7F031D; + + if (Ports[0]) delete Ports[0]; + if (Ports[1]) delete Ports[1]; + Ports[0] = NULL; + Ports[1] = NULL; + + if (Num == 0) + { + // TODO: port 0 (SD) + Ports[1] = new DSi_MMCStorage(this, true, "nand.bin"); + } + else + { + // TODO: SDIO (wifi) + } } -void DSi_SD::DoSavestate(Savestate* file) +void DSi_SDHost::DoSavestate(Savestate* file) { // TODO! } -u16 DSi_SD::Read(u32 addr) +void DSi_SDHost::SetIRQ(u32 irq) { + u32 oldflags = IRQStatus & ~IRQMask; + + IRQStatus |= (1<<irq); + u32 newflags = IRQStatus & ~IRQMask; + + if ((oldflags == 0) && (newflags != 0)) + NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC); +} + +void DSi_SDHost::SendResponse(u32 val, bool last) +{ + *(u32*)&ResponseBuffer[6] = *(u32*)&ResponseBuffer[4]; + *(u32*)&ResponseBuffer[4] = *(u32*)&ResponseBuffer[2]; + *(u32*)&ResponseBuffer[2] = *(u32*)&ResponseBuffer[0]; + *(u32*)&ResponseBuffer[0] = val; + + if (last) SetIRQ(0); +} + + +u16 DSi_SDHost::Read(u32 addr) +{ + //printf("SDMMC READ %08X %08X\n", addr, NDS::GetPC(1)); + switch (addr & 0x1FF) { + case 0x000: return Command; case 0x002: return PortSelect & 0x030F; + case 0x004: return Param & 0xFFFF; + case 0x006: return Param >> 16; + + case 0x00C: return ResponseBuffer[0]; + case 0x00E: return ResponseBuffer[1]; + case 0x010: return ResponseBuffer[2]; + case 0x012: return ResponseBuffer[3]; + case 0x014: return ResponseBuffer[4]; + case 0x016: return ResponseBuffer[5]; + case 0x018: return ResponseBuffer[6]; + case 0x01A: return ResponseBuffer[7]; + + case 0x01C: return IRQStatus & 0x031D; + case 0x01E: return (IRQStatus >> 16) & 0x8B7F; + case 0x020: return IRQMask & 0x031D; + case 0x022: return (IRQMask >> 16) & 0x8B7F; + + case 0x0E0: return SoftReset; } - printf("unknown %s read %08X\n", Num?"SDIO":"SD/MMC", addr); + printf("unknown %s read %08X\n", SD_DESC, addr); return 0; } -void DSi_SD::Write(u32 addr, u16 val) +void DSi_SDHost::Write(u32 addr, u16 val) { + //printf("SDMMC WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1)); + switch (addr & 0x1FF) { + case 0x000: + { + Command = val; + u8 cmd = Command & 0x3F; + + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; + if (dev) + { + switch ((Command >> 6) & 0x3) + { + case 0: dev->SendCMD(cmd, Param); break; + case 1: dev->SendACMD(cmd, Param); break; + default: + printf("%s: unknown command type %d, %02X %08X\n", SD_DESC, (Command>>6)&0x3, cmd, Param); + break; + } + } + } + return; + case 0x002: PortSelect = val; return; + case 0x004: Param = (Param & 0xFFFF0000) | val; return; + case 0x006: Param = (Param & 0x0000FFFF) | (val << 16); return; + + case 0x01C: IRQStatus &= ~(u32)val; return; + case 0x01E: IRQStatus &= ~((u32)val << 16); return; + case 0x020: IRQMask = (IRQMask & 0x8B7F0000) | (val & 0x031D); return; + case 0x022: IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); return; + + case 0x0E0: + if ((SoftReset & 0x0001) && !(val & 0x0001)) + { + printf("%s: RESET\n", SD_DESC); + // TODO: STOP_INTERNAL_ACTION + // TODO: SD_RESPONSE + IRQStatus = 0; + // TODO: ERROR_DETAIL_STATUS + // TODO: CARD_CLK_CTL + // TODO: CARD_OPTION + // TODO: CARD_IRQ_STAT + // TODO: FIFO16 shit + } + SoftReset = 0x0006 | (val & 0x0001); + return; + } + + printf("unknown %s write %08X %04X\n", SD_DESC, addr, val); +} + + +DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path) : DSi_SDDevice(host) +{ + Internal = internal; + strncpy(FilePath, path, 1023); FilePath[1023] = '\0'; + + File = Platform::OpenLocalFile(path, "r+b"); + + CSR = 0x00; // checkme +} + +DSi_MMCStorage::~DSi_MMCStorage() +{ + if (File) fclose(File); +} + +void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) +{ + switch (cmd) + { + case 0x00: // reset/etc + Host->SendResponse(CSR, true); + return; + + case 0x08: // set voltage + Host->SendResponse(param, true); + return; } - printf("unknown %s write %08X %04X\n", Num?"SDIO":"SD/MMC", addr, val); + printf("MMC: unknown CMD %02X %08X\n", cmd, param); +} + +void DSi_MMCStorage::SendACMD(u8 cmd, u32 param) +{ + printf("MMC: ACMD %02X %08X\n", cmd, param); } diff --git a/src/DSi_SD.h b/src/DSi_SD.h index ce3eb84..248755d 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -19,16 +19,21 @@ #ifndef DSI_SD_H #define DSI_SD_H -class DSi_SD +class DSi_SDDevice; + + +class DSi_SDHost { public: - DSi_SD(u32 num); - ~DSi_SD(); + DSi_SDHost(u32 num); + ~DSi_SDHost(); void Reset(); void DoSavestate(Savestate* file); + void SendResponse(u32 val, bool last); + u16 Read(u32 addr); void Write(u32 addr, u16 val); @@ -36,6 +41,50 @@ private: u32 Num; u16 PortSelect; + u16 SoftReset; + + u32 IRQStatus; // IF + u32 IRQMask; // ~IE + + u16 Command; + u32 Param; + u16 ResponseBuffer[8]; + + DSi_SDDevice* Ports[2]; + + void SetIRQ(u32 irq); +}; + + +class DSi_SDDevice +{ +public: + DSi_SDDevice(DSi_SDHost* host) { Host = host; } + ~DSi_SDDevice() {} + + virtual void SendCMD(u8 cmd, u32 param) = 0; + virtual void SendACMD(u8 cmd, u32 param) = 0; + +protected: + DSi_SDHost* Host; +}; + + +class DSi_MMCStorage : public DSi_SDDevice +{ +public: + DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path); + ~DSi_MMCStorage(); + + void SendCMD(u8 cmd, u32 param); + void SendACMD(u8 cmd, u32 param); + +private: + bool Internal; + char FilePath[1024]; + FILE* File; + + u8 CSR; }; #endif // DSI_SD_H |