From ec042000cfa6b529569dccd5611efc5bfd73cd29 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 3 Jul 2019 00:07:51 +0200 Subject: lay base for DSi wifi --- src/DSi_NWifi.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/DSi_NWifi.cpp (limited to 'src/DSi_NWifi.cpp') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp new file mode 100644 index 0000000..4e5d26d --- /dev/null +++ b/src/DSi_NWifi.cpp @@ -0,0 +1,49 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "DSi.h" +#include "DSi_NWifi.h" + + +DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) +{ + // +} + +DSi_NWifi::~DSi_NWifi() +{ + // +} + + +void DSi_NWifi::SendCMD(u8 cmd, u32 param) +{ + printf("NWIFI: unknown CMD %d %08X\n", cmd, param); +} + +void DSi_NWifi::SendACMD(u8 cmd, u32 param) +{ + printf("NWIFI: unknown ACMD %d %08X\n", cmd, param); +} + +void DSi_NWifi::ContinueTransfer() +{ + // +} -- cgit v1.2.3 From 5062ed543a881af2b1c4a7629d90812afeef945c Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 3 Jul 2019 01:17:23 +0200 Subject: HARK HARK HARK HARK --- src/DSi_NWifi.cpp | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/DSi_NWifi.h | 16 ++- 2 files changed, 306 insertions(+), 3 deletions(-) (limited to 'src/DSi_NWifi.cpp') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 4e5d26d..5236551 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -22,9 +22,98 @@ #include "DSi_NWifi.h" +const u8 CIS0[256] = +{ + 0x01, 0x03, 0xD9, 0x01, 0xFF, + 0x20, 0x04, 0x71, 0x02, 0x00, 0x02, + 0x21, 0x02, 0x0C, 0x00, + 0x22, 0x04, 0x00, 0x00, 0x08, 0x32, + 0x1A, 0x05, 0x01, 0x01, 0x00, 0x02, 0x07, + 0x1B, 0x08, 0xC1, 0x41, 0x30, 0x30, 0xFF, 0xFF, 0x32, 0x00, + 0x14, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +const u8 CIS1[256] = +{ + 0x20, 0x04, 0x71, 0x02, 0x00, 0x02, + 0x21, 0x02, 0x0C, 0x00, + 0x22, 0x2A, 0x01, + 0x01, 0x11, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, + 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x00, + 0x00, 0x01, 0x0A, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, + 0x80, 0x01, 0x06, + 0x81, 0x01, 0x07, + 0x82, 0x01, 0xDF, + 0xFF, + 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) { - // + TransferCmd = 0xFFFFFFFF; + RemSize = 0; } DSi_NWifi::~DSi_NWifi() @@ -33,8 +122,149 @@ DSi_NWifi::~DSi_NWifi() } +u8 DSi_NWifi::F0_Read(u32 addr) +{ + switch (addr) + { + case 0x00000: return 0x11; + case 0x00001: return 0x00; + + case 0x00002: return 0x02; // writable?? + case 0x00003: return 0x02; + + case 0x00008: return 0x17; + + case 0x00009: return 0x00; + case 0x0000A: return 0x10; + case 0x0000B: return 0x00; + + case 0x00012: return 0x03; + + case 0x00109: return 0x00; + case 0x0010A: return 0x11; + case 0x0010B: return 0x00; + } + + if (addr >= 0x01000 && addr < 0x01100) + { + return CIS0[addr & 0xFF]; + } + if (addr >= 0x01100 && addr < 0x01200) + { + return CIS1[addr & 0xFF]; + } + + printf("NWIFI: unknown func0 read %05X\n", addr); + return 0; +} + +void DSi_NWifi::F0_Write(u32 addr, u8 val) +{ + printf("NWIFI: unknown func0 write %05X %02X\n", addr, val); +} + + +u8 DSi_NWifi::F1_Read(u32 addr) +{ + switch (addr) + { + } + + printf("NWIFI: unknown func1 read %05X\n", addr); + return 0; +} + +void DSi_NWifi::F1_Write(u32 addr, u8 val) +{ + printf("NWIFI: unknown func1 write %05X %02X\n", addr, val); +} + + +u8 DSi_NWifi::SDIO_Read(u32 func, u32 addr) +{ + switch (func) + { + case 0: return F0_Read(addr); + } + + printf("NWIFI: unknown SDIO read %d %05X\n", func, addr); + return 0; +} + +void DSi_NWifi::SDIO_Write(u32 func, u32 addr, u8 val) +{ + switch (func) + { + case 0: return F0_Write(addr, val); + } + + printf("NWIFI: unknown SDIO write %d %05X %02X\n", func, addr, val); +} + + void DSi_NWifi::SendCMD(u8 cmd, u32 param) { + switch (cmd) + { + case 52: // IO_RW_DIRECT + { + u32 func = (param >> 28) & 0x7; + u32 addr = (param >> 9) & 0x1FFFF; + + if (param & (1<<31)) + { + // write + + u8 val = param & 0xFF; + SDIO_Write(func, addr, val); + if (param & (1<<27)) + val = SDIO_Read(func, addr); // checkme + Host->SendResponse(val | 0x1000, true); + } + else + { + // read + + u8 val = SDIO_Read(func, addr); + Host->SendResponse(val | 0x1000, true); + } + } + return; + + case 53: // IO_RW_EXTENDED + { + u32 addr = (param >> 9) & 0x1FFFF; + + TransferCmd = param; + TransferAddr = addr; + if (param & (1<<27)) + { + RemSize = (param & 0x1FF) << 9; // checkme + } + else + { + RemSize = (param & 0x1FF); + if (!RemSize) RemSize = 0x200; + } + + if (param & (1<<31)) + { + // write + + WriteBlock(); + Host->SendResponse(0x1000, true); + } + else + { + // read + + ReadBlock(); + Host->SendResponse(0x1000, true); + } + } + return; + } + printf("NWIFI: unknown CMD %d %08X\n", cmd, param); } @@ -45,5 +275,64 @@ void DSi_NWifi::SendACMD(u8 cmd, u32 param) void DSi_NWifi::ContinueTransfer() { - // + if (TransferCmd & (1<<31)) + WriteBlock(); + else + ReadBlock(); +} + +void DSi_NWifi::ReadBlock() +{ + u32 func = (TransferCmd >> 28) & 0x7; + u32 len = (TransferCmd & (1<<27)) ? 0x200 : RemSize; + + u8 data[0x200]; + + for (u32 i = 0; i < len; i++) + { + data[i] = SDIO_Read(func, TransferAddr); + if (TransferCmd & (1<<26)) + { + TransferAddr++; + TransferAddr &= 0x1FFFF; // checkme + } + } + Host->SendData(data, len); + + if (RemSize > 0) + { + RemSize -= len; + if (RemSize == 0) + { + // TODO? + } + } +} + +void DSi_NWifi::WriteBlock() +{ + u32 func = (TransferCmd >> 28) & 0x7; + u32 len = (TransferCmd & (1<<27)) ? 0x200 : RemSize; + + u8 data[0x200]; + Host->ReceiveData(data, len); + + for (u32 i = 0; i < len; i++) + { + SDIO_Write(func, TransferAddr, data[i]); + if (TransferCmd & (1<<26)) + { + TransferAddr++; + TransferAddr &= 0x1FFFF; // checkme + } + } + + if (RemSize > 0) + { + RemSize -= len; + if (RemSize == 0) + { + // TODO? + } + } } diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 34c3dd4..5d61951 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -33,7 +33,21 @@ public: void ContinueTransfer(); private: - // + u32 TransferCmd; + u32 TransferAddr; + u32 RemSize; + + u8 F0_Read(u32 addr); + void F0_Write(u32 addr, u8 val); + + u8 F1_Read(u32 addr); + void F1_Write(u32 addr, u8 val); + + u8 SDIO_Read(u32 func, u32 addr); + void SDIO_Write(u32 func, u32 addr, u8 val); + + void ReadBlock(); + void WriteBlock(); }; #endif // DSI_NWIFI_H -- cgit v1.2.3 From 06716794a1d69512312e1dc251b9762d27b15c8d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 24 Jul 2019 18:48:52 +0200 Subject: lots of things. attempting to make wifi init work. not there yet. --- src/DSi.cpp | 55 ++++++++++---- src/DSi_AES.cpp | 23 ++++++ src/DSi_NWifi.cpp | 214 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/DSi_NWifi.h | 27 +++++++ src/DSi_SD.cpp | 70 ++++++++++++++---- src/DSi_SD.h | 2 +- src/NDS.h | 3 +- 7 files changed, 344 insertions(+), 50 deletions(-) (limited to 'src/DSi_NWifi.cpp') diff --git a/src/DSi.cpp b/src/DSi.cpp index 26a67f4..aed6b89 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -73,6 +73,7 @@ u64 ConsoleID; u8 eMMC_CID[16]; u8 ITCMInit[0x8000]; +u8 ARM7Init[0x3C00]; bool Init() @@ -120,6 +121,9 @@ void Reset() memcpy(NDS::ARM9->ITCM, ITCMInit, 0x8000); + for (u32 i = 0; i < 0x3C00; i+=4) + ARM7Write32(0x03FFC400+i, *(u32*)&ARM7Init[i]); + DSi_I2C::Reset(); DSi_AES::Reset(); @@ -138,9 +142,16 @@ void Reset() NDS::MapSharedWRAM(3); - // TEST - u8 derp[16] = {0xE5, 0xCC, 0x5A, 0x8B, 0x56, 0xD0, 0xC9, 0x72, 0x9C, 0x17, 0xE8, 0xDC, 0x39, 0x12, 0x36, 0xA9}; - for (int i = 0; i < 16; i+=4) ARM7Write32(0x03FFC580+i, *(u32*)&derp[i]); + u32 eaddr = 0x03FFE6E4; + ARM7Write32(eaddr+0x00, *(u32*)&eMMC_CID[0]); + ARM7Write32(eaddr+0x04, *(u32*)&eMMC_CID[4]); + ARM7Write32(eaddr+0x08, *(u32*)&eMMC_CID[8]); + ARM7Write32(eaddr+0x0C, *(u32*)&eMMC_CID[12]); + ARM7Write16(eaddr+0x2C, 0x0001); + ARM7Write16(eaddr+0x2E, 0x0001); + ARM7Write16(eaddr+0x3C, 0x0100); + ARM7Write16(eaddr+0x3E, 0x40E0); + ARM7Write16(eaddr+0x42, 0x0001); } bool LoadBIOS() @@ -328,19 +339,31 @@ bool LoadNAND() } memset(ITCMInit, 0, 0x8000); + memset(ARM7Init, 0, 0x3C00); - f = fopen("dsikeys.bin", "rb"); + f = fopen("initmem9.bin", "rb"); if (f) { // first 0x2524 bytes are loaded to 0x01FFC400 u32 dstaddr = 0x01FFC400; - fread(&ITCMInit[dstaddr & 0x7FFF], 0x2524, 1, f); + fread(&ITCMInit[dstaddr & 0x7FFF], /*0x2524*/0x3C00, 1, f); + fclose(f); + } + else + { + printf("DSi ARM9 meminit not found\n"); + } + + f = fopen("initmem7.bin", "rb"); + if (f) + { + fread(ARM7Init, 0x3C00, 1, f); fclose(f); } else { - printf("DSi keys not found\n"); + printf("DSi ARM7 meminit not found\n"); } return true; @@ -559,7 +582,7 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val) u8 ARM9Read8(u32 addr) -{ +{if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 8 9 %08X %08X\n", addr, NDS::GetPC(0)); switch (addr & 0xFF000000) { case 0x03000000: @@ -588,7 +611,7 @@ u8 ARM9Read8(u32 addr) } u16 ARM9Read16(u32 addr) -{ +{if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 16 9 %08X %08X\n", addr, NDS::GetPC(0)); switch (addr & 0xFF000000) { case 0x03000000: @@ -617,7 +640,8 @@ u16 ARM9Read16(u32 addr) } u32 ARM9Read32(u32 addr) -{ +{if(addr==0x029D02D8) printf("READ SHITTY VTABLE: %08X\n", NDS::GetPC(0)); +if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 32 9 %08X %08X\n", addr, NDS::GetPC(0)); switch (addr & 0xFF000000) { case 0x03000000: @@ -712,7 +736,7 @@ void ARM9Write16(u32 addr, u16 val) } void ARM9Write32(u32 addr, u32 val) -{ +{if(addr==0x02B05E34) printf("VGONP. %08X, %08X\n", val, NDS::GetPC(0)); switch (addr & 0xFF000000) { case 0x03000000: @@ -768,7 +792,8 @@ bool ARM9GetMemRegion(u32 addr, bool write, NDS::MemRegion* region) u8 ARM7Read8(u32 addr) -{ +{if(addr>=0x3FFC400 && addr<0x3FFE728) printf("OGON 8 %08X %08X\n", addr, NDS::GetPC(1)); +if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 8 7 %08X %08X\n", addr, NDS::GetPC(1)); switch (addr & 0xFF800000) { case 0x03000000: @@ -797,7 +822,8 @@ u8 ARM7Read8(u32 addr) } u16 ARM7Read16(u32 addr) -{ +{if(addr>=0x3FFC400 && addr<0x3FFE728) printf("OGON 16 %08X %08X\n", addr, NDS::GetPC(1)); +if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 16 7 %08X %08X\n", addr, NDS::GetPC(1)); switch (addr & 0xFF800000) { case 0x03000000: @@ -826,7 +852,8 @@ u16 ARM7Read16(u32 addr) } u32 ARM7Read32(u32 addr) -{ +{if(addr>=0x3FFC400 && addr<0x3FFE728) printf("OGON 32 %08X %08X\n", addr, NDS::GetPC(1)); +if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 32 7 %08X %08X\n", addr, NDS::GetPC(1)); switch (addr & 0xFF800000) { case 0x03000000: @@ -855,7 +882,7 @@ u32 ARM7Read32(u32 addr) } void ARM7Write8(u32 addr, u8 val) -{ +{if(addr==0x0228CD74) printf("RAKAKA %02X %08X\n", val, NDS::GetPC(1)); switch (addr & 0xFF800000) { case 0x03000000: diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index 8ae9082..4aa97bc 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -22,6 +22,7 @@ #include "DSi_AES.h" #include "FIFO.h" #include "tiny-AES-c/aes.hpp" +#include "Platform.h" namespace DSi_AES @@ -130,6 +131,7 @@ void Reset() // initialize keys, as per GBAtek +#if 0 // slot 0: modcrypt *(u32*)&KeyX[0][0] = 0x746E694E; *(u32*)&KeyX[0][4] = 0x6F646E65; @@ -148,6 +150,27 @@ void Reset() *(u32*)&KeyY[3][0] = 0x0AB9DC76; *(u32*)&KeyY[3][4] = 0xBD4DC4D3; *(u32*)&KeyY[3][8] = 0x202DDD1D; +#endif + FILE* f = Platform::OpenLocalFile("aeskeys.bin", "rb"); + if (f) + { + fread(KeyNormal[0], 16, 1, f); + fread(KeyX[0], 16, 1, f); + fread(KeyY[0], 16, 1, f); + fread(KeyNormal[1], 16, 1, f); + fread(KeyX[1], 16, 1, f); + fread(KeyY[1], 16, 1, f); + fread(KeyNormal[2], 16, 1, f); + fread(KeyX[2], 16, 1, f); + fread(KeyY[2], 16, 1, f); + fread(KeyNormal[3], 16, 1, f); + fread(KeyX[3], 16, 1, f); + fread(KeyY[3], 16, 1, f); + + fclose(f); + } + else + printf("AES: aeskeys.bin not found\n"); } diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 5236551..e0591fb 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -114,11 +114,20 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) { TransferCmd = 0xFFFFFFFF; RemSize = 0; + + WindowData = 0; + WindowReadAddr = 0; + WindowWriteAddr = 0; + + // TODO: check the actual mailbox size (presumably 0x200) + for (int i = 0; i < 8; i++) + Mailbox[i] = new FIFO(0x200); } DSi_NWifi::~DSi_NWifi() { - // + for (int i = 0; i < 8; i++) + delete Mailbox[i]; } @@ -165,9 +174,54 @@ void DSi_NWifi::F0_Write(u32 addr, u8 val) u8 DSi_NWifi::F1_Read(u32 addr) -{ - switch (addr) +{printf("F1 READ %05X\n", addr); + if (addr < 0x100) + { + return Mailbox[4]->Read(); + } + else if (addr < 0x200) + { + return Mailbox[5]->Read(); + } + else if (addr < 0x300) + { + return Mailbox[6]->Read(); + } + else if (addr < 0x400) + { + return Mailbox[7]->Read(); + } + else if (addr < 0x800) + { + switch (addr) + { + case 0x00450: return 1; // HAX!! + + case 0x00474: return WindowData & 0xFF; + case 0x00475: return (WindowData >> 8) & 0xFF; + case 0x00476: return (WindowData >> 16) & 0xFF; + case 0x00477: return WindowData >> 24; + } + } + else if (addr < 0x1000) + { + return Mailbox[4]->Read(); + } + else if (addr < 0x1800) + { + return Mailbox[5]->Read(); + } + else if (addr < 0x2000) + { + return Mailbox[6]->Read(); + } + else if (addr < 0x2800) + { + return Mailbox[7]->Read(); + } + else { + return Mailbox[4]->Read(); } printf("NWIFI: unknown func1 read %05X\n", addr); @@ -175,7 +229,91 @@ u8 DSi_NWifi::F1_Read(u32 addr) } void DSi_NWifi::F1_Write(u32 addr, u8 val) -{ +{printf("F1 WRITE %05X %02X\n", addr, val); + if (addr < 0x100) + { + if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); + Mailbox[0]->Write(val); + if (addr == 0xFF) BMI_Command(); + return; + } + else if (addr < 0x200) + { + if (Mailbox[1]->IsFull()) printf("!!! NWIFI: MBOX1 FULL\n"); + Mailbox[1]->Write(val); + return; + } + else if (addr < 0x300) + { + if (Mailbox[2]->IsFull()) printf("!!! NWIFI: MBOX2 FULL\n"); + Mailbox[2]->Write(val); + return; + } + else if (addr < 0x400) + { + if (Mailbox[3]->IsFull()) printf("!!! NWIFI: MBOX3 FULL\n"); + Mailbox[3]->Write(val); + return; + } + else if (addr < 0x800) + { + switch (addr) + { + case 0x00474: WindowData = (WindowData & 0xFFFFFF00) | val; return; + case 0x00475: WindowData = (WindowData & 0xFFFF00FF) | (val << 8); return; + case 0x00476: WindowData = (WindowData & 0xFF00FFFF) | (val << 16); return; + case 0x00477: WindowData = (WindowData & 0x00FFFFFF) | (val << 24); return; + + case 0x00478: + WindowWriteAddr = (WindowWriteAddr & 0xFFFFFF00) | val; + WindowWrite(); + return; + case 0x00479: WindowWriteAddr = (WindowWriteAddr & 0xFFFF00FF) | (val << 8); return; + case 0x0047A: WindowWriteAddr = (WindowWriteAddr & 0xFF00FFFF) | (val << 16); return; + case 0x0047B: WindowWriteAddr = (WindowWriteAddr & 0x00FFFFFF) | (val << 24); return; + + case 0x0047C: + WindowReadAddr = (WindowReadAddr & 0xFFFFFF00) | val; + WindowRead(); + return; + case 0x0047D: WindowReadAddr = (WindowReadAddr & 0xFFFF00FF) | (val << 8); return; + case 0x0047E: WindowReadAddr = (WindowReadAddr & 0xFF00FFFF) | (val << 16); return; + case 0x0047F: WindowReadAddr = (WindowReadAddr & 0x00FFFFFF) | (val << 24); return; + } + } + else if (addr < 0x1000) + { + if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); + Mailbox[0]->Write(val); + if (addr == 0xFFF) BMI_Command(); + return; + } + else if (addr < 0x1800) + { + if (Mailbox[1]->IsFull()) printf("!!! NWIFI: MBOX1 FULL\n"); + Mailbox[1]->Write(val); + return; + } + else if (addr < 0x2000) + { + if (Mailbox[2]->IsFull()) printf("!!! NWIFI: MBOX2 FULL\n"); + Mailbox[2]->Write(val); + return; + } + else if (addr < 0x2800) + { + if (Mailbox[3]->IsFull()) printf("!!! NWIFI: MBOX3 FULL\n"); + Mailbox[3]->Write(val); + return; + } + else + { + if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); + Mailbox[0]->Write(val); + if (addr == 0x3FFF) BMI_Command(); // CHECKME + return; + } + printf("NWIFI: unknown func1 write %05X %02X\n", addr, val); } @@ -185,6 +323,7 @@ u8 DSi_NWifi::SDIO_Read(u32 func, u32 addr) switch (func) { case 0: return F0_Read(addr); + case 1: return F1_Read(addr); } printf("NWIFI: unknown SDIO read %d %05X\n", func, addr); @@ -196,6 +335,7 @@ void DSi_NWifi::SDIO_Write(u32 func, u32 addr, u8 val) switch (func) { case 0: return F0_Write(addr, val); + case 1: return F1_Write(addr, val); } printf("NWIFI: unknown SDIO write %d %05X %02X\n", func, addr, val); @@ -203,7 +343,7 @@ void DSi_NWifi::SDIO_Write(u32 func, u32 addr, u8 val) void DSi_NWifi::SendCMD(u8 cmd, u32 param) -{ +{printf("NWIFI CMD %d %08X %08X\n", cmd, param, NDS::GetPC(1)); switch (cmd) { case 52: // IO_RW_DIRECT @@ -315,24 +455,62 @@ void DSi_NWifi::WriteBlock() u32 len = (TransferCmd & (1<<27)) ? 0x200 : RemSize; u8 data[0x200]; - Host->ReceiveData(data, len); - - for (u32 i = 0; i < len; i++) + if (Host->ReceiveData(data, len)) { - SDIO_Write(func, TransferAddr, data[i]); - if (TransferCmd & (1<<26)) + for (u32 i = 0; i < len; i++) { - TransferAddr++; - TransferAddr &= 0x1FFFF; // checkme + SDIO_Write(func, TransferAddr, data[i]); + if (TransferCmd & (1<<26)) + { + TransferAddr++; + TransferAddr &= 0x1FFFF; // checkme + } } - } - if (RemSize > 0) - { - RemSize -= len; - if (RemSize == 0) + if (RemSize > 0) { - // TODO? + RemSize -= len; + if (RemSize == 0) + { + // TODO? + } } } } + + +void DSi_NWifi::BMI_Command() +{ + // HLE command handling stub + u32 cmd = MB_Read32(0); + printf("BMI: cmd %08X\n", cmd); + + switch (cmd) + { + case 0x08: // BMI_GET_TARGET_ID + MB_Write32(4, 0xFFFFFFFF); + MB_Write32(4, 0x0000000C); + MB_Write32(4, 0x20000118); + MB_Write32(4, 0x00000002); + return; + } +} + + +void DSi_NWifi::WindowRead() +{ + printf("NWifi: window read %08X\n", WindowReadAddr); + + switch (WindowReadAddr) + { + case 0x40EC: WindowData = 0x02000001; return; + + // SOC_RESET_CAUSE + case 0x40C0: WindowData = 2; return; + } +} + +void DSi_NWifi::WindowWrite() +{ + printf("NWifi: window write %08X %08X\n", WindowWriteAddr, WindowData); +} diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 5d61951..4ec010e 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -20,6 +20,7 @@ #define DSI_NWIFI_H #include "DSi_SD.h" +#include "FIFO.h" class DSi_NWifi : public DSi_SDDevice { @@ -48,6 +49,32 @@ private: void ReadBlock(); void WriteBlock(); + + void BMI_Command(); + + void WindowRead(); + void WindowWrite(); + + u32 MB_Read32(int n) + { + u32 ret = Mailbox[n]->Read(); + ret |= (Mailbox[n]->Read() << 8); + ret |= (Mailbox[n]->Read() << 16); + ret |= (Mailbox[n]->Read() << 24); + return ret; + } + + void MB_Write32(int n, u32 val) + { + Mailbox[n]->Write(val & 0xFF); val >>= 8; + Mailbox[n]->Write(val & 0xFF); val >>= 8; + Mailbox[n]->Write(val & 0xFF); val >>= 8; + Mailbox[n]->Write(val & 0xFF); + } + + FIFO* Mailbox[8]; + + u32 WindowData, WindowReadAddr, WindowWriteAddr; }; #endif // DSI_NWIFI_H diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 6e73df5..c9edd78 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -185,7 +185,8 @@ void DSi_SDHost::SendData(u8* data, u32 len) // but if IRQ24 is thrown instantly, the handler clears IRQ0 before the // send-command function starts polling IRQ status u32 param = Num | (last << 1); - NDS::ScheduleEvent(NDS::Event_DSi_SDTransfer, false, 512, FinishSend, param); + NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer, + false, 512, FinishSend, param); } void DSi_SDHost::FinishReceive(u32 param) @@ -199,13 +200,19 @@ void DSi_SDHost::FinishReceive(u32 param) if (dev) dev->ContinueTransfer(); } -void DSi_SDHost::ReceiveData(u8* data, u32 len) +bool DSi_SDHost::ReceiveData(u8* data, u32 len) { printf("%s: data TX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask); if (len != BlockLen16) printf("!! BAD BLOCKLEN\n"); - DSi_SDDevice* dev = Ports[PortSelect & 0x1]; u32 f = CurFIFO; + if ((DataFIFO[f]->Level() << 1) < len) + { + printf("%s: FIFO not full enough for a transfer (%d / %d)\n", SD_DESC, DataFIFO[f]->Level()<<1, len); + return false; + } + + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; for (u32 i = 0; i < len; i += 2) *(u16*)&data[i] = DataFIFO[f]->Read(); @@ -213,7 +220,7 @@ void DSi_SDHost::ReceiveData(u8* data, u32 len) if (BlockCountInternal <= 1) { - printf("%s: data32 TX complete", SD_DESC); + printf("%s: data TX complete", SD_DESC); if (StopAction & (1<<8)) { @@ -232,12 +239,14 @@ void DSi_SDHost::ReceiveData(u8* data, u32 len) { BlockCountInternal--; } + + return true; } u16 DSi_SDHost::Read(u32 addr) { - //printf("SDMMC READ %08X %08X\n", addr, NDS::GetPC(1)); + //if(Num)printf("SDIO READ %08X %08X\n", addr, NDS::GetPC(1)); switch (addr & 0x1FF) { @@ -383,7 +392,7 @@ u32 DSi_SDHost::ReadFIFO32() void DSi_SDHost::Write(u32 addr, u16 val) { - //printf("SDMMC WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1)); + //if(Num)printf("SDIO WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1)); switch (addr & 0x1FF) { @@ -421,7 +430,11 @@ void DSi_SDHost::Write(u32 addr, u16 val) case 0x01C: IRQStatus &= (val | 0xFFFF0000); return; case 0x01E: IRQStatus &= ((val << 16) | 0xFFFF); return; case 0x020: IRQMask = (IRQMask & 0x8B7F0000) | (val & 0x031D); return; - case 0x022: IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); return; + case 0x022: + IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); + if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme + if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme + return; case 0x024: SDClock = val & 0x03FF; return; case 0x026: @@ -430,6 +443,33 @@ void DSi_SDHost::Write(u32 addr, u16 val) return; case 0x028: SDOption = val & 0xC1FF; return; + case 0x030: // FIFO16 + { + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; + u32 f = CurFIFO; + if (DataFIFO[f]->IsFull()) + { + // TODO + printf("!!!! %s FIFO FULL\n", SD_DESC); + return; + } + + DataFIFO[f]->Write(val); + + if (DataFIFO[f]->Level() < (BlockLen16>>1)) + { + ClearIRQ(25); + SetIRQ(24); + return; + } + + // we completed one block, send it to the SD card + // TODO measure the actual delay!! + NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer, + false, 2048, FinishReceive, Num); + } + return; + case 0x0D8: DataCtl = (val & 0x0022); DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1); @@ -494,13 +534,9 @@ void DSi_SDHost::WriteFIFO32(u32 val) } // we completed one block, send it to the SD card - - //ClearIRQ(24); - //SetIRQ(25); - - //if (dev) dev->ContinueTransfer(); // TODO measure the actual delay!! - NDS::ScheduleEvent(NDS::Event_DSi_SDTransfer, false, 2048, FinishReceive, Num); + NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer, + false, 2048, FinishReceive, Num); } @@ -726,7 +762,9 @@ void DSi_MMCStorage::WriteBlock(u64 addr) printf("SD/MMC: write block @ %08X, len=%08X\n", addr, BlockSize); u8 data[0x200]; - Host->ReceiveData(data, BlockSize); - fseek(File, addr, SEEK_SET); - fwrite(data, 1, BlockSize, File); + if (Host->ReceiveData(data, BlockSize)) + { + fseek(File, addr, SEEK_SET); + fwrite(data, 1, BlockSize, File); + } } diff --git a/src/DSi_SD.h b/src/DSi_SD.h index 855dd5e..22475d6 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -40,7 +40,7 @@ public: static void FinishReceive(u32 param); void SendResponse(u32 val, bool last); void SendData(u8* data, u32 len); - void ReceiveData(u8* data, u32 len); + bool ReceiveData(u8* data, u32 len); u16 Read(u32 addr); void Write(u32 addr, u16 val); diff --git a/src/NDS.h b/src/NDS.h index 850e829..e32908b 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -43,7 +43,8 @@ enum Event_Sqrt, // DSi - Event_DSi_SDTransfer, + Event_DSi_SDMMCTransfer, + Event_DSi_SDIOTransfer, Event_MAX }; -- cgit v1.2.3 From 0918da7b004ea2259989ab7063cfa1e20216f10a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 24 Jul 2019 21:13:08 +0200 Subject: add BMI commands and other shit --- src/DSi_NWifi.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++------- src/DSi_NWifi.h | 4 +-- 2 files changed, 79 insertions(+), 12 deletions(-) (limited to 'src/DSi_NWifi.cpp') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index e0591fb..6f23740 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -266,7 +266,7 @@ void DSi_NWifi::F1_Write(u32 addr, u8 val) case 0x00478: WindowWriteAddr = (WindowWriteAddr & 0xFFFFFF00) | val; - WindowWrite(); + WindowWrite(WindowWriteAddr, WindowData); return; case 0x00479: WindowWriteAddr = (WindowWriteAddr & 0xFFFF00FF) | (val << 8); return; case 0x0047A: WindowWriteAddr = (WindowWriteAddr & 0xFF00FFFF) | (val << 16); return; @@ -274,7 +274,7 @@ void DSi_NWifi::F1_Write(u32 addr, u8 val) case 0x0047C: WindowReadAddr = (WindowReadAddr & 0xFFFFFF00) | val; - WindowRead(); + WindowData = WindowRead(WindowReadAddr); return; case 0x0047D: WindowReadAddr = (WindowReadAddr & 0xFFFF00FF) | (val << 8); return; case 0x0047E: WindowReadAddr = (WindowReadAddr & 0xFF00FFFF) | (val << 16); return; @@ -487,30 +487,97 @@ void DSi_NWifi::BMI_Command() switch (cmd) { + case 0x03: // BMI_WRITE_MEMORY + { + u32 addr = MB_Read32(0); + u32 len = MB_Read32(0); + printf("BMI mem write %08X %08X\n", addr, len); + + for (int i = 0; i < len; i++) + { + u8 val = Mailbox[0]->Read(); + + // TODO: do something with it!! + } + } + return; + + case 0x04: // BMI_EXECUTE + { + u32 entry = MB_Read32(0); + u32 arg = MB_Read32(0); + + printf("BMI_EXECUTE %08X %08X\n", entry, arg); + } + return; + + case 0x06: // BMI_READ_SOC_REGISTER + { + u32 addr = MB_Read32(0); + u32 val = WindowRead(addr); + MB_Write32(4, val); + } + return; + + case 0x07: // BMI_WRITE_SOC_REGISTER + { + u32 addr = MB_Read32(0); + u32 val = MB_Read32(0); + WindowWrite(addr, val); + } + return; + case 0x08: // BMI_GET_TARGET_ID MB_Write32(4, 0xFFFFFFFF); MB_Write32(4, 0x0000000C); - MB_Write32(4, 0x20000118); + //MB_Write32(4, 0x20000118); + MB_Write32(4, 0x23000024); // ROM version (TODO: how to determine correct one?) MB_Write32(4, 0x00000002); return; + + case 0x0D: // BMI_LZ_STREAM_START + { + u32 addr = MB_Read32(0); + printf("BMI_LZ_STREAM_START %08X\n", addr); + } + return; + + case 0x0E: // BMI_LZ_DATA + { + u32 len = MB_Read32(0); + printf("BMI LZ write %08X\n", len); + + for (int i = 0; i < len; i++) + { + u8 val = Mailbox[0]->Read(); + + // TODO: do something with it!! + } + } + return; } } -void DSi_NWifi::WindowRead() +u32 DSi_NWifi::WindowRead(u32 addr) { - printf("NWifi: window read %08X\n", WindowReadAddr); + printf("NWifi: window read %08X\n", addr); - switch (WindowReadAddr) + switch (addr) { - case 0x40EC: WindowData = 0x02000001; return; + case 0x40EC: // chip ID + // 0D000000 / 0D000001 == AR6013 + // TODO: check firmware.bin to determine the correct value + return 0x0D000001; // SOC_RESET_CAUSE - case 0x40C0: WindowData = 2; return; + case 0x40C0: return 2; } + + return 0; } -void DSi_NWifi::WindowWrite() +void DSi_NWifi::WindowWrite(u32 addr, u32 val) { - printf("NWifi: window write %08X %08X\n", WindowWriteAddr, WindowData); + printf("NWifi: window write %08X %08X\n", addr, val); } diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 4ec010e..0a36705 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -52,8 +52,8 @@ private: void BMI_Command(); - void WindowRead(); - void WindowWrite(); + u32 WindowRead(u32 addr); + void WindowWrite(u32 addr, u32 val); u32 MB_Read32(int n) { -- cgit v1.2.3 From f7f4ff0519309669e78b994e7c759d13808f0a87 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 4 Aug 2019 02:16:16 +0200 Subject: wifi: take this shit further. complete wifi init --- src/DSi.cpp | 20 ++-- src/DSi_NWifi.cpp | 328 +++++++++++++++++++++++++++++++++++++++++++++++++++--- src/DSi_NWifi.h | 41 +++++++ src/DSi_SD.cpp | 105 +++++++++++++---- src/DSi_SD.h | 19 +++- src/FIFO.h | 9 ++ src/NDS.h | 1 + src/SPI.cpp | 1 + src/SPI.h | 1 + 9 files changed, 468 insertions(+), 57 deletions(-) (limited to 'src/DSi_NWifi.cpp') diff --git a/src/DSi.cpp b/src/DSi.cpp index aed6b89..17d7f0d 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -582,7 +582,7 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val) u8 ARM9Read8(u32 addr) -{if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 8 9 %08X %08X\n", addr, NDS::GetPC(0)); +{ switch (addr & 0xFF000000) { case 0x03000000: @@ -611,7 +611,7 @@ u8 ARM9Read8(u32 addr) } u16 ARM9Read16(u32 addr) -{if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 16 9 %08X %08X\n", addr, NDS::GetPC(0)); +{ switch (addr & 0xFF000000) { case 0x03000000: @@ -640,8 +640,7 @@ u16 ARM9Read16(u32 addr) } u32 ARM9Read32(u32 addr) -{if(addr==0x029D02D8) printf("READ SHITTY VTABLE: %08X\n", NDS::GetPC(0)); -if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 32 9 %08X %08X\n", addr, NDS::GetPC(0)); +{ switch (addr & 0xFF000000) { case 0x03000000: @@ -736,7 +735,7 @@ void ARM9Write16(u32 addr, u16 val) } void ARM9Write32(u32 addr, u32 val) -{if(addr==0x02B05E34) printf("VGONP. %08X, %08X\n", val, NDS::GetPC(0)); +{ switch (addr & 0xFF000000) { case 0x03000000: @@ -792,8 +791,7 @@ bool ARM9GetMemRegion(u32 addr, bool write, NDS::MemRegion* region) u8 ARM7Read8(u32 addr) -{if(addr>=0x3FFC400 && addr<0x3FFE728) printf("OGON 8 %08X %08X\n", addr, NDS::GetPC(1)); -if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 8 7 %08X %08X\n", addr, NDS::GetPC(1)); +{ switch (addr & 0xFF800000) { case 0x03000000: @@ -822,8 +820,7 @@ if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 8 7 %08X %08X\n", addr, } u16 ARM7Read16(u32 addr) -{if(addr>=0x3FFC400 && addr<0x3FFE728) printf("OGON 16 %08X %08X\n", addr, NDS::GetPC(1)); -if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 16 7 %08X %08X\n", addr, NDS::GetPC(1)); +{ switch (addr & 0xFF800000) { case 0x03000000: @@ -852,8 +849,7 @@ if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 16 7 %08X %08X\n", addr, } u32 ARM7Read32(u32 addr) -{if(addr>=0x3FFC400 && addr<0x3FFE728) printf("OGON 32 %08X %08X\n", addr, NDS::GetPC(1)); -if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 32 7 %08X %08X\n", addr, NDS::GetPC(1)); +{ switch (addr & 0xFF800000) { case 0x03000000: @@ -882,7 +878,7 @@ if (addr>=0x2FFD7BC && addr<0x2FFD800) printf("EMMCGONP 32 7 %08X %08X\n", addr, } void ARM7Write8(u32 addr, u8 val) -{if(addr==0x0228CD74) printf("RAKAKA %02X %08X\n", val, NDS::GetPC(1)); +{ switch (addr & 0xFF800000) { case 0x03000000: diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 6f23740..013173f 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -20,6 +20,7 @@ #include #include "DSi.h" #include "DSi_NWifi.h" +#include "SPI.h" const u8 CIS0[256] = @@ -110,11 +111,25 @@ const u8 CIS1[256] = }; +// hax +DSi_NWifi* hax_wifi; +void triggerirq(u32 param) +{ + hax_wifi->SetIRQ_F1_Counter(0); +} + + DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) { TransferCmd = 0xFFFFFFFF; RemSize = 0; + F0_IRQEnable = 0; + F0_IRQStatus = 0; + + F1_IRQEnable = 0; F1_IRQEnable_CPU = 0; F1_IRQEnable_Error = 0; F1_IRQEnable_Counter = 0; + F1_IRQStatus = 0; F1_IRQStatus_CPU = 0; F1_IRQStatus_Error = 0; F1_IRQStatus_Counter = 0; + WindowData = 0; WindowReadAddr = 0; WindowWriteAddr = 0; @@ -122,6 +137,30 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) // TODO: check the actual mailbox size (presumably 0x200) for (int i = 0; i < 8; i++) Mailbox[i] = new FIFO(0x200); + + u8* mac = SPI_Firmware::GetWifiMAC(); + printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + memset(EEPROM, 0, 0x400); + + *(u32*)&EEPROM[0x000] = 0x300; + *(u16*)&EEPROM[0x008] = 0x8348; // TODO: determine properly (country code) + memcpy(&EEPROM[0x00A], mac, 6); + *(u32*)&EEPROM[0x010] = 0x60000000; + + memset(&EEPROM[0x03C], 0xFF, 0x70); + memset(&EEPROM[0x140], 0xFF, 0x8); + + u16 chk = 0xFFFF; + for (int i = 0; i < 0x300; i+=2) + chk ^= *(u16*)&EEPROM[i]; + + *(u16*)&EEPROM[0x004] = chk; + + EEPROMReady = 0; + + BootPhase = 0; } DSi_NWifi::~DSi_NWifi() @@ -131,6 +170,61 @@ DSi_NWifi::~DSi_NWifi() } +// CHECKME +// can IRQ status bits be set when the corresponding IRQs are disabled in the enable register? +// otherwise, does disabling them clear the status register? + +void DSi_NWifi::UpdateIRQ() +{ + F0_IRQStatus = 0; + IRQ = false; + + if (F1_IRQStatus & F1_IRQEnable) + F0_IRQStatus |= (1<<1); + + if (F0_IRQEnable & (1<<0)) + { + if (F0_IRQStatus & F0_IRQEnable) + IRQ = true; + } + + Host->SetCardIRQ(); +} + +void DSi_NWifi::UpdateIRQ_F1() +{ + F1_IRQStatus = 0; + + if (!Mailbox[4]->IsEmpty()) F1_IRQStatus |= (1<<0); + if (!Mailbox[5]->IsEmpty()) F1_IRQStatus |= (1<<1); + if (!Mailbox[6]->IsEmpty()) F1_IRQStatus |= (1<<2); + if (!Mailbox[7]->IsEmpty()) F1_IRQStatus |= (1<<3); + if (F1_IRQStatus_Counter & F1_IRQEnable_Counter) F1_IRQStatus |= (1<<4); + if (F1_IRQStatus_CPU & F1_IRQEnable_CPU) F1_IRQStatus |= (1<<6); + if (F1_IRQStatus_Error & F1_IRQEnable_Error) F1_IRQStatus |= (1<<7); + + UpdateIRQ(); +} + +void DSi_NWifi::SetIRQ_F1_Counter(u32 n) +{ + F1_IRQStatus_Counter |= (1<Read(); + u8 ret = Mailbox[4]->Read(); + UpdateIRQ_F1(); + return ret; } else if (addr < 0x200) { - return Mailbox[5]->Read(); + u8 ret = Mailbox[5]->Read(); + UpdateIRQ_F1(); + return ret; } else if (addr < 0x300) { - return Mailbox[6]->Read(); + u8 ret = Mailbox[6]->Read(); + UpdateIRQ_F1(); + return ret; } else if (addr < 0x400) { - return Mailbox[7]->Read(); + u8 ret = Mailbox[7]->Read(); + UpdateIRQ_F1(); + return ret; } else if (addr < 0x800) { switch (addr) { + case 0x00400: return F1_IRQStatus; + case 0x00401: return F1_IRQStatus_CPU; + case 0x00402: return F1_IRQStatus_Error; + case 0x00403: return F1_IRQStatus_Counter; + + case 0x00405: + { + u8 ret = 0; + + if (Mailbox[4]->Level() >= 4) ret |= (1<<0); + if (Mailbox[5]->Level() >= 4) ret |= (1<<1); + if (Mailbox[6]->Level() >= 4) ret |= (1<<2); + if (Mailbox[7]->Level() >= 4) ret |= (1<<3); + + return ret; + } + + case 0x00408: return Mailbox[4]->Peek(0); + case 0x00409: return Mailbox[4]->Peek(1); + case 0x0040A: return Mailbox[4]->Peek(2); + case 0x0040B: return Mailbox[4]->Peek(3); + + case 0x00418: return F1_IRQEnable; + case 0x00419: return F1_IRQEnable_CPU; + case 0x0041A: return F1_IRQEnable_Error; + case 0x0041B: return F1_IRQEnable_Counter; + + // GROSS FUCKING HACK + case 0x00440: ClearIRQ_F1_Counter(0); return 0; case 0x00450: return 1; // HAX!! case 0x00474: return WindowData & 0xFF; @@ -205,23 +347,33 @@ u8 DSi_NWifi::F1_Read(u32 addr) } else if (addr < 0x1000) { - return Mailbox[4]->Read(); + u8 ret = Mailbox[4]->Read(); + UpdateIRQ_F1(); + return ret; } else if (addr < 0x1800) { - return Mailbox[5]->Read(); + u8 ret = Mailbox[5]->Read(); + UpdateIRQ_F1(); + return ret; } else if (addr < 0x2000) { - return Mailbox[6]->Read(); + u8 ret = Mailbox[6]->Read(); + UpdateIRQ_F1(); + return ret; } else if (addr < 0x2800) { - return Mailbox[7]->Read(); + u8 ret = Mailbox[7]->Read(); + UpdateIRQ_F1(); + return ret; } else { - return Mailbox[4]->Read(); + u8 ret = Mailbox[4]->Read(); + UpdateIRQ_F1(); + return ret; } printf("NWIFI: unknown func1 read %05X\n", addr); @@ -229,36 +381,48 @@ u8 DSi_NWifi::F1_Read(u32 addr) } void DSi_NWifi::F1_Write(u32 addr, u8 val) -{printf("F1 WRITE %05X %02X\n", addr, val); +{ if (addr < 0x100) { if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); Mailbox[0]->Write(val); - if (addr == 0xFF) BMI_Command(); + if (addr == 0xFF) HandleCommand(); + UpdateIRQ_F1(); return; } else if (addr < 0x200) { if (Mailbox[1]->IsFull()) printf("!!! NWIFI: MBOX1 FULL\n"); Mailbox[1]->Write(val); + UpdateIRQ_F1(); return; } else if (addr < 0x300) { if (Mailbox[2]->IsFull()) printf("!!! NWIFI: MBOX2 FULL\n"); Mailbox[2]->Write(val); + UpdateIRQ_F1(); return; } else if (addr < 0x400) { if (Mailbox[3]->IsFull()) printf("!!! NWIFI: MBOX3 FULL\n"); Mailbox[3]->Write(val); + UpdateIRQ_F1(); return; } else if (addr < 0x800) { switch (addr) { + case 0x00418: F1_IRQEnable = val; UpdateIRQ_F1(); return; + case 0x00419: F1_IRQEnable_CPU = val; UpdateIRQ_F1(); return; + case 0x0041A: F1_IRQEnable_Error = val; UpdateIRQ_F1(); return; + case 0x0041B: F1_IRQEnable_Counter = val; UpdateIRQ_F1(); return; + + // GROSS FUCKING HACK + case 0x00440: ClearIRQ_F1_Counter(0); return; + case 0x00474: WindowData = (WindowData & 0xFFFFFF00) | val; return; case 0x00475: WindowData = (WindowData & 0xFFFF00FF) | (val << 8); return; case 0x00476: WindowData = (WindowData & 0xFF00FFFF) | (val << 16); return; @@ -285,32 +449,37 @@ void DSi_NWifi::F1_Write(u32 addr, u8 val) { if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); Mailbox[0]->Write(val); - if (addr == 0xFFF) BMI_Command(); + if (addr == 0xFFF) HandleCommand(); + UpdateIRQ_F1(); return; } else if (addr < 0x1800) { if (Mailbox[1]->IsFull()) printf("!!! NWIFI: MBOX1 FULL\n"); Mailbox[1]->Write(val); + UpdateIRQ_F1(); return; } else if (addr < 0x2000) { if (Mailbox[2]->IsFull()) printf("!!! NWIFI: MBOX2 FULL\n"); Mailbox[2]->Write(val); + UpdateIRQ_F1(); return; } else if (addr < 0x2800) { if (Mailbox[3]->IsFull()) printf("!!! NWIFI: MBOX3 FULL\n"); Mailbox[3]->Write(val); + UpdateIRQ_F1(); return; } else { if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); Mailbox[0]->Write(val); - if (addr == 0x3FFF) BMI_Command(); // CHECKME + if (addr == 0x3FFF) HandleCommand(); // CHECKME + UpdateIRQ_F1(); return; } @@ -343,7 +512,7 @@ void DSi_NWifi::SDIO_Write(u32 func, u32 addr, u8 val) void DSi_NWifi::SendCMD(u8 cmd, u32 param) -{printf("NWIFI CMD %d %08X %08X\n", cmd, param, NDS::GetPC(1)); +{ switch (cmd) { case 52: // IO_RW_DIRECT @@ -426,6 +595,8 @@ void DSi_NWifi::ReadBlock() u32 func = (TransferCmd >> 28) & 0x7; u32 len = (TransferCmd & (1<<27)) ? 0x200 : RemSize; + len = Host->GetTransferrableLen(len); + u8 data[0x200]; for (u32 i = 0; i < len; i++) @@ -437,7 +608,7 @@ void DSi_NWifi::ReadBlock() TransferAddr &= 0x1FFFF; // checkme } } - Host->SendData(data, len); + len = Host->SendData(data, len); if (RemSize > 0) { @@ -454,8 +625,10 @@ void DSi_NWifi::WriteBlock() u32 func = (TransferCmd >> 28) & 0x7; u32 len = (TransferCmd & (1<<27)) ? 0x200 : RemSize; + len = Host->GetTransferrableLen(len); + u8 data[0x200]; - if (Host->ReceiveData(data, len)) + if (len = Host->ReceiveData(data, len)) { for (u32 i = 0; i < len; i++) { @@ -479,14 +652,32 @@ void DSi_NWifi::WriteBlock() } +void DSi_NWifi::HandleCommand() +{ + switch (BootPhase) + { + case 0: return BMI_Command(); + case 1: return WMI_Command(); + } +} + void DSi_NWifi::BMI_Command() { // HLE command handling stub u32 cmd = MB_Read32(0); - printf("BMI: cmd %08X\n", cmd); switch (cmd) { + case 0x01: // BMI_DONE + { + printf("BMI_DONE\n"); + EEPROMReady = 1; // GROSS FUCKING HACK + u8 ready_msg[8] = {0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00}; + SendWMIFrame(ready_msg, 8, 0, 0x00, 0x0000); + BootPhase = 1; + } + return; + case 0x03: // BMI_WRITE_MEMORY { u32 addr = MB_Read32(0); @@ -546,16 +737,94 @@ void DSi_NWifi::BMI_Command() { u32 len = MB_Read32(0); printf("BMI LZ write %08X\n", len); + //FILE* f = fopen("wififirm.bin", "ab"); for (int i = 0; i < len; i++) { u8 val = Mailbox[0]->Read(); // TODO: do something with it!! + //fwrite(&val, 1, 1, f); } + //fclose(f); } return; + + default: + printf("unknown BMI command %08X\n", cmd); + return; + } +} + +void DSi_NWifi::WMI_Command() +{ + // HLE command handling stub + u16 h0 = MB_Read16(0); + u16 len = MB_Read16(0); + u16 h2 = MB_Read16(0); + + u16 cmd = MB_Read16(0); + printf("WMI: cmd %04X\n", cmd); + + switch (cmd) + { + case 0x0002: // service connect + { + u16 svc_id = MB_Read16(0); + u16 conn_flags = MB_Read16(0); + + u8 svc_resp[10]; + *(u16*)&svc_resp[0] = 0x0003; + *(u16*)&svc_resp[2] = svc_id; + svc_resp[4] = 0; + svc_resp[5] = (svc_id & 0xFF) + 1; + *(u16*)&svc_resp[6] = 0x0001; + *(u16*)&svc_resp[8] = 0x0001; + SendWMIFrame(svc_resp, 10, 0, 0x00, 0x0000); + } + break; + + case 0x0004: // setup complete + { + u8 ready_evt[14]; + memset(ready_evt, 0, 14); + *(u16*)&ready_evt[0] = 0x1001; + memcpy(&ready_evt[2], SPI_Firmware::GetWifiMAC(), 6); + ready_evt[8] = 0x02; + *(u32*)&ready_evt[10] = 0x23000024; + // ctrl[0] = trailer size + // trailer[1] = trailer extra size + // trailer[0] = trailer type??? + SendWMIFrame(ready_evt, 14, 1, 0x00, 0x0000); + } + break; + + default: + printf("unknown WMI command %04X\n", cmd); + break; + } + + MB_Drain(0); +} + +void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) +{ + u32 wlen = 0; + + Mailbox[4]->Write(ep); // eid + Mailbox[4]->Write(flags); // flags + MB_Write16(4, len); // payload length + MB_Write16(4, ctrl); // ctrl + wlen += 6; + + for (int i = 0; i < len; i++) + { + Mailbox[4]->Write(data[i]); + wlen++; } + + for (; wlen & 0x7F; wlen++) + Mailbox[4]->Write(0); } @@ -563,6 +832,29 @@ u32 DSi_NWifi::WindowRead(u32 addr) { printf("NWifi: window read %08X\n", addr); + if ((addr & 0xFFFF00) == 0x520000) + { + // RAM host interest area + // TODO: different base based on hardware version + + switch (addr & 0xFF) + { + case 0x54: + // base address of EEPROM data + // TODO find what the actual address is! + return 0x1FFC00; + case 0x58: return EEPROMReady; // hax + } + + return 0; + } + + // hax + if ((addr & 0x1FFC00) == 0x1FFC00) + { + return *(u32*)&EEPROM[addr & 0x3FF]; + } + switch (addr) { case 0x40EC: // chip ID diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 0a36705..e5fe637 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -33,11 +33,19 @@ public: void ContinueTransfer(); + void SetIRQ_F1_Counter(u32 n); + private: u32 TransferCmd; u32 TransferAddr; u32 RemSize; + void UpdateIRQ(); + void UpdateIRQ_F1(); + //void SetIRQ_F1_Counter(u32 n); + void ClearIRQ_F1_Counter(u32 n); + void SetIRQ_F1_CPU(u32 n); + u8 F0_Read(u32 addr); void F0_Write(u32 addr, u8 val); @@ -50,11 +58,28 @@ private: void ReadBlock(); void WriteBlock(); + void HandleCommand(); void BMI_Command(); + void WMI_Command(); + + void SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl); u32 WindowRead(u32 addr); void WindowWrite(u32 addr, u32 val); + u16 MB_Read16(int n) + { + u16 ret = Mailbox[n]->Read(); + ret |= (Mailbox[n]->Read() << 8); + return ret; + } + + void MB_Write16(int n, u16 val) + { + Mailbox[n]->Write(val & 0xFF); val >>= 8; + Mailbox[n]->Write(val & 0xFF); + } + u32 MB_Read32(int n) { u32 ret = Mailbox[n]->Read(); @@ -72,9 +97,25 @@ private: Mailbox[n]->Write(val & 0xFF); } + void MB_Drain(int n) + { + while (!Mailbox[n]->IsEmpty()) Mailbox[n]->Read(); + } + FIFO* Mailbox[8]; + u8 F0_IRQEnable; + u8 F0_IRQStatus; + + u8 F1_IRQEnable, F1_IRQEnable_CPU, F1_IRQEnable_Error, F1_IRQEnable_Counter; + u8 F1_IRQStatus, F1_IRQStatus_CPU, F1_IRQStatus_Error, F1_IRQStatus_Counter; + u32 WindowData, WindowReadAddr, WindowWriteAddr; + + u8 EEPROM[0x400]; + u32 EEPROMReady; + + u32 BootPhase; }; #endif // DSI_NWIFI_H diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index c9edd78..07eca83 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -73,6 +73,10 @@ void DSi_SDHost::Reset() IRQStatus = 0; IRQMask = 0x8B7F031D; + CardIRQStatus = 0; + CardIRQMask = 0xC007; + CardIRQCtl = 0; + DataCtl = 0; Data32IRQ = 0; DataMode = 0; @@ -145,6 +149,25 @@ void DSi_SDHost::SetIRQ(u32 irq) if (irq == 24 || irq == 25) UpdateData32IRQ(); } +void DSi_SDHost::SetCardIRQ() +{ + if (!(CardIRQCtl & (1<<0))) return; + + u16 oldflags = CardIRQStatus & ~CardIRQMask; + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; + + if (dev->IRQ) CardIRQStatus |= (1<<0); + else CardIRQStatus &= ~(1<<0); + + u16 newflags = CardIRQStatus & ~CardIRQMask; + + if ((oldflags == 0) && (newflags != 0)) // checkme + { + NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC); + NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO_Data1 : NDS::IRQ2_DSi_SD_Data1); + } +} + void DSi_SDHost::SendResponse(u32 val, bool last) { *(u32*)&ResponseBuffer[6] = *(u32*)&ResponseBuffer[4]; @@ -166,10 +189,10 @@ void DSi_SDHost::FinishSend(u32 param) //if (param & 0x2) host->SetIRQ(2); } -void DSi_SDHost::SendData(u8* data, u32 len) +u32 DSi_SDHost::SendData(u8* data, u32 len) { printf("%s: data RX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask); - if (len != BlockLen16) printf("!! BAD BLOCKLEN\n"); + if (len != BlockLen16) { printf("!! BAD BLOCKLEN\n"); len = BlockLen16; } bool last = (BlockCountInternal == 0); @@ -187,6 +210,8 @@ void DSi_SDHost::SendData(u8* data, u32 len) u32 param = Num | (last << 1); NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer, false, 512, FinishSend, param); + + return len; } void DSi_SDHost::FinishReceive(u32 param) @@ -200,16 +225,16 @@ void DSi_SDHost::FinishReceive(u32 param) if (dev) dev->ContinueTransfer(); } -bool DSi_SDHost::ReceiveData(u8* data, u32 len) +u32 DSi_SDHost::ReceiveData(u8* data, u32 len) { printf("%s: data TX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask); - if (len != BlockLen16) printf("!! BAD BLOCKLEN\n"); + if (len != BlockLen16) { printf("!! BAD BLOCKLEN\n"); len = BlockLen16; } u32 f = CurFIFO; if ((DataFIFO[f]->Level() << 1) < len) { printf("%s: FIFO not full enough for a transfer (%d / %d)\n", SD_DESC, DataFIFO[f]->Level()<<1, len); - return false; + return 0; } DSi_SDDevice* dev = Ports[PortSelect & 0x1]; @@ -240,7 +265,13 @@ bool DSi_SDHost::ReceiveData(u8* data, u32 len) BlockCountInternal--; } - return true; + return len; +} + +u32 DSi_SDHost::GetTransferrableLen(u32 len) +{ + if (len > BlockLen16) len = BlockLen16; // checkme + return len; } @@ -278,6 +309,10 @@ u16 DSi_SDHost::Read(u32 addr) case 0x02C: return 0; // TODO + case 0x034: return CardIRQCtl; + case 0x036: return CardIRQStatus; + case 0x038: return CardIRQMask; + case 0x030: // FIFO16 { // TODO: decrement BlockLen???? @@ -389,7 +424,7 @@ u32 DSi_SDHost::ReadFIFO32() return ret; } - +int morp = 0; void DSi_SDHost::Write(u32 addr, u16 val) { //if(Num)printf("SDIO WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1)); @@ -470,6 +505,20 @@ void DSi_SDHost::Write(u32 addr, u16 val) } return; + case 0x034: + CardIRQCtl = val & 0x0305; + printf("[%d] CardIRQCtl = %04X\n", Num, val); + SetCardIRQ(); + return; + case 0x036: + CardIRQStatus &= val; + return; + case 0x038: + CardIRQMask = val & 0xC007; + printf("[%d] CardIRQMask = %04X\n", Num, val); + SetCardIRQ(); + return; + case 0x0D8: DataCtl = (val & 0x0022); DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1); @@ -729,42 +778,54 @@ void DSi_MMCStorage::ContinueTransfer() { if (RWCommand == 0) return; + u32 len = 0; + switch (RWCommand) { case 18: - ReadBlock(RWAddress); + len = ReadBlock(RWAddress); break; case 25: - WriteBlock(RWAddress); + len = WriteBlock(RWAddress); break; } - RWAddress += BlockSize; + RWAddress += len; } -void DSi_MMCStorage::ReadBlock(u64 addr) +u32 DSi_MMCStorage::ReadBlock(u64 addr) { - if (!File) return; - printf("SD/MMC: reading block @ %08X, len=%08X\n", addr, BlockSize); + u32 len = BlockSize; + len = Host->GetTransferrableLen(len); + u8 data[0x200]; - fseek(File, addr, SEEK_SET); - fread(data, 1, BlockSize, File); - Host->SendData(data, BlockSize); + if (File) + { + fseek(File, addr, SEEK_SET); + fread(data, 1, len, File); + } + return Host->SendData(data, len); } -void DSi_MMCStorage::WriteBlock(u64 addr) +u32 DSi_MMCStorage::WriteBlock(u64 addr) { - if (!File) return; - printf("SD/MMC: write block @ %08X, len=%08X\n", addr, BlockSize); + u32 len = BlockSize; + len = Host->GetTransferrableLen(len); + u8 data[0x200]; - if (Host->ReceiveData(data, BlockSize)) + if (len = Host->ReceiveData(data, len)) { - fseek(File, addr, SEEK_SET); - fwrite(data, 1, BlockSize, File); + if (File) + { + fseek(File, addr, SEEK_SET); + fwrite(data, 1, len, File); + } } + + return len; } diff --git a/src/DSi_SD.h b/src/DSi_SD.h index 22475d6..149b72a 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -39,8 +39,11 @@ public: static void FinishSend(u32 param); static void FinishReceive(u32 param); void SendResponse(u32 val, bool last); - void SendData(u8* data, u32 len); - bool ReceiveData(u8* data, u32 len); + u32 SendData(u8* data, u32 len); + u32 ReceiveData(u8* data, u32 len); + u32 GetTransferrableLen(u32 len); + + void SetCardIRQ(); u16 Read(u32 addr); void Write(u32 addr, u16 val); @@ -58,6 +61,10 @@ private: u32 IRQStatus; // IF u32 IRQMask; // ~IE + u16 CardIRQStatus; + u16 CardIRQMask; + u16 CardIRQCtl; + u16 DataCtl; u16 Data32IRQ; u32 DataMode; // 0=16bit 1=32bit @@ -83,12 +90,14 @@ private: class DSi_SDDevice { public: - DSi_SDDevice(DSi_SDHost* host) { Host = host; } + DSi_SDDevice(DSi_SDHost* host) { Host = host; IRQ = false; } ~DSi_SDDevice() {} virtual void SendCMD(u8 cmd, u32 param) = 0; virtual void ContinueTransfer() = 0; + bool IRQ; + protected: DSi_SDHost* Host; }; @@ -127,8 +136,8 @@ private: void SetState(u32 state) { CSR &= ~(0xF << 9); CSR |= (state << 9); } - void ReadBlock(u64 addr); - void WriteBlock(u64 addr); + u32 ReadBlock(u64 addr); + u32 WriteBlock(u64 addr); }; #endif // DSI_SD_H diff --git a/src/FIFO.h b/src/FIFO.h index a9e9ed8..213db7a 100644 --- a/src/FIFO.h +++ b/src/FIFO.h @@ -89,6 +89,15 @@ public: return Entries[ReadPos]; } + T Peek(u32 offset) + { + u32 pos = ReadPos + offset; + if (pos >= NumEntries) + pos -= NumEntries; + + return Entries[pos]; + } + u32 Level() { return NumOccupied; } bool IsEmpty() { return NumOccupied == 0; } bool IsFull() { return NumOccupied >= NumEntries; } diff --git a/src/NDS.h b/src/NDS.h index e32908b..fd94a01 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -45,6 +45,7 @@ enum // DSi Event_DSi_SDMMCTransfer, Event_DSi_SDIOTransfer, + Event_DSi_NWifi, Event_MAX }; diff --git a/src/SPI.cpp b/src/SPI.cpp index 8bee66f..783e638 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -225,6 +225,7 @@ void SetupDirectBoot() u8 GetConsoleType() { return Firmware[0x1D]; } u8 GetWifiVersion() { return Firmware[0x2F]; } u8 GetRFVersion() { return Firmware[0x40]; } +u8* GetWifiMAC() { return &Firmware[0x36]; } u8 Read() { diff --git a/src/SPI.h b/src/SPI.h index 21ad9a6..44de876 100644 --- a/src/SPI.h +++ b/src/SPI.h @@ -29,6 +29,7 @@ void SetupDirectBoot(); u8 GetConsoleType(); u8 GetWifiVersion(); u8 GetRFVersion(); +u8* GetWifiMAC(); } -- cgit v1.2.3 From 77f4663f49caffbfb948ab14e42b6f8ade11d58d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 1 Jun 2020 16:24:59 +0200 Subject: betterer SD/MMC code. Flipnote can save shit! --- src/DSi_AES.cpp | 12 +- src/DSi_I2C.cpp | 16 +-- src/DSi_NWifi.cpp | 10 +- src/DSi_SD.cpp | 398 +++++++++++++++++++++++++++++------------------------- src/DSi_SD.h | 18 ++- 5 files changed, 253 insertions(+), 201 deletions(-) (limited to 'src/DSi_NWifi.cpp') diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index 7aae8f3..4cb1169 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -213,12 +213,12 @@ u32 ReadCnt() ret |= InputFIFO->Level(); ret |= (OutputFIFO->Level() << 5); -//printf("READ AES CNT: %08X, LEVELS: IN=%d OUT=%d\n", ret, InputFIFO->Level(), OutputFIFO->Level()); + return ret; } void WriteCnt(u32 val) -{printf("AES CNT = %08X\n", val); +{ u32 oldcnt = Cnt; Cnt = val & 0xFC1FF000; @@ -294,12 +294,12 @@ void WriteCnt(u32 val) } } - printf("AES CNT: %08X / mode=%d key=%d inDMA=%d outDMA=%d blocks=%d\n", - val, AESMode, (val >> 26) & 0x3, InputDMASize, OutputDMASize, RemBlocks); + //printf("AES CNT: %08X / mode=%d key=%d inDMA=%d outDMA=%d blocks=%d\n", + // val, AESMode, (val >> 26) & 0x3, InputDMASize, OutputDMASize, RemBlocks); } void WriteBlkCnt(u32 val) -{printf("AES BLOCK CNT %08X / %d\n", val, val>>16); +{ BlkCnt = val; } @@ -405,7 +405,7 @@ void Update() // CHECKME Cnt &= ~(1<<21); } -printf("AES: FINISHED\n"); + Cnt &= ~(1<<31); if (Cnt & (1<<30)) NDS::SetIRQ2(NDS::IRQ2_DSi_AES); DSi::StopNDMAs(1, 0x2A); diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp index b2ca6e4..9984f5e 100644 --- a/src/DSi_I2C.cpp +++ b/src/DSi_I2C.cpp @@ -84,7 +84,7 @@ u8 Read(bool last) return 0; } - printf("BPTWL: read %02X -> %02X\n", CurPos, Registers[CurPos]); + //printf("BPTWL: read %02X -> %02X\n", CurPos, Registers[CurPos]); return Registers[CurPos++]; } @@ -124,7 +124,7 @@ void Write(u8 val, bool last) Registers[CurPos] = val; } - printf("BPTWL: write %02X -> %02X\n", CurPos, val); + //printf("BPTWL: write %02X -> %02X\n", CurPos, val); CurPos++; // CHECKME } @@ -166,7 +166,7 @@ void Reset() void WriteCnt(u8 val) { - printf("I2C: write CNT %02X, %08X\n", val, NDS::GetPC(1)); + //printf("I2C: write CNT %02X, %08X\n", val, NDS::GetPC(1)); // TODO: check ACK flag // TODO: transfer delay @@ -193,7 +193,7 @@ void WriteCnt(u8 val) break; } - printf("I2C read, device=%02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast); + //printf("I2C read, device=%02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast); } else { @@ -204,7 +204,7 @@ void WriteCnt(u8 val) if (val & (1<<1)) { Device = Data & 0xFE; - printf("I2C: %s start, device=%02X\n", (Data&0x01)?"read":"write", Device); + //printf("I2C: %s start, device=%02X\n", (Data&0x01)?"read":"write", Device); switch (Device) { @@ -219,7 +219,7 @@ void WriteCnt(u8 val) } else { - printf("I2C write, device=%02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast); + //printf("I2C write, device=%02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast); switch (Device) { @@ -243,12 +243,12 @@ void WriteCnt(u8 val) } u8 ReadData() -{printf("I2C: read data: %02X\n", Data); +{ return Data; } void WriteData(u8 val) -{printf("I2C: write data: %02X\n", val); +{ Data = val; } diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 013173f..79bc632 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -515,6 +515,12 @@ void DSi_NWifi::SendCMD(u8 cmd, u32 param) { switch (cmd) { + case 12: + // stop command + // CHECKME: does the SDIO controller actually send those?? + // DSi firmware sets it to send them + return; + case 52: // IO_RW_DIRECT { u32 func = (param >> 28) & 0x7; @@ -608,7 +614,7 @@ void DSi_NWifi::ReadBlock() TransferAddr &= 0x1FFFF; // checkme } } - len = Host->SendData(data, len); + len = Host->DataRX(data, len); if (RemSize > 0) { @@ -628,7 +634,7 @@ void DSi_NWifi::WriteBlock() len = Host->GetTransferrableLen(len); u8 data[0x200]; - if (len = Host->ReceiveData(data, len)) + if (len = Host->DataTX(data, len)) { for (u32 i = 0; i < len; i++) { diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index a45a8ce..5231b99 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -24,7 +24,27 @@ #include "Platform.h" -#define SD_DESC (Num?"SDIO":"SD/MMC") +// observed IRQ behavior during transfers +// +// during reads: +// * bit23 is cleared during the first block, always set otherwise. weird +// * bit24 (RXRDY) gets set when the FIFO is full +// +// during reads with FIFO32: +// * FIFO16 drains directly into FIFO32 +// * when bit24 is set, FIFO32 is already full (with contents from the other FIFO) +// * reading from an empty FIFO just wraps around (and sets bit21) +// * FIFO32 starts filling when bit24 would be set? +// +// +// TX: +// * when sending command, if current FIFO full +// * upon ContinueTransfer(), if current FIFO full +// * -> upon DataTX() if current FIFO full +// * when filling FIFO + + +#define SD_DESC Num?"SDIO":"SD/MMC" DSi_SDHost::DSi_SDHost(u32 num) @@ -33,6 +53,7 @@ DSi_SDHost::DSi_SDHost(u32 num) DataFIFO[0] = new FIFO(0x100); DataFIFO[1] = new FIFO(0x100); + DataFIFO32 = new FIFO(0x80); Ports[0] = NULL; Ports[1] = NULL; @@ -42,6 +63,7 @@ DSi_SDHost::~DSi_SDHost() { delete DataFIFO[0]; delete DataFIFO[1]; + delete DataFIFO32; if (Ports[0]) delete Ports[0]; if (Ports[1]) delete Ports[1]; @@ -69,6 +91,7 @@ void DSi_SDHost::Reset() DataFIFO[0]->Clear(); DataFIFO[1]->Clear(); CurFIFO = 0; + DataFIFO32->Clear(); IRQStatus = 0; IRQMask = 0x8B7F031D; @@ -84,6 +107,8 @@ void DSi_SDHost::Reset() BlockLen16 = 0; BlockLen32 = 0; StopAction = 0; + TXReq = false; + if (Ports[0]) delete Ports[0]; if (Ports[1]) delete Ports[1]; Ports[0] = NULL; @@ -125,8 +150,8 @@ void DSi_SDHost::UpdateData32IRQ() oldflags &= (Data32IRQ >> 11); Data32IRQ &= ~0x0300; - if (IRQStatus & (1<<24)) Data32IRQ |= (1<<8); - if (!(IRQStatus & (1<<25))) Data32IRQ |= (1<<9); + if (DataFIFO32->Level() >= (BlockLen32>>2)) Data32IRQ |= (1<<8); + if (!DataFIFO32->IsEmpty()) Data32IRQ |= (1<<9); u32 newflags = ((Data32IRQ >> 8) & 0x1) | (((~Data32IRQ) >> 8) & 0x2); newflags &= (Data32IRQ >> 11); @@ -138,8 +163,6 @@ void DSi_SDHost::UpdateData32IRQ() void DSi_SDHost::ClearIRQ(u32 irq) { IRQStatus &= ~(1<CurFIFO ^= 1; + host->CheckSwapFIFO(); - host->ClearIRQ(25); - host->SetIRQ(24); - //if (param & 0x2) host->SetIRQ(2); - - // TODO: this is an assumption and should eventually be confirmed - // Flipnote sets DMA blocklen to 128 words and totallen to 1024 words - // so, presumably, DMA should trigger when the FIFO is full - // 'full' being when it reaches whatever BlockLen16 is set to, or the - // other blocklen register, or when it is actually full (but that makes - // less sense) - DSi::CheckNDMAs(1, host->Num ? 0x29 : 0x28); + if (host->DataMode == 1) + host->UpdateFIFO32(); + else + host->SetIRQ(24); } -u32 DSi_SDHost::SendData(u8* data, u32 len) +u32 DSi_SDHost::DataRX(u8* data, u32 len) { - //printf("%s: data RX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask); if (len != BlockLen16) { printf("!! BAD BLOCKLEN\n"); len = BlockLen16; } bool last = (BlockCountInternal == 0); @@ -232,52 +245,112 @@ u32 DSi_SDHost::SendData(u8* data, u32 len) // send-command function starts polling IRQ status u32 param = Num | (last << 1); NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer, - false, 512, FinishSend, param); + false, 512, FinishRX, param); return len; } -void DSi_SDHost::FinishReceive(u32 param) +void DSi_SDHost::FinishTX(u32 param) { DSi_SDHost* host = (param & 0x1) ? DSi::SDIO : DSi::SDMMC; DSi_SDDevice* dev = host->Ports[host->PortSelect & 0x1]; - host->ClearIRQ(24); - host->SetIRQ(25); + if (host->BlockCountInternal == 0) + { + if (host->StopAction & (1<<8)) + { + if (dev) dev->SendCMD(12, 0); + } - if (dev) dev->ContinueTransfer(); + // CHECKME: presumably IRQ2 should not trigger here, but rather + // when the data transfer is done + //SetIRQ(0); + host->SetIRQ(2); + host->TXReq = false; + } + else + { + if (dev) dev->ContinueTransfer(); + } } -u32 DSi_SDHost::ReceiveData(u8* data, u32 len) +u32 DSi_SDHost::DataTX(u8* data, u32 len) { - printf("%s: data TX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask); - if (len != BlockLen16) { printf("!! BAD BLOCKLEN\n"); len = BlockLen16; } + TXReq = true; u32 f = CurFIFO; - if ((DataFIFO[f]->Level() << 1) < len) + + if (DataMode == 1) { - printf("%s: FIFO not full enough for a transfer (%d / %d)\n", SD_DESC, DataFIFO[f]->Level()<<1, len); - return 0; + if ((DataFIFO32->Level() << 2) < len) + { + if (DataFIFO32->IsEmpty()) + { + SetIRQ(25); + DSi::CheckNDMAs(1, Num ? 0x29 : 0x28); + } + return 0; + } + + // drain FIFO32 into FIFO16 + + if (!DataFIFO[f]->IsEmpty()) printf("VERY BAD!! TRYING TO DRAIN FIFO32 INTO FIFO16 BUT IT CONTAINS SHIT ALREADY\n"); + for (;;) + { + u32 f = CurFIFO; + if ((DataFIFO[f]->Level() << 1) >= BlockLen16) break; + if (DataFIFO32->IsEmpty()) break; + + u32 val = DataFIFO32->Read(); + DataFIFO[f]->Write(val & 0xFFFF); + DataFIFO[f]->Write(val >> 16); + } + + UpdateData32IRQ(); + + if (BlockCount32 > 1) + BlockCount32--; + } + else + { + if ((DataFIFO[f]->Level() << 1) < len) + { + if (DataFIFO[f]->IsEmpty()) SetIRQ(25); + return 0; + } } - DSi_SDDevice* dev = Ports[PortSelect & 0x1]; for (u32 i = 0; i < len; i += 2) *(u16*)&data[i] = DataFIFO[f]->Read(); CurFIFO ^= 1; + BlockCountInternal--; + + NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer, + false, 512, FinishTX, Num); + + return len; +} + +u32 DSi_SDHost::GetTransferrableLen(u32 len) +{ + if (len > BlockLen16) len = BlockLen16; // checkme + return len; +} + +void DSi_SDHost::CheckRX() +{ + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; + + CheckSwapFIFO(); if (BlockCountInternal <= 1) { - printf("%s: data TX complete", SD_DESC); - if (StopAction & (1<<8)) { - printf(", sending CMD12"); if (dev) dev->SendCMD(12, 0); } - printf("\n"); - // CHECKME: presumably IRQ2 should not trigger here, but rather // when the data transfer is done //SetIRQ(0); @@ -286,22 +359,34 @@ u32 DSi_SDHost::ReceiveData(u8* data, u32 len) else { BlockCountInternal--; - } - return len; + if (dev) dev->ContinueTransfer(); + } } -u32 DSi_SDHost::GetTransferrableLen(u32 len) +void DSi_SDHost::CheckTX() { - if (len > BlockLen16) len = BlockLen16; // checkme - return len; + if (!TXReq) return; + + if (DataMode == 1) + { + if ((DataFIFO32->Level() << 2) < BlockLen32) + return; + } + else + { + u32 f = CurFIFO; + if ((DataFIFO[f]->Level() << 1) < BlockLen16) + return; + } + + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; + if (dev) dev->ContinueTransfer(); } u16 DSi_SDHost::Read(u32 addr) { - if(!Num)printf("SDMMC READ %08X %08X\n", addr, NDS::GetPC(1)); - switch (addr & 0x1FF) { case 0x000: return Command; @@ -353,53 +438,7 @@ u16 DSi_SDHost::Read(u32 addr) case 0x036: return CardIRQStatus; case 0x038: return CardIRQMask; - case 0x030: // FIFO16 - { - // TODO: decrement BlockLen???? - - u32 f = CurFIFO; - if (DataFIFO[f]->IsEmpty()) - { - // TODO - return 0; - } - - DSi_SDDevice* dev = Ports[PortSelect & 0x1]; - u16 ret = DataFIFO[f]->Read(); - - if (DataFIFO[f]->IsEmpty()) - { - ClearIRQ(24); - - if (BlockCountInternal <= 1) - { - printf("%s: data RX complete", SD_DESC); - - if (StopAction & (1<<8)) - { - printf(", sending CMD12"); - if (dev) dev->SendCMD(12, 0); - } - - printf("\n"); - - // CHECKME: presumably IRQ2 should not trigger here, but rather - // when the data transfer is done - //SetIRQ(0); - SetIRQ(2); - } - else - { - BlockCountInternal--; - - if (dev) dev->ContinueTransfer(); - } - - SetIRQ(25); - } - - return ret; - } + case 0x030: return ReadFIFO16(); case 0x0D8: return DataCtl; @@ -414,61 +453,52 @@ u16 DSi_SDHost::Read(u32 addr) return 0; } -u32 DSi_SDHost::ReadFIFO32() +u16 DSi_SDHost::ReadFIFO16() { - if (DataMode != 1) return 0; - - // TODO: decrement BlockLen???? - u32 f = CurFIFO; if (DataFIFO[f]->IsEmpty()) { // TODO + // on hardware it seems to wrap around. underflow bit is set upon the first 'empty' read. return 0; } DSi_SDDevice* dev = Ports[PortSelect & 0x1]; - u32 ret = DataFIFO[f]->Read(); - ret |= (DataFIFO[f]->Read() << 16); + u16 ret = DataFIFO[f]->Read(); if (DataFIFO[f]->IsEmpty()) { - ClearIRQ(24); - - if (BlockCountInternal <= 1) - { - printf("%s: data32 RX complete", SD_DESC); + CheckRX(); + } - if (StopAction & (1<<8)) - { - printf(", sending CMD12"); - if (dev) dev->SendCMD(12, 0); - } + return ret; +} - printf("\n"); +u32 DSi_SDHost::ReadFIFO32() +{ + if (DataMode != 1) return 0; - // CHECKME: presumably IRQ2 should not trigger here, but rather - // when the data transfer is done - //SetIRQ(0); - SetIRQ(2); - } - else - { - BlockCountInternal--; + if (DataFIFO32->IsEmpty()) + { + // TODO + return 0; + } - if (dev) dev->ContinueTransfer(); - } + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; + u32 ret = DataFIFO32->Read(); - SetIRQ(25); + if (DataFIFO32->IsEmpty()) + { + CheckRX(); } + UpdateData32IRQ(); + return ret; } void DSi_SDHost::Write(u32 addr, u16 val) { - if(!Num)printf("SDMMC WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1)); - switch (addr & 0x1FF) { case 0x000: @@ -528,36 +558,10 @@ void DSi_SDHost::Write(u32 addr, u16 val) return; case 0x028: SDOption = val & 0xC1FF; return; - case 0x030: // FIFO16 - { - DSi_SDDevice* dev = Ports[PortSelect & 0x1]; - u32 f = CurFIFO; - if (DataFIFO[f]->IsFull()) - { - // TODO - printf("!!!! %s FIFO (16) FULL\n", SD_DESC); - return; - } - - DataFIFO[f]->Write(val); - - if (DataFIFO[f]->Level() < (BlockLen16>>1)) - { - ClearIRQ(25); - SetIRQ(24); - return; - } - - // we completed one block, send it to the SD card - // TODO measure the actual delay!! - NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer, - false, 2048, FinishReceive, Num); - } - return; + case 0x030: WriteFIFO16(val); return; case 0x034: CardIRQCtl = val & 0x0305; - printf("[%d] CardIRQCtl = %04X\n", Num, val); SetCardIRQ(); return; case 0x036: @@ -565,7 +569,6 @@ void DSi_SDHost::Write(u32 addr, u16 val) return; case 0x038: CardIRQMask = val & 0xC007; - printf("[%d] CardIRQMask = %04X\n", Num, val); SetCardIRQ(); return; @@ -593,12 +596,7 @@ void DSi_SDHost::Write(u32 addr, u16 val) case 0x100: Data32IRQ = (val & 0x1802) | (Data32IRQ & 0x0300); - if (val & (1<<10)) - { - // kind of hacky - u32 f = CurFIFO; - DataFIFO[f]->Clear(); - } + if (val & (1<<10)) DataFIFO32->Clear(); DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1); printf("%s: data mode %d-bit\n", SD_DESC, DataMode?32:16); return; @@ -609,35 +607,76 @@ void DSi_SDHost::Write(u32 addr, u16 val) printf("unknown %s write %08X %04X\n", SD_DESC, addr, val); } -void DSi_SDHost::WriteFIFO32(u32 val) +void DSi_SDHost::WriteFIFO16(u16 val) { - if (DataMode != 1) return; - - printf("%s: WRITE FIFO32: LEVEL=%d/%d\n", SD_DESC, DataFIFO[CurFIFO]->Level(), (BlockLen16>>1)); - DSi_SDDevice* dev = Ports[PortSelect & 0x1]; u32 f = CurFIFO; if (DataFIFO[f]->IsFull()) { // TODO - printf("!!!! %s FIFO (32) FULL\n", SD_DESC); + printf("!!!! %s FIFO (16) FULL\n", SD_DESC); return; } - DataFIFO[f]->Write(val & 0xFFFF); - DataFIFO[f]->Write(val >> 16); + DataFIFO[f]->Write(val); + + CheckTX(); +} + +void DSi_SDHost::WriteFIFO32(u32 val) +{ + if (DataMode != 1) return; - if (DataFIFO[f]->Level() < (BlockLen16>>1)) + if (DataFIFO32->IsFull()) { - ClearIRQ(25); - SetIRQ(24); + // TODO + printf("!!!! %s FIFO (32) FULL\n", SD_DESC); return; } - // we completed one block, send it to the SD card - // TODO measure the actual delay!! - NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer, - false, 2048, FinishReceive, Num); + DataFIFO32->Write(val); + + CheckTX(); + + UpdateData32IRQ(); +} + +void DSi_SDHost::UpdateFIFO32() +{ + // check whether we can drain FIFO32 into FIFO16, or vice versa + + if (DataMode != 1) return; + + if (!DataFIFO32->IsEmpty()) printf("VERY BAD!! TRYING TO DRAIN FIFO16 INTO FIFO32 BUT IT CONTAINS SHIT ALREADY\n"); + for (;;) + { + u32 f = CurFIFO; + if ((DataFIFO32->Level() << 2) >= BlockLen32) break; + if (DataFIFO[f]->IsEmpty()) break; + + u32 val = DataFIFO[f]->Read(); + val |= (DataFIFO[f]->Read() << 16); + DataFIFO32->Write(val); + } + + UpdateData32IRQ(); + + if ((DataFIFO32->Level() << 2) >= BlockLen32) + { + DSi::CheckNDMAs(1, Num ? 0x29 : 0x28); + } +} + +void DSi_SDHost::CheckSwapFIFO() +{ + // check whether we can swap the FIFOs + + u32 f = CurFIFO; + bool cur_empty = (DataMode == 1) ? DataFIFO32->IsEmpty() : DataFIFO[f]->IsEmpty(); + if (cur_empty && ((DataFIFO[f^1]->Level() << 1) >= BlockLen16)) + { + CurFIFO ^= 1; + } } @@ -813,7 +852,7 @@ void DSi_MMCStorage::SendACMD(u8 cmd, u32 param) case 13: // get SSR Host->SendResponse(CSR, true); - Host->SendData(SSR, 64); + Host->DataRX(SSR, 64); return; case 41: // set operating conditions @@ -834,7 +873,7 @@ void DSi_MMCStorage::SendACMD(u8 cmd, u32 param) case 51: // get SCR Host->SendResponse(CSR, true); - Host->SendData(SCR, 8); + Host->DataRX(SCR, 8); return; } @@ -863,8 +902,6 @@ void DSi_MMCStorage::ContinueTransfer() u32 DSi_MMCStorage::ReadBlock(u64 addr) { - //printf("SD/MMC: reading block @ %08X, len=%08X\n", addr, BlockSize); - u32 len = BlockSize; len = Host->GetTransferrableLen(len); @@ -874,18 +911,17 @@ u32 DSi_MMCStorage::ReadBlock(u64 addr) fseek(File, addr, SEEK_SET); fread(data, 1, len, File); } - return Host->SendData(data, len); + + return Host->DataRX(data, len); } u32 DSi_MMCStorage::WriteBlock(u64 addr) { - printf("SD/MMC: write block @ %08X, len=%08X\n", addr, BlockSize); - u32 len = BlockSize; len = Host->GetTransferrableLen(len); u8 data[0x200]; - if (len = Host->ReceiveData(data, len)) + if (len = Host->DataTX(data, len)) { if (File) { diff --git a/src/DSi_SD.h b/src/DSi_SD.h index f4ca26c..2862173 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -36,20 +36,29 @@ public: void DoSavestate(Savestate* file); - static void FinishSend(u32 param); - static void FinishReceive(u32 param); + static void FinishRX(u32 param); + static void FinishTX(u32 param); void SendResponse(u32 val, bool last); - u32 SendData(u8* data, u32 len); - u32 ReceiveData(u8* data, u32 len); + u32 DataRX(u8* data, u32 len); + u32 DataTX(u8* data, u32 len); u32 GetTransferrableLen(u32 len); + void CheckRX(); + void CheckTX(); + bool TXReq; + void SetCardIRQ(); u16 Read(u32 addr); void Write(u32 addr, u16 val); + u16 ReadFIFO16(); + void WriteFIFO16(u16 val); u32 ReadFIFO32(); void WriteFIFO32(u32 val); + void UpdateFIFO32(); + void CheckSwapFIFO(); + private: u32 Num; @@ -78,6 +87,7 @@ private: FIFO* DataFIFO[2]; u32 CurFIFO; // FIFO accessible for read/write + FIFO* DataFIFO32; DSi_SDDevice* Ports[2]; -- cgit v1.2.3