summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2014-01-25 23:02:29 +0100
committerPierre Bourdon <delroth@gmail.com>2014-02-16 19:22:40 +0100
commitbdedaa24a9747b4890622cd356ed0a6761bad27d (patch)
tree8822c9823b28d0e004d1ea35b4006f6243e20505 /Source/Core
parent353c145e64f90dd84fde145b32fe2c6b054aefc7 (diff)
MMIO: Port the EXI MMIOs to the new interface.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/EXI.cpp42
-rw-r--r--Source/Core/Core/HW/EXI.h3
-rw-r--r--Source/Core/Core/HW/EXI_Channel.cpp258
-rw-r--r--Source/Core/Core/HW/EXI_Channel.h29
-rw-r--r--Source/Core/Core/HW/HW.cpp2
-rw-r--r--Source/Core/Core/HW/Memmap.cpp2
6 files changed, 145 insertions, 191 deletions
diff --git a/Source/Core/Core/HW/EXI.cpp b/Source/Core/Core/HW/EXI.cpp
index 4e9c9057ef..850d4812e6 100644
--- a/Source/Core/Core/HW/EXI.cpp
+++ b/Source/Core/Core/HW/EXI.cpp
@@ -9,6 +9,7 @@
#include "ProcessorInterface.h"
#include "../PowerPC/PowerPC.h"
+#include "MMIO.h"
#include "EXI.h"
#include "Sram.h"
@@ -62,6 +63,19 @@ void PauseAndLock(bool doLock, bool unpauseOnUnlock)
channel->PauseAndLock(doLock, unpauseOnUnlock);
}
+void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
+{
+ for (int i = 0; i < MAX_EXI_CHANNELS; ++i)
+ {
+ _dbg_assert_(EXPANSIONINTERFACE, g_Channels[i] != nullptr);
+ // Each channel has 5 32 bit registers assigned to it. We offset the
+ // base that we give to each channel for registration.
+ //
+ // Be careful: this means the base is no longer aligned on a page
+ // boundary and using "base | FOO" is not valid!
+ g_Channels[i]->RegisterMMIO(mmio, base + 5 * 4 * i);
+ }
+}
void ChangeDeviceCallback(u64 userdata, int cyclesLate)
{
@@ -101,34 +115,14 @@ void Update()
void Read32(u32& _uReturnValue, const u32 _iAddress)
{
- // TODO 0xfff00000 is mapped to EXI -> mapped to first MB of maskrom
- u32 iAddr = _iAddress & 0x3FF;
- u32 iRegister = (iAddr >> 2) % 5;
- u32 iChannel = (iAddr >> 2) / 5;
-
- _dbg_assert_(EXPANSIONINTERFACE, iChannel < MAX_EXI_CHANNELS);
-
- if (iChannel < MAX_EXI_CHANNELS)
- {
- g_Channels[iChannel]->Read32(_uReturnValue, iRegister);
- }
- else
- {
- _uReturnValue = 0;
- }
+ // HACK: Remove this function when the new MMIO interface is used.
+ Memory::mmio_mapping->Read(_iAddress, _uReturnValue);
}
void Write32(const u32 _iValue, const u32 _iAddress)
{
- // TODO 0xfff00000 is mapped to EXI -> mapped to first MB of maskrom
- u32 iAddr = _iAddress & 0x3FF;
- u32 iRegister = (iAddr >> 2) % 5;
- u32 iChannel = (iAddr >> 2) / 5;
-
- _dbg_assert_(EXPANSIONINTERFACE, iChannel < MAX_EXI_CHANNELS);
-
- if (iChannel < MAX_EXI_CHANNELS)
- g_Channels[iChannel]->Write32(_iValue, iRegister);
+ // HACK: Remove this function when the new MMIO interface is used.
+ Memory::mmio_mapping->Write(_iAddress, _iValue);
}
void UpdateInterrupts()
diff --git a/Source/Core/Core/HW/EXI.h b/Source/Core/Core/HW/EXI.h
index b60dbda105..21c33ad16a 100644
--- a/Source/Core/Core/HW/EXI.h
+++ b/Source/Core/Core/HW/EXI.h
@@ -8,6 +8,7 @@
#include "EXI_Channel.h"
#include "Thread.h"
class PointerWrap;
+namespace MMIO { class Mapping; }
enum
{
@@ -22,6 +23,8 @@ void Shutdown();
void DoState(PointerWrap &p);
void PauseAndLock(bool doLock, bool unpauseOnUnlock);
+void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
+
void Update();
void UpdateInterrupts();
diff --git a/Source/Core/Core/HW/EXI_Channel.cpp b/Source/Core/Core/HW/EXI_Channel.cpp
index a57b06914c..52fd79fa3c 100644
--- a/Source/Core/Core/HW/EXI_Channel.cpp
+++ b/Source/Core/Core/HW/EXI_Channel.cpp
@@ -7,6 +7,7 @@
#include "EXI.h"
#include "../ConfigManager.h"
#include "../Movie.h"
+#include "MMIO.h"
#define EXI_READ 0
#define EXI_WRITE 1
@@ -41,6 +42,117 @@ CEXIChannel::~CEXIChannel()
RemoveDevices();
}
+void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
+{
+ // Warning: the base is not aligned on a page boundary here. We can't use |
+ // to select a register address, instead we need to use +.
+
+ mmio->Register(base + EXI_STATUS,
+ MMIO::ComplexRead<u32>([this](u32) {
+ // check if external device is present
+ // pretty sure it is memcard only, not entirely sure
+ if (m_ChannelId == 2)
+ {
+ m_Status.EXT = 0;
+ }
+ else
+ {
+ m_Status.EXT = GetDevice(1)->IsPresent() ? 1 : 0;
+ }
+
+ return m_Status.Hex;
+ }),
+ MMIO::ComplexWrite<u32>([this](u32, u32 val) {
+ UEXI_STATUS newStatus(val);
+
+ m_Status.EXIINTMASK = newStatus.EXIINTMASK;
+ if (newStatus.EXIINT)
+ m_Status.EXIINT = 0;
+
+ m_Status.TCINTMASK = newStatus.TCINTMASK;
+ if (newStatus.TCINT)
+ m_Status.TCINT = 0;
+
+ m_Status.CLK = newStatus.CLK;
+
+ if (m_ChannelId == 0 || m_ChannelId == 1)
+ {
+ m_Status.EXTINTMASK = newStatus.EXTINTMASK;
+
+ if (newStatus.EXTINT)
+ m_Status.EXTINT = 0;
+ }
+
+ if (m_ChannelId == 0)
+ m_Status.ROMDIS = newStatus.ROMDIS;
+
+ IEXIDevice* pDevice = GetDevice(m_Status.CHIP_SELECT ^ newStatus.CHIP_SELECT);
+ m_Status.CHIP_SELECT = newStatus.CHIP_SELECT;
+ if (pDevice != NULL)
+ pDevice->SetCS(m_Status.CHIP_SELECT);
+
+ CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
+ })
+ );
+
+ mmio->Register(base + EXI_DMAADDR,
+ MMIO::DirectRead<u32>(&m_DMAMemoryAddress),
+ MMIO::DirectWrite<u32>(&m_DMAMemoryAddress)
+ );
+ mmio->Register(base + EXI_DMALENGTH,
+ MMIO::DirectRead<u32>(&m_DMALength),
+ MMIO::DirectWrite<u32>(&m_DMALength)
+ );
+ mmio->Register(base + EXI_DMACONTROL,
+ MMIO::DirectRead<u32>(&m_Control.Hex),
+ MMIO::ComplexWrite<u32>([this](u32, u32 val) {
+ m_Control.Hex = val;
+
+ if (m_Control.TSTART)
+ {
+ IEXIDevice* pDevice = GetDevice(m_Status.CHIP_SELECT);
+ if (pDevice == NULL)
+ return;
+
+ if (m_Control.DMA == 0)
+ {
+ // immediate data
+ switch (m_Control.RW)
+ {
+ 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: pDevice->ImmReadWrite(m_ImmData, m_Control.TLEN + 1); break;
+ default: _dbg_assert_msg_(EXPANSIONINTERFACE,0,"EXI Imm: Unknown transfer type %i", m_Control.RW);
+ }
+ m_Control.TSTART = 0;
+ }
+ else
+ {
+ // DMA
+ switch (m_Control.RW)
+ {
+ case EXI_READ: pDevice->DMARead (m_DMAMemoryAddress, m_DMALength); break;
+ case EXI_WRITE: pDevice->DMAWrite(m_DMAMemoryAddress, m_DMALength); break;
+ default: _dbg_assert_msg_(EXPANSIONINTERFACE,0,"EXI DMA: Unknown transfer type %i", m_Control.RW);
+ }
+ m_Control.TSTART = 0;
+ }
+
+ if(!m_Control.TSTART) // completed !
+ {
+ m_Status.TCINT = 1;
+ CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
+ }
+ }
+ })
+ );
+
+ mmio->Register(base + EXI_IMMDATA,
+ MMIO::DirectRead<u32>(&m_ImmData),
+ MMIO::DirectWrite<u32>(&m_ImmData)
+ );
+}
+
void CEXIChannel::RemoveDevices()
{
for (auto& device : m_pDevices)
@@ -115,152 +227,6 @@ void CEXIChannel::Update()
device->Update();
}
-void CEXIChannel::Read32(u32& _uReturnValue, const u32 _iRegister)
-{
- switch (_iRegister)
- {
- case EXI_STATUS:
- {
- // check if external device is present
- // pretty sure it is memcard only, not entirely sure
- if (m_ChannelId == 2)
- {
- m_Status.EXT = 0;
- }
- else
- {
- m_Status.EXT = GetDevice(1)->IsPresent() ? 1 : 0;
- }
-
- _uReturnValue = m_Status.Hex;
- break;
- }
-
- case EXI_DMAADDR:
- _uReturnValue = m_DMAMemoryAddress;
- break;
-
- case EXI_DMALENGTH:
- _uReturnValue = m_DMALength;
- break;
-
- case EXI_DMACONTROL:
- _uReturnValue = m_Control.Hex;
- break;
-
- case EXI_IMMDATA:
- _uReturnValue = m_ImmData;
- break;
-
- default:
- _dbg_assert_(EXPANSIONINTERFACE, 0);
- _uReturnValue = 0xDEADBEEF;
- }
-
- DEBUG_LOG(EXPANSIONINTERFACE, "(r32) 0x%08x channel: %i register: %s",
- _uReturnValue, m_ChannelId, Debug_GetRegisterName(_iRegister));
-}
-
-void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
-{
- DEBUG_LOG(EXPANSIONINTERFACE, "(w32) 0x%08x channel: %i register: %s",
- _iValue, m_ChannelId, Debug_GetRegisterName(_iRegister));
-
- switch (_iRegister)
- {
- case EXI_STATUS:
- {
- UEXI_STATUS newStatus(_iValue);
-
- m_Status.EXIINTMASK = newStatus.EXIINTMASK;
- if (newStatus.EXIINT)
- m_Status.EXIINT = 0;
-
- m_Status.TCINTMASK = newStatus.TCINTMASK;
- if (newStatus.TCINT)
- m_Status.TCINT = 0;
-
- m_Status.CLK = newStatus.CLK;
-
- if (m_ChannelId == 0 || m_ChannelId == 1)
- {
- m_Status.EXTINTMASK = newStatus.EXTINTMASK;
-
- if (newStatus.EXTINT)
- m_Status.EXTINT = 0;
- }
-
- if (m_ChannelId == 0)
- m_Status.ROMDIS = newStatus.ROMDIS;
-
- IEXIDevice* pDevice = GetDevice(m_Status.CHIP_SELECT ^ newStatus.CHIP_SELECT);
- m_Status.CHIP_SELECT = newStatus.CHIP_SELECT;
- if (pDevice != NULL)
- pDevice->SetCS(m_Status.CHIP_SELECT);
-
- CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
- }
- break;
-
- case EXI_DMAADDR:
- INFO_LOG(EXPANSIONINTERFACE, "Wrote DMAAddr, channel %i", m_ChannelId);
- m_DMAMemoryAddress = _iValue;
- break;
-
- case EXI_DMALENGTH:
- INFO_LOG(EXPANSIONINTERFACE, "Wrote DMALength, channel %i", m_ChannelId);
- m_DMALength = _iValue;
- break;
-
- case EXI_DMACONTROL:
- INFO_LOG(EXPANSIONINTERFACE, "Wrote DMAControl, channel %i", m_ChannelId);
- m_Control.Hex = _iValue;
-
- if (m_Control.TSTART)
- {
- IEXIDevice* pDevice = GetDevice(m_Status.CHIP_SELECT);
- if (pDevice == NULL)
- return;
-
- if (m_Control.DMA == 0)
- {
- // immediate data
- switch (m_Control.RW)
- {
- 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: pDevice->ImmReadWrite(m_ImmData, m_Control.TLEN + 1); break;
- default: _dbg_assert_msg_(EXPANSIONINTERFACE,0,"EXI Imm: Unknown transfer type %i", m_Control.RW);
- }
- m_Control.TSTART = 0;
- }
- else
- {
- // DMA
- switch (m_Control.RW)
- {
- case EXI_READ: pDevice->DMARead (m_DMAMemoryAddress, m_DMALength); break;
- case EXI_WRITE: pDevice->DMAWrite(m_DMAMemoryAddress, m_DMALength); break;
- default: _dbg_assert_msg_(EXPANSIONINTERFACE,0,"EXI DMA: Unknown transfer type %i", m_Control.RW);
- }
- m_Control.TSTART = 0;
- }
-
- if(!m_Control.TSTART) // completed !
- {
- m_Status.TCINT = 1;
- CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
- }
- }
- break;
-
- case EXI_IMMDATA:
- INFO_LOG(EXPANSIONINTERFACE, "Wrote IMMData, channel %i", m_ChannelId);
- m_ImmData = _iValue;
- break;
- }
-}
-
void CEXIChannel::DoState(PointerWrap &p)
{
p.DoPOD(m_Status);
diff --git a/Source/Core/Core/HW/EXI_Channel.h b/Source/Core/Core/HW/EXI_Channel.h
index 582ea48513..aedc09c3ea 100644
--- a/Source/Core/Core/HW/EXI_Channel.h
+++ b/Source/Core/Core/HW/EXI_Channel.h
@@ -9,30 +9,20 @@
#include "EXI_Device.h"
#include <memory>
+namespace MMIO { class Mapping; }
+
class CEXIChannel
{
private:
enum
{
- EXI_STATUS = 0,
- EXI_DMAADDR = 1,
- EXI_DMALENGTH = 2,
- EXI_DMACONTROL = 3,
- EXI_IMMDATA = 4
+ EXI_STATUS = 0x00,
+ EXI_DMAADDR = 0x04,
+ EXI_DMALENGTH = 0x08,
+ EXI_DMACONTROL = 0x0C,
+ EXI_IMMDATA = 0x10
};
- const char* Debug_GetRegisterName(u32 _register)
- {
- switch (_register)
- {
- case EXI_STATUS: return "STATUS";
- case EXI_DMAADDR: return "DMAADDR";
- case EXI_DMALENGTH: return "DMALENGTH";
- case EXI_DMACONTROL: return "DMACONTROL";
- case EXI_IMMDATA: return "IMMDATA";
- default: return "!!! Unknown EXI Register !!!";
- }
- }
// EXI Status Register - "Channel Parameter Register"
union UEXI_STATUS
@@ -104,15 +94,14 @@ public:
CEXIChannel(u32 ChannelId);
~CEXIChannel();
+ void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
+
void AddDevice(const TEXIDevices device_type, const int device_num);
void AddDevice(IEXIDevice* pDevice, const int device_num, bool notifyPresenceChanged=true);
// Remove all devices
void RemoveDevices();
- void Read32(u32& _uReturnValue, const u32 _iRegister);
- void Write32(const u32 _iValue, const u32 _iRegister);
-
void Update();
bool IsCausingInterrupt();
void DoState(PointerWrap &p);
diff --git a/Source/Core/Core/HW/HW.cpp b/Source/Core/Core/HW/HW.cpp
index 586344ecc6..63f934588a 100644
--- a/Source/Core/Core/HW/HW.cpp
+++ b/Source/Core/Core/HW/HW.cpp
@@ -38,11 +38,11 @@ namespace HW
VideoInterface::Init();
SerialInterface::Init();
ProcessorInterface::Init();
+ ExpansionInterface::Init(); // Needs to be initialized before Memory
Memory::Init();
DSP::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPHLE);
DVDInterface::Init();
GPFifo::Init();
- ExpansionInterface::Init();
CCPU::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore);
SystemTimers::Init();
diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp
index 7c37adeb67..e912f6fa5f 100644
--- a/Source/Core/Core/HW/Memmap.cpp
+++ b/Source/Core/Core/HW/Memmap.cpp
@@ -316,6 +316,7 @@ void InitMMIO(MMIO::Mapping* mmio)
DSP::RegisterMMIO(mmio, 0xCC005000);
DVDInterface::RegisterMMIO(mmio, 0xCC006000);
SerialInterface::RegisterMMIO(mmio, 0xCC006400);
+ ExpansionInterface::RegisterMMIO(mmio, 0xCC006800);
AudioInterface::RegisterMMIO(mmio, 0xCC006C00);
}
@@ -326,6 +327,7 @@ void InitMMIOWii(MMIO::Mapping* mmio)
WII_IPCInterface::RegisterMMIO(mmio, 0xCD000000);
DVDInterface::RegisterMMIO(mmio, 0xCD006000);
SerialInterface::RegisterMMIO(mmio, 0xCD006400);
+ ExpansionInterface::RegisterMMIO(mmio, 0xCD006800);
AudioInterface::RegisterMMIO(mmio, 0xCD006C00);
}