as you wish, Sorer

(starting work on shared-memory system)
This commit is contained in:
Arisotura 2022-08-19 22:56:01 +02:00
parent 5f77ad3394
commit d8b735822a
2 changed files with 209 additions and 93 deletions

View File

@ -41,6 +41,9 @@ u16 IO[0x1000>>1];
u16 Random; u16 Random;
// general, always-on microsecond counter
u64 USTimestamp;
u64 USCounter; u64 USCounter;
u64 USCompare; u64 USCompare;
bool BlockBeaconIRQ14; bool BlockBeaconIRQ14;
@ -214,6 +217,8 @@ void Reset()
memset(&IOPORT(0x018), 0xFF, 6); memset(&IOPORT(0x018), 0xFF, 6);
memset(&IOPORT(0x020), 0xFF, 6); memset(&IOPORT(0x020), 0xFF, 6);
USTimestamp = 0;
USCounter = 0; USCounter = 0;
USCompare = 0; USCompare = 0;
BlockBeaconIRQ14 = false; BlockBeaconIRQ14 = false;
@ -1207,6 +1212,8 @@ void MSTimer()
void USTimer(u32 param) void USTimer(u32 param)
{ {
USTimestamp++;
WifiAP::USTimer(); WifiAP::USTimer();
bool switchOffPowerSaving = false; bool switchOffPowerSaving = false;
@ -1389,10 +1396,6 @@ void USTimer(u32 param)
{ {
SendMPReply(*(u16*)&RXBuffer[0xC + 24], *(u16*)&RXBuffer[0xC + 26]); SendMPReply(*(u16*)&RXBuffer[0xC + 24], *(u16*)&RXBuffer[0xC + 26]);
} }
/*else if (RXBuffer[0xC + 4] & 0x01)
{
DummyMPReplyFrame(*(u16*)&RXBuffer[0xC + 24], *(u16*)&RXBuffer[0xC + 26]);
}*/
} }
} }
@ -1454,26 +1457,15 @@ void RFTransfer_Type3()
} }
// TODO: wifi waitstates
u16 Read(u32 addr) u16 Read(u32 addr)
{//printf("WIFI READ %08X\n", addr); {
if (addr >= 0x04810000) if (addr >= 0x04810000)
return 0; return 0;
addr &= 0x7FFE; addr &= 0x7FFE;
//printf("WIFI: read %08X\n", addr);
if (addr >= 0x4000 && addr < 0x6000) if (addr >= 0x4000 && addr < 0x6000)
{ {
//if (addr>=0x4000 && addr<0x400C) printf("READ TX HEADER 0480%04X, %08X\n", addr, NDS::GetPC(1));
//if (addr>=0x4234 && addr<0x4240) printf("READ TX HEADER 0480%04X, %08X\n", addr, NDS::GetPC(1));
//if (RXBuffer[12] == 0x0228)
{
//u16 headeraddr = IOPORT(W_RXBufReadCursor) << 1;
//if ((addr & 0x1FFE) == (headeraddr + 12 + 28))
//if (*(u16*)&RAM[(addr - 0x1C) & 0x1FFE] == 0x0228)
// printf("READ SHITTY CMD HEADER %08X\n", NDS::GetPC(1));
}
return *(u16*)&RAM[addr & 0x1FFE]; return *(u16*)&RAM[addr & 0x1FFE];
} }
if (addr >= 0x2000 && addr < 0x4000) if (addr >= 0x2000 && addr < 0x4000)
@ -1558,12 +1550,12 @@ u16 Read(u32 addr)
} }
void Write(u32 addr, u16 val) void Write(u32 addr, u16 val)
{//printf("WIFI WRITE %08X %04X\n", addr, val); {
if (addr >= 0x04810000) if (addr >= 0x04810000)
return; return;
addr &= 0x7FFE; addr &= 0x7FFE;
//printf("WIFI: write %08X %04X\n", addr, val);
if (addr >= 0x4000 && addr < 0x6000) if (addr >= 0x4000 && addr < 0x6000)
{ {
*(u16*)&RAM[addr & 0x1FFE] = val; *(u16*)&RAM[addr & 0x1FFE] = val;
@ -1762,7 +1754,7 @@ void Write(u32 addr, u16 val)
case W_USCompare2: USCompare = (USCompare & 0xFFFF0000FFFFFFFF) | ((u64)val << 32); return; case W_USCompare2: USCompare = (USCompare & 0xFFFF0000FFFFFFFF) | ((u64)val << 32); return;
case W_USCompare3: USCompare = (USCompare & 0x0000FFFFFFFFFFFF) | ((u64)val << 48); return; case W_USCompare3: USCompare = (USCompare & 0x0000FFFFFFFFFFFF) | ((u64)val << 48); return;
case W_CmdCount: /*printf("CMDCOUNT=%d (%04X)\n", val*10, val);*/ CmdCounter = val * 10; return; case W_CmdCount: CmdCounter = val * 10; return;
case W_BBCnt: case W_BBCnt:
IOPORT(W_BBCnt) = val; IOPORT(W_BBCnt) = val;
@ -1907,16 +1899,11 @@ void Write(u32 addr, u16 val)
case 0x268: case 0x268:
return; return;
case W_RXFilter:
//printf("wifi: stupid RX filter=%04X\n", val);
break;
default: default:
//printf("WIFI unk: write %08X %04X\n", addr, val); //printf("WIFI unk: write %08X %04X\n", addr, val);
break; break;
} }
//printf("WIFI: write %08X %04X\n", addr, val);
IOPORT(addr&0xFFF) = val; IOPORT(addr&0xFFF) = val;
} }

View File

@ -73,14 +73,82 @@ struct MPQueueHeader
u32 PacketWriteOffset; u32 PacketWriteOffset;
}; };
struct MPPacketHeader
{
u32 Magic;
u32 Length;
u32 SenderID;
};
QSharedMemory* MPQueue; QSharedMemory* MPQueue;
QSystemSemaphore* MPQueueSem[16]; //QSystemSemaphore* MPQueueSem[16];
int InstanceID;
u32 SyncReadOffset; u32 SyncReadOffset;
u32 PacketReadOffset; u32 PacketReadOffset;
const u32 kSyncStart = 0x0010;
const u32 kSyncEnd = 0x0100;
const u32 kPacketStart = 0x0100;
const u32 kPacketEnd = 0x10000;
#define NIFI_VER 2 #define NIFI_VER 2
// we need to come up with our own abstraction layer for named semaphores
// because QSystemSemaphore doesn't support waiting with a timeout
// and, as such, is unsuitable to our needs
//#ifdef _WIN32
#if 1
HANDLE SemPool[32];
void SemPoolInit()
{
for (int i = 0; i < 32; i++)
SemPool[i] = INVALID_HANDLE_VALUE;
}
bool SemInit(int num)
{
if (SemPool[num] != INVALID_HANDLE_VALUE)
return true;
char semname[64];
sprintf(semname, "Local\\melonNIFI_Sem%d", num);
HANDLE sem = CreateSemaphore(nullptr, 0, 64, semname);
SemPool[num] = sem;
return sem != INVALID_HANDLE_VALUE;
}
void SemDeinit(int num)
{
if (SemPool[num] != INVALID_HANDLE_VALUE)
{
CloseHandle(SemPool[num]);
SemPool[num] = INVALID_HANDLE_VALUE;
}
}
bool SemPost(int num)
{
SemInit(num);
return ReleaseSemaphore(SemPool[num], 1, nullptr) != 0;
}
bool SemWait(int num, int timeout)
{
return WaitForSingleObject(SemPool[num], timeout) == WAIT_OBJECT_0;
}
#else
// TODO: code semaphore shit for other platforms!
#endif // _WIN32
void _logpacket(bool tx, u8* data, int len) void _logpacket(bool tx, u8* data, int len)
{return; {return;
@ -112,7 +180,7 @@ void _logpacket(bool tx, u8* data, int len)
bool Init() bool Init()
{ {
int opt_true = 1; /*int opt_true = 1;
int res0, res1; int res0, res1;
#ifdef __WIN32__ #ifdef __WIN32__
@ -201,9 +269,14 @@ bool Init()
MPUniqueID ^= *(u32*)&mac[2]; MPUniqueID ^= *(u32*)&mac[2];
printf("local MP unique ID: %08X\n", MPUniqueID); printf("local MP unique ID: %08X\n", MPUniqueID);
return true; return true;*/
/*MPQueue = new QSharedMemory("melonNIFI"); /*u8* mac = SPI_Firmware::GetWifiMAC();
MPUniqueID = *(u32*)&mac[0];
MPUniqueID ^= *(u32*)&mac[2];
printf("local MP unique ID: %08X\n", MPUniqueID);*/
MPQueue = new QSharedMemory("melonNIFI_FIFO");
if (!MPQueue->attach()) if (!MPQueue->attach())
{ {
@ -217,15 +290,42 @@ bool Init()
MPQueue->lock(); MPQueue->lock();
memset(MPQueue->data(), 0, MPQueue->size()); memset(MPQueue->data(), 0, MPQueue->size());
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data(); MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
header->NumInstances = 1; header->SyncWriteOffset = kSyncStart;
header->InstanceBitmask = 0x0001; header->PacketWriteOffset = kPacketStart;
header->SyncWriteOffset = 0x0010;
header->PacketWriteOffset = 0x0100;
MPQueue->unlock(); MPQueue->unlock();
} }
printf("sharedmem good\n");*/
MPQueue->lock();
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
u16 mask = header->InstanceBitmask;
for (int i = 0; i < 16; i++)
{
if (!(mask & (1<<i)))
{
InstanceID = i;
header->InstanceBitmask |= (1<<i);
break;
}
}
header->NumInstances++;
SyncReadOffset = header->SyncWriteOffset;
PacketReadOffset = header->PacketWriteOffset;
MPQueue->unlock();
/*for (int i = 0; i < 16; i++)
{
QString key = QString("melonSEMA%1").arg(i);
MPQueueSem[i] = new QSystemSemaphore(key, 0, (i==InstanceID) ? QSystemSemaphore::Create : QSystemSemaphore::Open)
}*/
SemPoolInit();
SemInit(InstanceID);
SemInit(16+InstanceID);
printf("MP comm init OK, instance ID %d\n", InstanceID);
return true; return true;
} }
@ -242,86 +342,115 @@ void DeInit()
#endif // __WIN32__ #endif // __WIN32__
} }
int SendPacket(u8* data, int len) void PacketFIFORead(void* buf, int len)
{ {
if (MPSocket[0] < 0) u8* data = (u8*)MPQueue->data();
return 0;
if (len > 2048-12) u32 offset = PacketReadOffset;
if ((offset + len) >= kPacketEnd)
{ {
printf("MP_SendPacket: error: packet too long (%d)\n", len); u32 part1 = kPacketEnd - offset;
return 0; memcpy(buf, &data[offset], part1);
memcpy(&((u8*)buf)[part1], &data[kPacketStart], len - part1);
offset = kPacketStart + len - part1;
}
else
{
memcpy(buf, &data[offset], len);
offset += len;
} }
*(u32*)&PacketBuffer[0] = htonl(0x4946494E); // NIFI PacketReadOffset = offset;
PacketBuffer[4] = NIFI_VER;
PacketBuffer[5] = 0;
*(u16*)&PacketBuffer[6] = htons(len);
*(u32*)&PacketBuffer[8] = MPUniqueID;
memcpy(&PacketBuffer[12], data, len);
_logpacket(true, data, len);
int slen = sendto(MPSocket[0], (const char*)PacketBuffer, len+12, 0, &MPSendAddr[0], sizeof(sockaddr_t));
if (slen < 12) return 0;
return slen - 12;
} }
int RecvPacket(u8* data, bool block) void PacketFIFOWrite(void* buf, int len)
{ {
if (MPSocket[0] < 0) u8* data = (u8*)MPQueue->data();
return 0; MPQueueHeader* header = (MPQueueHeader*)&data[0];
fd_set fd; u32 offset = header->PacketWriteOffset;
struct timeval tv; if ((offset + len) >= kPacketEnd)
{
u32 part1 = kPacketEnd - offset;
memcpy(&data[offset], buf, part1);
memcpy(&data[kPacketStart], &((u8*)buf)[part1], len - part1);
offset = kPacketStart + len - part1;
}
else
{
memcpy(&data[offset], buf, len);
offset += len;
}
header->PacketWriteOffset = offset;
}
int SendPacket(u8* packet, int len)
{
MPQueue->lock();
u8* data = (u8*)MPQueue->data();
MPQueueHeader* header = (MPQueueHeader*)&data[0];
u16 mask = header->InstanceBitmask;
u32 offset = header->PacketWriteOffset;
// TODO: check if the FIFO is full!
MPPacketHeader pktheader;
pktheader.Magic = 0x4946494E;
pktheader.Length = len;
pktheader.SenderID = InstanceID;
PacketFIFOWrite(&pktheader, sizeof(pktheader));
PacketFIFOWrite(packet, len);
for (int i = 0; i < 16; i++)
{
if (mask & (1<<i))
SemPost(i);
}
MPQueue->unlock();
return len;
}
int RecvPacket(u8* packet, bool block)
{
MPQueue->lock();
u8* data = (u8*)MPQueue->data();
MPQueueHeader* header = (MPQueueHeader*)&data[0];
for (;;) for (;;)
{ {
FD_ZERO(&fd); if (!SemWait(InstanceID, block ? 500 : 0))
FD_SET(MPSocket[0], &fd);
tv.tv_sec = 0;
//tv.tv_usec = block ? 5000 : 0;
tv.tv_usec = block ? 500*1000 : 0;
if (!select(MPSocket[0]+1, &fd, 0, 0, &tv))
{ {
MPQueue->unlock();
return 0; return 0;
} }
sockaddr_t fromAddr; MPPacketHeader pktheader;
socklen_t fromLen = sizeof(sockaddr_t); PacketFIFORead(&pktheader, sizeof(pktheader));
int rlen = recvfrom(MPSocket[0], (char*)PacketBuffer, 2048, 0, &fromAddr, &fromLen);
if (rlen < 12+24)
{
continue;
}
rlen -= 12;
if (ntohl(*(u32*)&PacketBuffer[0]) != 0x4946494E) if (pktheader.Magic != 0x4946494E)
{ {
printf("MP: !!!! PACKET FIFO IS CRAPOED\n");
MPQueue->unlock();
return 0;
}
if (pktheader.SenderID == InstanceID)
{
// skip this packet
PacketReadOffset += pktheader.Length;
if (PacketReadOffset >= kPacketEnd)
PacketReadOffset += kPacketStart - kPacketEnd;
continue; continue;
} }
if (PacketBuffer[4] != NIFI_VER || PacketBuffer[5] != 0) PacketFIFORead(packet, pktheader.Length);
{ MPQueue->unlock();
continue; return pktheader.Length;
}
if (ntohs(*(u16*)&PacketBuffer[6]) != rlen)
{
continue;
}
if (*(u32*)&PacketBuffer[8] == MPUniqueID)
{
continue;
}
zanf = *(u16*)&PacketBuffer[12+6];
_logpacket(false, &PacketBuffer[12], rlen);
memcpy(data, &PacketBuffer[12], rlen);
return rlen;
} }
} }