From 6cccbb91ec06a47a6369d6cce41f5d1cd1e07983 Mon Sep 17 00:00:00 2001 From: sktsqrl Date: Wed, 4 Jul 2012 16:00:42 -0700 Subject: [PATCH] bba: implement recv buffer full interrupt (windows) hopefully fix crashes from closing dolphin while recving --- Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp | 9 ++-- .../Core/Core/Src/HW/EXI_DeviceEthernet.cpp | 42 +++++++++++++++---- Source/Core/Core/Src/HW/EXI_DeviceEthernet.h | 42 ++++++++++++------- 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp index e5cd78eb0e..15d2e1f6bb 100644 --- a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp +++ b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp @@ -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) diff --git a/Source/Core/Core/Src/HW/EXI_DeviceEthernet.cpp b/Source/Core/Core/Src/HW/EXI_DeviceEthernet.cpp index 66ecc26bc4..40fc4f12c0 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceEthernet.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceEthernet.cpp @@ -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) diff --git a/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h b/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h index a7b2260d19..453e8d5843 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h +++ b/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h @@ -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