diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index 3f203ceed3..984543d921 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -155,6 +155,7 @@ void SConfig::SaveSettings() ini.Set("Core", "SlotA", m_EXIDevice[0]); ini.Set("Core", "SlotB", m_EXIDevice[1]); ini.Set("Core", "SerialPort1", m_EXIDevice[2]); + ini.Set("Core", "BBA_MAC", m_bba_mac); char sidevicenum[16]; 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", "SlotB", (int*)&m_EXIDevice[1], 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", "TimeProfiling",&m_LocalCoreStartupParameter.bJITILTimeProfiling, false); ini.Get("Core", "OutputIR", &m_LocalCoreStartupParameter.bJITILOutputIR, false); diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index fee8b6a95e..f6353a1191 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -64,6 +64,7 @@ struct SConfig : NonCopyable std::string m_strMemoryCardB; TEXIDevices m_EXIDevice[3]; TSIDevices m_SIDevice[4]; + std::string m_bba_mac; // interface language INTERFACE_LANGUAGE m_InterfaceLanguage; diff --git a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp index 66f268248b..a6ab9dccfe 100644 --- a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp +++ b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp @@ -17,6 +17,7 @@ #include "StringUtil.h" #include "../Memmap.h" +//#pragma optimize("",off) // GROSS CODE ALERT: headers need to be included in the following order #include "TAP_Win32.h" #include "../EXI_Device.h" @@ -67,16 +68,19 @@ bool IsTAPDevice(const char *guid) else { 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)) { 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 (!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(netcard_key); @@ -93,20 +97,20 @@ bool IsTAPDevice(const char *guid) return false; } -bool GetGUID(char *name, int name_size) +bool GetGUIDs(std::vector& guids) { LONG status; HKEY control_net_key; DWORD len; int i = 0; - bool stop = false; + bool found_all = false; status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &control_net_key); if (status != ERROR_SUCCESS) return false; - while (!stop) + while (!found_all) { char enum_name[256]; char connection_string[256]; @@ -116,21 +120,25 @@ bool GetGUID(char *name, int name_size) const char name_string[] = "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) break; else if (status != ERROR_SUCCESS) 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) { 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) { @@ -140,8 +148,8 @@ bool GetGUID(char *name, int name_size) { if (IsTAPDevice(enum_name)) { - snprintf(name, name_size, "%s", enum_name); - stop = true; + guids.push_back(enum_name); + //found_all = true; } } @@ -152,24 +160,43 @@ bool GetGUID(char *name, int name_size) RegCloseKey(control_net_key); - if (!stop) - return false; + //if (!found_all) + //return false; 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 bool CEXIETHERNET::deactivate() { - DEBUGPRINT("Deactivating BBA..."); + INFO_LOG(SP1, "Deactivating BBA..."); if (!isActivated()) return true; CloseHandle(mHRecvEvent); mHRecvEvent = INVALID_HANDLE_VALUE; CloseHandle(mHAdapter); mHAdapter = INVALID_HANDLE_VALUE; - DEBUGPRINT("Success!"); + INFO_LOG(SP1, "Success!"); return true; } @@ -183,89 +210,80 @@ bool CEXIETHERNET::activate() if (isActivated()) return true; - DEBUGPRINT("Activating BBA..."); + INFO_LOG(SP1, "Activating BBA..."); DWORD len; - char device_path[256]; - char device_guid[0x100]; + std::vector device_guids; - 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; } - /* Open Windows TAP-Win32 adapter */ - snprintf(device_path, sizeof(device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid, TAPSUFFIX); - - mHAdapter = CreateFile ( - device_path, - GENERIC_READ | GENERIC_WRITE, - 0, - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, - 0 ); - + for (int i = 0; i < device_guids.size(); i++) + { + if (Win32TAPHelper::OpenTAP(mHAdapter, device_guids.at(i))) + { + ERROR_LOG(SP1, "OPENED %s", device_guids.at(i).c_str()); + i = device_guids.size(); + } + } if (mHAdapter == INVALID_HANDLE_VALUE) { - DEBUGPRINT("Failed to open TAP at %s", device_path); + INFO_LOG(SP1, "Failed to open any TAP"); return false; } /* 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]; - if (DeviceIoControl (mHAdapter, TAP_IOCTL_GET_VERSION, - &info, sizeof (info), &info, sizeof (info), &len, NULL)) - { - DEBUGPRINT("TAP-Win32 Driver Version %d.%d %s", - info[0], info[1], (info[2] ? "(DEBUG)" : "")); - } - if ( !(info[0] > TAP_WIN32_MIN_MAJOR - || (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) ) - { - 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); - return false; - } + INFO_LOG(SP1, "TAP-Win32 Driver Version %d.%d %s", + info[0], info[1], (info[2] ? "(DEBUG)" : "")); + } + if ( !(info[0] > TAP_WIN32_MIN_MAJOR + || (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) ) + { + PanicAlert("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); + return false; } /* 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, - &mMtu, sizeof (mMtu), &mMtu, sizeof (mMtu), &len, NULL)) - { - DEBUGPRINT("Couldn't get device MTU"); - return false; - } - DEBUGPRINT("TAP-Win32 MTU=%d (ignored)", mMtu); + INFO_LOG(SP1, "Couldn't get device MTU"); + return false; } + INFO_LOG(SP1, "TAP-Win32 MTU=%d (ignored)", mMtu); /* 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; - if (!DeviceIoControl (mHAdapter, TAP_IOCTL_SET_MEDIA_STATUS, - &status, sizeof (status), &status, sizeof (status), &len, NULL)) - { - DEBUGPRINT("WARNING: The TAP-Win32 driver rejected a TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call."); - return false; - } - else - { - DEBUGPRINT("TAP-WIN32 status as Connected"); - } + INFO_LOG(SP1, "WARNING: The TAP-Win32 driver rejected a" + "TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call."); + return false; } //set up recv event - mHRecvEvent = CreateEvent(NULL, false, false, NULL); - memset((void*)&mReadOverlapped, 0 , sizeof(mReadOverlapped)); + if ((mHRecvEvent = CreateEvent(NULL, false, false, NULL)) == NULL) + { + INFO_LOG(SP1, "Failed to create recv event:%x", GetLastError()); + return false; + } + ZeroMemory(&mReadOverlapped, sizeof(mReadOverlapped)); resume(); - DEBUGPRINT("Success!"); + INFO_LOG(SP1, "Success!"); return true; - //TODO: Activate Device! } bool CEXIETHERNET::CheckRecieved() @@ -273,40 +291,65 @@ bool CEXIETHERNET::CheckRecieved() if (!isActivated()) return false; - // I have no idea o_O 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) { - if (!isActivated()) - activate(); - - DEBUGPRINT("Packet (%i): %s", size, ArrayToString(etherpckt, size).c_str()); + fixup_ip_checksum((u16*)etherpckt + 7, 20); + INFO_LOG(SP1, "Packet (%zu):\n%s", size, ArrayToString(etherpckt, size, 0, 16).c_str()); DWORD numBytesWrit; OVERLAPPED overlap; - memset((void*)&overlap, 0, sizeof(overlap)); - //ZERO_OBJECT(overlap); + ZeroMemory(&overlap, sizeof(overlap)); //overlap.hEvent = mHRecvEvent; if (!WriteFile(mHAdapter, etherpckt, size, &numBytesWrit, &overlap)) { // Fail Boat 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) { - 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; } recordSendComplete(); - //exit(0); return true; } 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 u32 available_bytes_in_cb; if (rbwpp < mRBRPP) @@ -316,9 +359,8 @@ bool CEXIETHERNET::handleRecvdPacket() else //rbwpp > mRBRPP available_bytes_in_cb = CB_SIZE - rbwpp + (mRBRPP - CB_OFFSET); - //DUMPWORD(rbwpp); - //DUMPWORD(mRBRPP); - //DUMPWORD(available_bytes_in_cb); + INFO_LOG(SP1, "rbwpp %i mRBRPP %04x available_bytes_in_cb %i", + rbwpp, mRBRPP, available_bytes_in_cb); _dbg_assert_(SP1, available_bytes_in_cb <= CB_SIZE); if (available_bytes_in_cb != CB_SIZE)//< mRecvBufferLength + SIZEOF_RECV_DESCRIPTOR) @@ -327,23 +369,24 @@ bool CEXIETHERNET::handleRecvdPacket() mCbw.write(mRecvBuffer, mRecvBufferLength); mCbw.align(); rbwpp = (int)(mCbw.p_write() + CB_OFFSET); - //DUMPWORD(rbwpp); + + INFO_LOG(SP1, "rbwpp %i", rbwpp); - //mPacketsRcvd++; + mPacketsRecvd++; 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; - DEBUGPRINT("BBA Recv interrupt raised"); - //interrupt.raiseEXI("BBA Recv"); + mBbaMem[BBA_IR] |= INT_R; + INFO_LOG(SP1, "BBA Recv interrupt raised"); m_bInterruptSet = true; } } - if (mBbaMem[BBA_NCRA] & BBA_NCRA_SR) +wait_for_next: + if (mBbaMem[BBA_NCRA] & NCRA_SR) startRecv(); return true; @@ -351,10 +394,10 @@ bool CEXIETHERNET::handleRecvdPacket() bool CEXIETHERNET::resume() { - if(!isActivated()) + if (!isActivated()) return true; - DEBUGPRINT("BBA resume"); + INFO_LOG(SP1, "BBA resume"); //mStop = false; RegisterWaitForSingleObject(&mHReadWait, mHRecvEvent, ReadWaitCallback, @@ -362,10 +405,10 @@ bool CEXIETHERNET::resume() mReadOverlapped.hEvent = mHRecvEvent; - if (mBbaMem[BBA_NCRA] & BBA_NCRA_SR) + if (mBbaMem[BBA_NCRA] & NCRA_SR) startRecv(); - DEBUGPRINT("BBA resume complete"); + INFO_LOG(SP1, "BBA resume complete"); return true; } @@ -374,11 +417,11 @@ bool CEXIETHERNET::startRecv() if (!isActivated()) return false;// Should actually be an assert - DEBUGPRINT("startRecv... "); + INFO_LOG(SP1, "startRecv... "); if (mWaiting) { - DEBUGPRINT("already waiting"); + INFO_LOG(SP1, "already waiting"); return true; } @@ -388,7 +431,7 @@ bool CEXIETHERNET::startRecv() if (res) { // Operation completed immediately - DEBUGPRINT("completed, res %i", res); + INFO_LOG(SP1, "completed, res %i", res); mWaiting = true; } else @@ -397,7 +440,7 @@ bool CEXIETHERNET::startRecv() if (res == ERROR_IO_PENDING) { //'s ok :) - DEBUGPRINT("pending"); + INFO_LOG(SP1, "pending"); // WaitCallback will be called mWaiting = true; } @@ -415,19 +458,15 @@ VOID CALLBACK CEXIETHERNET::ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFir { static int sNumber = 0; int cNumber = sNumber++; - DEBUGPRINT("WaitCallback %i", cNumber); - - if (TimerFired) - return; - + INFO_LOG(SP1, "WaitCallback %i", cNumber); + __assume(!TimerFired); CEXIETHERNET* self = (CEXIETHERNET*)lpParameter; - if(self->mHAdapter == INVALID_HANDLE_VALUE) - return; + __assume(self->mHAdapter != INVALID_HANDLE_VALUE); GetOverlappedResult(self->mHAdapter, &self->mReadOverlapped, &self->mRecvBufferLength, false); self->mWaiting = false; self->handleRecvdPacket(); - DEBUGPRINT("WaitCallback %i done", cNumber); + INFO_LOG(SP1, "WaitCallback %i done", cNumber); } union bba_descr @@ -440,7 +479,7 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size) { if (size < SIZEOF_ETH_HEADER) { - DEBUGPRINT("Packet too small: %i bytes", size); + INFO_LOG(SP1, "Packet too small: %i bytes", size); return false; } @@ -451,12 +490,12 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size) //since neither tmbinc, riptool.dol, or libogc does... 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; } if (size >= CB_SIZE) { - DEBUGPRINT("Packet too big: %i bytes", size); + INFO_LOG(SP1, "Packet too big: %i bytes", size); return false; } @@ -482,7 +521,7 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 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", + 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.packet_len, descr.status); @@ -490,3 +529,4 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size) return true; } +//#pragma optimize("",on) \ No newline at end of file diff --git a/Source/Core/Core/Src/HW/EXI_Channel.cpp b/Source/Core/Core/Src/HW/EXI_Channel.cpp index c73ed0b275..2af1ae1e88 100644 --- a/Source/Core/Core/Src/HW/EXI_Channel.cpp +++ b/Source/Core/Core/Src/HW/EXI_Channel.cpp @@ -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_WRITE: pDevice->ImmWrite(m_ImmData, m_Control.TLEN + 1); break; case EXI_READWRITE: + ERROR_LOG(SP1, "RW UNSUPPORTED"); /* Only used by USBGecko? pDevice->ImmWrite(m_ImmData, m_Control.TLEN + 1); m_ImmData = pDevice->ImmRead(m_Control.TLEN + 1); */ diff --git a/Source/Core/Core/Src/HW/EXI_Device.cpp b/Source/Core/Core/Src/HW/EXI_Device.cpp index 83a766ad93..ed7f560677 100644 --- a/Source/Core/Core/Src/HW/EXI_Device.cpp +++ b/Source/Core/Core/Src/HW/EXI_Device.cpp @@ -130,7 +130,7 @@ IEXIDevice* EXIDevice_Create(TEXIDevices _EXIDevice) break; case EXIDEVICE_ETH: - return new CEXIETHERNET(); + return new CEXIETHERNET(SConfig::GetInstance().m_bba_mac); break; case EXIDEVICE_AM_BASEBOARD: diff --git a/Source/Core/Core/Src/HW/EXI_DeviceEthernet.cpp b/Source/Core/Core/Src/HW/EXI_DeviceEthernet.cpp index 7c4b4ab717..cd2a790101 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceEthernet.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceEthernet.cpp @@ -16,57 +16,51 @@ // http://code.google.com/p/dolphin-emu/ #include "Memmap.h" - +//#pragma optimize("",off) #include "EXI_Device.h" #include "EXI_DeviceEthernet.h" -#include - -//#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 RISE(flags) ((SwappedData & (flags)) && !(mBbaMem[0x00] & (flags))) +const u8 CEXIETHERNET::mac_address_default[6] = { 0x00, 0x09, 0xbf, 0x01, 0x00, 0xc1 }; -static u32 mPacketsSent = 0; -static u8 mac_address[6] = {0x00, 0x09, 0xbf, 0x01, 0x00, 0xc1}; // (shuffle2) from my bba -static u32 Expecting; - -CEXIETHERNET::CEXIETHERNET() : +CEXIETHERNET::CEXIETHERNET(const std::string& mac_addr) : m_uPosition(0), m_uCommand(0), mWriteBuffer(2048), mCbw(mBbaMem + CB_OFFSET, CB_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; mReadP = INVALID_P; mWaiting = false; mReadyToSend = false; Activated = false; m_bInterruptSet = false; + #ifdef _WIN32 mHAdapter = INVALID_HANDLE_VALUE; mHRecvEvent = INVALID_HANDLE_VALUE; @@ -76,36 +70,32 @@ CEXIETHERNET::CEXIETHERNET() : mRecvBufferLength = 0; mExpectSpecialImmRead = false; - - Expecting = EXPECT_NONE; mExpectVariableLengthImmWrite = false; -#ifdef FILEDEBUG - ME = fopen("Debug.txt", "wb"); -#endif } CEXIETHERNET::~CEXIETHERNET() { -#ifdef FILEDEBUG - fclose(ME); -#endif + /*/ crashy crashy + if (isActivated()) + deactivate(); + //*/ } 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 (mExpectVariableLengthImmWrite) { + INFO_LOG(SP1, "Variable write complete. Final size: %i bytes", + mWriteBuffer.size()); mExpectVariableLengthImmWrite = false; mReadyToSend = true; } mExpectSpecialImmRead = false; 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 Temp = m_bInterruptSet; - //m_bInterruptSet = false; - //return Temp; return m_bInterruptSet; } void CEXIETHERNET::recordSendComplete() { - mBbaMem[BBA_NCRA] &= ~0x06; - if (mBbaMem[BBA_IMR] & BBA_INTERRUPT_SENT) + mBbaMem[BBA_NCRA] &= ~(NCRA_ST0 | NCRA_ST1); + if (mBbaMem[BBA_IMR] & INT_T) { - mBbaMem[BBA_IR] |= BBA_INTERRUPT_SENT; - DEBUGPRINT("\t\tBBA Send interrupt raised"); - //exit(0); + mBbaMem[BBA_IR] |= INT_T; + INFO_LOG(SP1, "\t\tBBA Send interrupt raised"); m_bInterruptSet = true; - //interrupt.raiseEXI("BBA Send"); } - startRecv(); + // TODO why did sonic put this here? + //startRecv(); mPacketsSent++; } bool CEXIETHERNET::checkRecvBuffer() { - if (mRecvBufferLength != 0) - { + if (mRecvBufferLength) handleRecvdPacket(); - } 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) { - DEBUGPRINT("\t[INFO]Variable length IMM write"); - if (_uSize == 4) - { - // Correct - _uData = Common::swap32(_uData); - } - else if (_uSize == 2) - { - // Correct - _uData = (u16)Common::swap32(_uData); - } - mWriteBuffer.write(_uSize, &_uData); + INFO_LOG(SP1, "\tvariable length imm write"); + if (size == 4) + data = Common::swap32(data); + else if (size == 2) + data = Common::swap16((u16)data); + mWriteBuffer.write(size, &data); return; } 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); - exit(0); + ERROR_LOG(SP1, "write error: writep + size = %04x + %i", mWriteP, size); + 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) { - 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: { - DEBUGPRINT("\t\t[INFO]BBA_NCRA"); - // Correct, we use the swap here - u32 SwappedData = (u8)Common::swap32(_uData); - if (RISE(BBA_NCRA_RESET)) + INFO_LOG(SP1, "\t\tNCRA"); + + // TODO is it really necessary to check last value? + 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 - // Whinecube did nothing else as well - DEBUGPRINT("\t\t[INFO]BBA Reset"); + INFO_LOG(SP1, "\t\treset"); + activate(); } - if (RISE(BBA_NCRA_SR) && isActivated()) + if (RISE(NCRA_SR)) { - DEBUGPRINT("\t\t[INFO]BBA Start Receive"); - //exit(0); + INFO_LOG(SP1, "\t\tstart receive"); 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) { - DEBUGPRINT("\t\t\t[EEE]Not ready to send!"); - exit(0); - //throw hardware_fatal_exception("BBA Transmit without a packet!"); + INFO_LOG(SP1, "\t\ttramsit without a packet!"); } sendPacket(mWriteBuffer.p(), mWriteBuffer.size()); mReadyToSend = false; } - 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)) - { - //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); - } - } - + case 0x03: + mBbaMem[0x03] = ~data; + if (data & 0x80) + m_bInterruptSet = false; 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)); + case BBA_IR: + _dbg_assert_(SP1, size == 1); + INFO_LOG(SP1, "\t\tinterrupt reset %02x & ~(%02x) => %02x", + mBbaMem[BBA_IR], MAKE(u8, data), mBbaMem[BBA_IR] & ~MAKE(u8, data)); + 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(); 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); + case BBA_NWAYC: + INFO_LOG(SP1, "\t\tNWAYC"); + mBbaMem[BBA_NWAYC] = data; + if (mBbaMem[BBA_NWAYC] & (NWAYC_ANE | NWAYC_ANS_RA)) + { + // 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; - 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) - { - 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; + INFO_LOG(SP1, "\t\tdefault: data: %0*x to %x", size * 2, data, mWriteP); + memcpy(mBbaMem + mWriteP, &data, size); + mWriteP = mWriteP + (u16)size; } return; } - else if (_uSize == 2 && _uData == 0) + else if (size == 2 && data == 0) { - // Device ID Request - // 100% this returns correctly - DEBUGPRINT("\t[INFO]Request Dev ID"); + INFO_LOG(SP1, "\trequest cid"); mSpecialImmData = EXI_DEVTYPE_ETHER; mExpectSpecialImmRead = true; 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 - DEBUGPRINT("\t[INFO]Write to BBA register!"); - if (_uSize == 4) - { - // Dunno if this is correct TODO - u32 SwappedData = _uData; - mWriteP = (u8)getbitsw(SwappedData, 16, 23); - } + INFO_LOG(SP1, "\twrite to register"); + if (size == 4) + mWriteP = (u8)getbitsw(data, 16, 23); else //size == 2 - { - // Correct, Size of 1 untested, should be correct. - u16 SwappedData = (u16)Common::swap32(_uData >> 8); - 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) + mWriteP = (u8)getbitsw(data & ~0x4000, 16, 23); // Dunno about this... + + if (mWriteP == BBA_WRTXFIFOD) { mWriteBuffer.clear(); 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 { - DEBUGPRINT("\t\t[INFO]BBA Write pointer set to 0x%0*X", _uSize, mWriteP); - //exit(0); + INFO_LOG(SP1, "\t\twritep set to %0*x", size * 2, mWriteP); } 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) { - case 0x20: //MAC address - 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: + case BBA_NCRA: // These Two lines were commented out in Whinecube //mBbaMem[mReadP] = 0x00; //if(!sendInProgress()) - mBbaMem[mReadP] &= ~(0x06); - //DEBUGPRINT("\t\t[INFO]mBbaMem[0x%x] &= ~(0x06);! Now 0x%x", mReadP, mBbaMem[mReadP]); - //exit(0); + mBbaMem[BBA_NCRA] &= ~(NCRA_ST0 | NCRA_ST1); + INFO_LOG(SP1, "\tNCRA %02x", mBbaMem[BBA_NCRA]); break; - case 0x03: - mBbaMem[mReadP] = 0x80; - //DEBUGPRINT("\t\t[INFO]mBbaMem[0x%x] = 0x80;! Now %x", mReadP, mBbaMem[mReadP]); - //exit(0); + case BBA_NCRB: // Revision ID + INFO_LOG(SP1, "\tNCRB"); break; - case 0x0e: - case 0x0f: // TWP - Transmit Buffer Write Page Pointer Register + case BBA_NAFR_PAR0: + INFO_LOG(SP1, "\tMac Address"); + memcpy(mBbaMem + mReadP, mac_address, 6); break; - case 0x5b: // ?? - case 0x5c: // These two go together + case 0x03: // status TODO more fields + mBbaMem[mReadP] = m_bInterruptSet ? 0x80 : 0; + INFO_LOG(SP1, "\tStatus", mBbaMem[mReadP]); break; - case 0x31: // NWAYS - NWAY Status Register - // HACK - activate(); - mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF); - case 0x09: // IR - case 0x08: // IRM - case 0x100: // Input Queue? - case 0x110: // ?? Not even in YAGCD - case 0x04: // LTPS - Last Transmitted Packet Status (transmit error code ?) - case 0x30: // NWAYC - NWAY Configuration Register + case BBA_LTPS: + INFO_LOG(SP1, "\tLPTS"); + break; + case BBA_IMR: + INFO_LOG(SP1, "\tIMR"); + break; + case BBA_IR: + INFO_LOG(SP1, "\tIR"); + break; + 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; default: - DEBUGPRINT("Read from 0x%02x", mReadP); - //exit(0); + ERROR_LOG(SP1, "UNKNOWN BBA REG READ %02x", mReadP); break; } - //DEBUGPRINT("BBA Read pointer set to 0x%0*X, Data: 0x%08X", _uSize, mReadP, _uData); return; } - DEBUGPRINT("\t[EEE]Not expecting ImmWrite of size %d", _uSize); - DEBUGPRINT("\t\t[INFO] SKIPPING!"); - //exit(0); + + ERROR_LOG(SP1, "\tNot expecting imm write of size %d", size); + 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) { - // 100% that this returns correctly - DEBUGPRINT("\t[INFO]special IMMRead"); + INFO_LOG(SP1, "\tspecial imm read %08x", mSpecialImmData); mExpectSpecialImmRead = false; return mSpecialImmData; } + 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); - exit(0); + ERROR_LOG(SP1, "\tRead error: readp + size = %04x + %i", mReadP, size); + return 0; } u32 uResult = 0; - memcpy(&uResult, mBbaMem + mReadP, _uSize); - // TODO: We do as well? - uResult = Common::swap32(uResult); //Whinecube : we have a byteswap problem... + memcpy(&uResult, mBbaMem + mReadP, size); - //DEBUGPRINT("Mem spot is 0x%02x uResult is 0x%x", mBbaMem[mReadP], uResult); - /*#ifndef _WIN32 - if(CheckRecieved()) - 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; + uResult = Common::swap32(uResult); + + INFO_LOG(SP1, "\tRead from BBA address %0*x, %i byte%s: %0*x", + mReadP >= CB_OFFSET ? 4 : 2, mReadP, + size, (size==1?"":"s"),size*2, getbitsw(uResult, 0, size * 8 - 1)); + mReadP = mReadP + size; return uResult; } else { - DEBUGPRINT("\t[EEE]Unhandled IMM read of %d bytes", _uSize); - exit(0); + ERROR_LOG(SP1, "Unhandled imm read size %d", size); + 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) { - DEBUGPRINT("DMA Write: Address is 0x%x and size is 0x%x", _uAddr, _uSize); - mWriteBuffer.write(_uSize, Memory::GetPointer(_uAddr)); + INFO_LOG(SP1, "DMA Write: Address is 0x%x and size is 0x%x", addr, size); + mWriteBuffer.write(size, Memory::GetPointer(addr)); return; } - else - { - DEBUGPRINT("Unhandled BBA DMA write: %i, 0x%08X", _uSize, _uAddr); - //if(g::bouehr) - exit(0); - //return EXI_UNHANDLED; - } + + ERROR_LOG(SP1, "Unhandled BBA DMA write: %i, %08x", size, addr); } -void CEXIETHERNET::DMARead(u32 _uAddr, u32 _uSize) +void CEXIETHERNET::DMARead(u32 addr, u32 size) { 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; } - //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", - mReadP >= CB_OFFSET ? 4 : 2, mReadP, _uSize); - //exit(0); - mReadP = mReadP + _uSize; + memcpy(Memory::GetPointer(addr), mBbaMem + mReadP, size); + INFO_LOG(SP1, "DMA Read from BBA address %0*x, %i bytes to %08x", + mReadP >= CB_OFFSET ? 4 : 2, mReadP, size, addr); + mReadP = mReadP + (u16)size; return; } - else - { - 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; - } + + ERROR_LOG(SP1, "Unhandled BBA DMA read: %i, %08x", size, addr); } +//#pragma optimize("",on) \ No newline at end of file diff --git a/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h b/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h index ff19a18905..a9f352c8b1 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h +++ b/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h @@ -39,8 +39,6 @@ inline u32 getbitsw(u32 dword, int start, int end) { return (dword & makemaskw(start, end)) >> (31 - end); } -void DEBUGPRINT(const char * format, ...); - class WriteBuffer { public: @@ -56,7 +54,7 @@ public: { if (_size + s >= ucapacity) { - DEBUGPRINT("Write too large!"); + INFO_LOG(SP1, "Write too large!"); exit(0); } @@ -113,7 +111,108 @@ private: #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 { BBA_RECV_SIZE = 0x800, @@ -125,65 +224,6 @@ enum SIZEOF_RECV_DESCRIPTOR = 4, 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 @@ -192,19 +232,22 @@ enum EXPECT_ID }; +static u32 mPacketsSent = 0; + class CEXIETHERNET : public IEXIDevice { public: - CEXIETHERNET(); + CEXIETHERNET(const std::string& mac_addr); ~CEXIETHERNET(); + void SetMAC(u8 *new_addr); 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); + void ImmWrite(u32 data, u32 size); + u32 ImmRead(u32 size); + void DMAWrite(u32 addr, u32 size); + void DMARead(u32 addr, u32 size); //private: // STATE_TO_SAVE @@ -212,7 +255,7 @@ public: u32 m_uCommand; bool m_bInterruptSet; - u32 mWriteP, mReadP; + u16 mWriteP, mReadP; bool mExpectSpecialImmRead; //reset to false on deselect u32 mSpecialImmData; @@ -251,6 +294,8 @@ public: volatile bool mWaiting; + static const u8 mac_address_default[6]; + u8 mac_address[6]; u8 mRecvBuffer[BBA_RECV_SIZE]; #ifdef _WIN32 HANDLE mHAdapter, mHRecvEvent, mHReadWait;