Add save commands for SRAM/FRAM. Improve EEPROM.
Handle possible endian file read issues at file access time instead of using Swap64 on every access. Code comments and clean up.
This commit is contained in:
parent
9761df422a
commit
2d4aa2a195
|
@ -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)
|
||||
{
|
||||
|
@ -98,57 +99,92 @@ 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -156,10 +192,10 @@ u32 CEXIAgp::ImmRead(u32 _uSize)
|
|||
}
|
||||
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);
|
||||
|
@ -167,8 +203,25 @@ u32 CEXIAgp::ImmRead(u32 _uSize)
|
|||
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);
|
||||
|
@ -176,7 +229,8 @@ u32 CEXIAgp::ImmRead(u32 _uSize)
|
|||
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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
// Fall-through intentional
|
||||
case 0xAE0A0000: // end DMA
|
||||
m_eeprom_pos = 0;
|
||||
// Fall-through intentional
|
||||
default:
|
||||
m_current_cmd = _uData;
|
||||
m_return_pos = 0;
|
||||
m_hash = 0xFF;
|
||||
|
@ -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);
|
||||
|
|
|
@ -23,7 +23,10 @@ public:
|
|||
private:
|
||||
enum
|
||||
{
|
||||
EE_READ = 0x80
|
||||
EE_IGNORE_BITS = 0x4,
|
||||
EE_DATA_BITS = 0x40,
|
||||
EE_READ_FALSE = 0xA,
|
||||
EE_READ_TRUE = 0xB,
|
||||
};
|
||||
|
||||
int m_slot;
|
||||
|
@ -41,8 +44,13 @@ private:
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue