mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 07:09:48 -06:00
bba: implement recv buffer full interrupt
(windows) hopefully fix crashes from closing dolphin while recving
This commit is contained in:
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
#include "../Memmap.h"
|
#include "../Memmap.h"
|
||||||
//#pragma optimize("",off)
|
|
||||||
// GROSS CODE ALERT: headers need to be included in the following order
|
// GROSS CODE ALERT: headers need to be included in the following order
|
||||||
#include "TAP_Win32.h"
|
#include "TAP_Win32.h"
|
||||||
#include "../EXI_Device.h"
|
#include "../EXI_Device.h"
|
||||||
@ -314,7 +313,7 @@ bool CEXIETHERNET::RecvInit()
|
|||||||
ZeroMemory(&mReadOverlapped, sizeof(mReadOverlapped));
|
ZeroMemory(&mReadOverlapped, sizeof(mReadOverlapped));
|
||||||
|
|
||||||
RegisterWaitForSingleObject(&mHReadWait, mHRecvEvent, ReadWaitCallback,
|
RegisterWaitForSingleObject(&mHReadWait, mHRecvEvent, ReadWaitCallback,
|
||||||
this, INFINITE, WT_EXECUTEDEFAULT);//WT_EXECUTEINWAITTHREAD
|
this, INFINITE, WT_EXECUTEDEFAULT);
|
||||||
|
|
||||||
mReadOverlapped.hEvent = mHRecvEvent;
|
mReadOverlapped.hEvent = mHRecvEvent;
|
||||||
|
|
||||||
@ -340,7 +339,7 @@ bool CEXIETHERNET::RecvStart()
|
|||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
ERROR_LOG(SP1, "RECV COMPLETED IMMEDIATELY");
|
// Completed immediately
|
||||||
RecvHandlePacket();
|
RecvHandlePacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +351,5 @@ void CEXIETHERNET::RecvStop()
|
|||||||
if (!IsActivated())
|
if (!IsActivated())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CancelIo(mHAdapter);
|
UnregisterWaitEx(mHReadWait, INVALID_HANDLE_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#pragma optimize("",on)
|
|
||||||
|
@ -478,12 +478,11 @@ inline bool CEXIETHERNET::RecvMACFilter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::inc_rwp()
|
inline void CEXIETHERNET::inc_rwp()
|
||||||
{
|
{
|
||||||
u16 *rwp = (u16 *)&mBbaMem[BBA_RWP];
|
u16 *rwp = (u16 *)&mBbaMem[BBA_RWP];
|
||||||
|
|
||||||
if (*rwp + 1 == page_ptr(BBA_RHBP))
|
if (*rwp + 1 == page_ptr(BBA_RHBP))
|
||||||
// TODO check if BP is used as well
|
|
||||||
*rwp = page_ptr(BBA_BP);
|
*rwp = page_ptr(BBA_BP);
|
||||||
else
|
else
|
||||||
(*rwp)++;
|
(*rwp)++;
|
||||||
@ -497,6 +496,8 @@ bool CEXIETHERNET::RecvHandlePacket()
|
|||||||
u8 *end_ptr;
|
u8 *end_ptr;
|
||||||
u8 *read_ptr;
|
u8 *read_ptr;
|
||||||
Descriptor *descriptor;
|
Descriptor *descriptor;
|
||||||
|
u32 status = 0;
|
||||||
|
u16 rwp_initial = page_ptr(BBA_RWP);
|
||||||
|
|
||||||
if (!RecvMACFilter())
|
if (!RecvMACFilter())
|
||||||
goto wait_for_next;
|
goto wait_for_next;
|
||||||
@ -530,12 +531,24 @@ bool CEXIETHERNET::RecvHandlePacket()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (write_ptr == end_ptr)
|
if (write_ptr == end_ptr)
|
||||||
// TODO check if BP is used as well
|
|
||||||
write_ptr = ptr_from_page_ptr(BBA_BP);
|
write_ptr = ptr_from_page_ptr(BBA_BP);
|
||||||
|
|
||||||
if (write_ptr == read_ptr)
|
if (write_ptr == read_ptr)
|
||||||
{
|
{
|
||||||
ERROR_LOG(SP1, "recv buffer full error - not implemented");
|
/*
|
||||||
|
halt copy
|
||||||
|
if (cur_packet_size >= PAGE_SIZE)
|
||||||
|
desc.status |= FO | BF
|
||||||
|
if (RBFIM)
|
||||||
|
raise RBFI
|
||||||
|
if (AUTORCVR)
|
||||||
|
discard bad packet
|
||||||
|
else
|
||||||
|
inc MPC instad of recving packets
|
||||||
|
*/
|
||||||
|
status |= DESC_FO | DESC_BF;
|
||||||
|
mBbaMem[BBA_IR] |= mBbaMem[BBA_IMR] & INT_RBF;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,10 +564,25 @@ bool CEXIETHERNET::RecvHandlePacket()
|
|||||||
page_ptr(BBA_RHBP));
|
page_ptr(BBA_RHBP));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Update descriptor
|
// Is the current frame multicast?
|
||||||
descriptor->set(*(u16 *)&mBbaMem[BBA_RWP], 4 + mRecvBufferLength, 0);
|
if (mRecvBuffer[0] & 0x01)
|
||||||
|
status |= DESC_MF;
|
||||||
|
|
||||||
mBbaMem[BBA_LRPS] = descriptor->get_status();
|
if (status & DESC_BF)
|
||||||
|
{
|
||||||
|
if (mBbaMem[BBA_MISC2] & MISC2_AUTORCVR)
|
||||||
|
{
|
||||||
|
*(u16 *)&mBbaMem[BBA_RWP] = rwp_initial;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "RBF while AUTORCVR == 0!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor->set(*(u16 *)&mBbaMem[BBA_RWP], 4 + mRecvBufferLength, status);
|
||||||
|
|
||||||
|
mBbaMem[BBA_LRPS] = status;
|
||||||
|
|
||||||
// Raise interrupt
|
// Raise interrupt
|
||||||
if (mBbaMem[BBA_IMR] & INT_R)
|
if (mBbaMem[BBA_IMR] & INT_R)
|
||||||
|
@ -82,14 +82,26 @@ enum NWAYS
|
|||||||
|
|
||||||
enum MISC1
|
enum MISC1
|
||||||
{
|
{
|
||||||
MISC1_BURSTDMA = 0x01,
|
MISC1_BURSTDMA = 0x01,
|
||||||
MISC1_DISLDMA = 0x02,
|
MISC1_DISLDMA = 0x02,
|
||||||
MISC1_TPF = 0x04,
|
MISC1_TPF = 0x04,
|
||||||
MISC1_TPH = 0x08,
|
MISC1_TPH = 0x08,
|
||||||
MISC1_TXF = 0x10,
|
MISC1_TXF = 0x10,
|
||||||
MISC1_TXH = 0x20,
|
MISC1_TXH = 0x20,
|
||||||
MISC1_TXFIFORST = 0x40,
|
MISC1_TXFIFORST = 0x40,
|
||||||
MISC1_RXFIFORST = 0x80
|
MISC1_RXFIFORST = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MISC2
|
||||||
|
{
|
||||||
|
MISC2_HBRLEN0 = 0x01,
|
||||||
|
MISC2_HBRLEN1 = 0x02,
|
||||||
|
MISC2_RUNTSIZE = 0x04,
|
||||||
|
MISC2_DREQBCTRL = 0x08,
|
||||||
|
MISC2_RINTSEL = 0x10,
|
||||||
|
MISC2_ITPSEL = 0x20,
|
||||||
|
MISC2_A11A8EN = 0x40,
|
||||||
|
MISC2_AUTORCVR = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -148,8 +160,9 @@ enum
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
BBA_RECV_SIZE = 0x800,
|
BBA_NUM_PAGES = 0x10,
|
||||||
BBA_MEM_SIZE = 0x1000
|
BBA_PAGE_SIZE = 0x100,
|
||||||
|
BBA_MEM_SIZE = BBA_NUM_PAGES * BBA_PAGE_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { EXI_DEVTYPE_ETHER = 0x04020200 };
|
enum { EXI_DEVTYPE_ETHER = 0x04020200 };
|
||||||
@ -178,6 +191,8 @@ enum RecvStatus
|
|||||||
DESC_RERR = 0x80
|
DESC_RERR = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BBA_RECV_SIZE 0x800
|
||||||
|
|
||||||
class CEXIETHERNET : public IEXIDevice
|
class CEXIETHERNET : public IEXIDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -261,18 +276,13 @@ public:
|
|||||||
{
|
{
|
||||||
u32 word;
|
u32 word;
|
||||||
|
|
||||||
void set(u32 const next_page, u32 const packet_length, u32 const status)
|
inline void set(u32 const next_page, u32 const packet_length, u32 const status)
|
||||||
{
|
{
|
||||||
word = 0;
|
word = 0;
|
||||||
word |= (status & 0xff) << 24;
|
word |= (status & 0xff) << 24;
|
||||||
word |= (packet_length & 0xfff) << 12;
|
word |= (packet_length & 0xfff) << 12;
|
||||||
word |= next_page & 0xfff;
|
word |= next_page & 0xfff;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 get_status() const
|
|
||||||
{
|
|
||||||
return (word >> 24) & 0xff;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline u16 page_ptr(int const index) const
|
inline u16 page_ptr(int const index) const
|
||||||
|
Reference in New Issue
Block a user