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

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]; 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)

View File

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