More work on BBA. Socket Test gets stuck in a loop, but now it's also receiving packets in that loop, Linux only. The device to set up in Linux is a bit of a pain as well. Breaks Windows compiling, but I will commit another with Windows fix in a moment
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3284 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
e72b77931c
commit
cd03e98d3c
|
@ -27,6 +27,7 @@
|
|||
#if !defined(__APPLE__)
|
||||
#include <stropts.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <assert.h>
|
||||
#endif
|
||||
int fd = -1;
|
||||
bool CEXIETHERNET::deactivate()
|
||||
|
@ -63,6 +64,7 @@ bool CEXIETHERNET::activate() {
|
|||
DEBUGPRINT(" Error with IOCTL: 0x%X\n", err);
|
||||
return false;
|
||||
}
|
||||
ioctl( fd, TUNSETNOCSUM, 1 );
|
||||
#endif
|
||||
DEBUGPRINT("Returned Socket name is: %s\n", ifr.ifr_name);
|
||||
resume();
|
||||
|
@ -123,23 +125,22 @@ bool CEXIETHERNET::startRecv() {
|
|||
//exit(0);
|
||||
if(!isActivated())
|
||||
return false;// Should actually be an assert
|
||||
if(!CheckRecieved()) // Check if we have data
|
||||
return false; // Nope
|
||||
if(!CheckRecieved())
|
||||
return false;
|
||||
DEBUGPRINT("startRecv... ");
|
||||
if(mWaiting) {
|
||||
DEBUGPRINT("already waiting\n");
|
||||
return true;
|
||||
}
|
||||
u32 BytesRead = 0;
|
||||
u8 B[2];
|
||||
int Num = 0;
|
||||
while(read(fd, B, 1))
|
||||
u8 B[1514];
|
||||
if((BytesRead = read(fd, B, 1500)) > 0)
|
||||
{
|
||||
DEBUGPRINT("Read 1 Byte!\n");
|
||||
mRecvBuffer.write(1, B);
|
||||
Num++;
|
||||
strncpy((char*)mRecvBuffer.p(), (const char*)B, BytesRead);
|
||||
}
|
||||
DEBUGPRINT("Read %d bytes\n", Num);
|
||||
DEBUGPRINT("Read %d bytes\n", BytesRead);
|
||||
mRecvBufferLength = BytesRead;
|
||||
handleRecvdPacket();
|
||||
return true;
|
||||
}
|
||||
bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
|
||||
|
@ -166,6 +167,101 @@ bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
|
|||
}
|
||||
bool CEXIETHERNET::handleRecvdPacket()
|
||||
{
|
||||
DEBUGPRINT(" Handle received Packet!\n");
|
||||
exit(0);
|
||||
|
||||
int rbwpp = mCbw.p_write() + CB_OFFSET; //read buffer write page pointer
|
||||
u32 available_bytes_in_cb;
|
||||
if(rbwpp < mRBRPP)
|
||||
available_bytes_in_cb = mRBRPP - rbwpp;
|
||||
else if(rbwpp == mRBRPP)
|
||||
available_bytes_in_cb = mRBEmpty ? CB_SIZE : 0;
|
||||
else //rbwpp > mRBRPP
|
||||
available_bytes_in_cb = CB_SIZE - rbwpp + (mRBRPP - CB_OFFSET);
|
||||
|
||||
//DUMPWORD(rbwpp);
|
||||
//DUMPWORD(mRBRPP);
|
||||
//DUMPWORD(available_bytes_in_cb);
|
||||
|
||||
assert(available_bytes_in_cb <= CB_SIZE);
|
||||
if(available_bytes_in_cb != CB_SIZE)//< mRecvBufferLength + SIZEOF_RECV_DESCRIPTOR)
|
||||
if(available_bytes_in_cb != CB_SIZE)//< mRecvBufferLength + SIZEOF_RECV_DESCRIPTOR)
|
||||
return true;
|
||||
cbwriteDescriptor(mRecvBufferLength);
|
||||
mCbw.write(mRecvBuffer.p(), mRecvBufferLength);
|
||||
mCbw.align();
|
||||
rbwpp = mCbw.p_write() + CB_OFFSET;
|
||||
//DUMPWORD(rbwpp);
|
||||
|
||||
//mPacketsRcvd++;
|
||||
mRecvBufferLength = 0;
|
||||
|
||||
if(mBbaMem[0x08] & BBA_INTERRUPT_RECV)
|
||||
{
|
||||
if(!(mBbaMem[0x09] & BBA_INTERRUPT_RECV))
|
||||
{
|
||||
mBbaMem[0x09] |= BBA_INTERRUPT_RECV;
|
||||
DEBUGPRINT("BBA Recv interrupt raised\n");
|
||||
m_bInterruptSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(mBbaMem[BBA_NCRA] & BBA_NCRA_SR)
|
||||
{
|
||||
startRecv();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
union bba_descr {
|
||||
struct { u32 next_packet_ptr:12, packet_len:12, status:8; };
|
||||
u32 word;
|
||||
};
|
||||
bool CEXIETHERNET::cbwriteDescriptor(u32 size) {
|
||||
//if(size < 0x3C) {//60
|
||||
#define ETHERNET_HEADER_SIZE 0xE
|
||||
if(size < ETHERNET_HEADER_SIZE)
|
||||
{
|
||||
DEBUGPRINT("Packet too small: %i bytes\n", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
size += SIZEOF_RECV_DESCRIPTOR; //The descriptor supposed to include the size of itself
|
||||
|
||||
//We should probably not implement wraparound here,
|
||||
//since neither tmbinc, riptool.dol, or libogc does...
|
||||
if(mCbw.p_write() + SIZEOF_RECV_DESCRIPTOR >= CB_SIZE)
|
||||
{
|
||||
DEBUGPRINT("The descriptor won't fit\n");
|
||||
return false;
|
||||
}
|
||||
if(size >= CB_SIZE)
|
||||
{
|
||||
DEBUGPRINT("Packet too big: %i bytes\n", size);
|
||||
return false;
|
||||
}
|
||||
|
||||
bba_descr descr;
|
||||
descr.word = 0;
|
||||
descr.packet_len = size;
|
||||
descr.status = 0;
|
||||
u32 npp;
|
||||
if(mCbw.p_write() + size < CB_SIZE)
|
||||
{
|
||||
npp = mCbw.p_write() + size + CB_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
npp = mCbw.p_write() + size + CB_OFFSET - CB_SIZE;
|
||||
}
|
||||
npp = (npp + 0xff) & ~0xff;
|
||||
if(npp >= CB_SIZE + CB_OFFSET)
|
||||
npp -= CB_SIZE;
|
||||
descr.next_packet_ptr = npp >> 8;
|
||||
//DWORD swapped = swapw(descr.word);
|
||||
//next_packet_ptr:12, packet_len:12, status:8;
|
||||
DEBUGPRINT("Writing descriptor 0x%08X @ 0x%04X: next 0x%03X len 0x%03X status 0x%02X\n",
|
||||
descr.word, mCbw.p_write() + CB_OFFSET, descr.next_packet_ptr,
|
||||
descr.packet_len, descr.status);
|
||||
mCbw.write(&descr.word, SIZEOF_RECV_DESCRIPTOR);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,29 @@ CEXIETHERNET::CEXIETHERNET() :
|
|||
Expecting = EXPECT_NONE;
|
||||
mExpectVariableLengthImmWrite = false;
|
||||
}
|
||||
|
||||
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\n", 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\n", cs ? "true" : "false", mExpectVariableLengthImmWrite ? "true" : "false");
|
||||
|
@ -215,8 +237,6 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
|
|||
DEBUGPRINT( "\t\t[INFO]BBA_NWAYC\n");
|
||||
if(Common::swap32(_uData) & (BBA_NWAYC_ANE | BBA_NWAYC_ANS_RA))
|
||||
{
|
||||
DEBUGPRINT("\t\t\tACTIVATING!\n");
|
||||
activate();
|
||||
//say we've successfully negotiated for 10 Mbit full duplex
|
||||
//should placate libogc
|
||||
mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
|
||||
|
@ -335,18 +355,25 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
|
|||
case 0x20: //MAC address
|
||||
DEBUGPRINT( "\t\t[INFO]Mac Address!\n");
|
||||
memcpy(mBbaMem + mReadP, mac_address, 6);
|
||||
DEBUGPRINT("\t\t\tACTIVATING!\n");
|
||||
activate();
|
||||
//say we've successfully negotiated for 10 Mbit full duplex
|
||||
//should placate libogc
|
||||
mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
|
||||
break;
|
||||
case 0x01: //Revision ID
|
||||
break;
|
||||
case 0x16: //RWP - Receive Buffer Write Page Pointer
|
||||
DEBUGPRINT( "\t\t[INFO]RWP!\n");
|
||||
exit(0);
|
||||
//MAKE(WORD, mBbaMem[mReadP]) = ((WORD)mCbw.p_write() + CB_OFFSET) >> 8;
|
||||
//exit(0);
|
||||
// TODO: Dunno if correct
|
||||
MAKE(u16, mBbaMem[mReadP]) = ((u16)mCbw.p_write() + CB_OFFSET) >> 8;
|
||||
break;
|
||||
case 0x18: //RRP - Receive Buffer Read Page Pointer
|
||||
DEBUGPRINT( "\t\t[INFO]RRP!\n");
|
||||
exit(0);
|
||||
//MAKE(WORD, mBbaMem[mReadP]) = (mRBRPP) >> 8;
|
||||
//exit(0);
|
||||
// TODO: Dunno if correct
|
||||
MAKE(u16, mBbaMem[mReadP]) = (mRBRPP) >> 8;
|
||||
break;
|
||||
case 0x3A: //bit 1 set if no data available
|
||||
DEBUGPRINT( "\t\t[INFO]Bit 1 set!\n");
|
||||
|
@ -399,7 +426,8 @@ u32 CEXIETHERNET::ImmRead(u32 _uSize)
|
|||
|
||||
//DEBUGPRINT("Mem spot is 0x%02x uResult is 0x%x\n", mBbaMem[mReadP], uResult);
|
||||
#ifndef _WIN32
|
||||
CheckRecieved();
|
||||
if(CheckRecieved())
|
||||
startRecv();
|
||||
#endif
|
||||
DEBUGPRINT( "\t[INFO]Read from BBA address 0x%0*X, %i byte%s: 0x%0*X\n",mReadP >= CB_OFFSET ? 4 : 2, mReadP, _uSize, (_uSize==1?"":"s"),_uSize*2, getbitsw(uResult, 0, _uSize * 8 - 1));
|
||||
mReadP = mReadP + _uSize;
|
||||
|
@ -433,6 +461,26 @@ void CEXIETHERNET::DMAWrite(u32 _uAddr, u32 _uSize)
|
|||
|
||||
void CEXIETHERNET::DMARead(u32 _uAddr, u32 _uSize)
|
||||
{
|
||||
DEBUGPRINT( "DMAR\n");
|
||||
exit(0);
|
||||
if(mReadP != INVALID_P)
|
||||
{
|
||||
if(mReadP + _uSize > BBAMEM_SIZE)
|
||||
{
|
||||
DEBUGPRINT("Read error: mReadP + size = 0x%04X + %i\n", mReadP, _uSize);
|
||||
return;
|
||||
}
|
||||
//mem.write_physical(address, size, mBbaMem + mReadP);
|
||||
memcpy(Memory::GetPointer(_uAddr), mBbaMem + mReadP, _uSize);
|
||||
DEBUGPRINT("DMA Read from BBA address 0x%0*X, %i bytes\n",
|
||||
mReadP >= CB_OFFSET ? 4 : 2, mReadP, _uSize);
|
||||
mReadP = mReadP + (u16)_uSize;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGPRINT("Unhandled BBA DMA read: %i, 0x%08X\n", _uSize, _uAddr);
|
||||
//if(g::bouehr)
|
||||
exit(0);
|
||||
//throw bouehr_exception("Unhandled BBA DMA read");
|
||||
//return EXI_UNHANDLED;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -37,6 +37,99 @@ 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, ...);
|
||||
class WriteBuffer {
|
||||
|
@ -141,9 +234,10 @@ private:
|
|||
bool isActivated();
|
||||
bool resume();
|
||||
bool startRecv();
|
||||
bool cbwriteDescriptor(u32 size);
|
||||
|
||||
volatile bool mWaiting;
|
||||
WriteBuffer mRecvBuffer;
|
||||
Container<u8> mRecvBuffer;
|
||||
#ifdef _WIN32
|
||||
HANDLE mHAdapter, mHRecvEvent, mHReadWait;
|
||||
DWORD mMtu;
|
||||
|
|
Loading…
Reference in New Issue