wifi: take this shit further. complete wifi init

This commit is contained in:
Arisotura
2019-08-04 02:16:16 +02:00
parent 0918da7b00
commit f7f4ff0519
9 changed files with 472 additions and 61 deletions

View File

@ -20,6 +20,7 @@
#include <stdio.h>
#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<u8>(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<<n);
UpdateIRQ_F1();
}
void DSi_NWifi::ClearIRQ_F1_Counter(u32 n)
{
F1_IRQStatus_Counter &= ~(1<<n);
UpdateIRQ_F1();
}
void DSi_NWifi::SetIRQ_F1_CPU(u32 n)
{
F1_IRQStatus_CPU |= (1<<n);
UpdateIRQ_F1();
}
u8 DSi_NWifi::F0_Read(u32 addr)
{
switch (addr)
@ -141,6 +235,9 @@ u8 DSi_NWifi::F0_Read(u32 addr)
case 0x00002: return 0x02; // writable??
case 0x00003: return 0x02;
case 0x00004: return F0_IRQEnable;
case 0x00005: return F0_IRQStatus;
case 0x00008: return 0x17;
case 0x00009: return 0x00;
@ -169,32 +266,77 @@ u8 DSi_NWifi::F0_Read(u32 addr)
void DSi_NWifi::F0_Write(u32 addr, u8 val)
{
switch (addr)
{
case 0x00004:
F0_IRQEnable = val;
UpdateIRQ();
return;
}
printf("NWIFI: unknown func0 write %05X %02X\n", addr, val);
}
u8 DSi_NWifi::F1_Read(u32 addr)
{printf("F1 READ %05X\n", addr);
{
if (addr < 0x100)
{
return Mailbox[4]->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