Commit 402a60ea authored by StapleButter's avatar StapleButter
Browse files

wifi: proper TX/RX status switch and RX check

readme: little update
parent 49f8aec6
...@@ -15,7 +15,10 @@ melonDS requires BIOS/firmware copies from a DS. Files required: ...@@ -15,7 +15,10 @@ melonDS requires BIOS/firmware copies from a DS. Files required:
* bios9.bin, 4KB: ARM9 BIOS * bios9.bin, 4KB: ARM9 BIOS
* firmware.bin, 256KB: firmware * firmware.bin, 256KB: firmware
Note: the DS-mode firmware in the 3DS isn't bootable, it only contains the bare minimum to run games. Firmware boot requires a firmware dump from an original DS or DS Lite.
DS firmwares dumped from a DSi or 3DS aren't bootable and only contain configuration data, thus they are only suitable when booting games directly.
DS BIOS dumps from a 3DS can be used with no compatibility issues. DSi BIOS dumps should be usable too, provided they were dumped properly.
As for the rest, the interface should be pretty straightforward. If you have a question, don't hesitate to ask, though! As for the rest, the interface should be pretty straightforward. If you have a question, don't hesitate to ask, though!
......
...@@ -67,6 +67,10 @@ u8 RXBuffer[2048]; ...@@ -67,6 +67,10 @@ u8 RXBuffer[2048];
u32 RXTime; u32 RXTime;
u16 RXEndAddr; u16 RXEndAddr;
u32 ComStatus; // 0=waiting for packets 1=receiving 2=sending
u32 TXCurSlot;
u32 RXCounter;
bool MPInited; bool MPInited;
...@@ -75,10 +79,11 @@ bool MPInited; ...@@ -75,10 +79,11 @@ bool MPInited;
// 1. preamble // 1. preamble
// 2. IRQ7 // 2. IRQ7
// 3. send data // 3. send data
// 4. wait for client replies (duration: 112 + ((10 * CMD_REPLYTIME) * numclients)) // 4. optional IRQ1
// 5. IRQ7 // 5. wait for client replies (duration: 112 + ((10 * CMD_REPLYTIME) * numclients))
// 6. send ack (16 bytes, 1Mbps) // 6. IRQ7
// 7. optional IRQ1, along with IRQ12 if the transfer was successful or if // 7. send ack (16 bytes, 1Mbps)
// 8. optional IRQ1, along with IRQ12 if the transfer was successful or if
// there's no time left for a retry // there's no time left for a retry
// //
// if the transfer has to be retried (for example, didn't get replies from all clients) // if the transfer has to be retried (for example, didn't get replies from all clients)
...@@ -89,14 +94,14 @@ bool MPInited; ...@@ -89,14 +94,14 @@ bool MPInited;
// //
// RFSTATUS values: // RFSTATUS values:
// 0 = initial // 0 = initial
// 1 = RX???? // 1 = waiting for incoming packets
// 2 = switching from RX to TX // 2 = switching from RX to TX
// 3 = TX // 3 = TX
// 4 = switching from TX to RX // 4 = switching from TX to RX
// 5 = MP host data sent, waiting for replies (RFPINS=0x0084) // 5 = MP host data sent, waiting for replies (RFPINS=0x0084)
// 6 = RX // 6 = RX
// 7 = ?? // 7 = ??
// 8 = MP host sending ack (RFPINS=0x0046) // 8 = MP client sending reply, MP host sending ack (RFPINS=0x0046)
// 9 = idle // 9 = idle
...@@ -176,6 +181,10 @@ void Reset() ...@@ -176,6 +181,10 @@ void Reset()
USCompare = 0; USCompare = 0;
BlockBeaconIRQ14 = false; BlockBeaconIRQ14 = false;
ComStatus = 0;
TXCurSlot = -1;
RXCounter = 0;
CmdCounter = 0; CmdCounter = 0;
} }
...@@ -427,12 +436,12 @@ u32 NumClients(u16 bitmask) ...@@ -427,12 +436,12 @@ u32 NumClients(u16 bitmask)
return ret; return ret;
} }
void CheckRX(bool block); bool CheckRX(bool block);
void ProcessTX(TXSlot* slot, int num) bool ProcessTX(TXSlot* slot, int num)
{ {
slot->CurPhaseTime--; slot->CurPhaseTime--;
if (slot->CurPhaseTime > 0) return; if (slot->CurPhaseTime > 0) return false;
switch (slot->CurPhase) switch (slot->CurPhase)
{ {
...@@ -448,13 +457,13 @@ void ProcessTX(TXSlot* slot, int num) ...@@ -448,13 +457,13 @@ void ProcessTX(TXSlot* slot, int num)
// CHECKME // CHECKME
// hardware seems to do this automatically? // hardware seems to do this automatically?
// I saw it done on captured packets, but saw no code to do it // I saw it done on captured packets, but saw no code to do it
if (num == 1) /*if (num == 1)
{ {
if (slot->Length > 32) if (slot->Length > 32)
{ {
*(u16*)&RAM[slot->Addr + 0xC + (slot->Length-6)] = *(u16*)&RAM[slot->Addr + 0x26]; *(u16*)&RAM[slot->Addr + 0xC + (slot->Length-6)] = *(u16*)&RAM[slot->Addr + 0x26];
} }
} }*/
if (num != 5) SetIRQ(7); if (num != 5) SetIRQ(7);
*(u16*)&RAM[slot->Addr + 0xC + 22] = IOPORT(W_TXSeqNo) << 4; *(u16*)&RAM[slot->Addr + 0xC + 22] = IOPORT(W_TXSeqNo) << 4;
...@@ -480,7 +489,7 @@ void ProcessTX(TXSlot* slot, int num) ...@@ -480,7 +489,7 @@ void ProcessTX(TXSlot* slot, int num)
slot->CurPhase = 2; slot->CurPhase = 2;
slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * nclients); slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * nclients);
printf("tx done. listen to replies\n"); printf("tx done. listen to replies\n");
CheckRX(true); if (CheckRX(true)) ComStatus |= 0x2;
// TODO: RFSTATUS/RFPINS // TODO: RFSTATUS/RFPINS
...@@ -517,7 +526,7 @@ printf("tx done. listen to replies\n"); ...@@ -517,7 +526,7 @@ printf("tx done. listen to replies\n");
FireTX(); FireTX();
} }
break; return true;
case 2: // MP host transfer done case 2: // MP host transfer done
{ {
...@@ -554,43 +563,43 @@ printf("tx done. listen to replies\n"); ...@@ -554,43 +563,43 @@ printf("tx done. listen to replies\n");
printf("MP TX over\n"); printf("MP TX over\n");
FireTX(); FireTX();
} }
break; return true;
} }
return false;
} }
void CheckRX(bool block) bool CheckRX(bool block)
{ {
if (!(IOPORT(W_RXCnt) & 0x8000)) if (!(IOPORT(W_RXCnt) & 0x8000))
return; return false;
u16 framelen;
u16 framectl;
u8 txrate;
bool bssidmatch;
u16 rxflags;
for (;;)
{
int rxlen = Platform::MP_RecvPacket(RXBuffer, block); int rxlen = Platform::MP_RecvPacket(RXBuffer, block);
if (rxlen < 12+24) return; if (rxlen == 0) return false;
if (rxlen < 12+24) continue;
u16 framelen = *(u16*)&RXBuffer[10]; framelen = *(u16*)&RXBuffer[10];
if (framelen != rxlen-12) if (framelen != rxlen-12)
{ {
printf("bad frame length\n"); printf("bad frame length\n");
return; continue;
} }
framelen -= 4; framelen -= 4;
/*if (RXTime > 0) framectl = *(u16*)&RXBuffer[12+0];
{ txrate = RXBuffer[8];
printf("!! getting packet while already receiving\n");
return;
}
if (IOPORT(W_TXBusy) & 0x9D)
{
printf("!! getting packet while sending\n");
return;
}*/
u16 framectl = *(u16*)&RXBuffer[12+0];
u8 txrate = RXBuffer[8];
u32 a_src, a_dst, a_bss; u32 a_src, a_dst, a_bss;
u16 rxflags = 0x0010; rxflags = 0x0010;
switch (framectl & 0x000C) switch (framectl & 0x000C)
{ {
case 0x0000: // management case 0x0000: // management
...@@ -603,7 +612,7 @@ void CheckRX(bool block) ...@@ -603,7 +612,7 @@ void CheckRX(bool block)
case 0x0004: // control case 0x0004: // control
printf("blarg\n"); printf("blarg\n");
return; continue;
case 0x0008: // data case 0x0008: // data
switch (framectl & 0x0300) switch (framectl & 0x0300)
...@@ -625,7 +634,7 @@ void CheckRX(bool block) ...@@ -625,7 +634,7 @@ void CheckRX(bool block)
break; break;
case 0x0300: // DS to DS case 0x0300: // DS to DS
printf("blarg\n"); printf("blarg\n");
return; continue;
} }
framectl &= 0xE7FF; framectl &= 0xE7FF;
if (framectl == 0x0228) rxflags |= 0x000C; if (framectl == 0x0228) rxflags |= 0x000C;
...@@ -637,20 +646,24 @@ void CheckRX(bool block) ...@@ -637,20 +646,24 @@ void CheckRX(bool block)
} }
if (MACEqual(&RXBuffer[12 + a_src], (u8*)&IOPORT(W_MACAddr0))) if (MACEqual(&RXBuffer[12 + a_src], (u8*)&IOPORT(W_MACAddr0)))
return; // oops. we received a packet we just sent. continue; // oops. we received a packet we just sent.
bool bssidmatch = MACEqual(&RXBuffer[12 + a_bss], (u8*)&IOPORT(W_BSSID0)); bssidmatch = MACEqual(&RXBuffer[12 + a_bss], (u8*)&IOPORT(W_BSSID0));
if (!(IOPORT(W_BSSID0) & 0x0001) && !(RXBuffer[12 + a_bss] & 0x01) && if (!(IOPORT(W_BSSID0) & 0x0001) && !(RXBuffer[12 + a_bss] & 0x01) &&
!bssidmatch) !bssidmatch)
{ {
printf("received packet %04X but it didn't pass the BSSID check\n", framectl); printf("received packet %04X but it didn't pass the BSSID check\n", framectl);
return; continue;
}
break;
} }
//if (framectl != 0x0080 && framectl != 0x0228) //if (framectl != 0x0080 && framectl != 0x0228)
printf("wifi: received packet FC:%04X SN:%04X CL:%04X\n", framectl, *(u16*)&RXBuffer[12+4+6+6+6], *(u16*)&RXBuffer[12+4+6+6+6+2+2]); printf("wifi: received packet FC:%04X SN:%04X CL:%04X\n", framectl, *(u16*)&RXBuffer[12+4+6+6+6], *(u16*)&RXBuffer[12+4+6+6+6+2+2]);
// make RX header // make RX header
// TODO: make it upon RX end
if (bssidmatch) rxflags |= 0x8000; if (bssidmatch) rxflags |= 0x8000;
...@@ -679,7 +692,7 @@ void CheckRX(bool block) ...@@ -679,7 +692,7 @@ void CheckRX(bool block)
{ {
printf("wifi: RX buffer full\n"); printf("wifi: RX buffer full\n");
// TODO: proper error management // TODO: proper error management
return; return false;
} }
} }
...@@ -690,6 +703,7 @@ void CheckRX(bool block) ...@@ -690,6 +703,7 @@ void CheckRX(bool block)
RXEndAddr = (addr & ~0x3) >> 1; RXEndAddr = (addr & ~0x3) >> 1;
SetIRQ(6); SetIRQ(6);
return true;
} }
...@@ -735,7 +749,7 @@ void USTimer(u32 param) ...@@ -735,7 +749,7 @@ void USTimer(u32 param)
if (!uspart) MSTimer(); if (!uspart) MSTimer();
if (!(uspart & 0x1FF)) CheckRX(false); //if (!(uspart & 0x1FF)) CheckRX(false);
} }
if (IOPORT(W_CmdCountCnt) & 0x0001) if (IOPORT(W_CmdCountCnt) & 0x0001)
...@@ -749,17 +763,54 @@ void USTimer(u32 param) ...@@ -749,17 +763,54 @@ void USTimer(u32 param)
if (IOPORT(W_ContentFree) != 0) if (IOPORT(W_ContentFree) != 0)
IOPORT(W_ContentFree)--; IOPORT(W_ContentFree)--;
if (ComStatus == 0)
{
u16 txbusy = IOPORT(W_TXBusy); u16 txbusy = IOPORT(W_TXBusy);
if (txbusy) if (txbusy)
{ {
if (txbusy & 0x0080) ProcessTX(&TXSlots[5], 5); ComStatus = 0x2;
else if (txbusy & 0x0010) ProcessTX(&TXSlots[4], 4); if (txbusy & 0x0080) TXCurSlot = 5;
else if (txbusy & 0x0008) ProcessTX(&TXSlots[3], 3); else if (txbusy & 0x0010) TXCurSlot = 4;
else if (txbusy & 0x0004) ProcessTX(&TXSlots[2], 2); else if (txbusy & 0x0008) TXCurSlot = 3;
else if (txbusy & 0x0002) ProcessTX(&TXSlots[1], 1); else if (txbusy & 0x0004) TXCurSlot = 2;
else if (txbusy & 0x0001) ProcessTX(&TXSlots[0], 0); else if (txbusy & 0x0002) TXCurSlot = 1;
else if (txbusy & 0x0001) TXCurSlot = 0;
}
else
{
if ((!(RXCounter & 0x1FF)))
{
if (CheckRX(false))
ComStatus = 0x1;
}
RXCounter++;
}
}
if (ComStatus & 0x2)
{
bool finished = ProcessTX(&TXSlots[TXCurSlot], TXCurSlot);
if (finished)
{
// transfer finished, see if there's another slot to do
// checkme: priority order of beacon/reply
u16 txbusy = IOPORT(W_TXBusy);
if (txbusy & 0x0080) TXCurSlot = 5;
else if (txbusy & 0x0010) TXCurSlot = 4;
else if (txbusy & 0x0008) TXCurSlot = 3;
else if (txbusy & 0x0004) TXCurSlot = 2;
else if (txbusy & 0x0002) TXCurSlot = 1;
else if (txbusy & 0x0001) TXCurSlot = 0;
else
{
TXCurSlot = -1;
ComStatus = 0;
RXCounter = 0;
} }
if (RXTime) }
}
if (ComStatus & 0x1)
{ {
// TODO: make sure it isn't possible to send and receive at the same time // TODO: make sure it isn't possible to send and receive at the same time
RXTime--; RXTime--;
...@@ -768,6 +819,12 @@ void USTimer(u32 param) ...@@ -768,6 +819,12 @@ void USTimer(u32 param)
IOPORT(W_RXBufWriteCursor) = RXEndAddr; IOPORT(W_RXBufWriteCursor) = RXEndAddr;
SetIRQ(0); SetIRQ(0);
if (TXCurSlot == -1)
{
ComStatus = 0;
RXCounter = 0;
}
if ((RXBuffer[0] & 0x0F) == 0x0C) if ((RXBuffer[0] & 0x0F) == 0x0C)
{ {
u16 clientmask = *(u16*)&RXBuffer[0xC + 26]; u16 clientmask = *(u16*)&RXBuffer[0xC + 26];
...@@ -914,6 +971,10 @@ u16 Read(u32 addr) ...@@ -914,6 +971,10 @@ u16 Read(u32 addr)
} }
} }
break; break;
case W_TXBusy:
return IOPORT(W_TXBusy) & 0x001F; // no bit for MP replies. odd
//case 0x214: NDS::debug(0); break; //case 0x214: NDS::debug(0); break;
//case 0x040: NDS::debug(0); break; //case 0x040: NDS::debug(0); break;
//case 0x54: printf("wifi: read WRCSR -> %04X\n", IOPORT(0x54)); break; //case 0x54: printf("wifi: read WRCSR -> %04X\n", IOPORT(0x54)); break;
...@@ -1198,6 +1259,11 @@ void Write(u32 addr, u16 val) ...@@ -1198,6 +1259,11 @@ void Write(u32 addr, u16 val)
addr, val, IOPORT(W_TXReqRead), (u32)(USCounter-mpreplywindow)); addr, val, IOPORT(W_TXReqRead), (u32)(USCounter-mpreplywindow));
break; break;
case 0x228:
case 0x244:
printf("wifi: write port%03X %04X\n", addr, val);
break;
// read-only ports // read-only ports
case 0x000: case 0x000:
case 0x044: case 0x044:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment