From f7f4ff0519309669e78b994e7c759d13808f0a87 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 4 Aug 2019 02:16:16 +0200 Subject: [PATCH] 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 | 113 ++++++++++++---- src/DSi_SD.h | 19 ++- src/FIFO.h | 9 ++ src/NDS.h | 1 + src/SPI.cpp | 1 + src/SPI.h | 1 + 9 files changed, 472 insertions(+), 61 deletions(-) diff --git a/src/DSi.cpp b/src/DSi.cpp index aed6b89f..17d7f0d1 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 6f237401..013173f3 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,23 +737,124 @@ 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); +} + 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 0a36705c..e5fe637f 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 c9edd788..07eca83c 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); - u8 data[0x200]; - fseek(File, addr, SEEK_SET); - fread(data, 1, BlockSize, File); - Host->SendData(data, BlockSize); -} - -void 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 (File) { fseek(File, addr, SEEK_SET); - fwrite(data, 1, BlockSize, File); + fread(data, 1, len, File); } + return Host->SendData(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 (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 22475d6c..149b72a2 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 a9e9ed80..213db7a2 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 e32908b9..fd94a01d 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 8bee66f4..783e6386 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 21ad9a66..44de8765 100644 --- a/src/SPI.h +++ b/src/SPI.h @@ -29,6 +29,7 @@ void SetupDirectBoot(); u8 GetConsoleType(); u8 GetWifiVersion(); u8 GetRFVersion(); +u8* GetWifiMAC(); }