aboutsummaryrefslogtreecommitdiff
path: root/src/Wifi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Wifi.cpp')
-rw-r--r--src/Wifi.cpp254
1 files changed, 160 insertions, 94 deletions
diff --git a/src/Wifi.cpp b/src/Wifi.cpp
index 1265f6f..2331de6 100644
--- a/src/Wifi.cpp
+++ b/src/Wifi.cpp
@@ -67,6 +67,10 @@ u8 RXBuffer[2048];
u32 RXTime;
u16 RXEndAddr;
+u32 ComStatus; // 0=waiting for packets 1=receiving 2=sending
+u32 TXCurSlot;
+u32 RXCounter;
+
bool MPInited;
@@ -75,10 +79,11 @@ bool MPInited;
// 1. preamble
// 2. IRQ7
// 3. send data
-// 4. wait for client replies (duration: 112 + ((10 * CMD_REPLYTIME) * numclients))
-// 5. IRQ7
-// 6. send ack (16 bytes, 1Mbps)
-// 7. optional IRQ1, along with IRQ12 if the transfer was successful or if
+// 4. optional IRQ1
+// 5. wait for client replies (duration: 112 + ((10 * CMD_REPLYTIME) * numclients))
+// 6. IRQ7
+// 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
//
// if the transfer has to be retried (for example, didn't get replies from all clients)
@@ -89,14 +94,14 @@ bool MPInited;
//
// RFSTATUS values:
// 0 = initial
-// 1 = RX????
+// 1 = waiting for incoming packets
// 2 = switching from RX to TX
// 3 = TX
// 4 = switching from TX to RX
// 5 = MP host data sent, waiting for replies (RFPINS=0x0084)
// 6 = RX
// 7 = ??
-// 8 = MP host sending ack (RFPINS=0x0046)
+// 8 = MP client sending reply, MP host sending ack (RFPINS=0x0046)
// 9 = idle
@@ -176,6 +181,10 @@ void Reset()
USCompare = 0;
BlockBeaconIRQ14 = false;
+ ComStatus = 0;
+ TXCurSlot = -1;
+ RXCounter = 0;
+
CmdCounter = 0;
}
@@ -427,12 +436,12 @@ u32 NumClients(u16 bitmask)
return ret;
}
-void CheckRX(bool block);
+bool CheckRX(bool block);
-void ProcessTX(TXSlot* slot, int num)
+bool ProcessTX(TXSlot* slot, int num)
{
slot->CurPhaseTime--;
- if (slot->CurPhaseTime > 0) return;
+ if (slot->CurPhaseTime > 0) return false;
switch (slot->CurPhase)
{
@@ -448,13 +457,13 @@ void ProcessTX(TXSlot* slot, int num)
// CHECKME
// hardware seems to do this automatically?
// I saw it done on captured packets, but saw no code to do it
- if (num == 1)
+ /*if (num == 1)
{
if (slot->Length > 32)
{
*(u16*)&RAM[slot->Addr + 0xC + (slot->Length-6)] = *(u16*)&RAM[slot->Addr + 0x26];
}
- }
+ }*/
if (num != 5) SetIRQ(7);
*(u16*)&RAM[slot->Addr + 0xC + 22] = IOPORT(W_TXSeqNo) << 4;
@@ -480,7 +489,7 @@ void ProcessTX(TXSlot* slot, int num)
slot->CurPhase = 2;
slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * nclients);
printf("tx done. listen to replies\n");
- CheckRX(true);
+ if (CheckRX(true)) ComStatus |= 0x2;
// TODO: RFSTATUS/RFPINS
@@ -517,7 +526,7 @@ printf("tx done. listen to replies\n");
FireTX();
}
- break;
+ return true;
case 2: // MP host transfer done
{
@@ -554,103 +563,107 @@ printf("tx done. listen to replies\n");
printf("MP TX over\n");
FireTX();
}
- break;
+ return true;
}
+
+ return false;
}
-void CheckRX(bool block)
+bool CheckRX(bool block)
{
if (!(IOPORT(W_RXCnt) & 0x8000))
- return;
+ return false;
- int rxlen = Platform::MP_RecvPacket(RXBuffer, block);
- if (rxlen < 12+24) return;
+ u16 framelen;
+ u16 framectl;
+ u8 txrate;
+ bool bssidmatch;
+ u16 rxflags;
- u16 framelen = *(u16*)&RXBuffer[10];
- if (framelen != rxlen-12)
+ for (;;)
{
- printf("bad frame length\n");
- return;
- }
- framelen -= 4;
-
- /*if (RXTime > 0)
- {
- 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];
+ int rxlen = Platform::MP_RecvPacket(RXBuffer, block);
+ if (rxlen == 0) return false;
+ if (rxlen < 12+24) continue;
- u32 a_src, a_dst, a_bss;
- u16 rxflags = 0x0010;
- switch (framectl & 0x000C)
- {
- case 0x0000: // management
- a_src = 10;
- a_dst = 4;
- a_bss = 16;
- if ((framectl & 0x00F0) == 0x0080)
- rxflags |= 0x0001;
- break;
+ framelen = *(u16*)&RXBuffer[10];
+ if (framelen != rxlen-12)
+ {
+ printf("bad frame length\n");
+ continue;
+ }
+ framelen -= 4;
- case 0x0004: // control
- printf("blarg\n");
- return;
+ framectl = *(u16*)&RXBuffer[12+0];
+ txrate = RXBuffer[8];
- case 0x0008: // data
- switch (framectl & 0x0300)
+ u32 a_src, a_dst, a_bss;
+ rxflags = 0x0010;
+ switch (framectl & 0x000C)
{
- case 0x0000: // STA to STA
+ case 0x0000: // management
a_src = 10;
a_dst = 4;
a_bss = 16;
+ if ((framectl & 0x00F0) == 0x0080)
+ rxflags |= 0x0001;
break;
- case 0x0100: // STA to DS
- a_src = 10;
- a_dst = 16;
- a_bss = 4;
- break;
- case 0x0200: // DS to STA
- a_src = 16;
- a_dst = 4;
- a_bss = 10;
- break;
- case 0x0300: // DS to DS
+
+ case 0x0004: // control
printf("blarg\n");
- return;
+ continue;
+
+ case 0x0008: // data
+ switch (framectl & 0x0300)
+ {
+ case 0x0000: // STA to STA
+ a_src = 10;
+ a_dst = 4;
+ a_bss = 16;
+ break;
+ case 0x0100: // STA to DS
+ a_src = 10;
+ a_dst = 16;
+ a_bss = 4;
+ break;
+ case 0x0200: // DS to STA
+ a_src = 16;
+ a_dst = 4;
+ a_bss = 10;
+ break;
+ case 0x0300: // DS to DS
+ printf("blarg\n");
+ continue;
+ }
+ framectl &= 0xE7FF;
+ if (framectl == 0x0228) rxflags |= 0x000C;
+ else if (framectl == 0x0218) rxflags |= 0x000D;
+ else if (framectl == 0x0118) rxflags |= 0x000E; // checkme
+ else if (framectl == 0x0158) rxflags |= 0x000F; // wild guess. those two might be swapped
+ else rxflags |= 0x0008;
+ break;
}
- framectl &= 0xE7FF;
- if (framectl == 0x0228) rxflags |= 0x000C;
- else if (framectl == 0x0218) rxflags |= 0x000D;
- else if (framectl == 0x0118) rxflags |= 0x000E; // checkme
- else if (framectl == 0x0158) rxflags |= 0x000F; // wild guess. those two might be swapped
- else rxflags |= 0x0008;
- break;
- }
- if (MACEqual(&RXBuffer[12 + a_src], (u8*)&IOPORT(W_MACAddr0)))
- return; // oops. we received a packet we just sent.
+ if (MACEqual(&RXBuffer[12 + a_src], (u8*)&IOPORT(W_MACAddr0)))
+ continue; // oops. we received a packet we just sent.
- bool bssidmatch = MACEqual(&RXBuffer[12 + a_bss], (u8*)&IOPORT(W_BSSID0));
- if (!(IOPORT(W_BSSID0) & 0x0001) && !(RXBuffer[12 + a_bss] & 0x01) &&
- !bssidmatch)
- {
- printf("received packet %04X but it didn't pass the BSSID check\n", framectl);
- return;
+ bssidmatch = MACEqual(&RXBuffer[12 + a_bss], (u8*)&IOPORT(W_BSSID0));
+ if (!(IOPORT(W_BSSID0) & 0x0001) && !(RXBuffer[12 + a_bss] & 0x01) &&
+ !bssidmatch)
+ {
+ printf("received packet %04X but it didn't pass the BSSID check\n", framectl);
+ continue;
+ }
+
+ break;
}
//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]);
// make RX header
+ // TODO: make it upon RX end
if (bssidmatch) rxflags |= 0x8000;
@@ -679,7 +692,7 @@ void CheckRX(bool block)
{
printf("wifi: RX buffer full\n");
// TODO: proper error management
- return;
+ return false;
}
}
@@ -690,6 +703,7 @@ void CheckRX(bool block)
RXEndAddr = (addr & ~0x3) >> 1;
SetIRQ(6);
+ return true;
}
@@ -735,7 +749,7 @@ void USTimer(u32 param)
if (!uspart) MSTimer();
- if (!(uspart & 0x1FF)) CheckRX(false);
+ //if (!(uspart & 0x1FF)) CheckRX(false);
}
if (IOPORT(W_CmdCountCnt) & 0x0001)
@@ -749,17 +763,54 @@ void USTimer(u32 param)
if (IOPORT(W_ContentFree) != 0)
IOPORT(W_ContentFree)--;
- u16 txbusy = IOPORT(W_TXBusy);
- if (txbusy)
+ if (ComStatus == 0)
+ {
+ u16 txbusy = IOPORT(W_TXBusy);
+ if (txbusy)
+ {
+ ComStatus = 0x2;
+ 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
+ {
+ if ((!(RXCounter & 0x1FF)))
+ {
+ if (CheckRX(false))
+ ComStatus = 0x1;
+ }
+
+ RXCounter++;
+ }
+ }
+
+ if (ComStatus & 0x2)
{
- if (txbusy & 0x0080) ProcessTX(&TXSlots[5], 5);
- else if (txbusy & 0x0010) ProcessTX(&TXSlots[4], 4);
- else if (txbusy & 0x0008) ProcessTX(&TXSlots[3], 3);
- else if (txbusy & 0x0004) ProcessTX(&TXSlots[2], 2);
- else if (txbusy & 0x0002) ProcessTX(&TXSlots[1], 1);
- else if (txbusy & 0x0001) ProcessTX(&TXSlots[0], 0);
+ 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
RXTime--;
@@ -768,6 +819,12 @@ void USTimer(u32 param)
IOPORT(W_RXBufWriteCursor) = RXEndAddr;
SetIRQ(0);
+ if (TXCurSlot == -1)
+ {
+ ComStatus = 0;
+ RXCounter = 0;
+ }
+
if ((RXBuffer[0] & 0x0F) == 0x0C)
{
u16 clientmask = *(u16*)&RXBuffer[0xC + 26];
@@ -914,6 +971,10 @@ u16 Read(u32 addr)
}
}
break;
+
+ case W_TXBusy:
+ return IOPORT(W_TXBusy) & 0x001F; // no bit for MP replies. odd
+
//case 0x214: NDS::debug(0); break;
//case 0x040: NDS::debug(0); break;
//case 0x54: printf("wifi: read WRCSR -> %04X\n", IOPORT(0x54)); break;
@@ -1198,6 +1259,11 @@ void Write(u32 addr, u16 val)
addr, val, IOPORT(W_TXReqRead), (u32)(USCounter-mpreplywindow));
break;
+ case 0x228:
+ case 0x244:
+ printf("wifi: write port%03X %04X\n", addr, val);
+ break;
+
// read-only ports
case 0x000:
case 0x044: