bba: implement recv buffer full interrupt

(windows) hopefully fix crashes from closing dolphin while recving
This commit is contained in:
sktsqrl 2012-07-04 16:00:42 -07:00
parent 9cff8316d2
commit 6cccbb91ec
3 changed files with 64 additions and 29 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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