wifi: implement CMD retries
This commit is contained in:
parent
c3943b29ec
commit
9c5cde8109
54
src/Wifi.cpp
54
src/Wifi.cpp
|
@ -101,6 +101,8 @@ u16 MPClientMask, MPClientFail;
|
||||||
|
|
||||||
u8 MPClientReplies[15*1024];
|
u8 MPClientReplies[15*1024];
|
||||||
|
|
||||||
|
u16 MPLastSeqno;
|
||||||
|
|
||||||
bool MPInited;
|
bool MPInited;
|
||||||
bool LANInited;
|
bool LANInited;
|
||||||
|
|
||||||
|
@ -259,6 +261,8 @@ void Reset()
|
||||||
MPClientFail = 0;
|
MPClientFail = 0;
|
||||||
memset(MPClientReplies, 0, sizeof(MPClientReplies));
|
memset(MPClientReplies, 0, sizeof(MPClientReplies));
|
||||||
|
|
||||||
|
MPLastSeqno = 0xFFFF;
|
||||||
|
|
||||||
CmdCounter = 0;
|
CmdCounter = 0;
|
||||||
|
|
||||||
USUntilPowerOn = 0;
|
USUntilPowerOn = 0;
|
||||||
|
@ -335,6 +339,8 @@ void DoSavestate(Savestate* file)
|
||||||
|
|
||||||
file->VarArray(MPClientReplies, sizeof(MPClientReplies));
|
file->VarArray(MPClientReplies, sizeof(MPClientReplies));
|
||||||
|
|
||||||
|
file->Var16(&MPLastSeqno);
|
||||||
|
|
||||||
file->Var32((u32*)&USUntilPowerOn);
|
file->Var32((u32*)&USUntilPowerOn);
|
||||||
file->Bool32(&ForcePowerOn);
|
file->Bool32(&ForcePowerOn);
|
||||||
|
|
||||||
|
@ -591,6 +597,7 @@ void TXSendFrame(TXSlot* slot, int num)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
*(u16*)&TXBuffer[12 + 24+2] = MPClientMask;
|
||||||
Platform::MP_SendCmd(TXBuffer, 12+len, USTimestamp);
|
Platform::MP_SendCmd(TXBuffer, 12+len, USTimestamp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -642,9 +649,11 @@ void StartTX_Cmd()
|
||||||
if (rate == 0x14) slot->Rate = 2;
|
if (rate == 0x14) slot->Rate = 2;
|
||||||
else slot->Rate = 1;
|
else slot->Rate = 1;
|
||||||
|
|
||||||
|
MPClientMask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2] & MPClientFail;
|
||||||
|
MPClientFail &= MPClientMask;
|
||||||
|
|
||||||
u32 duration = PreambleLen(slot->Rate) + (slot->Length * (slot->Rate==2 ? 4:8));
|
u32 duration = PreambleLen(slot->Rate) + (slot->Length * (slot->Rate==2 ? 4:8));
|
||||||
u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2] & 0xFFFE;
|
duration += 112 + ((10 + IOPORT(W_CmdReplyTime)) * NumClients(MPClientMask));
|
||||||
duration += 112 + ((10 + IOPORT(W_CmdReplyTime)) * NumClients(clientmask));
|
|
||||||
duration += (32 * (slot->Rate==2 ? 4:8));
|
duration += (32 * (slot->Rate==2 ? 4:8));
|
||||||
|
|
||||||
if (CmdCounter > (duration + 100))
|
if (CmdCounter > (duration + 100))
|
||||||
|
@ -711,6 +720,7 @@ void FireTX()
|
||||||
|
|
||||||
if (txstart & 0x0002)
|
if (txstart & 0x0002)
|
||||||
{
|
{
|
||||||
|
MPClientFail = 0xFFFE;
|
||||||
StartTX_Cmd();
|
StartTX_Cmd();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -724,7 +734,7 @@ void FireTX()
|
||||||
|
|
||||||
void SendMPDefaultReply()
|
void SendMPDefaultReply()
|
||||||
{
|
{
|
||||||
u8 reply[12 + 32];
|
u8 reply[12 + 28];
|
||||||
|
|
||||||
*(u16*)&reply[0xA] = 28; // length
|
*(u16*)&reply[0xA] = 28; // length
|
||||||
|
|
||||||
|
@ -961,20 +971,17 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
}
|
}
|
||||||
SetStatus(5);
|
SetStatus(5);
|
||||||
|
|
||||||
u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2] & 0xFFFE;
|
|
||||||
MPReplyTimer = 16 + PreambleLen(slot->Rate);
|
MPReplyTimer = 16 + PreambleLen(slot->Rate);
|
||||||
MPClientMask = clientmask;
|
|
||||||
MPClientFail = clientmask;
|
|
||||||
|
|
||||||
u16 res = 0;
|
u16 res = 0;
|
||||||
if (clientmask)
|
if (MPClientMask)
|
||||||
res = Platform::MP_RecvReplies(MPClientReplies, USTimestamp, clientmask);
|
res = Platform::MP_RecvReplies(MPClientReplies, USTimestamp, MPClientMask);
|
||||||
MPClientFail &= ~res;
|
MPClientFail &= ~res;
|
||||||
|
|
||||||
// TODO: 112 likely includes the ack preamble, which needs adjusted
|
// TODO: 112 likely includes the ack preamble, which needs adjusted
|
||||||
// for long-preamble settings
|
// for long-preamble settings
|
||||||
slot->CurPhase = 2;
|
slot->CurPhase = 2;
|
||||||
slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * NumClients(clientmask));
|
slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * NumClients(MPClientMask));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1051,10 +1058,6 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
|
|
||||||
case 3: // MP host ack transfer (reply wait done)
|
case 3: // MP host ack transfer (reply wait done)
|
||||||
{
|
{
|
||||||
// checkme
|
|
||||||
IOPORT(W_TXBusy) &= ~(1<<1);
|
|
||||||
IOPORT(W_TXSlotCmd) &= 0x7FFF; // confirmed
|
|
||||||
|
|
||||||
if (!MPClientFail)
|
if (!MPClientFail)
|
||||||
*(u16*)&RAM[slot->Addr] = 0x0001;
|
*(u16*)&RAM[slot->Addr] = 0x0001;
|
||||||
else
|
else
|
||||||
|
@ -1072,15 +1075,24 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
IOPORT(W_TXStat) = 0x0B01;
|
IOPORT(W_TXStat) = 0x0B01;
|
||||||
SetIRQ(1);
|
SetIRQ(1);
|
||||||
}
|
}
|
||||||
SetStatus(1);
|
|
||||||
|
|
||||||
// TODO: retry the whole cycle if some clients failed to respond
|
if (MPClientFail)
|
||||||
// AND if there is enough time left in CMDCOUNT
|
{
|
||||||
// (games seem to always configure CMDCOUNT such that there is no time for retries)
|
// if some clients failed to respond: try again
|
||||||
|
StartTX_Cmd();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IOPORT(W_TXBusy) &= ~(1<<1);
|
||||||
|
IOPORT(W_TXSlotCmd) &= 0x7FFF;
|
||||||
|
|
||||||
|
SetStatus(1);
|
||||||
SetIRQ(12);
|
SetIRQ(12);
|
||||||
|
|
||||||
FireTX();
|
FireTX();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 13: // MP transfer failed (timeout)
|
case 13: // MP transfer failed (timeout)
|
||||||
|
@ -1159,6 +1171,7 @@ void FinishRX()
|
||||||
// TODO: RX stats
|
// TODO: RX stats
|
||||||
|
|
||||||
u16 framectl = *(u16*)&RXBuffer[12];
|
u16 framectl = *(u16*)&RXBuffer[12];
|
||||||
|
u16 seqno = *(u16*)&RXBuffer[12 + 22];
|
||||||
|
|
||||||
// check the frame's destination address
|
// check the frame's destination address
|
||||||
// note: the hardware always checks the first address field, regardless of the frame type/etc
|
// note: the hardware always checks the first address field, regardless of the frame type/etc
|
||||||
|
@ -1187,6 +1200,7 @@ void FinishRX()
|
||||||
// * MP CMD frames with a duplicate sequence number are ignored
|
// * MP CMD frames with a duplicate sequence number are ignored
|
||||||
|
|
||||||
u16 rxflags = 0x0010;
|
u16 rxflags = 0x0010;
|
||||||
|
bool cmd_dupe = false;
|
||||||
|
|
||||||
switch ((framectl >> 2) & 0x3)
|
switch ((framectl >> 2) & 0x3)
|
||||||
{
|
{
|
||||||
|
@ -1288,6 +1302,9 @@ void FinishRX()
|
||||||
}
|
}
|
||||||
else if (MACEqual(&RXBuffer[12 + 4], MPCmdMAC))
|
else if (MACEqual(&RXBuffer[12 + 4], MPCmdMAC))
|
||||||
{
|
{
|
||||||
|
if (seqno == MPLastSeqno) cmd_dupe = true;
|
||||||
|
MPLastSeqno = seqno;
|
||||||
|
|
||||||
rxflags |= 0x000C;
|
rxflags |= 0x000C;
|
||||||
}
|
}
|
||||||
else if (MACEqual(&RXBuffer[12 + 4], MPAckMAC))
|
else if (MACEqual(&RXBuffer[12 + 4], MPAckMAC))
|
||||||
|
@ -1353,6 +1370,8 @@ void FinishRX()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cmd_dupe)
|
||||||
|
{
|
||||||
// build the RX header
|
// build the RX header
|
||||||
|
|
||||||
u16 headeraddr = IOPORT(W_RXBufWriteCursor) << 1;
|
u16 headeraddr = IOPORT(W_RXBufWriteCursor) << 1;
|
||||||
|
@ -1373,6 +1392,7 @@ void FinishRX()
|
||||||
IOPORT(W_RXBufWriteCursor) = (addr & ~0x3) >> 1;
|
IOPORT(W_RXBufWriteCursor) = (addr & ~0x3) >> 1;
|
||||||
|
|
||||||
SetIRQ(0);
|
SetIRQ(0);
|
||||||
|
}
|
||||||
|
|
||||||
if ((rxflags & 0x800F) == 0x800C)
|
if ((rxflags & 0x800F) == 0x800C)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue