aboutsummaryrefslogtreecommitdiff
path: root/src/Wifi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Wifi.cpp')
-rw-r--r--src/Wifi.cpp235
1 files changed, 213 insertions, 22 deletions
diff --git a/src/Wifi.cpp b/src/Wifi.cpp
index 0f1c239..99d0017 100644
--- a/src/Wifi.cpp
+++ b/src/Wifi.cpp
@@ -19,22 +19,39 @@
#include <stdio.h>
#include <string.h>
#include "NDS.h"
+#include "SPI.h"
#include "Wifi.h"
namespace Wifi
{
+u8 RAM[0x2000];
+u16 IO[0x1000>>1];
+
+#define IOPORT(x) IO[(x)>>1]
+
+u16 Random;
+
u16 BBCnt;
u8 BBWrite;
u8 BBRegs[0x100];
u8 BBRegsRO[0x100];
+u8 RFVersion;
+u16 RFCnt;
+u16 RFData1;
+u16 RFData2;
+u32 RFRegs[0x40];
+
void Reset()
{
- BBCnt = 0;
- BBWrite = 0;
+ memset(RAM, 0, 0x2000);
+ memset(IO, 0, 0x1000);
+
+ Random = 1;
+
memset(BBRegs, 0, 0x100);
memset(BBRegsRO, 0, 0x100);
@@ -65,56 +82,230 @@ void Reset()
BBREG_FIXED(i, 0x00);
}
#undef BBREG_FIXED
+
+ RFVersion = SPI_Firmware::GetRFVersion();
+ memset(RFRegs, 0, 4*0x40);
+
+ memset(&IOPORT(0x018), 0xFF, 6);
+ memset(&IOPORT(0x020), 0xFF, 6);
}
+void RFTransfer_Type2()
+{
+ u32 id = (IOPORT(W_RFData2) >> 2) & 0x1F;
+
+ if (IOPORT(W_RFData2) & 0x0080)
+ {
+ u32 data = RFRegs[id];
+ IOPORT(W_RFData1) = data & 0xFFFF;
+ IOPORT(W_RFData2) = (IOPORT(W_RFData2) & 0xFFFC) | ((data >> 16) & 0x3);
+ }
+ else
+ {
+ u32 data = IOPORT(W_RFData1) | ((IOPORT(W_RFData2) & 0x0003) << 16);
+ RFRegs[id] = data;
+ }
+}
+
+void RFTransfer_Type3()
+{
+ u32 id = (IOPORT(W_RFData1) >> 8) & 0x3F;
+
+ u32 cmd = IOPORT(W_RFData2) & 0xF;
+ if (cmd == 6)
+ {
+ IOPORT(W_RFData1) = (IOPORT(W_RFData1) & 0xFF00) | (RFRegs[id] & 0xFF);
+ }
+ else if (cmd == 5)
+ {
+ u32 data = IOPORT(W_RFData1) & 0xFF;
+ RFRegs[id] = data;
+ }
+}
+
+
+// TODO: wifi waitstates
+
u16 Read(u32 addr)
{
- addr &= 0x7FFF;
+ addr &= 0x7FFE;
+ //printf("WIFI: read %08X\n", addr);
+ if (addr >= 0x4000 && addr < 0x6000)
+ {
+ return *(u16*)&RAM[addr & 0x1FFE];
+ }
switch (addr)
{
- case 0x158:
- return BBCnt;
+ case W_Random: // random generator. not accurate
+ Random = (Random & 0x1) ^ (((Random & 0x3FF) << 1) | (Random >> 10));
+ return Random;
- case 0x15C:
- if ((BBCnt & 0xF000) != 0x6000)
+ case W_Preamble:
+ return IOPORT(W_Preamble) & 0x0003;
+
+ case W_BBRead:
+ if ((IOPORT(W_BBCnt) & 0xF000) != 0x6000)
{
- printf("WIFI: bad BB read, CNT=%04X\n", BBCnt);
+ printf("WIFI: bad BB read, CNT=%04X\n", IOPORT(W_BBCnt));
return 0;
}
- return BBRegs[BBCnt & 0xFF];
+ return BBRegs[IOPORT(W_BBCnt) & 0xFF];
- case 0x15E:
- return 0; // cheap
+ case W_BBBusy:
+ return 0; // TODO eventually (BB busy flag)
+ case W_RFBusy:
+ return 0; // TODO eventually (RF busy flag)
}
- printf("WIFI: unknown read %08X\n", addr);
- return 0;
+ //printf("WIFI: read %08X\n", addr);
+ return IOPORT(addr&0xFFF);
}
void Write(u32 addr, u16 val)
{
- addr &= 0x7FFF;
+ addr &= 0x7FFE;
+ //printf("WIFI: write %08X %04X\n", addr, val);
+ if (addr >= 0x4000 && addr < 0x6000)
+ {
+ *(u16*)&RAM[addr & 0x1FFE] = val;
+ return;
+ }
switch (addr)
{
- case 0x158:
- BBCnt = val;
- if ((BBCnt & 0xF000) == 0x5000)
+ case W_ModeReset:
+ {
+ u16 oldval = IOPORT(W_ModeReset);
+
+ if (!(oldval & 0x0001) && (val & 0x0001))
+ {
+ IOPORT(0x034) = 0x0002;
+ IOPORT(W_RFPins) = 0x0046;
+ IOPORT(W_RFStatus) = 9;
+ IOPORT(0x27C) = 0x0005;
+ // TODO: 02A2??
+ }
+ else if ((oldval & 0x0001) && !(val & 0x0001))
+ {
+ IOPORT(0x27C) = 0x000A;
+ }
+
+ if (val & 0x2000)
+ {
+ IOPORT(W_RXBufWriteAddr) = 0;
+ IOPORT(W_CmdTotalTime) = 0;
+ IOPORT(W_CmdReplyTime) = 0;
+ IOPORT(0x1A4) = 0;
+ IOPORT(0x278) = 0x000F;
+ // TODO: other ports??
+ }
+ if (val & 0x4000)
+ {
+ IOPORT(W_ModeWEP) = 0;
+ IOPORT(W_TXStatCnt) = 0;
+ IOPORT(0x00A) = 0;
+ IOPORT(W_MACAddr0) = 0;
+ IOPORT(W_MACAddr1) = 0;
+ IOPORT(W_MACAddr2) = 0;
+ IOPORT(W_BSSID0) = 0;
+ IOPORT(W_BSSID1) = 0;
+ IOPORT(W_BSSID2) = 0;
+ IOPORT(W_AIDLow) = 0;
+ IOPORT(W_AIDFull) = 0;
+ IOPORT(W_TXRetryLimit) = 0x0707;
+ IOPORT(0x02E) = 0;
+ IOPORT(W_RXBufBegin) = 0x4000;
+ IOPORT(W_RXBufEnd) = 0x4800;
+ IOPORT(W_TXBeaconTIM) = 0;
+ IOPORT(W_Preamble) = 0x0001;
+ IOPORT(W_RXFilter) = 0x0401;
+ IOPORT(0x0D4) = 0x0001;
+ IOPORT(W_RXFilter2) = 0x0008;
+ IOPORT(0x0EC) = 0x3F03;
+ IOPORT(W_TXHeaderCnt) = 0;
+ IOPORT(0x198) = 0;
+ IOPORT(0x1A2) = 0x0001;
+ IOPORT(0x224) = 0x0003;
+ IOPORT(0x230) = 0x0047;
+
+ }
+ }
+ break;
+
+ case W_ModeWEP:
+ val &= 0x007F;
+ break;
+
+ case W_IF:
+ // IF: TODO
+ return;
+ case W_IE:
+ printf("WIFI IE=%04X\n", val);
+ break;
+
+ case W_PowerState:
+ if (val & 0x0002)
{
- u32 regid = BBCnt & 0xFF;
+ // TODO: IRQ11
+ IOPORT(W_PowerState) = 0x0000;
+ }
+ return;
+ case W_PowerForce:
+ printf("WIFI: forcing power %04X\n", val);
+ val &= 0x8001;
+ if (val == 0x8001)
+ {
+ IOPORT(0x034) = 0x0002;
+ IOPORT(W_PowerState) = 0x0200;
+ IOPORT(W_TXReqRead) = 0;
+ IOPORT(W_RFPins) = 00046;
+ IOPORT(W_RFStatus) = 9;
+ }
+ break;
+
+ case W_BBCnt:
+ IOPORT(W_BBCnt) = val;
+ if ((IOPORT(W_BBCnt) & 0xF000) == 0x5000)
+ {
+ u32 regid = IOPORT(W_BBCnt) & 0xFF;
if (!BBRegsRO[regid])
- BBRegs[regid] = val & 0xFF;
+ BBRegs[regid] = IOPORT(W_BBWrite) & 0xFF;
}
return;
- case 0x15A:
- BBWrite = val;
+ case W_RFData2:
+ IOPORT(W_RFData2) = val;
+ if (RFVersion == 3) RFTransfer_Type3();
+ else RFTransfer_Type2();
+ return;
+ case W_RFCnt:
+ val &= 0x413F;
+ break;
+
+ // read-only ports
+ case 0x000:
+ case 0x044:
+ case 0x054:
+ case 0x0B0:
+ case 0x0B6:
+ case 0x0B8:
+ case 0x15C:
+ case 0x15E:
+ case 0x180:
+ case 0x19C:
+ case 0x1A8:
+ case 0x1AC:
+ case 0x1C4:
+ case 0x210:
+ case 0x214:
+ case 0x268:
return;
}
- printf("WIFI: unknown write %08X %04X\n", addr, val);
+ //printf("WIFI: write %08X %04X\n", addr, val);
+ IOPORT(addr&0xFFF) = val;
}
}