bba: generate MAC if needed

This commit is contained in:
sktsqrl 2012-07-07 13:44:26 -07:00
parent dd48b246b2
commit a02cbedb0f
3 changed files with 79 additions and 22 deletions

View File

@ -129,7 +129,7 @@ IEXIDevice* EXIDevice_Create(TEXIDevices device_type, const int channel_num)
break; break;
case EXIDEVICE_ETH: case EXIDEVICE_ETH:
result = new CEXIETHERNET(SConfig::GetInstance().m_bba_mac); result = new CEXIETHERNET();
break; break;
case EXIDEVICE_AM_BASEBOARD: case EXIDEVICE_AM_BASEBOARD:

View File

@ -19,12 +19,51 @@
#include "EXI_Device.h" #include "EXI_Device.h"
#include "EXI_DeviceEthernet.h" #include "EXI_DeviceEthernet.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "../ConfigManager.h"
// XXX: The BBA stores multi-byte elements as little endian. // XXX: The BBA stores multi-byte elements as little endian.
// Multiple parts of this implementation depend on dolphin // Multiple parts of this implementation depend on dolphin
// being compiled for a little endian host. // being compiled for a little endian host.
CEXIETHERNET::CEXIETHERNET(const std::string& mac_addr)
// TODO move this code into Common or something, for IOS to use
enum MACConsumer
{
BBA,
IOS
};
void GenerateMAC(MACConsumer type, u8 (&mac)[6])
{
memset(mac, 0, 6);
u8 const oui_bba[] = { 0x00, 0x09, 0xbf };
u8 const oui_ios[] = { 0x00, 0x17, 0xab };
switch (type)
{
case BBA:
memcpy(mac, oui_bba, 3);
break;
case IOS:
memcpy(mac, oui_ios, 3);
break;
}
srand((unsigned int)time(nullptr));
u8 id[3] =
{
rand() & 0xff,
rand() & 0xff,
rand() & 0xff
};
memcpy(&mac[3], id, 3);
}
CEXIETHERNET::CEXIETHERNET()
{ {
tx_fifo = new u8[1518]; tx_fifo = new u8[1518];
mBbaMem = new u8[BBA_MEM_SIZE]; mBbaMem = new u8[BBA_MEM_SIZE];
@ -33,28 +72,46 @@ CEXIETHERNET::CEXIETHERNET(const std::string& mac_addr)
mRecvBufferLength = 0; mRecvBufferLength = 0;
MXHardReset(); MXHardReset();
const u8 mac_address_default[6] = // Parse MAC address from config, and generate a new one if it doesn't
{ 0x00, 0x09, 0xbf, 0x01, 0x00, 0xc1 }; // exist or can't be parsed.
int x = 0; auto &mac_addr_setting = SConfig::GetInstance().m_bba_mac;
u8 new_addr[6] = { 0 }; bool mac_addr_valid = false;
for (size_t i = 0; i < mac_addr.size() && x < 12; i++) u8 mac_addr[6] = { 0 };
if (!mac_addr_setting.empty())
{ {
char c = mac_addr.at(i); int x = 0;
if (c >= '0' && c <= '9') {
new_addr[x / 2] |= (c - '0') << ((x & 1) ? 0 : 4); x++; for (size_t i = 0; i < mac_addr_setting.size() && x < 12; i++)
} else if (c >= 'A' && c <= 'F') { {
new_addr[x / 2] |= (c - 'A' + 10) << ((x & 1) ? 0 : 4); x++; char c = mac_addr_setting.at(i);
} else if (c >= 'a' && c <= 'f') { if (c >= '0' && c <= '9') {
new_addr[x / 2] |= (c - 'a' + 10) << ((x & 1) ? 0 : 4); x++; mac_addr[x / 2] |= (c - '0') << ((x & 1) ? 0 : 4); x++;
} else if (c >= 'A' && c <= 'F') {
mac_addr[x / 2] |= (c - 'A' + 10) << ((x & 1) ? 0 : 4); x++;
} else if (c >= 'a' && c <= 'f') {
mac_addr[x / 2] |= (c - 'a' + 10) << ((x & 1) ? 0 : 4); x++;
}
}
if (x / 2 == 6)
{
memcpy(&mBbaMem[BBA_NAFR_PAR0], mac_addr, 6);
mac_addr_valid = true;
} }
} }
if (x / 2 == 6) if (!mac_addr_valid)
memcpy(&mBbaMem[BBA_NAFR_PAR0], new_addr, 6); {
else GenerateMAC(BBA, mac_addr);
memcpy(&mBbaMem[BBA_NAFR_PAR0], mac_address_default, 6);
mac_addr_setting = ArrayToString(mac_addr, 6, 10, false);
SConfig::GetInstance().SaveSettings();
memcpy(&mBbaMem[BBA_NAFR_PAR0], mac_addr, 6);
}
// hax .. fully established 100BASE-T link // hax .. fully established 100BASE-T link
mBbaMem[BBA_NWAYS] = NWAYS_LS100 | NWAYS_LPNWAY | NWAYS_100TXF | NWAYS_ANCLPT; mBbaMem[BBA_NWAYS] = NWAYS_LS100 | NWAYS_LPNWAY | NWAYS_100TXF | NWAYS_ANCLPT;

View File

@ -196,7 +196,7 @@ enum RecvStatus
class CEXIETHERNET : public IEXIDevice class CEXIETHERNET : public IEXIDevice
{ {
public: public:
CEXIETHERNET(const std::string& mac_addr); CEXIETHERNET();
virtual ~CEXIETHERNET(); virtual ~CEXIETHERNET();
void SetCS(int cs); void SetCS(int cs);
bool IsPresent(); bool IsPresent();