Adding Current BBA code. Very much thanks from Masken of Whinecube. Doesn't work yet, so it's disabled saying it's not present. Byte swap problems for it not working? Will continue working. Someone in Windows needs to add the files to the project.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1480 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
514826f282
commit
6b6aa1bb17
|
@ -44,9 +44,7 @@ void Init()
|
|||
g_Channels[0].AddDevice(EXIDEVICE_MEMORYCARD_A, 0);
|
||||
g_Channels[0].AddDevice(EXIDEVICE_IPL, 1);
|
||||
g_Channels[1].AddDevice(EXIDEVICE_MEMORYCARD_B, 0);
|
||||
#if 0
|
||||
g_Channels[0].AddDevice(EXIDEVICE_ETH, 2);
|
||||
#endif
|
||||
//g_Channels[1].AddDevice(EXIDEVICE_MIC, 0);
|
||||
g_Channels[2].AddDevice(EXIDEVICE_AD16, 0);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,7 @@
|
|||
#include "EXI_DeviceMemoryCard.h"
|
||||
#include "EXI_DeviceAD16.h"
|
||||
#include "EXI_DeviceMic.h"
|
||||
#if 0
|
||||
#include "EXI_DeviceEthernet.h"
|
||||
#endif
|
||||
|
||||
#include "../Core.h"
|
||||
|
||||
|
@ -153,9 +151,7 @@ IEXIDevice* EXIDevice_Create(TEXIDevices _EXIDevice)
|
|||
break;
|
||||
|
||||
case EXIDEVICE_ETH:
|
||||
#if 0
|
||||
return new CEXIETHERNET();
|
||||
#endif
|
||||
break;
|
||||
|
||||
}
|
||||
|
|
|
@ -28,10 +28,17 @@ enum {
|
|||
unsigned int Expecting;
|
||||
CEXIETHERNET::CEXIETHERNET() :
|
||||
m_uPosition(0),
|
||||
m_uCommand(0)
|
||||
m_uCommand(0),
|
||||
mWriteBuffer(2000)
|
||||
{
|
||||
ID = 0x04020200;
|
||||
mWriteP = INVALID_P;
|
||||
mReadP = INVALID_P;
|
||||
|
||||
mExpectSpecialImmRead = false;
|
||||
|
||||
Expecting = EXPECT_NONE;
|
||||
mExpectVariableLengthImmWrite = false;
|
||||
}
|
||||
|
||||
void CEXIETHERNET::SetCS(int cs)
|
||||
|
@ -45,7 +52,7 @@ void CEXIETHERNET::SetCS(int cs)
|
|||
|
||||
bool CEXIETHERNET::IsPresent()
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CEXIETHERNET::Update()
|
||||
|
@ -56,63 +63,225 @@ bool CEXIETHERNET::IsInterruptSet()
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CEXIETHERNET::Transfer(u8& _byte)
|
||||
{
|
||||
//printf("%x %x POS: %d\n", _byte, m_uCommand, m_uPosition);
|
||||
//printf("%x %x \n", _byte, m_uCommand);
|
||||
if (m_uPosition == 0)
|
||||
{
|
||||
m_uCommand = _byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(m_uCommand)
|
||||
{
|
||||
case CMD_ID: // ID
|
||||
if (m_uPosition != 1)
|
||||
_byte = (u8)(ID >> (24-(((m_uPosition-2) & 3) * 8)));
|
||||
break;
|
||||
case CMD_READ_REG: // Read from Register
|
||||
// Size is 2
|
||||
// Todo, Actually read it
|
||||
break;
|
||||
default:
|
||||
printf("Unknown CMD 0x%x\n", m_uCommand);
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
m_uPosition++;
|
||||
}
|
||||
bool isActivated()
|
||||
{
|
||||
// Todo: Return actual check
|
||||
return true;
|
||||
}
|
||||
inline u8 makemaskb(int start, int end) {
|
||||
return (u8)_rotl((2 << (end - start)) - 1, 7 - end);
|
||||
}
|
||||
inline u32 makemaskh(int start, int end) {
|
||||
return (u32)_rotl((2 << (end - start)) - 1, 15 - end);
|
||||
}
|
||||
inline u32 makemaskw(int start, int end) {
|
||||
return _rotl((2 << (end - start)) - 1, 31 - end);
|
||||
}
|
||||
inline u8 getbitsb(u8 byte, int start, int end) {
|
||||
return (byte & makemaskb(start, end)) >> u8(7 - end);
|
||||
}
|
||||
inline u32 getbitsh(u32 hword, int start, int end) {
|
||||
return (hword & makemaskh(start, end)) >> u32(15 - end);
|
||||
}
|
||||
inline u32 getbitsw(u32 dword, int start, int end) {
|
||||
return (dword & makemaskw(start, end)) >> (31 - end);
|
||||
}
|
||||
|
||||
void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
|
||||
{
|
||||
printf("IMM Write, size 0x%x, data 0x%x\n", _uSize, _uData);
|
||||
while (_uSize--)
|
||||
if(mExpectVariableLengthImmWrite)
|
||||
{
|
||||
u8 uByte = _uData >> 24;
|
||||
this->Transfer(uByte);
|
||||
_uData <<= 8;
|
||||
printf("Not doing expecting variable length imm write!\n");
|
||||
exit(0);
|
||||
}
|
||||
else if(mWriteP != INVALID_P)
|
||||
{
|
||||
if(mWriteP + _uSize > BBAMEM_SIZE)
|
||||
{
|
||||
printf("Write error: mWriteP + size = 0x%04X + %i\n", mWriteP, _uSize);
|
||||
exit(0);
|
||||
}
|
||||
//BBADEGUB("Write to BBA address 0x%0*X, %i byte%s: 0x%0*X\n",mWriteP >= CB_OFFSET ? 4 : 2, mWriteP, size, (size==1?"":"s"), size*2, data);
|
||||
|
||||
switch(mWriteP)
|
||||
{
|
||||
case 0x09:
|
||||
printf("mWriteP is %x\n", mWriteP);
|
||||
exit(0);
|
||||
//BBADEGUB("BBA Interrupt reset 0x%02X & ~(0x%02X) => 0x%02X\n", mBbaMem[0x09], MAKE(BYTE, data), mBbaMem[0x09] & ~MAKE(BYTE, data));
|
||||
//MYASSERT(_uSize == 1);
|
||||
//mBbaMem[0x09] &= ~MAKE(BYTE, data);
|
||||
break;
|
||||
case BBA_NCRA:
|
||||
printf("mWriteP is %x\n", mWriteP);
|
||||
exit(0);
|
||||
/*#define RISE(flags) ((data & (flags)) && !(mBbaMem[0x00] & (flags)))
|
||||
if(RISE(BBA_NCRA_RESET))
|
||||
{
|
||||
printf("BBA Reset\n");
|
||||
}
|
||||
if(RISE(BBA_NCRA_SR) && isActivated())
|
||||
{
|
||||
BBADEGUB("BBA Start Recieve\n");
|
||||
HWGLE(startRecv());
|
||||
}
|
||||
if(RISE(BBA_NCRA_ST1))
|
||||
{
|
||||
BBADEGUB("BBA Start Transmit\n");
|
||||
if(!mReadyToSend)
|
||||
throw hardware_fatal_exception("BBA Transmit without a packet!");
|
||||
HWGLE(sendPacket(mWriteBuffer.p(), mWriteBuffer.size()));
|
||||
mReadyToSend = false;
|
||||
}
|
||||
mBbaMem[0x00] = MAKE(BYTE, data);*/
|
||||
break;
|
||||
case BBA_NWAYC:
|
||||
printf("mWriteP is %x\n", mWriteP);
|
||||
exit(0);
|
||||
/*if(data & (BBA_NWAYC_ANE | BBA_NWAYC_ANS_RA))
|
||||
{
|
||||
HWGLE(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 0x18: //RRP - Receive Buffer Read Page Pointer
|
||||
printf("mWriteP is %x\n", mWriteP);
|
||||
exit(0);
|
||||
/*MYASSERT(size == 2 || size == 1);
|
||||
mRBRPP = (BYTE)data << 8; //I hope this works with both write sizes.
|
||||
mRBEmpty = mRBRPP == ((WORD)mCbw.p_write() + CB_OFFSET);
|
||||
HWGLE(checkRecvBuffer());*/
|
||||
break;
|
||||
case 0x16: //RWP
|
||||
printf("mWriteP is %x\n", mWriteP);
|
||||
exit(0);
|
||||
/*MYASSERT(size == 2 || size == 1);
|
||||
MYASSERT(data == DWORD((WORD)mCbw.p_write() + CB_OFFSET) >> 8);*/
|
||||
break;
|
||||
default:
|
||||
printf("Default one!\n");
|
||||
memcpy(mBbaMem + mWriteP, &_uData, _uSize);
|
||||
mWriteP = mWriteP + _uSize;
|
||||
}
|
||||
return;
|
||||
}else if(_uSize == 2 && _uData == 0)
|
||||
{
|
||||
// Device ID Request
|
||||
mSpecialImmData = EXI_DEVTYPE_ETHER;
|
||||
mExpectSpecialImmRead = true;
|
||||
return;
|
||||
}
|
||||
else if((_uSize == 4 && (_uData & 0xC0000000) == 0xC0000000) || (_uSize == 2 && (_uData & 0x4000) == 0x4000))
|
||||
{ // Write to BBA Register
|
||||
printf("Write to BBA register!\n");
|
||||
if(_uSize == 4)
|
||||
mWriteP = (u8)getbitsw(_uData, 16, 23);
|
||||
else //size == 2
|
||||
mWriteP = (u8)getbitsw(_uData & ~0x4000, 16, 23); //Dunno about this...
|
||||
if(mWriteP == 0x48)
|
||||
{
|
||||
mWriteBuffer.clear();
|
||||
mExpectVariableLengthImmWrite = true;
|
||||
printf("Prepared for variable length write to address 0x48\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//BBADEGUB("BBA Write pointer set to 0x%0*X\n", size, mWriteP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if((_uSize == 4 && (_uData & 0xC0000000) == 0x80000000) || (_uSize == 2 && (_uData & 0x4000) == 0x0000))
|
||||
{
|
||||
printf("Read from BBA register!\n");
|
||||
// Read from BBA Register!
|
||||
if(_uSize == 4)
|
||||
{
|
||||
//Holy Fuck that's crazy
|
||||
mReadP = (u32)getbitsw(_uData, 8, 23);
|
||||
if(mReadP >= BBAMEM_SIZE)
|
||||
{
|
||||
printf("Illegal BBA address: 0x%04X\n", mReadP);
|
||||
//if(g::bouehr)
|
||||
exit(0);
|
||||
//return EXI_UNHANDLED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //size == 2
|
||||
mReadP = (u8)getbitsw(_uData, 16, 23);
|
||||
}
|
||||
switch(mReadP)
|
||||
{
|
||||
case 0x20: //MAC address
|
||||
printf("Mac Address!\n");
|
||||
exit(0);
|
||||
//memcpy(mBbaMem + mReadP, g::mac_address, 6);
|
||||
break;
|
||||
case 0x01: //Revision ID
|
||||
break;
|
||||
case 0x16: //RWP - Receive Buffer Write Page Pointer
|
||||
printf("RWP!\n");
|
||||
exit(0);
|
||||
//MAKE(WORD, mBbaMem[mReadP]) = ((WORD)mCbw.p_write() + CB_OFFSET) >> 8;
|
||||
break;
|
||||
case 0x18: //RRP - Receive Buffer Read Page Pointer
|
||||
printf("RRP!\n");
|
||||
exit(0);
|
||||
//MAKE(WORD, mBbaMem[mReadP]) = (mRBRPP) >> 8;
|
||||
break;
|
||||
case 0x3A: //bit 1 set if no data available
|
||||
printf("Bit 1 set!\n");
|
||||
exit(0);
|
||||
//mBbaMem[mReadP] = !mRBEmpty;
|
||||
break;
|
||||
case 0x00:
|
||||
//mBbaMem[mReadP] = 0x00;
|
||||
//if(!sendInProgress())
|
||||
mBbaMem[mReadP] &= ~(0x06);
|
||||
break;
|
||||
case 0x03:
|
||||
mBbaMem[mReadP] = 0x80;
|
||||
break;
|
||||
}
|
||||
//BBADEGUB("BBA Read pointer set to 0x%0*X\n", size, mReadP);
|
||||
return;
|
||||
}
|
||||
printf("Not expecting ImmWrite of size %d\n", _uSize);
|
||||
exit(0);
|
||||
}
|
||||
u32 CEXIETHERNET::ImmRead(u32 _uSize)
|
||||
{
|
||||
u32 uResult = 0;
|
||||
u32 uPosition = 0;
|
||||
printf("IMM Read, size 0x%x\n", _uSize);
|
||||
while (_uSize--)
|
||||
{
|
||||
u8 uByte = 0;
|
||||
this->Transfer(uByte);
|
||||
uResult |= uByte << (24-(uPosition++ * 8));
|
||||
if(mExpectSpecialImmRead) {
|
||||
printf("special IMMRead\n");
|
||||
mExpectSpecialImmRead = false;
|
||||
return mSpecialImmData;
|
||||
}
|
||||
return uResult;
|
||||
if(mReadP != INVALID_P)
|
||||
{
|
||||
if(mReadP + _uSize > BBAMEM_SIZE)
|
||||
{
|
||||
printf("Read error: mReadP + size = 0x%04X + %i\n", mReadP, _uSize);
|
||||
exit(0);
|
||||
}
|
||||
u32 uResult = 0;
|
||||
memcpy(&uResult, mBbaMem + mReadP, _uSize);
|
||||
// We do as well?
|
||||
//data = swapw(data); //we have a byteswap problem...
|
||||
printf("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;
|
||||
return uResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unhandled IMM read of %d bytes\n", _uSize);
|
||||
}
|
||||
printf("Not Expecting IMMRead of size %d!\n", _uSize);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void CEXIETHERNET::DMAWrite(u32 _uAddr, u32 _uSize)
|
||||
|
|
|
@ -18,6 +18,32 @@
|
|||
#ifndef _EXIDEVICE_ETHERNET_H
|
||||
#define _EXIDEVICE_ETHERNET_H
|
||||
|
||||
class WriteBuffer {
|
||||
public:
|
||||
WriteBuffer(u32 s) :_size(0) { _buffer = (u8*)malloc(s*sizeof(u8)); ucapacity = s;}
|
||||
~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!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
memcpy(_buffer + _size, src, s);
|
||||
_size = _size + s;
|
||||
}
|
||||
void clear() {
|
||||
_size = 0;
|
||||
}
|
||||
u8* const p() { return _buffer; }
|
||||
private:
|
||||
u8* _buffer;
|
||||
u32 ucapacity;
|
||||
u32 _size;
|
||||
};
|
||||
|
||||
class CEXIETHERNET : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
|
@ -35,6 +61,19 @@ private:
|
|||
// STATE_TO_SAVE
|
||||
u32 m_uPosition;
|
||||
u32 m_uCommand;
|
||||
|
||||
u32 mWriteP, mReadP;
|
||||
#define INVALID_P 0xFFFF
|
||||
|
||||
bool mExpectSpecialImmRead; //reset to false on deselect
|
||||
u32 mSpecialImmData;
|
||||
|
||||
#define BBAMEM_SIZE 0x1000
|
||||
u8 mBbaMem[BBAMEM_SIZE];
|
||||
|
||||
WriteBuffer mWriteBuffer;
|
||||
|
||||
bool mExpectVariableLengthImmWrite;
|
||||
bool mReadyToSend;
|
||||
unsigned int ID;
|
||||
u8 RegisterBlock[0x1000];
|
||||
|
@ -43,6 +82,47 @@ private:
|
|||
CMD_READ_REG = 0x01,
|
||||
};
|
||||
|
||||
void Transfer(u8& _uByte);
|
||||
};
|
||||
#define CB_OFFSET 0x100
|
||||
#define CB_SIZE (BBAMEM_SIZE - CB_OFFSET)
|
||||
#define SIZEOF_RECV_DESCRIPTOR 4
|
||||
|
||||
#define EXI_DEVTYPE_ETHER 0x04020200
|
||||
#define BBA_NCRA 0x00 /* Network Control Register A, RW */
|
||||
#define BBA_NCRA_RESET (1<<0) /* RESET */
|
||||
#define BBA_NCRA_ST0 (1<<1) /* ST0, Start transmit command/status */
|
||||
#define BBA_NCRA_ST1 (1<<2) /* ST1, " */
|
||||
#define BBA_NCRA_SR (1<<3) /* SR, Start Receive */
|
||||
|
||||
#define BBA_NCRB 0x01 /* Network Control Register B, RW */
|
||||
#define BBA_NCRB_PR (1<<0) /* PR, Promiscuous Mode */
|
||||
#define BBA_NCRB_CA (1<<1) /* CA, Capture Effect Mode */
|
||||
#define BBA_NCRB_PM (1<<2) /* PM, Pass Multicast */
|
||||
#define BBA_NCRB_PB (1<<3) /* PB, Pass Bad Frame */
|
||||
#define BBA_NCRB_AB (1<<4) /* AB, Accept Broadcast */
|
||||
#define BBA_NCRB_HBD (1<<5) /* HBD, reserved */
|
||||
#define BBA_NCRB_RXINTC0 (1<<6) /* RXINTC, Receive Interrupt Counter */
|
||||
#define BBA_NCRB_RXINTC1 (1<<7) /* " */
|
||||
#define BBA_NCRB_1_PACKET_PER_INT (0<<6) /* 0 0 */
|
||||
#define BBA_NCRB_2_PACKETS_PER_INT (1<<6) /* 0 1 */
|
||||
#define BBA_NCRB_4_PACKETS_PER_INT (2<<6) /* 1 0 */
|
||||
#define BBA_NCRB_8_PACKETS_PER_INT (3<<6) /* 1 1 */
|
||||
|
||||
#define BBA_NWAYC 0x30 /* NWAY Configuration Register, RW, 84h */
|
||||
#define BBA_NWAYC_FD (1<<0) /* FD, Full Duplex Mode */
|
||||
#define BBA_NWAYC_PS100 (1<<1) /* PS100/10, Port Select 100/10 */
|
||||
#define BBA_NWAYC_ANE (1<<2) /* ANE, Autonegotiation Enable */
|
||||
#define BBA_NWAYC_ANS_RA (1<<3) /* ANS, Restart Autonegotiation */
|
||||
#define BBA_NWAYC_LTE (1<<7) /* LTE, Link Test Enable */
|
||||
|
||||
#define BBA_NWAYS 0x31
|
||||
#define BBA_NWAYS_LS10 (1<<0)
|
||||
#define BBA_NWAYS_LS100 (1<<1)
|
||||
#define BBA_NWAYS_LPNWAY (1<<2)
|
||||
#define BBA_NWAYS_ANCLPT (1<<3)
|
||||
#define BBA_NWAYS_100TXF (1<<4)
|
||||
#define BBA_NWAYS_100TXH (1<<5)
|
||||
#define BBA_NWAYS_10TXF (1<<6)
|
||||
#define BBA_NWAYS_10TXH (1<<7)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,7 +38,7 @@ files = ["Console.cpp",
|
|||
"HW/EXI_DeviceAD16.cpp",
|
||||
"HW/EXI_DeviceMemoryCard.cpp",
|
||||
"HW/EXI_DeviceMic.cpp",
|
||||
# "HW/EXI_DeviceEthernet.cpp",
|
||||
"HW/EXI_DeviceEthernet.cpp",
|
||||
"HW/GPFifo.cpp",
|
||||
"HW/HW.cpp",
|
||||
"HW/Memmap.cpp",
|
||||
|
|
Loading…
Reference in New Issue