Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Datel AGP save commands for SRAM/FRAM. Improve EEPROM. #2045

Merged
merged 1 commit into from
Feb 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
154 changes: 122 additions & 32 deletions Source/Core/Core/HW/EXI_DeviceAGP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ void CEXIAgp::LoadFileToROM(const std::string& filename)

void CEXIAgp::LoadFileToEEPROM(const std::string& filename)
{
// Technically one of EEPROM, Flash, SRAM, FRAM
File::IOFile pStream(filename, "rb");
if (pStream)
{
Expand All @@ -98,85 +99,138 @@ void CEXIAgp::LoadFileToEEPROM(const std::string& filename)
m_eeprom_mask = (m_eeprom_size - 1);

m_eeprom.resize(m_eeprom_size);

pStream.ReadBytes(m_eeprom.data(), filesize);
if ((m_eeprom_size == 512) || (m_eeprom_size == 8192))
{
// Handle endian read - could be done with byte access in 0xAE commands instead
for (u32 index = 0; index < (m_eeprom_size / 8); index++)
{
u64 NewVal = 0;
for (u32 indexb = 0; indexb < 8; indexb++)
NewVal = (NewVal << 0x8) | m_eeprom[index * 8 + indexb];
((u64*)(m_eeprom.data()))[index] = NewVal;
}
m_eeprom_add_end = (m_eeprom_size == 512 ? (2 + 6) : (2 + 14));
m_eeprom_add_mask = (m_eeprom_size == 512 ? 0x3F : 0x3FF);
m_eeprom_read_mask = (m_eeprom_size == 512 ? 0x80 : 0x8000);
m_eeprom_status_mask = (m_rom_size == 0x2000000 ? 0x1FFFF00 : 0x1000000);
}
else
m_eeprom_status_mask = 0;
}
else
{
m_eeprom_size = 0;
m_eeprom.clear();
}

}

void CEXIAgp::SaveFileFromEEPROM(const std::string& filename)
{
File::IOFile pStream(filename, "wb");
if (pStream)
{
pStream.WriteBytes(m_eeprom.data(), m_eeprom_size);
if ((m_eeprom_size == 512) || (m_eeprom_size == 8192))
{
// Handle endian write - could be done with byte access in 0xAE commands instead
std::vector<u8> temp_eeprom(m_eeprom_size);
for (u32 index = 0; index < (m_eeprom_size / 8); index++)
{
u64 NewVal = ((u64*)(m_eeprom.data()))[index];
for (u32 indexb = 0; indexb < 8; indexb++)
temp_eeprom[index * 8 + (7-indexb)] = (NewVal >> (indexb * 8)) & 0xFF;
}
pStream.WriteBytes(temp_eeprom.data(), m_eeprom_size);
}
else
{
pStream.WriteBytes(m_eeprom.data(), m_eeprom_size);

This comment was marked as off-topic.

}
}
}

u32 CEXIAgp::ImmRead(u32 _uSize)
{
// We don't really care about _uSize
(void)_uSize;
u32 uData = 0;
u8 RomVal1, RomVal2, RomVal3, RomVal4;

switch (m_current_cmd)
{
case 0xAE000000:
case 0xAE000000: // Clock handshake?
uData = 0x5AAA5517; // 17 is precalculated hash
m_current_cmd = 0;
break;
case 0xAE010000:
case 0xAE010000: // Init?
uData = (m_return_pos == 0) ? 0x01020304 : 0xF0020304; // F0 is precalculated hash, 020304 is left over
if (m_return_pos == 1)
m_current_cmd = 0;
else
m_return_pos = 1;
break;
case 0xAE020000:
if (m_rw_offset == 0x8000000)
case 0xAE020000: // Read 2 bytes with 24 bit address
if (m_eeprom_write_status && ((m_rw_offset & m_eeprom_status_mask) == m_eeprom_status_mask) && (m_eeprom_status_mask != 0))
{
RomVal1 = 0x0;
RomVal2 = 0x1;
RomVal1 = 0x1;
RomVal2 = 0x0;
}
else
{
RomVal1 = m_rom[m_rw_offset++];
RomVal2 = m_rom[m_rw_offset++];
RomVal1 = m_rom[(m_rw_offset++) & m_rom_mask];
RomVal2 = m_rom[(m_rw_offset++) & m_rom_mask];
}
CRC8(&RomVal2, 1);
CRC8(&RomVal1, 1);
uData = (RomVal2 << 24) | (RomVal1 << 16) | (m_hash << 8);
m_current_cmd = 0;
break;
case 0xAE030000:
case 0xAE030000: // read the next 4 bytes out of 0x10000 group
if (_uSize == 1)
{
uData = 0xFF000000;
m_current_cmd = 0;
}
else
{
RomVal1 = m_rom[m_rw_offset++];
RomVal2 = m_rom[m_rw_offset++];
RomVal3 = m_rom[m_rw_offset++];
RomVal4 = m_rom[m_rw_offset++];
RomVal1 = m_rom[(m_rw_offset++) & m_rom_mask];
RomVal2 = m_rom[(m_rw_offset++) & m_rom_mask];
RomVal3 = m_rom[(m_rw_offset++) & m_rom_mask];
RomVal4 = m_rom[(m_rw_offset++) & m_rom_mask];
CRC8(&RomVal2, 1);
CRC8(&RomVal1, 1);
CRC8(&RomVal4, 1);
CRC8(&RomVal3, 1);
uData = (RomVal2 << 24) | (RomVal1 << 16) | (RomVal4 << 8) | (RomVal3);
}
break;
case 0xAE0B0000:
RomVal1 = m_eeprom_pos < 4 ? 0xA : (((u64*)m_eeprom.data())[(m_eeprom_cmd >> 1) & 0x3F] >> (m_eeprom_pos - 4)) & 0x1;
case 0xAE040000: // read 1 byte from 16 bit address
// ToDo: Flash special handling
if (m_eeprom_size == 0)
RomVal1 = 0xFF;
else
RomVal1 = (m_eeprom.data())[m_eeprom_pos];
CRC8(&RomVal1, 1);
uData = (RomVal1 << 24) | (m_hash << 16);
m_current_cmd = 0;
break;
case 0xAE0B0000: // read 1 bit from DMA with 6 or 14 bit address
// Change to byte access instead of endian file access?
RomVal1 = EE_READ_FALSE;
if ((m_eeprom_size != 0)
&& (m_eeprom_pos >= EE_IGNORE_BITS)
&& ((((u64*)m_eeprom.data())[(m_eeprom_cmd >> 1) & m_eeprom_add_mask]) >> ((EE_DATA_BITS - 1) - (m_eeprom_pos - EE_IGNORE_BITS))) & 0x1)
{
RomVal1 = EE_READ_TRUE;
}
RomVal2 = 0;
CRC8(&RomVal2, 1);
CRC8(&RomVal1, 1);
uData = (RomVal2 << 24) | (RomVal1 << 16) | (m_hash << 8);
m_eeprom_pos++;
m_current_cmd = 0;
break;
case 0xAE0C0000:
case 0xAE070000: // complete write 1 byte from 16 bit address
case 0xAE0C0000: // complete write 1 bit from dma with 6 or 14 bit address
uData = m_hash << 24;
m_current_cmd = 0;
break;
Expand All @@ -191,6 +245,7 @@ u32 CEXIAgp::ImmRead(u32 _uSize)

void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
{
// 0x00 = Execute current command?
if ((_uSize == 1) && ((_uData & 0xFF000000) == 0))
return;

Expand All @@ -199,9 +254,10 @@ void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
INFO_LOG(EXPANSIONINTERFACE, "AGP command %x", _uData);
switch (m_current_cmd)
{
case 0xAE020000:
case 0xAE030000:
m_rw_offset = ((_uData & 0xFFFFFF00) >> 7) & m_rom_mask;
case 0xAE020000: // set up 24 bit address for read 2 bytes
case 0xAE030000: // set up 24 bit address for read (0x10000 byte group)
// 25 bit address shifted one bit right = 24 bits
m_rw_offset = ((_uData & 0xFFFFFF00) >> (8 - 1));
m_return_pos = 0;
HashCmd = (_uData & 0xFF000000) >> 24;
CRC8(&HashCmd, 1);
Expand All @@ -210,20 +266,45 @@ void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
HashCmd = (_uData & 0x0000FF00) >> 8;
CRC8(&HashCmd, 1);
break;
case 0xAE0C0000:
if ((m_eeprom_pos < 0x8) || (m_eeprom_pos == ((m_eeprom_cmd & EE_READ) ? 0x8 : 0x48)))
case 0xAE040000: // set up 16 bit address for read 1 byte
// ToDo: Flash special handling
m_eeprom_pos = ((_uData & 0xFFFF0000) >> 0x10) & m_eeprom_mask;
HashCmd = (_uData & 0xFF000000) >> 24;
CRC8(&HashCmd, 1);
HashCmd = (_uData & 0x00FF0000) >> 16;
CRC8(&HashCmd, 1);
break;
case 0xAE070000: // write 1 byte from 16 bit address
// ToDo: Flash special handling
m_eeprom_pos = ((_uData & 0xFFFF0000) >> 0x10) & m_eeprom_mask;
if (m_eeprom_size != 0)
((m_eeprom.data()))[(m_eeprom_pos)] = (_uData & 0x0000FF00) >> 0x8;
HashCmd = (_uData & 0xFF000000) >> 24;
CRC8(&HashCmd, 1);
HashCmd = (_uData & 0x00FF0000) >> 16;
CRC8(&HashCmd, 1);
HashCmd = (_uData & 0x0000FF00) >> 8;
CRC8(&HashCmd, 1);
break;
case 0xAE0C0000: // write 1 bit from dma with 6 or 14 bit address
if ((m_eeprom_pos < m_eeprom_add_end) || (m_eeprom_pos == ((m_eeprom_cmd & m_eeprom_read_mask) ? m_eeprom_add_end : m_eeprom_add_end + EE_DATA_BITS)))
{
Mask = (u64)(1 << (0x8-(m_eeprom_pos > 0x8 ? 0x8 : m_eeprom_pos)));
Mask = (1ULL << (m_eeprom_add_end - std::min(m_eeprom_pos, m_eeprom_add_end)));
if ((_uData >> 16) & 0x1)
m_eeprom_cmd |= Mask;
else
m_eeprom_cmd &= ~Mask;
if (m_eeprom_pos == 0x48)
((u64*)(m_eeprom.data()))[(m_eeprom_cmd >> 1) & 0x3F] = m_eeprom_data;
if (m_eeprom_pos == m_eeprom_add_end + EE_DATA_BITS)
{
// Change to byte access instead of endian file access?
if (m_eeprom_size != 0)
((u64*)(m_eeprom.data()))[(m_eeprom_cmd >> 1) & m_eeprom_add_mask] = m_eeprom_data;
m_eeprom_write_status = true;
}
}
else
{
Mask = (u64)(1 << (0x47 - m_eeprom_pos));
Mask = (1ULL << (m_eeprom_add_end + EE_DATA_BITS - 1 - m_eeprom_pos));
if ((_uData >> 16) & 0x1)
m_eeprom_data |= Mask;
else
Expand All @@ -237,13 +318,17 @@ void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
CRC8(&HashCmd, 1);
break;
case 0xAE0B0000:
m_eeprom_write_status = false;
break;
case 0xAE000000:
case 0xAE010000:
case 0xAE090000:
case 0xAE0A0000:
default:
case 0xAE090000: // start DMA
m_eeprom_write_status = false; //ToDo: Verify with hardware which commands disable EEPROM CS

This comment was marked as off-topic.

// Fall-through intentional
case 0xAE0A0000: // end DMA
m_eeprom_pos = 0;

This comment was marked as off-topic.

// Fall-through intentional
default:
m_current_cmd = _uData;
m_return_pos = 0;
m_hash = 0xFF;
Expand All @@ -264,6 +349,11 @@ void CEXIAgp::DoState(PointerWrap &p)
p.Do(m_eeprom_mask);
p.Do(m_eeprom_pos);
p.Do(m_eeprom_size);
p.Do(m_eeprom_add_end);
p.Do(m_eeprom_add_mask);
p.Do(m_eeprom_read_mask);
p.Do(m_eeprom_status_mask);
p.Do(m_eeprom_write_status);
p.Do(m_hash);
p.Do(m_position);
p.Do(m_return_pos);
Expand Down
14 changes: 11 additions & 3 deletions Source/Core/Core/HW/EXI_DeviceAGP.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ class CEXIAgp
private:
enum
{
EE_READ = 0x80
EE_IGNORE_BITS = 0x4,
EE_DATA_BITS = 0x40,
EE_READ_FALSE = 0xA,
EE_READ_TRUE = 0xB,
};

int m_slot;
Expand All @@ -41,8 +44,13 @@ class CEXIAgp
u32 m_address = 0;
u32 m_rw_offset = 0;
u64 m_eeprom_data = 0;
u8 m_eeprom_pos = 0;
u16 m_eeprom_cmd = 0;
u16 m_eeprom_pos = 0;
u32 m_eeprom_cmd = 0;
u16 m_eeprom_add_end = 0;
u16 m_eeprom_add_mask = 0;
u16 m_eeprom_read_mask = 0;
u32 m_eeprom_status_mask = 0;
bool m_eeprom_write_status = false;

void LoadFileToROM(const std::string& filename);
void LoadFileToEEPROM(const std::string& filename);
Expand Down