summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/HW/SI/SI.cpp231
1 files changed, 112 insertions, 119 deletions
diff --git a/Source/Core/Core/HW/SI/SI.cpp b/Source/Core/Core/HW/SI/SI.cpp
index afcc466bd0..5e1fa38993 100644
--- a/Source/Core/Core/HW/SI/SI.cpp
+++ b/Source/Core/Core/HW/SI/SI.cpp
@@ -24,19 +24,12 @@
namespace SerialInterface
{
-static CoreTiming::EventType* s_change_device_event;
-static CoreTiming::EventType* s_tranfer_pending_event;
-
-static void RunSIBuffer(u64 user_data, s64 cycles_late);
-static void UpdateInterrupts();
-
// SI Interrupt Types
enum SIInterruptType
{
INT_RDSTINT = 0,
INT_TCINT = 1,
};
-static void GenerateSIInterrupt(SIInterruptType type);
// SI Internal Hardware Addresses
enum
@@ -207,6 +200,9 @@ union USIEXIClockCount
};
};
+static CoreTiming::EventType* s_change_device_event;
+static CoreTiming::EventType* s_tranfer_pending_event;
+
// STATE_TO_SAVE
static std::array<SSIChannel, MAX_SI_CHANNELS> s_channel;
static USIPoll s_poll;
@@ -215,6 +211,115 @@ static USIStatusReg s_status_reg;
static USIEXIClockCount s_exi_clock_count;
static std::array<u8, 128> s_si_buffer;
+static void SetNoResponse(u32 channel)
+{
+ // raise the NO RESPONSE error
+ switch (channel)
+ {
+ case 0:
+ s_status_reg.NOREP0 = 1;
+ break;
+ case 1:
+ s_status_reg.NOREP1 = 1;
+ break;
+ case 2:
+ s_status_reg.NOREP2 = 1;
+ break;
+ case 3:
+ s_status_reg.NOREP3 = 1;
+ break;
+ }
+ s_com_csr.COMERR = 1;
+}
+
+static void ChangeDeviceCallback(u64 user_data, s64 cycles_late)
+{
+ u8 channel = (u8)(user_data >> 32);
+ SIDevices device = (SIDevices)(u32)user_data;
+
+ // Skip redundant (spammed) device changes
+ if (GetDeviceType(channel) != device)
+ {
+ s_channel[channel].out.hex = 0;
+ s_channel[channel].in_hi.hex = 0;
+ s_channel[channel].in_lo.hex = 0;
+
+ SetNoResponse(channel);
+
+ AddDevice(device, channel);
+ }
+}
+
+static void UpdateInterrupts()
+{
+ // check if we have to update the RDSTINT flag
+ if (s_status_reg.RDST0 || s_status_reg.RDST1 || s_status_reg.RDST2 || s_status_reg.RDST3)
+ s_com_csr.RDSTINT = 1;
+ else
+ s_com_csr.RDSTINT = 0;
+
+ // check if we have to generate an interrupt
+ if ((s_com_csr.RDSTINT & s_com_csr.RDSTINTMSK) || (s_com_csr.TCINT & s_com_csr.TCINTMSK))
+ {
+ ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_SI, true);
+ }
+ else
+ {
+ ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_SI, false);
+ }
+}
+
+static void GenerateSIInterrupt(SIInterruptType type)
+{
+ switch (type)
+ {
+ case INT_RDSTINT:
+ s_com_csr.RDSTINT = 1;
+ break;
+ case INT_TCINT:
+ s_com_csr.TCINT = 1;
+ break;
+ }
+
+ UpdateInterrupts();
+}
+
+static void RunSIBuffer(u64 user_data, s64 cycles_late)
+{
+ if (s_com_csr.TSTART)
+ {
+ // Math in_length
+ int in_length = s_com_csr.INLNGTH;
+ if (in_length == 0)
+ in_length = 128;
+ else
+ in_length++;
+
+ // Math out_length
+ int out_length = s_com_csr.OUTLNGTH;
+ if (out_length == 0)
+ out_length = 128;
+ else
+ out_length++;
+
+ std::unique_ptr<ISIDevice>& device = s_channel[s_com_csr.CHANNEL].device;
+ int numOutput = device->RunBuffer(s_si_buffer.data(), in_length);
+
+ DEBUG_LOG(SERIALINTERFACE, "RunSIBuffer chan: %d inLen: %i outLen: %i processed: %i",
+ s_com_csr.CHANNEL, in_length, out_length, numOutput);
+
+ if (numOutput != 0)
+ {
+ s_com_csr.TSTART = 0;
+ GenerateSIInterrupt(INT_TCINT);
+ }
+ else
+ {
+ CoreTiming::ScheduleEvent(device->TransferInterval() - cycles_late, s_tranfer_pending_event);
+ }
+ }
+}
+
void DoState(PointerWrap& p)
{
for (int i = 0; i < MAX_SI_CHANNELS; i++)
@@ -251,9 +356,6 @@ void DoState(PointerWrap& p)
p.Do(s_si_buffer);
}
-static void ChangeDeviceCallback(u64 user_data, s64 cycles_late);
-static void RunSIBuffer(u64 user_data, s64 cycles_late);
-
void Init()
{
for (int i = 0; i < MAX_SI_CHANNELS; i++)
@@ -445,40 +547,6 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::DirectWrite<u32>(&s_exi_clock_count.hex));
}
-static void UpdateInterrupts()
-{
- // check if we have to update the RDSTINT flag
- if (s_status_reg.RDST0 || s_status_reg.RDST1 || s_status_reg.RDST2 || s_status_reg.RDST3)
- s_com_csr.RDSTINT = 1;
- else
- s_com_csr.RDSTINT = 0;
-
- // check if we have to generate an interrupt
- if ((s_com_csr.RDSTINT & s_com_csr.RDSTINTMSK) || (s_com_csr.TCINT & s_com_csr.TCINTMSK))
- {
- ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_SI, true);
- }
- else
- {
- ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_SI, false);
- }
-}
-
-void GenerateSIInterrupt(SIInterruptType type)
-{
- switch (type)
- {
- case INT_RDSTINT:
- s_com_csr.RDSTINT = 1;
- break;
- case INT_TCINT:
- s_com_csr.TCINT = 1;
- break;
- }
-
- UpdateInterrupts();
-}
-
void RemoveDevice(int device_number)
{
s_channel.at(device_number).device.reset();
@@ -500,45 +568,6 @@ void AddDevice(const SIDevices device, int device_number)
AddDevice(SIDevice_Create(device, device_number));
}
-static void SetNoResponse(u32 channel)
-{
- // raise the NO RESPONSE error
- switch (channel)
- {
- case 0:
- s_status_reg.NOREP0 = 1;
- break;
- case 1:
- s_status_reg.NOREP1 = 1;
- break;
- case 2:
- s_status_reg.NOREP2 = 1;
- break;
- case 3:
- s_status_reg.NOREP3 = 1;
- break;
- }
- s_com_csr.COMERR = 1;
-}
-
-static void ChangeDeviceCallback(u64 user_data, s64 cycles_late)
-{
- u8 channel = (u8)(user_data >> 32);
- SIDevices device = (SIDevices)(u32)user_data;
-
- // Skip redundant (spammed) device changes
- if (GetDeviceType(channel) != device)
- {
- s_channel[channel].out.hex = 0;
- s_channel[channel].in_hi.hex = 0;
- s_channel[channel].in_lo.hex = 0;
-
- SetNoResponse(channel);
-
- AddDevice(device, channel);
- }
-}
-
void ChangeDevice(SIDevices device, int channel)
{
// Called from GUI, so we need to use FromThread::NON_CPU.
@@ -591,42 +620,6 @@ SIDevices GetDeviceType(int channel)
return s_channel[channel].device->GetDeviceType();
}
-static void RunSIBuffer(u64 user_data, s64 cycles_late)
-{
- if (s_com_csr.TSTART)
- {
- // Math in_length
- int in_length = s_com_csr.INLNGTH;
- if (in_length == 0)
- in_length = 128;
- else
- in_length++;
-
- // Math out_length
- int out_length = s_com_csr.OUTLNGTH;
- if (out_length == 0)
- out_length = 128;
- else
- out_length++;
-
- std::unique_ptr<ISIDevice>& device = s_channel[s_com_csr.CHANNEL].device;
- int numOutput = device->RunBuffer(s_si_buffer.data(), in_length);
-
- DEBUG_LOG(SERIALINTERFACE, "RunSIBuffer chan: %d inLen: %i outLen: %i processed: %i",
- s_com_csr.CHANNEL, in_length, out_length, numOutput);
-
- if (numOutput != 0)
- {
- s_com_csr.TSTART = 0;
- GenerateSIInterrupt(INT_TCINT);
- }
- else
- {
- CoreTiming::ScheduleEvent(device->TransferInterval() - cycles_late, s_tranfer_pending_event);
- }
- }
-}
-
u32 GetPollXLines()
{
return s_poll.X;