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;
}
DWORD res = ReadFile(mHAdapter, mRecvBuffer, (DWORD)mRecvBuffer.size(),
DWORD res = ReadFile(mHAdapter, mRecvBuffer, BBA_RECV_SIZE,
&mRecvBufferLength, &mReadOverlapped);
if (res)

View File

@ -17,32 +17,31 @@
#include "Memmap.h"
#include <assert.h>
#include "../Core.h"
#include "EXI_Device.h"
#include "EXI_DeviceEthernet.h"
//#define SONICDEBUG
#ifdef SONICDEBUG
#define FILEDEBUG
#ifdef FILEDEBUG
FILE *ME = 0;
#endif
#endif
void DEBUGPRINT (const char * format, ...)
{
char buffer[0x1000];
va_list args;
va_start (args, format);
vsprintf (buffer,format, args);
#ifdef SONICDEBUG
#ifdef FILEDEBUG
fprintf(ME, "%s\n", buffer);
#endif
printf("%s\n", buffer);
#else
INFO_LOG(SP1, buffer);
#endif
va_end (args);
va_start(args, format);
vsprintf(buffer,format, args);
#ifdef SONICDEBUG
#ifdef FILEDEBUG
fprintf(ME, "%s\n", buffer);
#endif
printf("%s\n", buffer);
#else
INFO_LOG(SP1, buffer);
#endif
va_end(args);
}
@ -50,19 +49,17 @@ void DEBUGPRINT (const char * format, ...)
#define RISE(flags) ((SwappedData & (flags)) && !(mBbaMem[0x00] & (flags)))
int mPacketsSent = 0;
u8 mac_address[6] = {0x00, 0x1A, 0x4D, 0x5E, 0x64, 0x2B}; // Looks Appropriate
unsigned int Expecting;
static u32 mPacketsSent = 0;
static u8 mac_address[6] = {0x00, 0x09, 0xbf, 0x01, 0x00, 0xc1}; // (shuffle2) from my bba
static u32 Expecting;
CEXIETHERNET::CEXIETHERNET() :
m_uPosition(0),
m_uCommand(0),
mWriteBuffer(2048),
mCbw(mBbaMem + CB_OFFSET, CB_SIZE),
mRecvBuffer(2048)
mCbw(mBbaMem + CB_OFFSET, CB_SIZE)
{
memset(mBbaMem, 0, BBAMEM_SIZE);
ID = 0x04020200;
memset(mBbaMem, 0, BBA_MEM_SIZE);
mWriteP = INVALID_P;
mReadP = INVALID_P;
mWaiting = false;
@ -74,16 +71,16 @@ CEXIETHERNET::CEXIETHERNET() :
mHRecvEvent = INVALID_HANDLE_VALUE;
mHReadWait = INVALID_HANDLE_VALUE;
#endif
mRecvBufferLength = 0;
mExpectSpecialImmRead = false;
Expecting = EXPECT_NONE;
mExpectVariableLengthImmWrite = false;
#ifdef FILEDEBUG
#ifdef FILEDEBUG
ME = fopen("Debug.txt", "wb");
#endif
#endif
}
CEXIETHERNET::~CEXIETHERNET()
@ -93,32 +90,6 @@ CEXIETHERNET::~CEXIETHERNET()
#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)
{
DEBUGPRINT("Set CS: %s Expect Variable write?: %s", cs ? "true" : "false", mExpectVariableLengthImmWrite ? "true" : "false");
@ -155,10 +126,10 @@ bool CEXIETHERNET::IsInterruptSet()
return m_bInterruptSet;
}
void CEXIETHERNET::recordSendComplete()
void CEXIETHERNET::recordSendComplete()
{
mBbaMem[BBA_NCRA] &= ~0x06;
if(mBbaMem[BBA_IMR] & BBA_INTERRUPT_SENT)
if (mBbaMem[BBA_IMR] & BBA_INTERRUPT_SENT)
{
mBbaMem[BBA_IR] |= BBA_INTERRUPT_SENT;
DEBUGPRINT("\t\tBBA Send interrupt raised");
@ -170,9 +141,9 @@ void CEXIETHERNET::recordSendComplete()
mPacketsSent++;
}
bool CEXIETHERNET::checkRecvBuffer()
bool CEXIETHERNET::checkRecvBuffer()
{
if(mRecvBufferLength != 0)
if (mRecvBufferLength != 0)
{
handleRecvdPacket();
}
@ -185,12 +156,12 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
if (mExpectVariableLengthImmWrite)
{
DEBUGPRINT("\t[INFO]Variable length IMM write");
if(_uSize == 4)
if (_uSize == 4)
{
// Correct
_uData = Common::swap32(_uData);
}
else if(_uSize == 2)
else if (_uSize == 2)
{
// Correct
_uData = (u16)Common::swap32(_uData);
@ -198,27 +169,27 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
mWriteBuffer.write(_uSize, &_uData);
return;
}
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);
exit(0);
}
DEBUGPRINT("\t[INFO]Write to BBA address 0x%0*X, %i byte%s: 0x%0*X",mWriteP >= CB_OFFSET ? 4 : 2, mWriteP, _uSize, (_uSize==1?"":"s"), _uSize*2, _uData);
switch (mWriteP)
switch (mWriteP)
{
case BBA_IR:
case BBA_IR:
{
// Correct, we use swapped
assert(_uSize == 1);
_dbg_assert_(SP1, _uSize == 1);
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));
mBbaMem[BBA_IR] &= ~MAKE(u8, SwappedData);
break;
}
case BBA_NCRA:
case BBA_NCRA:
{
DEBUGPRINT("\t\t[INFO]BBA_NCRA");
// Correct, we use the swap here
@ -231,7 +202,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
}
if (RISE(BBA_NCRA_SR) && isActivated())
{
DEBUGPRINT("\t\t[INFO]BBA Start Recieve");
DEBUGPRINT("\t\t[INFO]BBA Start Receive");
//exit(0);
startRecv();
}
@ -249,72 +220,72 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
}
mBbaMem[BBA_NCRA] = MAKE(u8, SwappedData);
}
break;
case BBA_NWAYC:
DEBUGPRINT("\t\t[INFO]BBA_NWAYC");
if(Common::swap32(_uData) & (BBA_NWAYC_ANE | BBA_NWAYC_ANS_RA))
break;
case BBA_NWAYC:
DEBUGPRINT("\t\t[INFO]BBA_NWAYC");
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
//should placate libogc
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);
}
DEBUGPRINT("Not activate!");
exit(0);
}
}
break;
case BBA_RRP: //RRP - Receive Buffer Read Page Pointer
DEBUGPRINT("\t\t[INFO]RRP");
assert(_uSize == 2 || _uSize == 1);
mRBRPP = (u8)Common::swap32(_uData) << 8; //Whinecube: I hope this works with both write sizes.
mRBEmpty = (mRBRPP == ((u32)mCbw.p_write() + CB_OFFSET));
checkRecvBuffer();
break;
case BBA_RWP: //RWP - Receive Buffer Write Page Pointer
DEBUGPRINT("\t\t[INFO]RWP");
assert(_uSize == 2 || _uSize == 1);
DEBUGPRINT("\t\t\tThing is 0x%0X", (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
// TODO: This assert FAILS!
//assert(Common::swap32(_uData) == (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
break;
case BBA_NWAYS:
DEBUGPRINT("[ERR]Call to BBA_NWAYS directly!");
exit(0);
break;
case BBA_SI_ACTRL2:
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);
u32 SwappedData = 0;
if(_uSize == 4 || _uSize == 1)
break;
case BBA_RRP: //RRP - Receive Buffer Read Page Pointer
DEBUGPRINT("\t\t[INFO]RRP");
_dbg_assert_(SP1, _uSize == 2 || _uSize == 1);
mRBRPP = (u8)Common::swap32(_uData) << 8; //Whinecube: I hope this works with both write sizes.
mRBEmpty = (mRBRPP == ((u32)mCbw.p_write() + CB_OFFSET));
checkRecvBuffer();
break;
case BBA_RWP: //RWP - Receive Buffer Write Page Pointer
DEBUGPRINT("\t\t[INFO]RWP");
_dbg_assert_(SP1, _uSize == 2 || _uSize == 1);
DEBUGPRINT("\t\t\tThing is 0x%0X", (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
// TODO: This assert FAILS!
//assert(Common::swap32(_uData) == (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
break;
case BBA_NWAYS:
DEBUGPRINT("[ERR]Call to BBA_NWAYS directly!");
exit(0);
break;
case BBA_SI_ACTRL2:
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);
u32 SwappedData = 0;
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
// Size of 4 untested Though
SwappedData = Common::swap32(_uData);
if(_uSize == 4)
{
DEBUGPRINT("\t\t\tData is 0x%08x", SwappedData);
//exit(0);
}
DEBUGPRINT("\t\t\tData is 0x%08x", SwappedData);
//exit(0);
}
else if( _uSize == 2)
{
//Correct
SwappedData = (u16)(_uData >> 16);
//DEBUGPRINT("\t\t\tData is 0x%04x", SwappedData);
}
//u32 SwappedData = _uData;
memcpy(mBbaMem + mWriteP, &SwappedData, _uSize);
mWriteP = mWriteP + _uSize;
}
else if ( _uSize == 2)
{
//Correct
SwappedData = (u16)(_uData >> 16);
//DEBUGPRINT("\t\t\tData is 0x%04x", SwappedData);
}
//u32 SwappedData = _uData;
memcpy(mBbaMem + mWriteP, &SwappedData, _uSize);
mWriteP = mWriteP + _uSize;
}
return;
}
else if (_uSize == 2 && _uData == 0)
else if (_uSize == 2 && _uData == 0)
{
// Device ID Request
// 100% this returns correctly
@ -333,7 +304,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
u32 SwappedData = _uData;
mWriteP = (u8)getbitsw(SwappedData, 16, 23);
}
else //size == 2
else //size == 2
{
// Correct, Size of 1 untested, should be correct.
u16 SwappedData = (u16)Common::swap32(_uData >> 8);
@ -341,13 +312,13 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
}
//Write of size 4 data 0xc0006000 causes write pointer to be set to 0x0000 when swapped.
// When not swapped, the write pointer is set to 0x0060
if (mWriteP == 0x48)
if (mWriteP == 0x48)
{
mWriteBuffer.clear();
mExpectVariableLengthImmWrite = true;
DEBUGPRINT("\t\t[INFO]Prepared for variable length write to address 0x48");
}
else
}
else
{
DEBUGPRINT("\t\t[INFO]BBA Write pointer set to 0x%0*X", _uSize, mWriteP);
//exit(0);
@ -356,29 +327,29 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
}
else if ((_uSize == 4 && (_uData & 0xC0000000) == 0x80000000) || (_uSize == 2 && ((u16)Common::swap32(_uData >> 8) & 0x4000) == 0x0000))
{
u32 SwappedData = _uData;
// Read from BBA Register!
if(_uSize == 4)
if(_uSize == 4)
{
// Correct
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);
//if(g::bouehr)
exit(0);
//return EXI_UNHANDLED;
}
}
else
{
}
else
{
//Correct
//size == 2
mReadP = (u8)Common::swap32(_uData);
}
DEBUGPRINT("\t[INFO]Read from BBA register! 0x%X", mReadP);
switch (mReadP)
switch (mReadP)
{
case 0x20: //MAC address
DEBUGPRINT("\t\t[INFO]Mac Address!");
@ -423,7 +394,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
case 0x5c: // These two go together
break;
case 0x31: // NWAYS - NWAY Status Register
// HACK
// HACK
activate();
mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
case 0x09: // IR
@ -449,16 +420,16 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
u32 CEXIETHERNET::ImmRead(u32 _uSize)
{
DEBUGPRINT("IMM Read, size 0x%x", _uSize);
if (mExpectSpecialImmRead)
if (mExpectSpecialImmRead)
{
// 100% that this returns correctly
DEBUGPRINT("\t[INFO]special IMMRead");
mExpectSpecialImmRead = false;
return mSpecialImmData;
}
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);
exit(0);
@ -467,11 +438,11 @@ u32 CEXIETHERNET::ImmRead(u32 _uSize)
memcpy(&uResult, mBbaMem + mReadP, _uSize);
// TODO: We do as well?
uResult = Common::swap32(uResult); //Whinecube : we have a byteswap problem...
//DEBUGPRINT("Mem spot is 0x%02x uResult is 0x%x", mBbaMem[mReadP], uResult);
/*#ifndef _WIN32
if(CheckRecieved())
startRecv();
startRecv();
#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));
mReadP = mReadP + _uSize;
@ -488,13 +459,13 @@ u32 CEXIETHERNET::ImmRead(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);
mWriteBuffer.write(_uSize, Memory::GetPointer(_uAddr));
return;
}
else
}
else
{
DEBUGPRINT("Unhandled BBA DMA write: %i, 0x%08X", _uSize, _uAddr);
//if(g::bouehr)
@ -503,11 +474,11 @@ 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);
return;
@ -519,8 +490,8 @@ void CEXIETHERNET::DMARead(u32 _uAddr, u32 _uSize)
//exit(0);
mReadP = mReadP + _uSize;
return;
}
else
}
else
{
DEBUGPRINT("Unhandled BBA DMA read: %i, 0x%08X", _uSize, _uAddr);
//if(g::bouehr)

View File

@ -39,123 +39,24 @@ inline u32 getbitsw(u32 dword, int start, int end) {
return (dword & makemaskw(start, end)) >> (31 - end);
}
// Container Class Stolen from Whinecube
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, ...);
void DEBUGPRINT(const char * format, ...);
class WriteBuffer
{
public:
WriteBuffer(u32 s) :_size(0)
WriteBuffer(u32 s) : _size(0)
{
_buffer = (u8*)malloc(s*sizeof(u8));
ucapacity = s;
}
~WriteBuffer() { free(_buffer);}
~WriteBuffer() { free(_buffer); }
u32 size() const { return _size; }
u32 capacity() const { return ucapacity; }
void write(u32 s, const void *src)
{
if (_size + s >= ucapacity)
{
printf("Write too large!");
DEBUGPRINT("Write too large!");
exit(0);
}
@ -171,112 +72,55 @@ private:
u32 _size;
};
//Doesn't contain error checks for wraparound writes
// Doesn't contain error checks for wraparound writes
class CyclicBufferWriter
{
public:
CyclicBufferWriter(u8 *buffer, size_t cap)
{
_buffer = buffer; _cap = cap; _write = 0;
CyclicBufferWriter(u8 *buffer, size_t cap) {
_buffer = buffer; _capacity = cap; _write = 0;
}
size_t p_write() const { return _write; }
void reset() { _write = 0; }
void write(void *src, size_t size);
void align(); //aligns the write pointer to steps of 0x100, like the real BBA
void write(void *src, size_t size) {
_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:
size_t _write;
size_t _cap; //capacity
size_t _capacity;
u8 *_buffer;
};
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;
#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
};
#define INVALID_P 0xFFFF
// TODO: convert into unions
enum
{
BBA_RECV_SIZE = 0x800,
BBA_MEM_SIZE = 0x1000,
CB_OFFSET = 0x100,
CB_SIZE = (BBAMEM_SIZE - CB_OFFSET),
CB_SIZE = (BBA_MEM_SIZE - CB_OFFSET),
SIZEOF_RECV_DESCRIPTOR = 4,
EXI_DEVTYPE_ETHER = 0x04020200,
@ -286,7 +130,7 @@ enum
BBA_NCRA_ST0 = 0x02, // ST0, Start transmit command/status
BBA_NCRA_ST1 = 0x04, // ST1, "
BBA_NCRA_SR = 0x08, // SR, Start Receive
BBA_NCRB = 0x01, // Network Control Register B, RW
BBA_NCRB_PR = 0x01, // PR, Promiscuous Mode
BBA_NCRB_CA = 0x02, // CA, Capture Effect Mode
@ -300,7 +144,7 @@ enum
BBA_NCRB_2_PACKETS_PER_INT = 0x40, // 0 1
BBA_NCRB_4_PACKETS_PER_INT = 0x80, // 1 0
BBA_NCRB_8_PACKETS_PER_INT = 0xC0, // 1 1
BBA_IMR = 0x08, // Interrupt Mask Register, RW, 00h
BBA_IR = 0x09, // Interrupt Register, RW, 00h
@ -330,7 +174,7 @@ enum
BBA_NWAYS_10TXF = 0x40,
BBA_NWAYS_10TXH = 0x80,
BBA_INTERRUPT_RECV = 0x02,
BBA_INTERRUPT_RECV = 0x02,
BBA_INTERRUPT_SENT = 0x04,
BBA_INTERRUPT_RECV_ERROR = 0x08,
BBA_INTERRUPT_SEND_ERROR = 0x10,
@ -341,4 +185,81 @@ enum
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