bba: implement recv buffer full interrupt
(windows) hopefully fix crashes from closing dolphin while recving
This commit is contained in:
parent
9cff8316d2
commit
6cccbb91ec
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "StringUtil.h"
|
||||
#include "../Memmap.h"
|
||||
//#pragma optimize("",off)
|
||||
// GROSS CODE ALERT: headers need to be included in the following order
|
||||
#include "TAP_Win32.h"
|
||||
#include "../EXI_Device.h"
|
||||
|
@ -314,7 +313,7 @@ bool CEXIETHERNET::RecvInit()
|
|||
ZeroMemory(&mReadOverlapped, sizeof(mReadOverlapped));
|
||||
|
||||
RegisterWaitForSingleObject(&mHReadWait, mHRecvEvent, ReadWaitCallback,
|
||||
this, INFINITE, WT_EXECUTEDEFAULT);//WT_EXECUTEINWAITTHREAD
|
||||
this, INFINITE, WT_EXECUTEDEFAULT);
|
||||
|
||||
mReadOverlapped.hEvent = mHRecvEvent;
|
||||
|
||||
|
@ -340,7 +339,7 @@ bool CEXIETHERNET::RecvStart()
|
|||
|
||||
if (res)
|
||||
{
|
||||
ERROR_LOG(SP1, "RECV COMPLETED IMMEDIATELY");
|
||||
// Completed immediately
|
||||
RecvHandlePacket();
|
||||
}
|
||||
|
||||
|
@ -352,7 +351,5 @@ void CEXIETHERNET::RecvStop()
|
|||
if (!IsActivated())
|
||||
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];
|
||||
|
||||
if (*rwp + 1 == page_ptr(BBA_RHBP))
|
||||
// TODO check if BP is used as well
|
||||
*rwp = page_ptr(BBA_BP);
|
||||
else
|
||||
(*rwp)++;
|
||||
|
@ -497,6 +496,8 @@ bool CEXIETHERNET::RecvHandlePacket()
|
|||
u8 *end_ptr;
|
||||
u8 *read_ptr;
|
||||
Descriptor *descriptor;
|
||||
u32 status = 0;
|
||||
u16 rwp_initial = page_ptr(BBA_RWP);
|
||||
|
||||
if (!RecvMACFilter())
|
||||
goto wait_for_next;
|
||||
|
@ -530,12 +531,24 @@ bool CEXIETHERNET::RecvHandlePacket()
|
|||
}
|
||||
|
||||
if (write_ptr == end_ptr)
|
||||
// TODO check if BP is used as well
|
||||
write_ptr = ptr_from_page_ptr(BBA_BP);
|
||||
|
||||
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));
|
||||
#endif
|
||||
|
||||
// Update descriptor
|
||||
descriptor->set(*(u16 *)&mBbaMem[BBA_RWP], 4 + mRecvBufferLength, 0);
|
||||
// Is the current frame multicast?
|
||||
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
|
||||
if (mBbaMem[BBA_IMR] & INT_R)
|
||||
|
|
|
@ -82,14 +82,26 @@ enum NWAYS
|
|||
|
||||
enum MISC1
|
||||
{
|
||||
MISC1_BURSTDMA = 0x01,
|
||||
MISC1_DISLDMA = 0x02,
|
||||
MISC1_TPF = 0x04,
|
||||
MISC1_TPH = 0x08,
|
||||
MISC1_TXF = 0x10,
|
||||
MISC1_TXH = 0x20,
|
||||
MISC1_TXFIFORST = 0x40,
|
||||
MISC1_RXFIFORST = 0x80
|
||||
MISC1_BURSTDMA = 0x01,
|
||||
MISC1_DISLDMA = 0x02,
|
||||
MISC1_TPF = 0x04,
|
||||
MISC1_TPH = 0x08,
|
||||
MISC1_TXF = 0x10,
|
||||
MISC1_TXH = 0x20,
|
||||
MISC1_TXFIFORST = 0x40,
|
||||
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
|
||||
|
@ -148,8 +160,9 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
BBA_RECV_SIZE = 0x800,
|
||||
BBA_MEM_SIZE = 0x1000
|
||||
BBA_NUM_PAGES = 0x10,
|
||||
BBA_PAGE_SIZE = 0x100,
|
||||
BBA_MEM_SIZE = BBA_NUM_PAGES * BBA_PAGE_SIZE
|
||||
};
|
||||
|
||||
enum { EXI_DEVTYPE_ETHER = 0x04020200 };
|
||||
|
@ -178,6 +191,8 @@ enum RecvStatus
|
|||
DESC_RERR = 0x80
|
||||
};
|
||||
|
||||
#define BBA_RECV_SIZE 0x800
|
||||
|
||||
class CEXIETHERNET : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
|
@ -261,18 +276,13 @@ public:
|
|||
{
|
||||
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 |= (status & 0xff) << 24;
|
||||
word |= (packet_length & 0xfff) << 12;
|
||||
word |= next_page & 0xfff;
|
||||
}
|
||||
|
||||
u8 get_status() const
|
||||
{
|
||||
return (word >> 24) & 0xff;
|
||||
}
|
||||
};
|
||||
|
||||
inline u16 page_ptr(int const index) const
|
||||
|
|
Loading…
Reference in New Issue