more WIP BBA crap...nothing nice to see.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6672 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
33506f5bdc
commit
722b7db8f9
|
@ -155,6 +155,7 @@ void SConfig::SaveSettings()
|
||||||
ini.Set("Core", "SlotA", m_EXIDevice[0]);
|
ini.Set("Core", "SlotA", m_EXIDevice[0]);
|
||||||
ini.Set("Core", "SlotB", m_EXIDevice[1]);
|
ini.Set("Core", "SlotB", m_EXIDevice[1]);
|
||||||
ini.Set("Core", "SerialPort1", m_EXIDevice[2]);
|
ini.Set("Core", "SerialPort1", m_EXIDevice[2]);
|
||||||
|
ini.Set("Core", "BBA_MAC", m_bba_mac);
|
||||||
char sidevicenum[16];
|
char sidevicenum[16];
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
|
@ -279,6 +280,7 @@ void SConfig::LoadSettings()
|
||||||
ini.Get("Core", "SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD_A);
|
ini.Get("Core", "SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD_A);
|
||||||
ini.Get("Core", "SlotB", (int*)&m_EXIDevice[1], EXIDEVICE_NONE);
|
ini.Get("Core", "SlotB", (int*)&m_EXIDevice[1], EXIDEVICE_NONE);
|
||||||
ini.Get("Core", "SerialPort1", (int*)&m_EXIDevice[2], EXIDEVICE_NONE);
|
ini.Get("Core", "SerialPort1", (int*)&m_EXIDevice[2], EXIDEVICE_NONE);
|
||||||
|
ini.Get("Core", "BBA_MAC", &m_bba_mac);
|
||||||
ini.Get("Core", "ProfiledReJIT",&m_LocalCoreStartupParameter.bJITProfiledReJIT, false);
|
ini.Get("Core", "ProfiledReJIT",&m_LocalCoreStartupParameter.bJITProfiledReJIT, false);
|
||||||
ini.Get("Core", "TimeProfiling",&m_LocalCoreStartupParameter.bJITILTimeProfiling, false);
|
ini.Get("Core", "TimeProfiling",&m_LocalCoreStartupParameter.bJITILTimeProfiling, false);
|
||||||
ini.Get("Core", "OutputIR", &m_LocalCoreStartupParameter.bJITILOutputIR, false);
|
ini.Get("Core", "OutputIR", &m_LocalCoreStartupParameter.bJITILOutputIR, false);
|
||||||
|
|
|
@ -64,6 +64,7 @@ struct SConfig : NonCopyable
|
||||||
std::string m_strMemoryCardB;
|
std::string m_strMemoryCardB;
|
||||||
TEXIDevices m_EXIDevice[3];
|
TEXIDevices m_EXIDevice[3];
|
||||||
TSIDevices m_SIDevice[4];
|
TSIDevices m_SIDevice[4];
|
||||||
|
std::string m_bba_mac;
|
||||||
|
|
||||||
// interface language
|
// interface language
|
||||||
INTERFACE_LANGUAGE m_InterfaceLanguage;
|
INTERFACE_LANGUAGE m_InterfaceLanguage;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
#include "../Memmap.h"
|
#include "../Memmap.h"
|
||||||
|
//#pragma optimize("",off)
|
||||||
// GROSS CODE ALERT: headers need to be included in the following order
|
// GROSS CODE ALERT: headers need to be included in the following order
|
||||||
#include "TAP_Win32.h"
|
#include "TAP_Win32.h"
|
||||||
#include "../EXI_Device.h"
|
#include "../EXI_Device.h"
|
||||||
|
@ -67,16 +68,19 @@ bool IsTAPDevice(const char *guid)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
len = sizeof(component_id);
|
len = sizeof(component_id);
|
||||||
status = RegQueryValueEx(unit_key, component_id_string, NULL, &data_type, (LPBYTE)component_id, &len);
|
status = RegQueryValueEx(unit_key, component_id_string, NULL,
|
||||||
|
&data_type, (LPBYTE)component_id, &len);
|
||||||
|
|
||||||
if (!(status != ERROR_SUCCESS || data_type != REG_SZ))
|
if (!(status != ERROR_SUCCESS || data_type != REG_SZ))
|
||||||
{
|
{
|
||||||
len = sizeof(net_cfg_instance_id);
|
len = sizeof(net_cfg_instance_id);
|
||||||
status = RegQueryValueEx(unit_key, net_cfg_instance_id_string, NULL, &data_type, (LPBYTE)net_cfg_instance_id, &len);
|
status = RegQueryValueEx(unit_key, net_cfg_instance_id_string, NULL,
|
||||||
|
&data_type, (LPBYTE)net_cfg_instance_id, &len);
|
||||||
|
|
||||||
if (status == ERROR_SUCCESS && data_type == REG_SZ)
|
if (status == ERROR_SUCCESS && data_type == REG_SZ)
|
||||||
{
|
{
|
||||||
if (!strcmp(component_id, TAP_COMPONENT_ID) && !strcmp(net_cfg_instance_id, guid))
|
if (!strcmp(component_id, TAP_COMPONENT_ID) &&
|
||||||
|
!strcmp(net_cfg_instance_id, guid))
|
||||||
{
|
{
|
||||||
RegCloseKey(unit_key);
|
RegCloseKey(unit_key);
|
||||||
RegCloseKey(netcard_key);
|
RegCloseKey(netcard_key);
|
||||||
|
@ -93,20 +97,20 @@ bool IsTAPDevice(const char *guid)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetGUID(char *name, int name_size)
|
bool GetGUIDs(std::vector<std::string>& guids)
|
||||||
{
|
{
|
||||||
LONG status;
|
LONG status;
|
||||||
HKEY control_net_key;
|
HKEY control_net_key;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
bool stop = false;
|
bool found_all = false;
|
||||||
|
|
||||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &control_net_key);
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &control_net_key);
|
||||||
|
|
||||||
if (status != ERROR_SUCCESS)
|
if (status != ERROR_SUCCESS)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (!stop)
|
while (!found_all)
|
||||||
{
|
{
|
||||||
char enum_name[256];
|
char enum_name[256];
|
||||||
char connection_string[256];
|
char connection_string[256];
|
||||||
|
@ -116,21 +120,25 @@ bool GetGUID(char *name, int name_size)
|
||||||
const char name_string[] = "Name";
|
const char name_string[] = "Name";
|
||||||
|
|
||||||
len = sizeof(enum_name);
|
len = sizeof(enum_name);
|
||||||
status = RegEnumKeyEx(control_net_key, i, enum_name, &len, NULL, NULL, NULL, NULL);
|
status = RegEnumKeyEx(control_net_key, i, enum_name,
|
||||||
|
&len, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (status == ERROR_NO_MORE_ITEMS)
|
if (status == ERROR_NO_MORE_ITEMS)
|
||||||
break;
|
break;
|
||||||
else if (status != ERROR_SUCCESS)
|
else if (status != ERROR_SUCCESS)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
snprintf(connection_string, sizeof(connection_string), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, enum_name);
|
snprintf(connection_string, sizeof(connection_string),
|
||||||
|
"%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, enum_name);
|
||||||
|
|
||||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connection_key);
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string,
|
||||||
|
0, KEY_READ, &connection_key);
|
||||||
|
|
||||||
if (status == ERROR_SUCCESS)
|
if (status == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
len = sizeof(name_data);
|
len = sizeof(name_data);
|
||||||
status = RegQueryValueEx(connection_key, name_string, NULL, &name_type, (LPBYTE)name_data, &len);
|
status = RegQueryValueEx(connection_key, name_string, NULL,
|
||||||
|
&name_type, (LPBYTE)name_data, &len);
|
||||||
|
|
||||||
if (status != ERROR_SUCCESS || name_type != REG_SZ)
|
if (status != ERROR_SUCCESS || name_type != REG_SZ)
|
||||||
{
|
{
|
||||||
|
@ -140,8 +148,8 @@ bool GetGUID(char *name, int name_size)
|
||||||
{
|
{
|
||||||
if (IsTAPDevice(enum_name))
|
if (IsTAPDevice(enum_name))
|
||||||
{
|
{
|
||||||
snprintf(name, name_size, "%s", enum_name);
|
guids.push_back(enum_name);
|
||||||
stop = true;
|
//found_all = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,24 +160,43 @@ bool GetGUID(char *name, int name_size)
|
||||||
|
|
||||||
RegCloseKey(control_net_key);
|
RegCloseKey(control_net_key);
|
||||||
|
|
||||||
if (!stop)
|
//if (!found_all)
|
||||||
return false;
|
//return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenTAP(HANDLE& adapter, const std::string device_guid)
|
||||||
|
{
|
||||||
|
char device_path[256];
|
||||||
|
|
||||||
|
/* Open Windows TAP-Win32 adapter */
|
||||||
|
snprintf(device_path, sizeof(device_path), "%s%s%s",
|
||||||
|
USERMODEDEVICEDIR, device_guid.c_str(), TAPSUFFIX);
|
||||||
|
|
||||||
|
adapter = CreateFile(device_path, GENERIC_READ | GENERIC_WRITE, 0, 0,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
|
||||||
|
|
||||||
|
if (adapter == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
INFO_LOG(SP1, "Failed to open TAP at %s", device_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Win32TAPHelper
|
} // namespace Win32TAPHelper
|
||||||
|
|
||||||
bool CEXIETHERNET::deactivate()
|
bool CEXIETHERNET::deactivate()
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Deactivating BBA...");
|
INFO_LOG(SP1, "Deactivating BBA...");
|
||||||
if (!isActivated())
|
if (!isActivated())
|
||||||
return true;
|
return true;
|
||||||
CloseHandle(mHRecvEvent);
|
CloseHandle(mHRecvEvent);
|
||||||
mHRecvEvent = INVALID_HANDLE_VALUE;
|
mHRecvEvent = INVALID_HANDLE_VALUE;
|
||||||
CloseHandle(mHAdapter);
|
CloseHandle(mHAdapter);
|
||||||
mHAdapter = INVALID_HANDLE_VALUE;
|
mHAdapter = INVALID_HANDLE_VALUE;
|
||||||
DEBUGPRINT("Success!");
|
INFO_LOG(SP1, "Success!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,89 +210,80 @@ bool CEXIETHERNET::activate()
|
||||||
if (isActivated())
|
if (isActivated())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
DEBUGPRINT("Activating BBA...");
|
INFO_LOG(SP1, "Activating BBA...");
|
||||||
|
|
||||||
DWORD len;
|
DWORD len;
|
||||||
char device_path[256];
|
std::vector<std::string> device_guids;
|
||||||
char device_guid[0x100];
|
|
||||||
|
|
||||||
if (!Win32TAPHelper::GetGUID(device_guid, sizeof(device_guid)))
|
if (!Win32TAPHelper::GetGUIDs(device_guids))
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Failed to find a TAP GUID");
|
INFO_LOG(SP1, "Failed to find a TAP GUID");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open Windows TAP-Win32 adapter */
|
for (int i = 0; i < device_guids.size(); i++)
|
||||||
snprintf(device_path, sizeof(device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid, TAPSUFFIX);
|
{
|
||||||
|
if (Win32TAPHelper::OpenTAP(mHAdapter, device_guids.at(i)))
|
||||||
mHAdapter = CreateFile (
|
{
|
||||||
device_path,
|
ERROR_LOG(SP1, "OPENED %s", device_guids.at(i).c_str());
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
i = device_guids.size();
|
||||||
0,
|
}
|
||||||
0,
|
}
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
|
|
||||||
0 );
|
|
||||||
|
|
||||||
if (mHAdapter == INVALID_HANDLE_VALUE)
|
if (mHAdapter == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Failed to open TAP at %s", device_path);
|
INFO_LOG(SP1, "Failed to open any TAP");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get driver version info */
|
/* get driver version info */
|
||||||
|
ULONG info[3];
|
||||||
|
if (DeviceIoControl (mHAdapter, TAP_IOCTL_GET_VERSION,
|
||||||
|
&info, sizeof (info), &info, sizeof (info), &len, NULL))
|
||||||
{
|
{
|
||||||
ULONG info[3];
|
INFO_LOG(SP1, "TAP-Win32 Driver Version %d.%d %s",
|
||||||
if (DeviceIoControl (mHAdapter, TAP_IOCTL_GET_VERSION,
|
info[0], info[1], (info[2] ? "(DEBUG)" : ""));
|
||||||
&info, sizeof (info), &info, sizeof (info), &len, NULL))
|
}
|
||||||
{
|
if ( !(info[0] > TAP_WIN32_MIN_MAJOR
|
||||||
DEBUGPRINT("TAP-Win32 Driver Version %d.%d %s",
|
|| (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) )
|
||||||
info[0], info[1], (info[2] ? "(DEBUG)" : ""));
|
{
|
||||||
}
|
PanicAlert("ERROR: This version of Dolphin requires a TAP-Win32 driver"
|
||||||
if ( !(info[0] > TAP_WIN32_MIN_MAJOR
|
" that is at least version %d.%d -- If you recently upgraded your Dolphin"
|
||||||
|| (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) )
|
" distribution, a reboot is probably required at this point to get"
|
||||||
{
|
" Windows to see the new driver.",
|
||||||
DEBUGPRINT("ERROR: This version of Dolphin requires a TAP-Win32 driver that is at least version %d.%d -- If you recently upgraded your Dolphin distribution, a reboot is probably required at this point to get Windows to see the new driver.",
|
TAP_WIN32_MIN_MAJOR, TAP_WIN32_MIN_MINOR);
|
||||||
TAP_WIN32_MIN_MAJOR,
|
return false;
|
||||||
TAP_WIN32_MIN_MINOR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get driver MTU */
|
/* get driver MTU */
|
||||||
|
if (!DeviceIoControl(mHAdapter, TAP_IOCTL_GET_MTU,
|
||||||
|
&mMtu, sizeof (mMtu), &mMtu, sizeof (mMtu), &len, NULL))
|
||||||
{
|
{
|
||||||
if (!DeviceIoControl(mHAdapter, TAP_IOCTL_GET_MTU,
|
INFO_LOG(SP1, "Couldn't get device MTU");
|
||||||
&mMtu, sizeof (mMtu), &mMtu, sizeof (mMtu), &len, NULL))
|
return false;
|
||||||
{
|
|
||||||
DEBUGPRINT("Couldn't get device MTU");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DEBUGPRINT("TAP-Win32 MTU=%d (ignored)", mMtu);
|
|
||||||
}
|
}
|
||||||
|
INFO_LOG(SP1, "TAP-Win32 MTU=%d (ignored)", mMtu);
|
||||||
|
|
||||||
/* set driver media status to 'connected' */
|
/* set driver media status to 'connected' */
|
||||||
|
ULONG status = TRUE;
|
||||||
|
if (!DeviceIoControl(mHAdapter, TAP_IOCTL_SET_MEDIA_STATUS,
|
||||||
|
&status, sizeof (status), &status, sizeof (status), &len, NULL))
|
||||||
{
|
{
|
||||||
ULONG status = TRUE;
|
INFO_LOG(SP1, "WARNING: The TAP-Win32 driver rejected a"
|
||||||
if (!DeviceIoControl (mHAdapter, TAP_IOCTL_SET_MEDIA_STATUS,
|
"TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.");
|
||||||
&status, sizeof (status), &status, sizeof (status), &len, NULL))
|
return false;
|
||||||
{
|
|
||||||
DEBUGPRINT("WARNING: The TAP-Win32 driver rejected a TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DEBUGPRINT("TAP-WIN32 status as Connected");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//set up recv event
|
//set up recv event
|
||||||
mHRecvEvent = CreateEvent(NULL, false, false, NULL);
|
if ((mHRecvEvent = CreateEvent(NULL, false, false, NULL)) == NULL)
|
||||||
memset((void*)&mReadOverlapped, 0 , sizeof(mReadOverlapped));
|
{
|
||||||
|
INFO_LOG(SP1, "Failed to create recv event:%x", GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ZeroMemory(&mReadOverlapped, sizeof(mReadOverlapped));
|
||||||
resume();
|
resume();
|
||||||
|
|
||||||
DEBUGPRINT("Success!");
|
INFO_LOG(SP1, "Success!");
|
||||||
return true;
|
return true;
|
||||||
//TODO: Activate Device!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::CheckRecieved()
|
bool CEXIETHERNET::CheckRecieved()
|
||||||
|
@ -273,40 +291,65 @@ bool CEXIETHERNET::CheckRecieved()
|
||||||
if (!isActivated())
|
if (!isActivated())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// I have no idea o_O
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Required for lwip...not sure why
|
||||||
|
void fixup_ip_checksum(u16 *dataptr, u16 len)
|
||||||
|
{
|
||||||
|
u32 acc = 0;
|
||||||
|
u16 *data = dataptr;
|
||||||
|
u16 *chksum = &dataptr[5];
|
||||||
|
|
||||||
|
*chksum = 0;
|
||||||
|
|
||||||
|
while (len > 1) {
|
||||||
|
u16 s = *data++;
|
||||||
|
acc += Common::swap16(s);
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
acc = (acc >> 16) + (acc & 0xffff);
|
||||||
|
acc += (acc >> 16);
|
||||||
|
*chksum = Common::swap16(~acc);
|
||||||
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
|
bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
|
||||||
{
|
{
|
||||||
if (!isActivated())
|
fixup_ip_checksum((u16*)etherpckt + 7, 20);
|
||||||
activate();
|
INFO_LOG(SP1, "Packet (%zu):\n%s", size, ArrayToString(etherpckt, size, 0, 16).c_str());
|
||||||
|
|
||||||
DEBUGPRINT("Packet (%i): %s", size, ArrayToString(etherpckt, size).c_str());
|
|
||||||
|
|
||||||
DWORD numBytesWrit;
|
DWORD numBytesWrit;
|
||||||
OVERLAPPED overlap;
|
OVERLAPPED overlap;
|
||||||
memset((void*)&overlap, 0, sizeof(overlap));
|
ZeroMemory(&overlap, sizeof(overlap));
|
||||||
//ZERO_OBJECT(overlap);
|
|
||||||
//overlap.hEvent = mHRecvEvent;
|
//overlap.hEvent = mHRecvEvent;
|
||||||
if (!WriteFile(mHAdapter, etherpckt, size, &numBytesWrit, &overlap))
|
if (!WriteFile(mHAdapter, etherpckt, size, &numBytesWrit, &overlap))
|
||||||
{
|
{
|
||||||
// Fail Boat
|
// Fail Boat
|
||||||
DWORD res = GetLastError();
|
DWORD res = GetLastError();
|
||||||
DEBUGPRINT("Failed to send packet with error 0x%X", res);
|
INFO_LOG(SP1, "Failed to send packet with error 0x%X", res);
|
||||||
}
|
}
|
||||||
if (numBytesWrit != size)
|
if (numBytesWrit != size)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("BBA sendPacket %i only got %i bytes sent!", size, numBytesWrit);
|
INFO_LOG(SP1, "BBA sendPacket %i only got %i bytes sent!", size, numBytesWrit);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
recordSendComplete();
|
recordSendComplete();
|
||||||
//exit(0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::handleRecvdPacket()
|
bool CEXIETHERNET::handleRecvdPacket()
|
||||||
{
|
{
|
||||||
|
static u32 mPacketsRecvd = 0;
|
||||||
|
INFO_LOG(SP1, "handleRecvdPacket Packet %i (%i):\n%s", mPacketsRecvd, mRecvBufferLength,
|
||||||
|
ArrayToString(mRecvBuffer, mRecvBufferLength, 0, 16).c_str());
|
||||||
|
|
||||||
|
static u8 broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
if (memcmp(mRecvBuffer, broadcast, 6) && memcmp(mRecvBuffer, mac_address, 6))
|
||||||
|
{
|
||||||
|
INFO_LOG(SP1, "dropping packet - not for us");
|
||||||
|
goto wait_for_next;
|
||||||
|
}
|
||||||
|
|
||||||
int rbwpp = (int)(mCbw.p_write() + CB_OFFSET); // read buffer write page pointer
|
int rbwpp = (int)(mCbw.p_write() + CB_OFFSET); // read buffer write page pointer
|
||||||
u32 available_bytes_in_cb;
|
u32 available_bytes_in_cb;
|
||||||
if (rbwpp < mRBRPP)
|
if (rbwpp < mRBRPP)
|
||||||
|
@ -316,9 +359,8 @@ bool CEXIETHERNET::handleRecvdPacket()
|
||||||
else //rbwpp > mRBRPP
|
else //rbwpp > mRBRPP
|
||||||
available_bytes_in_cb = CB_SIZE - rbwpp + (mRBRPP - CB_OFFSET);
|
available_bytes_in_cb = CB_SIZE - rbwpp + (mRBRPP - CB_OFFSET);
|
||||||
|
|
||||||
//DUMPWORD(rbwpp);
|
INFO_LOG(SP1, "rbwpp %i mRBRPP %04x available_bytes_in_cb %i",
|
||||||
//DUMPWORD(mRBRPP);
|
rbwpp, mRBRPP, available_bytes_in_cb);
|
||||||
//DUMPWORD(available_bytes_in_cb);
|
|
||||||
|
|
||||||
_dbg_assert_(SP1, available_bytes_in_cb <= CB_SIZE);
|
_dbg_assert_(SP1, 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)
|
||||||
|
@ -327,23 +369,24 @@ bool CEXIETHERNET::handleRecvdPacket()
|
||||||
mCbw.write(mRecvBuffer, mRecvBufferLength);
|
mCbw.write(mRecvBuffer, mRecvBufferLength);
|
||||||
mCbw.align();
|
mCbw.align();
|
||||||
rbwpp = (int)(mCbw.p_write() + CB_OFFSET);
|
rbwpp = (int)(mCbw.p_write() + CB_OFFSET);
|
||||||
//DUMPWORD(rbwpp);
|
|
||||||
|
|
||||||
//mPacketsRcvd++;
|
INFO_LOG(SP1, "rbwpp %i", rbwpp);
|
||||||
|
|
||||||
|
mPacketsRecvd++;
|
||||||
mRecvBufferLength = 0;
|
mRecvBufferLength = 0;
|
||||||
|
|
||||||
if (mBbaMem[0x08] & BBA_INTERRUPT_RECV)
|
if ((mBbaMem[BBA_IMR] & INT_R) && !(mBbaMem[BBA_IR] & INT_R))
|
||||||
{
|
{
|
||||||
if (!(mBbaMem[0x09] & BBA_INTERRUPT_RECV))
|
if (mBbaMem[2])
|
||||||
{
|
{
|
||||||
mBbaMem[0x09] |= BBA_INTERRUPT_RECV;
|
mBbaMem[BBA_IR] |= INT_R;
|
||||||
DEBUGPRINT("BBA Recv interrupt raised");
|
INFO_LOG(SP1, "BBA Recv interrupt raised");
|
||||||
//interrupt.raiseEXI("BBA Recv");
|
|
||||||
m_bInterruptSet = true;
|
m_bInterruptSet = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBbaMem[BBA_NCRA] & BBA_NCRA_SR)
|
wait_for_next:
|
||||||
|
if (mBbaMem[BBA_NCRA] & NCRA_SR)
|
||||||
startRecv();
|
startRecv();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -351,10 +394,10 @@ bool CEXIETHERNET::handleRecvdPacket()
|
||||||
|
|
||||||
bool CEXIETHERNET::resume()
|
bool CEXIETHERNET::resume()
|
||||||
{
|
{
|
||||||
if(!isActivated())
|
if (!isActivated())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
DEBUGPRINT("BBA resume");
|
INFO_LOG(SP1, "BBA resume");
|
||||||
//mStop = false;
|
//mStop = false;
|
||||||
|
|
||||||
RegisterWaitForSingleObject(&mHReadWait, mHRecvEvent, ReadWaitCallback,
|
RegisterWaitForSingleObject(&mHReadWait, mHRecvEvent, ReadWaitCallback,
|
||||||
|
@ -362,10 +405,10 @@ bool CEXIETHERNET::resume()
|
||||||
|
|
||||||
mReadOverlapped.hEvent = mHRecvEvent;
|
mReadOverlapped.hEvent = mHRecvEvent;
|
||||||
|
|
||||||
if (mBbaMem[BBA_NCRA] & BBA_NCRA_SR)
|
if (mBbaMem[BBA_NCRA] & NCRA_SR)
|
||||||
startRecv();
|
startRecv();
|
||||||
|
|
||||||
DEBUGPRINT("BBA resume complete");
|
INFO_LOG(SP1, "BBA resume complete");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,11 +417,11 @@ bool CEXIETHERNET::startRecv()
|
||||||
if (!isActivated())
|
if (!isActivated())
|
||||||
return false;// Should actually be an assert
|
return false;// Should actually be an assert
|
||||||
|
|
||||||
DEBUGPRINT("startRecv... ");
|
INFO_LOG(SP1, "startRecv... ");
|
||||||
|
|
||||||
if (mWaiting)
|
if (mWaiting)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("already waiting");
|
INFO_LOG(SP1, "already waiting");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +431,7 @@ bool CEXIETHERNET::startRecv()
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
// Operation completed immediately
|
// Operation completed immediately
|
||||||
DEBUGPRINT("completed, res %i", res);
|
INFO_LOG(SP1, "completed, res %i", res);
|
||||||
mWaiting = true;
|
mWaiting = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -397,7 +440,7 @@ bool CEXIETHERNET::startRecv()
|
||||||
if (res == ERROR_IO_PENDING)
|
if (res == ERROR_IO_PENDING)
|
||||||
{
|
{
|
||||||
//'s ok :)
|
//'s ok :)
|
||||||
DEBUGPRINT("pending");
|
INFO_LOG(SP1, "pending");
|
||||||
// WaitCallback will be called
|
// WaitCallback will be called
|
||||||
mWaiting = true;
|
mWaiting = true;
|
||||||
}
|
}
|
||||||
|
@ -415,19 +458,15 @@ VOID CALLBACK CEXIETHERNET::ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFir
|
||||||
{
|
{
|
||||||
static int sNumber = 0;
|
static int sNumber = 0;
|
||||||
int cNumber = sNumber++;
|
int cNumber = sNumber++;
|
||||||
DEBUGPRINT("WaitCallback %i", cNumber);
|
INFO_LOG(SP1, "WaitCallback %i", cNumber);
|
||||||
|
__assume(!TimerFired);
|
||||||
if (TimerFired)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CEXIETHERNET* self = (CEXIETHERNET*)lpParameter;
|
CEXIETHERNET* self = (CEXIETHERNET*)lpParameter;
|
||||||
if(self->mHAdapter == INVALID_HANDLE_VALUE)
|
__assume(self->mHAdapter != INVALID_HANDLE_VALUE);
|
||||||
return;
|
|
||||||
GetOverlappedResult(self->mHAdapter, &self->mReadOverlapped,
|
GetOverlappedResult(self->mHAdapter, &self->mReadOverlapped,
|
||||||
&self->mRecvBufferLength, false);
|
&self->mRecvBufferLength, false);
|
||||||
self->mWaiting = false;
|
self->mWaiting = false;
|
||||||
self->handleRecvdPacket();
|
self->handleRecvdPacket();
|
||||||
DEBUGPRINT("WaitCallback %i done", cNumber);
|
INFO_LOG(SP1, "WaitCallback %i done", cNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
union bba_descr
|
union bba_descr
|
||||||
|
@ -440,7 +479,7 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size)
|
||||||
{
|
{
|
||||||
if (size < SIZEOF_ETH_HEADER)
|
if (size < SIZEOF_ETH_HEADER)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Packet too small: %i bytes", size);
|
INFO_LOG(SP1, "Packet too small: %i bytes", size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,12 +490,12 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size)
|
||||||
//since neither tmbinc, riptool.dol, or libogc does...
|
//since neither tmbinc, riptool.dol, or libogc does...
|
||||||
if (mCbw.p_write() + SIZEOF_RECV_DESCRIPTOR >= CB_SIZE)
|
if (mCbw.p_write() + SIZEOF_RECV_DESCRIPTOR >= CB_SIZE)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("The descriptor won't fit");
|
INFO_LOG(SP1, "The descriptor won't fit");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (size >= CB_SIZE)
|
if (size >= CB_SIZE)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Packet too big: %i bytes", size);
|
INFO_LOG(SP1, "Packet too big: %i bytes", size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +521,7 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size)
|
||||||
descr.next_packet_ptr = npp >> 8;
|
descr.next_packet_ptr = npp >> 8;
|
||||||
//DWORD swapped = swapw(descr.word);
|
//DWORD swapped = swapw(descr.word);
|
||||||
//next_packet_ptr:12, packet_len:12, status:8;
|
//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",
|
INFO_LOG(SP1, "Writing descriptor 0x%08X @ 0x%04X: next 0x%03X len 0x%03X status 0x%02X",
|
||||||
descr.word, mCbw.p_write() + CB_OFFSET, descr.next_packet_ptr,
|
descr.word, mCbw.p_write() + CB_OFFSET, descr.next_packet_ptr,
|
||||||
descr.packet_len, descr.status);
|
descr.packet_len, descr.status);
|
||||||
|
|
||||||
|
@ -490,3 +529,4 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
//#pragma optimize("",on)
|
|
@ -234,6 +234,7 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
|
||||||
case EXI_READ: m_ImmData = pDevice->ImmRead(m_Control.TLEN + 1); break;
|
case EXI_READ: m_ImmData = pDevice->ImmRead(m_Control.TLEN + 1); break;
|
||||||
case EXI_WRITE: pDevice->ImmWrite(m_ImmData, m_Control.TLEN + 1); break;
|
case EXI_WRITE: pDevice->ImmWrite(m_ImmData, m_Control.TLEN + 1); break;
|
||||||
case EXI_READWRITE:
|
case EXI_READWRITE:
|
||||||
|
ERROR_LOG(SP1, "RW UNSUPPORTED");
|
||||||
/* Only used by USBGecko?
|
/* Only used by USBGecko?
|
||||||
pDevice->ImmWrite(m_ImmData, m_Control.TLEN + 1);
|
pDevice->ImmWrite(m_ImmData, m_Control.TLEN + 1);
|
||||||
m_ImmData = pDevice->ImmRead(m_Control.TLEN + 1); */
|
m_ImmData = pDevice->ImmRead(m_Control.TLEN + 1); */
|
||||||
|
|
|
@ -130,7 +130,7 @@ IEXIDevice* EXIDevice_Create(TEXIDevices _EXIDevice)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIDEVICE_ETH:
|
case EXIDEVICE_ETH:
|
||||||
return new CEXIETHERNET();
|
return new CEXIETHERNET(SConfig::GetInstance().m_bba_mac);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIDEVICE_AM_BASEBOARD:
|
case EXIDEVICE_AM_BASEBOARD:
|
||||||
|
|
|
@ -16,57 +16,51 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Memmap.h"
|
#include "Memmap.h"
|
||||||
|
//#pragma optimize("",off)
|
||||||
#include "EXI_Device.h"
|
#include "EXI_Device.h"
|
||||||
#include "EXI_DeviceEthernet.h"
|
#include "EXI_DeviceEthernet.h"
|
||||||
#include <stdarg.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, "%s", buffer);
|
|
||||||
#endif
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define MAKE(type, arg) (*(type *)&(arg))
|
#define MAKE(type, arg) (*(type *)&(arg))
|
||||||
|
|
||||||
#define RISE(flags) ((SwappedData & (flags)) && !(mBbaMem[0x00] & (flags)))
|
const u8 CEXIETHERNET::mac_address_default[6] = { 0x00, 0x09, 0xbf, 0x01, 0x00, 0xc1 };
|
||||||
|
|
||||||
static u32 mPacketsSent = 0;
|
CEXIETHERNET::CEXIETHERNET(const std::string& mac_addr) :
|
||||||
static u8 mac_address[6] = {0x00, 0x09, 0xbf, 0x01, 0x00, 0xc1}; // (shuffle2) from my bba
|
|
||||||
static u32 Expecting;
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
memset(mBbaMem, 0, BBA_MEM_SIZE);
|
memset(mBbaMem, 0, BBA_MEM_SIZE);
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
u8 new_addr[6] = { 0 };
|
||||||
|
for (int i = 0; i < mac_addr.size() && x < 12; i++)
|
||||||
|
{
|
||||||
|
char c = mac_addr.at(i);
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
new_addr[x / 2] |= (c - '0') << ((x & 1) ? 0 : 4); x++;
|
||||||
|
} else if (c >= 'A' && c <= 'F') {
|
||||||
|
new_addr[x / 2] |= (c - 'A' + 10) << ((x & 1) ? 0 : 4); x++;
|
||||||
|
} else if (c >= 'a' && c <= 'f') {
|
||||||
|
new_addr[x / 2] |= (c - 'a' + 10) << ((x & 1) ? 0 : 4); x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x / 2 == 6)
|
||||||
|
memcpy(mac_address, new_addr, 6);
|
||||||
|
else
|
||||||
|
memcpy(mac_address, mac_address_default, 6);
|
||||||
|
|
||||||
|
ERROR_LOG(SP1, "BBA MAC %x%x%x%x%x%x",
|
||||||
|
mac_address[0], mac_address[1], mac_address[2],
|
||||||
|
mac_address[3], mac_address[4], mac_address[5]);
|
||||||
|
|
||||||
mWriteP = INVALID_P;
|
mWriteP = INVALID_P;
|
||||||
mReadP = INVALID_P;
|
mReadP = INVALID_P;
|
||||||
mWaiting = false;
|
mWaiting = false;
|
||||||
mReadyToSend = false;
|
mReadyToSend = false;
|
||||||
Activated = false;
|
Activated = false;
|
||||||
m_bInterruptSet = false;
|
m_bInterruptSet = false;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
mHAdapter = INVALID_HANDLE_VALUE;
|
mHAdapter = INVALID_HANDLE_VALUE;
|
||||||
mHRecvEvent = INVALID_HANDLE_VALUE;
|
mHRecvEvent = INVALID_HANDLE_VALUE;
|
||||||
|
@ -76,36 +70,32 @@ CEXIETHERNET::CEXIETHERNET() :
|
||||||
mRecvBufferLength = 0;
|
mRecvBufferLength = 0;
|
||||||
|
|
||||||
mExpectSpecialImmRead = false;
|
mExpectSpecialImmRead = false;
|
||||||
|
|
||||||
Expecting = EXPECT_NONE;
|
|
||||||
mExpectVariableLengthImmWrite = false;
|
mExpectVariableLengthImmWrite = false;
|
||||||
#ifdef FILEDEBUG
|
|
||||||
ME = fopen("Debug.txt", "wb");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CEXIETHERNET::~CEXIETHERNET()
|
CEXIETHERNET::~CEXIETHERNET()
|
||||||
{
|
{
|
||||||
#ifdef FILEDEBUG
|
/*/ crashy crashy
|
||||||
fclose(ME);
|
if (isActivated())
|
||||||
#endif
|
deactivate();
|
||||||
|
//*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::SetCS(int cs)
|
void CEXIETHERNET::SetCS(int cs)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Set CS: %s Expect Variable write?: %s", cs ? "true" : "false", mExpectVariableLengthImmWrite ? "true" : "false");
|
INFO_LOG(SP1, "chip select: %s%s", cs ? "true" : "false",
|
||||||
|
mExpectVariableLengthImmWrite ? ", expecting variable write" : "");
|
||||||
if (!cs)
|
if (!cs)
|
||||||
{
|
{
|
||||||
if (mExpectVariableLengthImmWrite)
|
if (mExpectVariableLengthImmWrite)
|
||||||
{
|
{
|
||||||
|
INFO_LOG(SP1, "Variable write complete. Final size: %i bytes",
|
||||||
|
mWriteBuffer.size());
|
||||||
mExpectVariableLengthImmWrite = false;
|
mExpectVariableLengthImmWrite = false;
|
||||||
mReadyToSend = true;
|
mReadyToSend = true;
|
||||||
}
|
}
|
||||||
mExpectSpecialImmRead = false;
|
mExpectSpecialImmRead = false;
|
||||||
mWriteP = mReadP = INVALID_P;
|
mWriteP = mReadP = INVALID_P;
|
||||||
m_bInterruptSet = false;
|
|
||||||
//mBbaMem[BBA_IR] = 0;
|
|
||||||
//mBbaMem[BBA_IRM] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,383 +111,307 @@ void CEXIETHERNET::Update()
|
||||||
|
|
||||||
bool CEXIETHERNET::IsInterruptSet()
|
bool CEXIETHERNET::IsInterruptSet()
|
||||||
{
|
{
|
||||||
//bool Temp = m_bInterruptSet;
|
|
||||||
//m_bInterruptSet = false;
|
|
||||||
//return Temp;
|
|
||||||
return m_bInterruptSet;
|
return m_bInterruptSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::recordSendComplete()
|
void CEXIETHERNET::recordSendComplete()
|
||||||
{
|
{
|
||||||
mBbaMem[BBA_NCRA] &= ~0x06;
|
mBbaMem[BBA_NCRA] &= ~(NCRA_ST0 | NCRA_ST1);
|
||||||
if (mBbaMem[BBA_IMR] & BBA_INTERRUPT_SENT)
|
if (mBbaMem[BBA_IMR] & INT_T)
|
||||||
{
|
{
|
||||||
mBbaMem[BBA_IR] |= BBA_INTERRUPT_SENT;
|
mBbaMem[BBA_IR] |= INT_T;
|
||||||
DEBUGPRINT("\t\tBBA Send interrupt raised");
|
INFO_LOG(SP1, "\t\tBBA Send interrupt raised");
|
||||||
//exit(0);
|
|
||||||
m_bInterruptSet = true;
|
m_bInterruptSet = true;
|
||||||
//interrupt.raiseEXI("BBA Send");
|
|
||||||
}
|
}
|
||||||
startRecv();
|
// TODO why did sonic put this here?
|
||||||
|
//startRecv();
|
||||||
mPacketsSent++;
|
mPacketsSent++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::checkRecvBuffer()
|
bool CEXIETHERNET::checkRecvBuffer()
|
||||||
{
|
{
|
||||||
if (mRecvBufferLength != 0)
|
if (mRecvBufferLength)
|
||||||
{
|
|
||||||
handleRecvdPacket();
|
handleRecvdPacket();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
|
void CEXIETHERNET::ImmWrite(u32 data, u32 size)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("IMM Write, size 0x%x, data32: 0x%08x data16: 0x%04x data8: 0x%02x mWriteP 0x%x", _uSize, _uData, (u16)Common::swap32(_uData >> 8), (u8)Common::swap32(_uData), mWriteP);
|
if (size == 1)
|
||||||
|
data = (u8)Common::swap32(data);
|
||||||
|
else if (size == 2)
|
||||||
|
data >>= 16;
|
||||||
|
|
||||||
|
INFO_LOG(SP1, "imm write %0*x writep 0x%x", size * 2, data, mWriteP);
|
||||||
|
|
||||||
if (mExpectVariableLengthImmWrite)
|
if (mExpectVariableLengthImmWrite)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("\t[INFO]Variable length IMM write");
|
INFO_LOG(SP1, "\tvariable length imm write");
|
||||||
if (_uSize == 4)
|
if (size == 4)
|
||||||
{
|
data = Common::swap32(data);
|
||||||
// Correct
|
else if (size == 2)
|
||||||
_uData = Common::swap32(_uData);
|
data = Common::swap16((u16)data);
|
||||||
}
|
mWriteBuffer.write(size, &data);
|
||||||
else if (_uSize == 2)
|
|
||||||
{
|
|
||||||
// Correct
|
|
||||||
_uData = (u16)Common::swap32(_uData);
|
|
||||||
}
|
|
||||||
mWriteBuffer.write(_uSize, &_uData);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (mWriteP != INVALID_P)
|
else if (mWriteP != INVALID_P)
|
||||||
{
|
{
|
||||||
if (mWriteP + _uSize > BBA_MEM_SIZE)
|
if (mWriteP + size > BBA_MEM_SIZE)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("[EEE]Write error: mWriteP + size = 0x%04X + %i", mWriteP, _uSize);
|
ERROR_LOG(SP1, "write error: writep + size = %04x + %i", mWriteP, size);
|
||||||
exit(0);
|
return;
|
||||||
}
|
}
|
||||||
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);
|
INFO_LOG(SP1, "\twrite to BBA address %0*x, %i byte%s: %0*x",
|
||||||
|
mWriteP >= CB_OFFSET ? 4 : 2, mWriteP, size, (size==1?"":"s"), size*2, data);
|
||||||
|
|
||||||
switch (mWriteP)
|
switch (mWriteP)
|
||||||
{
|
{
|
||||||
case BBA_IR:
|
|
||||||
{
|
|
||||||
// Correct, we use swapped
|
|
||||||
_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");
|
INFO_LOG(SP1, "\t\tNCRA");
|
||||||
// Correct, we use the swap here
|
|
||||||
u32 SwappedData = (u8)Common::swap32(_uData);
|
// TODO is it really necessary to check last value?
|
||||||
if (RISE(BBA_NCRA_RESET))
|
u8 NCRA_old = mBbaMem[BBA_NCRA];
|
||||||
|
mBbaMem[BBA_NCRA] = data;
|
||||||
|
#define RISE(flags) ((mBbaMem[BBA_NCRA] & flags) && !(NCRA_old & flags))
|
||||||
|
|
||||||
|
if (RISE(NCRA_RESET))
|
||||||
{
|
{
|
||||||
// Normal
|
INFO_LOG(SP1, "\t\treset");
|
||||||
// Whinecube did nothing else as well
|
activate();
|
||||||
DEBUGPRINT("\t\t[INFO]BBA Reset");
|
|
||||||
}
|
}
|
||||||
if (RISE(BBA_NCRA_SR) && isActivated())
|
if (RISE(NCRA_SR))
|
||||||
{
|
{
|
||||||
DEBUGPRINT("\t\t[INFO]BBA Start Receive");
|
INFO_LOG(SP1, "\t\tstart receive");
|
||||||
//exit(0);
|
|
||||||
startRecv();
|
startRecv();
|
||||||
}
|
}
|
||||||
if (RISE(BBA_NCRA_ST1))
|
if (RISE(NCRA_ST1))
|
||||||
{
|
{
|
||||||
DEBUGPRINT("\t\t[INFO]BBA Start Transmit");
|
INFO_LOG(SP1, "\t\tstart transmit");
|
||||||
if (!mReadyToSend)
|
if (!mReadyToSend)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("\t\t\t[EEE]Not ready to send!");
|
INFO_LOG(SP1, "\t\ttramsit without a packet!");
|
||||||
exit(0);
|
|
||||||
//throw hardware_fatal_exception("BBA Transmit without a packet!");
|
|
||||||
}
|
}
|
||||||
sendPacket(mWriteBuffer.p(), mWriteBuffer.size());
|
sendPacket(mWriteBuffer.p(), mWriteBuffer.size());
|
||||||
mReadyToSend = false;
|
mReadyToSend = false;
|
||||||
}
|
}
|
||||||
mBbaMem[BBA_NCRA] = MAKE(u8, SwappedData);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BBA_NWAYC:
|
case 0x03:
|
||||||
DEBUGPRINT("\t\t[INFO]BBA_NWAYC");
|
mBbaMem[0x03] = ~data;
|
||||||
if (Common::swap32(_uData) & (BBA_NWAYC_ANE | BBA_NWAYC_ANS_RA))
|
if (data & 0x80)
|
||||||
{
|
m_bInterruptSet = false;
|
||||||
//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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case BBA_RRP: //RRP - Receive Buffer Read Page Pointer
|
case BBA_IR:
|
||||||
DEBUGPRINT("\t\t[INFO]RRP");
|
_dbg_assert_(SP1, size == 1);
|
||||||
_dbg_assert_(SP1, _uSize == 2 || _uSize == 1);
|
INFO_LOG(SP1, "\t\tinterrupt reset %02x & ~(%02x) => %02x",
|
||||||
mRBRPP = (u8)Common::swap32(_uData) << 8; //Whinecube: I hope this works with both write sizes.
|
mBbaMem[BBA_IR], MAKE(u8, data), mBbaMem[BBA_IR] & ~MAKE(u8, data));
|
||||||
mRBEmpty = (mRBRPP == ((u32)mCbw.p_write() + CB_OFFSET));
|
mBbaMem[BBA_IR] &= ~MAKE(u8, data);
|
||||||
|
break;
|
||||||
|
case BBA_RWP: // RWP - Receive Buffer Write Page Pointer
|
||||||
|
INFO_LOG(SP1, "\t\tRWP");
|
||||||
|
_dbg_assert_(SP1, size == 2 || size == 1);
|
||||||
|
//_dbg_assert_(SP1, data == (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
|
||||||
|
if (data != (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "BBA RWP ASSERT data %x p_write %x", data, mCbw.p_write());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BBA_RRP: // RRP - Receive Buffer Read Page Pointer
|
||||||
|
INFO_LOG(SP1, "\t\tRRP");
|
||||||
|
_dbg_assert_(SP1, size == 2 || size == 1);
|
||||||
|
mRBRPP = (u8)data << 8; // Hope this works with both write sizes.
|
||||||
|
mRBEmpty = mRBRPP == ((u16)mCbw.p_write() + CB_OFFSET);
|
||||||
checkRecvBuffer();
|
checkRecvBuffer();
|
||||||
break;
|
break;
|
||||||
case BBA_RWP: //RWP - Receive Buffer Write Page Pointer
|
case BBA_NWAYC:
|
||||||
DEBUGPRINT("\t\t[INFO]RWP");
|
INFO_LOG(SP1, "\t\tNWAYC");
|
||||||
_dbg_assert_(SP1, _uSize == 2 || _uSize == 1);
|
mBbaMem[BBA_NWAYC] = data;
|
||||||
DEBUGPRINT("\t\t\tThing is 0x%0X", (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
|
if (mBbaMem[BBA_NWAYC] & (NWAYC_ANE | NWAYC_ANS_RA))
|
||||||
// TODO: This assert FAILS!
|
{
|
||||||
//assert(Common::swap32(_uData) == (u32)((u16)mCbw.p_write() + CB_OFFSET) >> 8);
|
// say we've successfully negotiated for 10 Mbit full duplex
|
||||||
|
// should placate libogc
|
||||||
|
mBbaMem[BBA_NWAYS] = NWAYS_LS100 | NWAYS_LPNWAY | NWAYS_ANCLPT | NWAYS_100TXF;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case BBA_NWAYS:
|
|
||||||
DEBUGPRINT("[ERR]Call to BBA_NWAYS directly!");
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
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);
|
INFO_LOG(SP1, "\t\tdefault: data: %0*x to %x", size * 2, data, mWriteP);
|
||||||
u32 SwappedData = 0;
|
memcpy(mBbaMem + mWriteP, &data, size);
|
||||||
if (_uSize == 4 || _uSize == 1)
|
mWriteP = mWriteP + (u16)size;
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
else if (_uSize == 2 && _uData == 0)
|
else if (size == 2 && data == 0)
|
||||||
{
|
{
|
||||||
// Device ID Request
|
INFO_LOG(SP1, "\trequest cid");
|
||||||
// 100% this returns correctly
|
|
||||||
DEBUGPRINT("\t[INFO]Request Dev ID");
|
|
||||||
mSpecialImmData = EXI_DEVTYPE_ETHER;
|
mSpecialImmData = EXI_DEVTYPE_ETHER;
|
||||||
mExpectSpecialImmRead = true;
|
mExpectSpecialImmRead = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ((_uSize == 4 && (_uData & 0xC0000000) == 0xC0000000) || (_uSize == 2 && ((u16)Common::swap32(_uData >> 8) & 0x4000) == 0x4000))
|
else if ((size == 4 && (data & 0xC0000000) == 0xC0000000) ||
|
||||||
|
(size == 2 && (data & 0x4000) == 0x4000))
|
||||||
{
|
{
|
||||||
// Write to BBA Register
|
INFO_LOG(SP1, "\twrite to register");
|
||||||
DEBUGPRINT("\t[INFO]Write to BBA register!");
|
if (size == 4)
|
||||||
if (_uSize == 4)
|
mWriteP = (u8)getbitsw(data, 16, 23);
|
||||||
{
|
|
||||||
// Dunno if this is correct TODO
|
|
||||||
u32 SwappedData = _uData;
|
|
||||||
mWriteP = (u8)getbitsw(SwappedData, 16, 23);
|
|
||||||
}
|
|
||||||
else //size == 2
|
else //size == 2
|
||||||
{
|
mWriteP = (u8)getbitsw(data & ~0x4000, 16, 23); // Dunno about this...
|
||||||
// Correct, Size of 1 untested, should be correct.
|
|
||||||
u16 SwappedData = (u16)Common::swap32(_uData >> 8);
|
if (mWriteP == BBA_WRTXFIFOD)
|
||||||
mWriteP = (u8)getbitsw(SwappedData & ~0x4000, 16, 23);
|
|
||||||
}
|
|
||||||
//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)
|
|
||||||
{
|
{
|
||||||
mWriteBuffer.clear();
|
mWriteBuffer.clear();
|
||||||
mExpectVariableLengthImmWrite = true;
|
mExpectVariableLengthImmWrite = true;
|
||||||
DEBUGPRINT("\t\t[INFO]Prepared for variable length write to address 0x48");
|
INFO_LOG(SP1, "\t\tprepared for variable length write to address 0x48");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUGPRINT("\t\t[INFO]BBA Write pointer set to 0x%0*X", _uSize, mWriteP);
|
INFO_LOG(SP1, "\t\twritep set to %0*x", size * 2, mWriteP);
|
||||||
//exit(0);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ((_uSize == 4 && (_uData & 0xC0000000) == 0x80000000) || (_uSize == 2 && ((u16)Common::swap32(_uData >> 8) & 0x4000) == 0x0000))
|
else if ((size == 4 && (data & 0xC0000000) == 0x80000000) ||
|
||||||
|
(size == 2 && (data & 0x4000) == 0x0000))
|
||||||
{
|
{
|
||||||
|
// Read from BBA Register
|
||||||
|
if (size == 4)
|
||||||
|
mReadP = (data >> 8) & 0xffff;
|
||||||
|
else //size == 2
|
||||||
|
mReadP = (u8)getbitsw(data, 16, 23);
|
||||||
|
|
||||||
|
INFO_LOG(SP1, "Read from BBA register 0x%x", mReadP);
|
||||||
|
|
||||||
u32 SwappedData = _uData;
|
|
||||||
// Read from BBA Register!
|
|
||||||
if(_uSize == 4)
|
|
||||||
{
|
|
||||||
// Correct
|
|
||||||
mReadP = (u16)getbitsw(SwappedData, 8, 23);
|
|
||||||
if (mReadP >= BBA_MEM_SIZE)
|
|
||||||
{
|
|
||||||
DEBUGPRINT("\t\t[EEE]Illegal BBA address: 0x%04X", mReadP);
|
|
||||||
//if(g::bouehr)
|
|
||||||
exit(0);
|
|
||||||
//return EXI_UNHANDLED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
case BBA_NCRA:
|
||||||
DEBUGPRINT("\t\t[INFO]Mac Address!");
|
|
||||||
memcpy(mBbaMem + mReadP, mac_address, 6);
|
|
||||||
break;
|
|
||||||
case 0x01: //Revision ID
|
|
||||||
break;
|
|
||||||
case 0x16: //RWP - Receive Buffer Write Page Pointer
|
|
||||||
DEBUGPRINT("\t\t[INFO]RWP! 0x%04x Swapped 0x%04x", (((u16)mCbw.p_write() + CB_OFFSET) >> 8), Common::swap16(((u16)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!");
|
|
||||||
//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!");
|
|
||||||
exit(0);
|
|
||||||
//mBbaMem[mReadP] = !mRBEmpty;
|
|
||||||
break;
|
|
||||||
case 0x00:
|
|
||||||
// These Two lines were commented out in Whinecube
|
// These Two lines were commented out in Whinecube
|
||||||
//mBbaMem[mReadP] = 0x00;
|
//mBbaMem[mReadP] = 0x00;
|
||||||
//if(!sendInProgress())
|
//if(!sendInProgress())
|
||||||
mBbaMem[mReadP] &= ~(0x06);
|
mBbaMem[BBA_NCRA] &= ~(NCRA_ST0 | NCRA_ST1);
|
||||||
//DEBUGPRINT("\t\t[INFO]mBbaMem[0x%x] &= ~(0x06);! Now 0x%x", mReadP, mBbaMem[mReadP]);
|
INFO_LOG(SP1, "\tNCRA %02x", mBbaMem[BBA_NCRA]);
|
||||||
//exit(0);
|
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case BBA_NCRB: // Revision ID
|
||||||
mBbaMem[mReadP] = 0x80;
|
INFO_LOG(SP1, "\tNCRB");
|
||||||
//DEBUGPRINT("\t\t[INFO]mBbaMem[0x%x] = 0x80;! Now %x", mReadP, mBbaMem[mReadP]);
|
|
||||||
//exit(0);
|
|
||||||
break;
|
break;
|
||||||
case 0x0e:
|
case BBA_NAFR_PAR0:
|
||||||
case 0x0f: // TWP - Transmit Buffer Write Page Pointer Register
|
INFO_LOG(SP1, "\tMac Address");
|
||||||
|
memcpy(mBbaMem + mReadP, mac_address, 6);
|
||||||
break;
|
break;
|
||||||
case 0x5b: // ??
|
case 0x03: // status TODO more fields
|
||||||
case 0x5c: // These two go together
|
mBbaMem[mReadP] = m_bInterruptSet ? 0x80 : 0;
|
||||||
|
INFO_LOG(SP1, "\tStatus", mBbaMem[mReadP]);
|
||||||
break;
|
break;
|
||||||
case 0x31: // NWAYS - NWAY Status Register
|
case BBA_LTPS:
|
||||||
// HACK
|
INFO_LOG(SP1, "\tLPTS");
|
||||||
activate();
|
break;
|
||||||
mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
|
case BBA_IMR:
|
||||||
case 0x09: // IR
|
INFO_LOG(SP1, "\tIMR");
|
||||||
case 0x08: // IRM
|
break;
|
||||||
case 0x100: // Input Queue?
|
case BBA_IR:
|
||||||
case 0x110: // ?? Not even in YAGCD
|
INFO_LOG(SP1, "\tIR");
|
||||||
case 0x04: // LTPS - Last Transmitted Packet Status (transmit error code ?)
|
break;
|
||||||
case 0x30: // NWAYC - NWAY Configuration Register
|
case BBA_RWP:
|
||||||
|
case BBA_RWP+1:
|
||||||
|
MAKE(u16, mBbaMem[BBA_RWP]) = Common::swap16((u16)mCbw.p_write() + CB_OFFSET);
|
||||||
|
INFO_LOG(SP1, "\tRWP 0x%04x", MAKE(u16, mBbaMem[mReadP]));
|
||||||
|
break;
|
||||||
|
case BBA_RRP:
|
||||||
|
case BBA_RRP+1:
|
||||||
|
MAKE(u16, mBbaMem[BBA_RRP]) = Common::swap16(mRBRPP);
|
||||||
|
INFO_LOG(SP1, "\tRRP 0x%04x", MAKE(u16, mBbaMem[mReadP]));
|
||||||
|
break;
|
||||||
|
case 0x3A: // bit 1 set if no data available
|
||||||
|
INFO_LOG(SP1, "\tBit 1 set!");
|
||||||
|
//mBbaMem[mReadP] = !mRBEmpty;
|
||||||
|
break;
|
||||||
|
case BBA_TWP:
|
||||||
|
case BBA_TWP+1:
|
||||||
|
INFO_LOG(SP1, "\tTWP");
|
||||||
|
break;
|
||||||
|
case BBA_NWAYC:
|
||||||
|
INFO_LOG(SP1, "\tNWAYC");
|
||||||
|
break;
|
||||||
|
case BBA_NWAYS:
|
||||||
|
mBbaMem[BBA_NWAYS] = NWAYS_LS100 | NWAYS_LPNWAY | NWAYS_ANCLPT | NWAYS_100TXF;
|
||||||
|
INFO_LOG(SP1, "\tNWAYS %02x", mBbaMem[BBA_NWAYS]);
|
||||||
|
break;
|
||||||
|
case BBA_SI_ACTRL:
|
||||||
|
INFO_LOG(SP1, "\tSI_ACTRL");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUGPRINT("Read from 0x%02x", mReadP);
|
ERROR_LOG(SP1, "UNKNOWN BBA REG READ %02x", mReadP);
|
||||||
//exit(0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//DEBUGPRINT("BBA Read pointer set to 0x%0*X, Data: 0x%08X", _uSize, mReadP, _uData);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DEBUGPRINT("\t[EEE]Not expecting ImmWrite of size %d", _uSize);
|
|
||||||
DEBUGPRINT("\t\t[INFO] SKIPPING!");
|
ERROR_LOG(SP1, "\tNot expecting imm write of size %d", size);
|
||||||
//exit(0);
|
ERROR_LOG(SP1, "\t\t SKIPPING!");
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CEXIETHERNET::ImmRead(u32 _uSize)
|
u32 CEXIETHERNET::ImmRead(u32 size)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("IMM Read, size 0x%x", _uSize);
|
INFO_LOG(SP1, "imm read %i readp %x", size, mReadP);
|
||||||
|
|
||||||
if (mExpectSpecialImmRead)
|
if (mExpectSpecialImmRead)
|
||||||
{
|
{
|
||||||
// 100% that this returns correctly
|
INFO_LOG(SP1, "\tspecial imm read %08x", mSpecialImmData);
|
||||||
DEBUGPRINT("\t[INFO]special IMMRead");
|
|
||||||
mExpectSpecialImmRead = false;
|
mExpectSpecialImmRead = false;
|
||||||
return mSpecialImmData;
|
return mSpecialImmData;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mReadP != INVALID_P)
|
if (mReadP != INVALID_P)
|
||||||
{
|
{
|
||||||
if (mReadP + _uSize > BBA_MEM_SIZE)
|
if (mReadP + size > BBA_MEM_SIZE)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("\t[EEE]Read error: mReadP + size = 0x%04X + %i", mReadP, _uSize);
|
ERROR_LOG(SP1, "\tRead error: readp + size = %04x + %i", mReadP, size);
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
u32 uResult = 0;
|
u32 uResult = 0;
|
||||||
memcpy(&uResult, mBbaMem + mReadP, _uSize);
|
memcpy(&uResult, mBbaMem + mReadP, size);
|
||||||
// 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);
|
uResult = Common::swap32(uResult);
|
||||||
/*#ifndef _WIN32
|
|
||||||
if(CheckRecieved())
|
INFO_LOG(SP1, "\tRead from BBA address %0*x, %i byte%s: %0*x",
|
||||||
startRecv();
|
mReadP >= CB_OFFSET ? 4 : 2, mReadP,
|
||||||
#endif*/
|
size, (size==1?"":"s"),size*2, getbitsw(uResult, 0, size * 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 + size;
|
||||||
mReadP = mReadP + _uSize;
|
|
||||||
return uResult;
|
return uResult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUGPRINT("\t[EEE]Unhandled IMM read of %d bytes", _uSize);
|
ERROR_LOG(SP1, "Unhandled imm read size %d", size);
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
DEBUGPRINT("[EEE]Not Expecting IMMRead of size %d!", _uSize);
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::DMAWrite(u32 _uAddr, u32 _uSize)
|
void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
if (mExpectVariableLengthImmWrite)
|
if (mExpectVariableLengthImmWrite)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("DMA Write: Address is 0x%x and size is 0x%x", _uAddr, _uSize);
|
INFO_LOG(SP1, "DMA Write: Address is 0x%x and size is 0x%x", addr, size);
|
||||||
mWriteBuffer.write(_uSize, Memory::GetPointer(_uAddr));
|
mWriteBuffer.write(size, Memory::GetPointer(addr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
ERROR_LOG(SP1, "Unhandled BBA DMA write: %i, %08x", size, addr);
|
||||||
DEBUGPRINT("Unhandled BBA DMA write: %i, 0x%08X", _uSize, _uAddr);
|
|
||||||
//if(g::bouehr)
|
|
||||||
exit(0);
|
|
||||||
//return EXI_UNHANDLED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::DMARead(u32 _uAddr, u32 _uSize)
|
void CEXIETHERNET::DMARead(u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
if (mReadP != INVALID_P)
|
if (mReadP != INVALID_P)
|
||||||
{
|
{
|
||||||
if (mReadP + _uSize > BBA_MEM_SIZE)
|
if (mReadP + size > BBA_MEM_SIZE)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Read error: mReadP + size = 0x%04X + %i", mReadP, _uSize);
|
INFO_LOG(SP1, "Read error: mReadP + size = %04x + %i", mReadP, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//mem.write_physical(address, size, mBbaMem + mReadP);
|
memcpy(Memory::GetPointer(addr), mBbaMem + mReadP, size);
|
||||||
memcpy(Memory::GetPointer(_uAddr), mBbaMem + mReadP, _uSize);
|
INFO_LOG(SP1, "DMA Read from BBA address %0*x, %i bytes to %08x",
|
||||||
DEBUGPRINT("DMA Read from BBA address 0x%0*X, %i bytes",
|
mReadP >= CB_OFFSET ? 4 : 2, mReadP, size, addr);
|
||||||
mReadP >= CB_OFFSET ? 4 : 2, mReadP, _uSize);
|
mReadP = mReadP + (u16)size;
|
||||||
//exit(0);
|
|
||||||
mReadP = mReadP + _uSize;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
ERROR_LOG(SP1, "Unhandled BBA DMA read: %i, %08x", size, addr);
|
||||||
DEBUGPRINT("Unhandled BBA DMA read: %i, 0x%08X", _uSize, _uAddr);
|
|
||||||
//if(g::bouehr)
|
|
||||||
exit(0);
|
|
||||||
//throw bouehr_exception("Unhandled BBA DMA read");
|
|
||||||
//return EXI_UNHANDLED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//#pragma optimize("",on)
|
|
@ -39,8 +39,6 @@ inline u32 getbitsw(u32 dword, int start, int end) {
|
||||||
return (dword & makemaskw(start, end)) >> (31 - end);
|
return (dword & makemaskw(start, end)) >> (31 - end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DEBUGPRINT(const char * format, ...);
|
|
||||||
|
|
||||||
class WriteBuffer
|
class WriteBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -56,7 +54,7 @@ public:
|
||||||
{
|
{
|
||||||
if (_size + s >= ucapacity)
|
if (_size + s >= ucapacity)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Write too large!");
|
INFO_LOG(SP1, "Write too large!");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +111,108 @@ private:
|
||||||
|
|
||||||
#define INVALID_P 0xFFFF
|
#define INVALID_P 0xFFFF
|
||||||
|
|
||||||
// TODO: convert into unions
|
// Network Control Register A, RW
|
||||||
|
enum NCRA
|
||||||
|
{
|
||||||
|
NCRA_RESET = 0x01, // RESET
|
||||||
|
NCRA_ST0 = 0x02, // Start transmit command/status
|
||||||
|
NCRA_ST1 = 0x04, // "
|
||||||
|
NCRA_SR = 0x08, // Start Receive
|
||||||
|
};
|
||||||
|
|
||||||
|
// Network Control Register B, RW
|
||||||
|
enum NCRB
|
||||||
|
{
|
||||||
|
NCRB_PR = 0x01, // Promiscuous Mode
|
||||||
|
NCRB_CA = 0x02, // Capture Effect Mode
|
||||||
|
NCRB_PM = 0x04, // Pass Multicast
|
||||||
|
NCRB_PB = 0x08, // Pass Bad Frame
|
||||||
|
NCRB_AB = 0x10, // Accept Broadcast
|
||||||
|
NCRB_HBD = 0x20, // reserved
|
||||||
|
NCRB_RXINTC = 0xC0, // Receive Interrupt Counter (mask)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interrupt Mask Register, RW, 00h
|
||||||
|
// Interrupt Register, RW, 00h
|
||||||
|
enum Interrupts
|
||||||
|
{
|
||||||
|
INT_FRAG = 0x01, // Fragment Counter
|
||||||
|
INT_R = 0x02, // Receive
|
||||||
|
INT_T = 0x04, // Transmit
|
||||||
|
INT_R_ERR = 0x08, // Receive Error
|
||||||
|
INT_T_ERR = 0x10, // Transmit Error
|
||||||
|
INT_FIFO_ERR = 0x20, // FIFO Error
|
||||||
|
INT_BUS_ERR = 0x40, // BUS Error
|
||||||
|
INT_RBF = 0x80, // RX Buffer Full
|
||||||
|
};
|
||||||
|
|
||||||
|
// NWAY Configuration Register, RW, 84h
|
||||||
|
enum NWAYC
|
||||||
|
{
|
||||||
|
NWAYC_FD = 0x01, // Full Duplex Mode
|
||||||
|
NWAYC_PS100 = 0x02, // Port Select 100/10
|
||||||
|
NWAYC_ANE = 0x03, // Autonegotiation Enable
|
||||||
|
NWAYC_ANS_RA = 0x04, // Restart Autonegotiation
|
||||||
|
NWAYC_LTE = 0x08, // Link Test Enable
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NWAYS
|
||||||
|
{
|
||||||
|
NWAYS_LS10 = 0x01,
|
||||||
|
NWAYS_LS100 = 0x02,
|
||||||
|
NWAYS_LPNWAY = 0x04,
|
||||||
|
NWAYS_ANCLPT = 0x08,
|
||||||
|
NWAYS_100TXF = 0x10,
|
||||||
|
NWAYS_100TXH = 0x20,
|
||||||
|
NWAYS_10TXF = 0x40,
|
||||||
|
NWAYS_10TXH = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BBA_NCRA = 0x00,
|
||||||
|
BBA_NCRB = 0x01,
|
||||||
|
|
||||||
|
BBA_LTPS = 0x04,
|
||||||
|
BBA_LRPS = 0x05,
|
||||||
|
|
||||||
|
BBA_IMR = 0x08,
|
||||||
|
BBA_IR = 0x09,
|
||||||
|
|
||||||
|
BBA_BP = 0x0a,
|
||||||
|
BBA_TLBP = 0x0c,
|
||||||
|
BBA_TWP = 0x0e,
|
||||||
|
BBA_TRP = 0x12,
|
||||||
|
BBA_RWP = 0x16,
|
||||||
|
BBA_RRP = 0x18,
|
||||||
|
BBA_RHBP = 0x1a,
|
||||||
|
|
||||||
|
BBA_RXINTT = 0x14,
|
||||||
|
|
||||||
|
BBA_NAFR_PAR0 = 0x20,
|
||||||
|
BBA_NAFR_PAR1 = 0x21,
|
||||||
|
BBA_NAFR_PAR2 = 0x22,
|
||||||
|
BBA_NAFR_PAR3 = 0x23,
|
||||||
|
BBA_NAFR_PAR4 = 0x24,
|
||||||
|
BBA_NAFR_PAR5 = 0x25,
|
||||||
|
|
||||||
|
BBA_NWAYC = 0x30,
|
||||||
|
BBA_NWAYS = 0x31,
|
||||||
|
|
||||||
|
BBA_GCA = 0x32,
|
||||||
|
|
||||||
|
BBA_MISC = 0x3d,
|
||||||
|
|
||||||
|
BBA_TXFIFOCNT = 0x3e,
|
||||||
|
BBA_WRTXFIFOD = 0x48,
|
||||||
|
|
||||||
|
BBA_MISC2 = 0x50,
|
||||||
|
|
||||||
|
BBA_SI_ACTRL = 0x5c,
|
||||||
|
BBA_SI_STATUS = 0x5d,
|
||||||
|
BBA_SI_ACTRL2 = 0x60,
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
BBA_RECV_SIZE = 0x800,
|
BBA_RECV_SIZE = 0x800,
|
||||||
|
@ -125,65 +224,6 @@ enum
|
||||||
SIZEOF_RECV_DESCRIPTOR = 4,
|
SIZEOF_RECV_DESCRIPTOR = 4,
|
||||||
|
|
||||||
EXI_DEVTYPE_ETHER = 0x04020200,
|
EXI_DEVTYPE_ETHER = 0x04020200,
|
||||||
|
|
||||||
BBA_NCRA = 0x00, // Network Control Register A, RW
|
|
||||||
BBA_NCRA_RESET = 0x01, // RESET
|
|
||||||
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
|
|
||||||
BBA_NCRB_PM = 0x04, // PM, Pass Multicast
|
|
||||||
BBA_NCRB_PB = 0x08, // PB, Pass Bad Frame
|
|
||||||
BBA_NCRB_AB = 0x10, // AB, Accept Broadcast
|
|
||||||
BBA_NCRB_HBD = 0x20, // HBD, reserved
|
|
||||||
BBA_NCRB_RXINTC0 = 0x40, // RXINTC, Receive Interrupt Counter
|
|
||||||
BBA_NCRB_RXINTC1 = 0x80, // "
|
|
||||||
BBA_NCRB_1_PACKET_PER_INT = 0x00, // 0 0
|
|
||||||
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
|
|
||||||
BBA_IR_FRAGI = 0x01, // FRAGI, Fragment Counter Interrupt
|
|
||||||
BBA_IR_RI = 0x02, // RI, Receive Interrupt
|
|
||||||
BBA_IR_TI = 0x04, // TI, Transmit Interrupt
|
|
||||||
BBA_IR_REI = 0x08, // REI, Receive Error Interrupt
|
|
||||||
BBA_IR_TEI = 0x10, // TEI, Transmit Error Interrupt
|
|
||||||
BBA_IR_FIFOEI = 0x20, // FIFOEI, FIFO Error Interrupt
|
|
||||||
BBA_IR_BUSEI = 0x40, // BUSEI, BUS Error Interrupt
|
|
||||||
BBA_IR_RBFI = 0x80, // RBFI, RX Buffer Full Interrupt
|
|
||||||
|
|
||||||
BBA_NWAYC = 0x30, // NWAY Configuration Register, RW, 84h
|
|
||||||
BBA_NWAYC_FD = 0x01, // FD, Full Duplex Mode
|
|
||||||
BBA_NWAYC_PS100 = 0x02, // PS100/10, Port Select 100/10
|
|
||||||
BBA_NWAYC_ANE = 0x04, // ANE, Autonegotiation Enable
|
|
||||||
BBA_NWAYC_ANS_RA = 0x08, // ANS, Restart Autonegotiation
|
|
||||||
BBA_NWAYC_LTE = 0x80, // LTE, Link Test Enable
|
|
||||||
|
|
||||||
BBA_NWAYS = 0x31,
|
|
||||||
BBA_NWAYS_LS10 = 0x01,
|
|
||||||
BBA_NWAYS_LS100 = 0x02,
|
|
||||||
BBA_NWAYS_LPNWAY = 0x04,
|
|
||||||
BBA_NWAYS_ANCLPT = 0x08,
|
|
||||||
BBA_NWAYS_100TXF = 0x10,
|
|
||||||
BBA_NWAYS_100TXH = 0x20,
|
|
||||||
BBA_NWAYS_10TXF = 0x40,
|
|
||||||
BBA_NWAYS_10TXH = 0x80,
|
|
||||||
|
|
||||||
BBA_INTERRUPT_RECV = 0x02,
|
|
||||||
BBA_INTERRUPT_SENT = 0x04,
|
|
||||||
BBA_INTERRUPT_RECV_ERROR = 0x08,
|
|
||||||
BBA_INTERRUPT_SEND_ERROR = 0x10,
|
|
||||||
|
|
||||||
BBA_RWP = 0x16, // Receive Buffer Write Page Pointer Register
|
|
||||||
BBA_RRP = 0x18, // Receive Buffer Read Page Pointer Register
|
|
||||||
|
|
||||||
BBA_SI_ACTRL2 = 0x60
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -192,19 +232,22 @@ enum
|
||||||
EXPECT_ID
|
EXPECT_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static u32 mPacketsSent = 0;
|
||||||
|
|
||||||
class CEXIETHERNET : public IEXIDevice
|
class CEXIETHERNET : public IEXIDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CEXIETHERNET();
|
CEXIETHERNET(const std::string& mac_addr);
|
||||||
~CEXIETHERNET();
|
~CEXIETHERNET();
|
||||||
|
void SetMAC(u8 *new_addr);
|
||||||
void SetCS(int _iCS);
|
void SetCS(int _iCS);
|
||||||
bool IsPresent();
|
bool IsPresent();
|
||||||
void Update();
|
void Update();
|
||||||
bool IsInterruptSet();
|
bool IsInterruptSet();
|
||||||
void ImmWrite(u32 _uData, u32 _uSize);
|
void ImmWrite(u32 data, u32 size);
|
||||||
u32 ImmRead(u32 _uSize);
|
u32 ImmRead(u32 size);
|
||||||
void DMAWrite(u32 _uAddr, u32 _uSize);
|
void DMAWrite(u32 addr, u32 size);
|
||||||
void DMARead(u32 _uAddr, u32 _uSize);
|
void DMARead(u32 addr, u32 size);
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
|
@ -212,7 +255,7 @@ public:
|
||||||
u32 m_uCommand;
|
u32 m_uCommand;
|
||||||
|
|
||||||
bool m_bInterruptSet;
|
bool m_bInterruptSet;
|
||||||
u32 mWriteP, mReadP;
|
u16 mWriteP, mReadP;
|
||||||
|
|
||||||
bool mExpectSpecialImmRead; //reset to false on deselect
|
bool mExpectSpecialImmRead; //reset to false on deselect
|
||||||
u32 mSpecialImmData;
|
u32 mSpecialImmData;
|
||||||
|
@ -251,6 +294,8 @@ public:
|
||||||
|
|
||||||
|
|
||||||
volatile bool mWaiting;
|
volatile bool mWaiting;
|
||||||
|
static const u8 mac_address_default[6];
|
||||||
|
u8 mac_address[6];
|
||||||
u8 mRecvBuffer[BBA_RECV_SIZE];
|
u8 mRecvBuffer[BBA_RECV_SIZE];
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE mHAdapter, mHRecvEvent, mHReadWait;
|
HANDLE mHAdapter, mHRecvEvent, mHReadWait;
|
||||||
|
|
Loading…
Reference in New Issue