From 6c75275593c854ab6324f9c38155930ed1ca9328 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 17 Jun 2019 18:40:45 +0200 Subject: [PATCH] moar SD/MMC commands --- src/DSi.cpp | 13 ++++---- src/DSi.h | 2 ++ src/DSi_SD.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++++---- src/DSi_SD.h | 13 ++++++-- 4 files changed, 100 insertions(+), 14 deletions(-) diff --git a/src/DSi.cpp b/src/DSi.cpp index 8315fb86..abd3bd64 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -60,6 +60,9 @@ u32 NWRAMMask[2][3]; DSi_SDHost* SDMMC; DSi_SDHost* SDIO; +u64 ConsoleID; +u8 eMMC_CID[16]; + bool Init() { @@ -262,14 +265,12 @@ bool LoadNAND() #define printhex(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[z]); printf("\n"); } #define printhex_rev(str, size) { for (int z = (size)-1; z >= 0; z--) printf("%02X", (str)[z]); printf("\n"); } - u8 emmc_cid[16]; - u8 consoleid[8]; fseek(f, 0xF000010, SEEK_SET); - fread(emmc_cid, 1, 16, f); - fread(consoleid, 1, 8, f); + fread(eMMC_CID, 1, 16, f); + fread(&ConsoleID, 1, 8, f); - printf("eMMC CID: "); printhex(emmc_cid, 16); - printf("Console ID: "); printhex_rev(consoleid, 8); + printf("eMMC CID: "); printhex(eMMC_CID, 16); + printf("Console ID: %llx\n", ConsoleID); fclose(f); } diff --git a/src/DSi.h b/src/DSi.h index 6d45a107..3ebee378 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -24,6 +24,8 @@ namespace DSi { +extern u8 eMMC_CID[16]; + bool Init(); void DeInit(); void Reset(); diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index a821fe58..35859cc8 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -52,6 +52,7 @@ void DSi_SDHost::Reset() } SoftReset = 0x0007; // CHECKME + SDClock = 0; Command = 0; Param = 0; @@ -67,8 +68,11 @@ void DSi_SDHost::Reset() if (Num == 0) { + DSi_MMCStorage* mmc = new DSi_MMCStorage(this, true, "nand.bin"); + mmc->SetCID(DSi::eMMC_CID); + // TODO: port 0 (SD) - Ports[1] = new DSi_MMCStorage(this, true, "nand.bin"); + Ports[1] = mmc; } else { @@ -129,6 +133,8 @@ u16 DSi_SDHost::Read(u32 addr) case 0x020: return IRQMask & 0x031D; case 0x022: return (IRQMask >> 16) & 0x8B7F; + case 0x024: return SDClock; + case 0x0E0: return SoftReset; } @@ -150,10 +156,13 @@ void DSi_SDHost::Write(u32 addr, u16 val) DSi_SDDevice* dev = Ports[PortSelect & 0x1]; if (dev) { + // CHECKME + // "Setting Command Type to "ACMD" is automatically sending an APP_CMD prefix prior to the command number" + // except DSi boot2 manually sends an APP_CMD prefix AND sets the next command to be ACMD switch ((Command >> 6) & 0x3) { case 0: dev->SendCMD(cmd, Param); break; - case 1: dev->SendACMD(cmd, Param); break; + case 1: /*dev->SendCMD(55, 0);*/ dev->SendCMD(cmd, Param); break; default: printf("%s: unknown command type %d, %02X %08X\n", SD_DESC, (Command>>6)&0x3, cmd, Param); break; @@ -171,6 +180,8 @@ void DSi_SDHost::Write(u32 addr, u16 val) case 0x020: IRQMask = (IRQMask & 0x8B7F0000) | (val & 0x031D); return; case 0x022: IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); return; + case 0x024: SDClock = val & 0x03FF; return; + case 0x0E0: if ((SoftReset & 0x0001) && !(val & 0x0001)) { @@ -200,6 +211,14 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path File = Platform::OpenLocalFile(path, "r+b"); CSR = 0x00; // checkme + + // TODO: busy bit + // TODO: SDHC/SDXC bit + OCR = 0x80FF8000; + + // TODO: customize based on card size etc + u8 csd_template[16] = {0x40, 0x40, 0x96, 0xE9, 0x7F, 0xDB, 0xF6, 0xDF, 0x01, 0x59, 0x0F, 0x2A, 0x01, 0x26, 0x90, 0x00}; + memcpy(CSD, csd_template, 16); } DSi_MMCStorage::~DSi_MMCStorage() @@ -209,21 +228,76 @@ DSi_MMCStorage::~DSi_MMCStorage() void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) { + if (CSR & (1<<5)) + { + CSR &= ~(1<<5); + return SendACMD(cmd, param); + } + switch (cmd) { - case 0x00: // reset/etc + case 0: // reset/etc Host->SendResponse(CSR, true); return; - case 0x08: // set voltage + case 2: + case 10: // get CID + Host->SendResponse(*(u32*)&CID[0], false); + Host->SendResponse(*(u32*)&CID[1], false); + Host->SendResponse(*(u32*)&CID[2], false); + Host->SendResponse(*(u32*)&CID[3], true); + //if (cmd == 2) SetState(0x02); + return; + + case 3: // get/set RCA + if (Internal) + { + RCA = param >> 16; + Host->SendResponse(CSR|0x10000, true); // huh?? + } + else + { + // TODO + printf("CMD3 on SD card: TODO\n"); + } + return; + + case 7: // select card (by RCA) + Host->SendResponse(CSR, true); + return; + + case 8: // set voltage Host->SendResponse(param, true); return; + + case 9: // get CSD + Host->SendResponse(*(u32*)&CSD[0], false); + Host->SendResponse(*(u32*)&CSD[1], false); + Host->SendResponse(*(u32*)&CSD[2], false); + Host->SendResponse(*(u32*)&CSD[3], true); + return; + + case 55: // ?? + printf("CMD55 %08X\n", param); + CSR |= (1<<5); + Host->SendResponse(CSR, true); + return; } - printf("MMC: unknown CMD %02X %08X\n", cmd, param); + printf("MMC: unknown CMD %d %08X\n", cmd, param); } void DSi_MMCStorage::SendACMD(u8 cmd, u32 param) { - printf("MMC: ACMD %02X %08X\n", cmd, param); + switch (cmd) + { + case 41: // set operating conditions + OCR &= 0xBF000000; + OCR |= (param & 0x40FFFFFF); + Host->SendResponse(OCR, true); + SetState(0x01); + return; + } + + printf("MMC: unknown ACMD %d %08X\n", cmd, param); } diff --git a/src/DSi_SD.h b/src/DSi_SD.h index 248755d1..d223fac3 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -42,6 +42,7 @@ private: u16 PortSelect; u16 SoftReset; + u16 SDClock; u32 IRQStatus; // IF u32 IRQMask; // ~IE @@ -63,7 +64,6 @@ public: ~DSi_SDDevice() {} virtual void SendCMD(u8 cmd, u32 param) = 0; - virtual void SendACMD(u8 cmd, u32 param) = 0; protected: DSi_SDHost* Host; @@ -76,6 +76,8 @@ public: DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path); ~DSi_MMCStorage(); + void SetCID(u8* cid) { memcpy(CID, cid, 16); } + void SendCMD(u8 cmd, u32 param); void SendACMD(u8 cmd, u32 param); @@ -84,7 +86,14 @@ private: char FilePath[1024]; FILE* File; - u8 CSR; + u8 CID[16]; + u8 CSD[16]; + + u32 CSR; + u32 OCR; + u32 RCA; + + void SetState(u32 state) { CSR &= ~(0xF << 9); CSR |= (state << 9); } }; #endif // DSI_SD_H