Some cleanup of BBA code. No behavioral changes.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4500 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2009-11-06 06:43:01 +00:00
parent 7a0055e113
commit 281636b79b
3 changed files with 234 additions and 342 deletions

View File

@ -384,7 +384,7 @@ bool CEXIETHERNET::startRecv()
return true; return true;
} }
DWORD res = ReadFile(mHAdapter, mRecvBuffer, (DWORD)mRecvBuffer.size(), DWORD res = ReadFile(mHAdapter, mRecvBuffer, BBA_RECV_SIZE,
&mRecvBufferLength, &mReadOverlapped); &mRecvBufferLength, &mReadOverlapped);
if (res) if (res)

View File

@ -17,32 +17,31 @@
#include "Memmap.h" #include "Memmap.h"
#include <assert.h>
#include "../Core.h"
#include "EXI_Device.h" #include "EXI_Device.h"
#include "EXI_DeviceEthernet.h" #include "EXI_DeviceEthernet.h"
//#define SONICDEBUG //#define SONICDEBUG
#ifdef SONICDEBUG
#define FILEDEBUG #define FILEDEBUG
#ifdef FILEDEBUG #ifdef FILEDEBUG
FILE *ME = 0; FILE *ME = 0;
#endif #endif
#endif
void DEBUGPRINT (const char * format, ...) void DEBUGPRINT (const char * format, ...)
{ {
char buffer[0x1000]; char buffer[0x1000];
va_list args; va_list args;
va_start (args, format); va_start(args, format);
vsprintf (buffer,format, args); vsprintf(buffer,format, args);
#ifdef SONICDEBUG #ifdef SONICDEBUG
#ifdef FILEDEBUG #ifdef FILEDEBUG
fprintf(ME, "%s\n", buffer); fprintf(ME, "%s\n", buffer);
#endif #endif
printf("%s\n", buffer); printf("%s\n", buffer);
#else #else
INFO_LOG(SP1, buffer); INFO_LOG(SP1, buffer);
#endif #endif
va_end (args); va_end(args);
} }
@ -50,19 +49,17 @@ void DEBUGPRINT (const char * format, ...)
#define RISE(flags) ((SwappedData & (flags)) && !(mBbaMem[0x00] & (flags))) #define RISE(flags) ((SwappedData & (flags)) && !(mBbaMem[0x00] & (flags)))
int mPacketsSent = 0; static u32 mPacketsSent = 0;
u8 mac_address[6] = {0x00, 0x1A, 0x4D, 0x5E, 0x64, 0x2B}; // Looks Appropriate static u8 mac_address[6] = {0x00, 0x09, 0xbf, 0x01, 0x00, 0xc1}; // (shuffle2) from my bba
unsigned int Expecting; static u32 Expecting;
CEXIETHERNET::CEXIETHERNET() : CEXIETHERNET::CEXIETHERNET() :
m_uPosition(0), m_uPosition(0),
m_uCommand(0), m_uCommand(0),
mWriteBuffer(2048), mWriteBuffer(2048),
mCbw(mBbaMem + CB_OFFSET, CB_SIZE), mCbw(mBbaMem + CB_OFFSET, CB_SIZE)
mRecvBuffer(2048)
{ {
memset(mBbaMem, 0, BBAMEM_SIZE); memset(mBbaMem, 0, BBA_MEM_SIZE);
ID = 0x04020200;
mWriteP = INVALID_P; mWriteP = INVALID_P;
mReadP = INVALID_P; mReadP = INVALID_P;
mWaiting = false; mWaiting = false;
@ -81,9 +78,9 @@ CEXIETHERNET::CEXIETHERNET() :
Expecting = EXPECT_NONE; Expecting = EXPECT_NONE;
mExpectVariableLengthImmWrite = false; mExpectVariableLengthImmWrite = false;
#ifdef FILEDEBUG #ifdef FILEDEBUG
ME = fopen("Debug.txt", "wb"); ME = fopen("Debug.txt", "wb");
#endif #endif
} }
CEXIETHERNET::~CEXIETHERNET() CEXIETHERNET::~CEXIETHERNET()
@ -93,32 +90,6 @@ CEXIETHERNET::~CEXIETHERNET()
#endif #endif
} }
void CyclicBufferWriter::write(void *src, size_t size)
{
assert(size < _cap);
u8* bsrc = (u8*) src;
if(_write + size >= _cap)
{
// wraparound
memcpy(_buffer + _write, src, _cap - _write);
memcpy(_buffer, bsrc + (_cap - _write), size - (_cap - _write));
_write = size - (_cap - _write);
}
else
{
memcpy(_buffer + _write, src, size);
_write += size;
}
//DEGUB("CBWrote %i bytes", size);
}
void CyclicBufferWriter::align()
{
_write = (_write + 0xff) & ~0xff;
if(_write >= _cap)
_write -= _cap;
}
void CEXIETHERNET::SetCS(int cs) void CEXIETHERNET::SetCS(int cs)
{ {
DEBUGPRINT("Set CS: %s Expect Variable write?: %s", cs ? "true" : "false", mExpectVariableLengthImmWrite ? "true" : "false"); DEBUGPRINT("Set CS: %s Expect Variable write?: %s", cs ? "true" : "false", mExpectVariableLengthImmWrite ? "true" : "false");
@ -158,7 +129,7 @@ bool CEXIETHERNET::IsInterruptSet()
void CEXIETHERNET::recordSendComplete() void CEXIETHERNET::recordSendComplete()
{ {
mBbaMem[BBA_NCRA] &= ~0x06; mBbaMem[BBA_NCRA] &= ~0x06;
if(mBbaMem[BBA_IMR] & BBA_INTERRUPT_SENT) if (mBbaMem[BBA_IMR] & BBA_INTERRUPT_SENT)
{ {
mBbaMem[BBA_IR] |= BBA_INTERRUPT_SENT; mBbaMem[BBA_IR] |= BBA_INTERRUPT_SENT;
DEBUGPRINT("\t\tBBA Send interrupt raised"); DEBUGPRINT("\t\tBBA Send interrupt raised");
@ -172,7 +143,7 @@ void CEXIETHERNET::recordSendComplete()
bool CEXIETHERNET::checkRecvBuffer() bool CEXIETHERNET::checkRecvBuffer()
{ {
if(mRecvBufferLength != 0) if (mRecvBufferLength != 0)
{ {
handleRecvdPacket(); handleRecvdPacket();
} }
@ -185,12 +156,12 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
if (mExpectVariableLengthImmWrite) if (mExpectVariableLengthImmWrite)
{ {
DEBUGPRINT("\t[INFO]Variable length IMM write"); DEBUGPRINT("\t[INFO]Variable length IMM write");
if(_uSize == 4) if (_uSize == 4)
{ {
// Correct // Correct
_uData = Common::swap32(_uData); _uData = Common::swap32(_uData);
} }
else if(_uSize == 2) else if (_uSize == 2)
{ {
// Correct // Correct
_uData = (u16)Common::swap32(_uData); _uData = (u16)Common::swap32(_uData);
@ -200,7 +171,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
} }
else if (mWriteP != INVALID_P) else if (mWriteP != INVALID_P)
{ {
if (mWriteP + _uSize > BBAMEM_SIZE) if (mWriteP + _uSize > BBA_MEM_SIZE)
{ {
DEBUGPRINT("[EEE]Write error: mWriteP + size = 0x%04X + %i", mWriteP, _uSize); DEBUGPRINT("[EEE]Write error: mWriteP + size = 0x%04X + %i", mWriteP, _uSize);
exit(0); exit(0);
@ -209,16 +180,16 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
switch (mWriteP) switch (mWriteP)
{ {
case BBA_IR: case BBA_IR:
{ {
// Correct, we use swapped // Correct, we use swapped
assert(_uSize == 1); _dbg_assert_(SP1, _uSize == 1);
u32 SwappedData = Common::swap32(_uData); u32 SwappedData = Common::swap32(_uData);
DEBUGPRINT("\t\t[INFO]BBA Interrupt reset 0x%02X & ~(0x%02X) => 0x%02X", mBbaMem[0x09], MAKE(u8, SwappedData), mBbaMem[0x09] & ~MAKE(u8, SwappedData)); DEBUGPRINT("\t\t[INFO]BBA Interrupt reset 0x%02X & ~(0x%02X) => 0x%02X", mBbaMem[0x09], MAKE(u8, SwappedData), mBbaMem[0x09] & ~MAKE(u8, SwappedData));
mBbaMem[BBA_IR] &= ~MAKE(u8, SwappedData); mBbaMem[BBA_IR] &= ~MAKE(u8, SwappedData);
break; break;
} }
case BBA_NCRA: case BBA_NCRA:
{ {
DEBUGPRINT("\t\t[INFO]BBA_NCRA"); DEBUGPRINT("\t\t[INFO]BBA_NCRA");
// Correct, we use the swap here // Correct, we use the swap here
@ -231,7 +202,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
} }
if (RISE(BBA_NCRA_SR) && isActivated()) if (RISE(BBA_NCRA_SR) && isActivated())
{ {
DEBUGPRINT("\t\t[INFO]BBA Start Recieve"); DEBUGPRINT("\t\t[INFO]BBA Start Receive");
//exit(0); //exit(0);
startRecv(); startRecv();
} }
@ -249,68 +220,68 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
} }
mBbaMem[BBA_NCRA] = MAKE(u8, SwappedData); mBbaMem[BBA_NCRA] = MAKE(u8, SwappedData);
} }
break; break;
case BBA_NWAYC: case BBA_NWAYC:
DEBUGPRINT("\t\t[INFO]BBA_NWAYC"); DEBUGPRINT("\t\t[INFO]BBA_NWAYC");
if(Common::swap32(_uData) & (BBA_NWAYC_ANE | BBA_NWAYC_ANS_RA)) if (Common::swap32(_uData) & (BBA_NWAYC_ANE | BBA_NWAYC_ANS_RA))
{
//say we've successfully negotiated for 10 Mbit full duplex
//should placate libogc
activate();
mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
}
else
{
if (_uData != 0x0)
{ {
//say we've successfully negotiated for 10 Mbit full duplex DEBUGPRINT("Not activate!");
//should placate libogc exit(0);
activate();
mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
}
else
{
if(_uData != 0x0)
{
DEBUGPRINT("Not activate!");
exit(0);
}
} }
}
break; break;
case BBA_RRP: //RRP - Receive Buffer Read Page Pointer case BBA_RRP: //RRP - Receive Buffer Read Page Pointer
DEBUGPRINT("\t\t[INFO]RRP"); DEBUGPRINT("\t\t[INFO]RRP");
assert(_uSize == 2 || _uSize == 1); _dbg_assert_(SP1, _uSize == 2 || _uSize == 1);
mRBRPP = (u8)Common::swap32(_uData) << 8; //Whinecube: I hope this works with both write sizes. mRBRPP = (u8)Common::swap32(_uData) << 8; //Whinecube: I hope this works with both write sizes.
mRBEmpty = (mRBRPP == ((u32)mCbw.p_write() + CB_OFFSET)); mRBEmpty = (mRBRPP == ((u32)mCbw.p_write() + CB_OFFSET));
checkRecvBuffer(); checkRecvBuffer();
break; break;
case BBA_RWP: //RWP - Receive Buffer Write Page Pointer case BBA_RWP: //RWP - Receive Buffer Write Page Pointer
DEBUGPRINT("\t\t[INFO]RWP"); DEBUGPRINT("\t\t[INFO]RWP");
assert(_uSize == 2 || _uSize == 1); _dbg_assert_(SP1, _uSize == 2 || _uSize == 1);
DEBUGPRINT("\t\t\tThing is 0x%0X", (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8); DEBUGPRINT("\t\t\tThing is 0x%0X", (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
// TODO: This assert FAILS! // TODO: This assert FAILS!
//assert(Common::swap32(_uData) == (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8); //assert(Common::swap32(_uData) == (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
break; break;
case BBA_NWAYS: case BBA_NWAYS:
DEBUGPRINT("[ERR]Call to BBA_NWAYS directly!"); DEBUGPRINT("[ERR]Call to BBA_NWAYS directly!");
exit(0); exit(0);
break; break;
case BBA_SI_ACTRL2: case BBA_SI_ACTRL2:
default: default:
DEBUGPRINT("\t\t[INFO]Default one!Size 0x%x _uData: 0x%08x Swapped 0x%08x to 0x%x", _uSize, _uData, Common::swap32(_uData),mWriteP); DEBUGPRINT("\t\t[INFO]Default one!Size 0x%x _uData: 0x%08x Swapped 0x%08x to 0x%x", _uSize, _uData, Common::swap32(_uData),mWriteP);
u32 SwappedData = 0; u32 SwappedData = 0;
if(_uSize == 4 || _uSize == 1) if (_uSize == 4 || _uSize == 1)
{
// Correct, use Swapped here
// Size of 4 untested Though
SwappedData = Common::swap32(_uData);
if(_uSize == 4)
{ {
// Correct, use Swapped here DEBUGPRINT("\t\t\tData is 0x%08x", SwappedData);
// Size of 4 untested Though //exit(0);
SwappedData = Common::swap32(_uData);
if(_uSize == 4)
{
DEBUGPRINT("\t\t\tData is 0x%08x", SwappedData);
//exit(0);
}
} }
else if( _uSize == 2) }
{ else if ( _uSize == 2)
//Correct {
SwappedData = (u16)(_uData >> 16); //Correct
//DEBUGPRINT("\t\t\tData is 0x%04x", SwappedData); SwappedData = (u16)(_uData >> 16);
} //DEBUGPRINT("\t\t\tData is 0x%04x", SwappedData);
//u32 SwappedData = _uData; }
memcpy(mBbaMem + mWriteP, &SwappedData, _uSize); //u32 SwappedData = _uData;
mWriteP = mWriteP + _uSize; memcpy(mBbaMem + mWriteP, &SwappedData, _uSize);
mWriteP = mWriteP + _uSize;
} }
return; return;
} }
@ -333,7 +304,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
u32 SwappedData = _uData; u32 SwappedData = _uData;
mWriteP = (u8)getbitsw(SwappedData, 16, 23); mWriteP = (u8)getbitsw(SwappedData, 16, 23);
} }
else //size == 2 else //size == 2
{ {
// Correct, Size of 1 untested, should be correct. // Correct, Size of 1 untested, should be correct.
u16 SwappedData = (u16)Common::swap32(_uData >> 8); u16 SwappedData = (u16)Common::swap32(_uData >> 8);
@ -363,7 +334,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
{ {
// Correct // Correct
mReadP = (u16)getbitsw(SwappedData, 8, 23); mReadP = (u16)getbitsw(SwappedData, 8, 23);
if (mReadP >= BBAMEM_SIZE) if (mReadP >= BBA_MEM_SIZE)
{ {
DEBUGPRINT("\t\t[EEE]Illegal BBA address: 0x%04X", mReadP); DEBUGPRINT("\t\t[EEE]Illegal BBA address: 0x%04X", mReadP);
//if(g::bouehr) //if(g::bouehr)
@ -423,7 +394,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
case 0x5c: // These two go together case 0x5c: // These two go together
break; break;
case 0x31: // NWAYS - NWAY Status Register case 0x31: // NWAYS - NWAY Status Register
// HACK // HACK
activate(); activate();
mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF); mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
case 0x09: // IR case 0x09: // IR
@ -458,7 +429,7 @@ u32 CEXIETHERNET::ImmRead(u32 _uSize)
} }
if (mReadP != INVALID_P) if (mReadP != INVALID_P)
{ {
if (mReadP + _uSize > BBAMEM_SIZE) if (mReadP + _uSize > BBA_MEM_SIZE)
{ {
DEBUGPRINT("\t[EEE]Read error: mReadP + size = 0x%04X + %i", mReadP, _uSize); DEBUGPRINT("\t[EEE]Read error: mReadP + size = 0x%04X + %i", mReadP, _uSize);
exit(0); exit(0);
@ -471,7 +442,7 @@ u32 CEXIETHERNET::ImmRead(u32 _uSize)
//DEBUGPRINT("Mem spot is 0x%02x uResult is 0x%x", mBbaMem[mReadP], uResult); //DEBUGPRINT("Mem spot is 0x%02x uResult is 0x%x", mBbaMem[mReadP], uResult);
/*#ifndef _WIN32 /*#ifndef _WIN32
if(CheckRecieved()) if(CheckRecieved())
startRecv(); startRecv();
#endif*/ #endif*/
DEBUGPRINT("\t[INFO]Read from BBA address 0x%0*X, %i byte%s: 0x%0*X",mReadP >= CB_OFFSET ? 4 : 2, mReadP, _uSize, (_uSize==1?"":"s"),_uSize*2, getbitsw(uResult, 0, _uSize * 8 - 1)); DEBUGPRINT("\t[INFO]Read from BBA address 0x%0*X, %i byte%s: 0x%0*X",mReadP >= CB_OFFSET ? 4 : 2, mReadP, _uSize, (_uSize==1?"":"s"),_uSize*2, getbitsw(uResult, 0, _uSize * 8 - 1));
mReadP = mReadP + _uSize; mReadP = mReadP + _uSize;
@ -488,7 +459,7 @@ u32 CEXIETHERNET::ImmRead(u32 _uSize)
void CEXIETHERNET::DMAWrite(u32 _uAddr, u32 _uSize) void CEXIETHERNET::DMAWrite(u32 _uAddr, u32 _uSize)
{ {
if(mExpectVariableLengthImmWrite) if (mExpectVariableLengthImmWrite)
{ {
DEBUGPRINT("DMA Write: Address is 0x%x and size is 0x%x", _uAddr, _uSize); DEBUGPRINT("DMA Write: Address is 0x%x and size is 0x%x", _uAddr, _uSize);
mWriteBuffer.write(_uSize, Memory::GetPointer(_uAddr)); mWriteBuffer.write(_uSize, Memory::GetPointer(_uAddr));
@ -505,9 +476,9 @@ void CEXIETHERNET::DMAWrite(u32 _uAddr, u32 _uSize)
void CEXIETHERNET::DMARead(u32 _uAddr, u32 _uSize) void CEXIETHERNET::DMARead(u32 _uAddr, u32 _uSize)
{ {
if(mReadP != INVALID_P) if (mReadP != INVALID_P)
{ {
if(mReadP + _uSize > BBAMEM_SIZE) if (mReadP + _uSize > BBA_MEM_SIZE)
{ {
DEBUGPRINT("Read error: mReadP + size = 0x%04X + %i", mReadP, _uSize); DEBUGPRINT("Read error: mReadP + size = 0x%04X + %i", mReadP, _uSize);
return; return;

View File

@ -39,123 +39,24 @@ inline u32 getbitsw(u32 dword, int start, int end) {
return (dword & makemaskw(start, end)) >> (31 - end); return (dword & makemaskw(start, end)) >> (31 - end);
} }
// Container Class Stolen from Whinecube void DEBUGPRINT(const char * format, ...);
template<class T> class SubContainer;
template<class T> class Container
{
public:
Container(size_t _size) {
b = 0;
allocate(_size);
}
Container(size_t _size, const T *data) {
b = 0;
allocate(size);
memcpy(a, data, _size);
}
~Container() {
if (a) /*if(_msize(a))*/ free(a);
}
void resize(size_t _size) {
if (b == _size)
return;
free(a);
allocate(_size);
}
/*void insert(int before, void *src, size_t size) {
char *temp = a;
a = new char[b + size];
if(a == NULL)
BFE("Memory insert failed in container");
memcpy(a, temp, before);
memcpy(a+before, src, size);
memcpy(a+before+size, temp+before, b-before);
b += size;
delete temp;
}*/
class SubContainer : public Container {
private:
SubContainer(void* ptr, size_t size) : Container(ptr, size) {}
friend class Container;
public:
~SubContainer() {
a = NULL;
b = 0;
}
};
SubContainer getSub(size_t pos) {
return SubContainer(((char*)a) + pos, b - pos);
}
operator T*() { return (T *)a; }
operator const T*() const { return (T *)a; }
T* p() { return (T *)a; }
const T* p() const { return (T *)a; }
T *operator->() { return (T *)a; }
size_t size() const { return b; }
void steal(Container<T> &src) {
resize(0); a = src.a; b = src.b;
src.a = NULL; src.b = 0;
}
void swap(Container<T> &other) {
T *ta = a; size_t tb = b;
a = other.a; b = other.b;
other.a = ta; other.b = tb;
}
protected:
void *a;
size_t b;
private:
Container(const Container&);
Container &operator=(const Container&);
Container(void* ptr, size_t _size) : a(ptr), b(_size) {}
friend class SubContainer;
void allocate(size_t _size)
{
if (_size > (100*1024*1024)) // 100 MB cap
exit(0);
//DEGUB("Resize: %i -> %i = %i\n", b, size, g_con_total);
//if(size > 1000*K) {
//DEGUB("Megabyte Container resize!\n");
//}
b = _size;
if (_size == 0)
a = NULL;
else
{
a = malloc(_size);
//if(!_CrtIsValidHeapPointer(a))
//throw generic_fatal_exception("malloc failed in Container");
}
}
};
void DEBUGPRINT (const char * format, ...);
class WriteBuffer class WriteBuffer
{ {
public: public:
WriteBuffer(u32 s) :_size(0) WriteBuffer(u32 s) : _size(0)
{ {
_buffer = (u8*)malloc(s*sizeof(u8)); _buffer = (u8*)malloc(s*sizeof(u8));
ucapacity = s; ucapacity = s;
} }
~WriteBuffer() { free(_buffer);} ~WriteBuffer() { free(_buffer); }
u32 size() const { return _size; } u32 size() const { return _size; }
u32 capacity() const { return ucapacity; } u32 capacity() const { return ucapacity; }
void write(u32 s, const void *src) void write(u32 s, const void *src)
{ {
if (_size + s >= ucapacity) if (_size + s >= ucapacity)
{ {
printf("Write too large!"); DEBUGPRINT("Write too large!");
exit(0); exit(0);
} }
@ -171,112 +72,55 @@ private:
u32 _size; u32 _size;
}; };
//Doesn't contain error checks for wraparound writes // Doesn't contain error checks for wraparound writes
class CyclicBufferWriter class CyclicBufferWriter
{ {
public: public:
CyclicBufferWriter(u8 *buffer, size_t cap) CyclicBufferWriter(u8 *buffer, size_t cap) {
{ _buffer = buffer; _capacity = cap; _write = 0;
_buffer = buffer; _cap = cap; _write = 0;
} }
size_t p_write() const { return _write; } size_t p_write() const { return _write; }
void reset() { _write = 0; } void reset() { _write = 0; }
void write(void *src, size_t size); void write(void *src, size_t size) {
void align(); //aligns the write pointer to steps of 0x100, like the real BBA _dbg_assert_(SP1, size < _capacity);
u8* bsrc = (u8*) src;
if (_write + size >= _capacity)
{
// wraparound
memcpy(_buffer + _write, src, _capacity - _write);
memcpy(_buffer, bsrc + (_capacity - _write), size - (_capacity - _write));
_write = size - (_capacity - _write);
} else {
memcpy(_buffer + _write, src, size);
_write += size;
}
//DEBUG_LOG(SP1, "CBWrote %i bytes", size);
}
// Aligns the write pointer to steps of 0x100, like the real BBA
void align() {
_write = (_write + 0xff) & ~0xff;
if(_write >= _capacity)
_write -= _capacity;
}
private: private:
size_t _write; size_t _write;
size_t _cap; //capacity size_t _capacity;
u8 *_buffer; u8 *_buffer;
}; };
class CEXIETHERNET : public IEXIDevice #define INVALID_P 0xFFFF
{
public:
CEXIETHERNET();
~CEXIETHERNET();
void SetCS(int _iCS);
bool IsPresent();
void Update();
bool IsInterruptSet();
void ImmWrite(u32 _uData, u32 _uSize);
u32 ImmRead(u32 _uSize);
void DMAWrite(u32 _uAddr, u32 _uSize);
void DMARead(u32 _uAddr, u32 _uSize);
//private:
// STATE_TO_SAVE
u32 m_uPosition;
u32 m_uCommand;
bool m_bInterruptSet;
u32 mWriteP, mReadP;
#define INVALID_P 0xFFFF
bool mExpectSpecialImmRead; //reset to false on deselect
u32 mSpecialImmData;
bool Activated;
u16 mRBRPP; //RRP - Receive Buffer Read Page Pointer
bool mRBEmpty;
#define BBAMEM_SIZE 0x1000
u8 mBbaMem[BBAMEM_SIZE];
WriteBuffer mWriteBuffer;
CyclicBufferWriter mCbw;
bool mExpectVariableLengthImmWrite;
bool mReadyToSend;
unsigned int ID;
u8 RegisterBlock[0x1000];
enum
{
CMD_ID = 0x00,
CMD_READ_REG = 0x01,
};
void recordSendComplete();
bool sendPacket(u8 *etherpckt, int size);
bool checkRecvBuffer();
bool handleRecvdPacket();
//TAP interface
bool activate();
bool CheckRecieved();
bool deactivate();
bool isActivated();
bool resume();
bool startRecv();
bool cbwriteDescriptor(u32 size);
volatile bool mWaiting;
Container<u8> mRecvBuffer;
#ifdef _WIN32
HANDLE mHAdapter, mHRecvEvent, mHReadWait;
DWORD mMtu;
OVERLAPPED mReadOverlapped;
DWORD mRecvBufferLength;
static VOID CALLBACK ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFired);
#else
u32 mRecvBufferLength;
#endif
};
enum
{
EXPECT_NONE = 0,
EXPECT_ID
};
// TODO: convert into unions // TODO: convert into unions
enum enum
{ {
BBA_RECV_SIZE = 0x800,
BBA_MEM_SIZE = 0x1000,
CB_OFFSET = 0x100, CB_OFFSET = 0x100,
CB_SIZE = (BBAMEM_SIZE - CB_OFFSET), CB_SIZE = (BBA_MEM_SIZE - CB_OFFSET),
SIZEOF_RECV_DESCRIPTOR = 4, SIZEOF_RECV_DESCRIPTOR = 4,
EXI_DEVTYPE_ETHER = 0x04020200, EXI_DEVTYPE_ETHER = 0x04020200,
@ -330,7 +174,7 @@ enum
BBA_NWAYS_10TXF = 0x40, BBA_NWAYS_10TXF = 0x40,
BBA_NWAYS_10TXH = 0x80, BBA_NWAYS_10TXH = 0x80,
BBA_INTERRUPT_RECV = 0x02, BBA_INTERRUPT_RECV = 0x02,
BBA_INTERRUPT_SENT = 0x04, BBA_INTERRUPT_SENT = 0x04,
BBA_INTERRUPT_RECV_ERROR = 0x08, BBA_INTERRUPT_RECV_ERROR = 0x08,
BBA_INTERRUPT_SEND_ERROR = 0x10, BBA_INTERRUPT_SEND_ERROR = 0x10,
@ -341,4 +185,81 @@ enum
BBA_SI_ACTRL2 = 0x60 BBA_SI_ACTRL2 = 0x60
}; };
enum
{
EXPECT_NONE = 0,
EXPECT_ID
};
class CEXIETHERNET : public IEXIDevice
{
public:
CEXIETHERNET();
~CEXIETHERNET();
void SetCS(int _iCS);
bool IsPresent();
void Update();
bool IsInterruptSet();
void ImmWrite(u32 _uData, u32 _uSize);
u32 ImmRead(u32 _uSize);
void DMAWrite(u32 _uAddr, u32 _uSize);
void DMARead(u32 _uAddr, u32 _uSize);
//private:
// STATE_TO_SAVE
u32 m_uPosition;
u32 m_uCommand;
bool m_bInterruptSet;
u32 mWriteP, mReadP;
bool mExpectSpecialImmRead; //reset to false on deselect
u32 mSpecialImmData;
bool Activated;
u16 mRBRPP; //RRP - Receive Buffer Read Page Pointer
bool mRBEmpty;
u8 mBbaMem[BBA_MEM_SIZE];
WriteBuffer mWriteBuffer;
CyclicBufferWriter mCbw;
bool mExpectVariableLengthImmWrite;
bool mReadyToSend;
u8 RegisterBlock[0x1000];
enum
{
CMD_ID = 0x00,
CMD_READ_REG = 0x01,
};
void recordSendComplete();
bool sendPacket(u8 *etherpckt, int size);
bool checkRecvBuffer();
bool handleRecvdPacket();
//TAP interface
bool activate();
bool CheckRecieved();
bool deactivate();
bool isActivated();
bool resume();
bool startRecv();
bool cbwriteDescriptor(u32 size);
volatile bool mWaiting;
u8 mRecvBuffer[BBA_RECV_SIZE];
#ifdef _WIN32
HANDLE mHAdapter, mHRecvEvent, mHReadWait;
DWORD mMtu;
OVERLAPPED mReadOverlapped;
DWORD mRecvBufferLength;
static VOID CALLBACK ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFired);
#else
u32 mRecvBufferLength;
#endif
};
#endif #endif