mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-26 15:49:50 -06:00
fix weirdo serialinterface (pad) errors. get rid of si_channel. i guess it was a bad idea :<
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2135 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -618,14 +618,6 @@
|
|||||||
RelativePath=".\Src\HW\SI.h"
|
RelativePath=".\Src\HW\SI.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\Src\HW\SI_Channel.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\Src\HW\SI_Channel.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Src\HW\SI_Device.cpp"
|
RelativePath=".\Src\HW\SI_Device.cpp"
|
||||||
>
|
>
|
||||||
|
@ -22,23 +22,96 @@
|
|||||||
#include "PeripheralInterface.h"
|
#include "PeripheralInterface.h"
|
||||||
|
|
||||||
#include "SI.h"
|
#include "SI.h"
|
||||||
#include "SI_Channel.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace SerialInterface
|
namespace SerialInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void RunSIBuffer();
|
||||||
|
void UpdateInterrupts();
|
||||||
|
|
||||||
// SI Interrupt Types
|
// SI Interrupt Types
|
||||||
enum SIInterruptType
|
enum SIInterruptType
|
||||||
{
|
{
|
||||||
INT_RDSTINT = 0,
|
INT_RDSTINT = 0,
|
||||||
INT_TCINT = 1,
|
INT_TCINT = 1,
|
||||||
};
|
};
|
||||||
|
static void GenerateSIInterrupt(SIInterruptType _SIInterrupt);
|
||||||
|
|
||||||
// SI number of channels
|
// SI number of channels
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
NUMBER_OF_CHANNELS = 4
|
NUMBER_OF_CHANNELS = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
// SI Internal Hardware Addresses
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SI_CHANNEL_0_OUT = 0x00,
|
||||||
|
SI_CHANNEL_0_IN_HI = 0x04,
|
||||||
|
SI_CHANNEL_0_IN_LO = 0x08,
|
||||||
|
SI_CHANNEL_1_OUT = 0x0C,
|
||||||
|
SI_CHANNEL_1_IN_HI = 0x10,
|
||||||
|
SI_CHANNEL_1_IN_LO = 0x14,
|
||||||
|
SI_CHANNEL_2_OUT = 0x18,
|
||||||
|
SI_CHANNEL_2_IN_HI = 0x1C,
|
||||||
|
SI_CHANNEL_2_IN_LO = 0x20,
|
||||||
|
SI_CHANNEL_3_OUT = 0x24,
|
||||||
|
SI_CHANNEL_3_IN_HI = 0x28,
|
||||||
|
SI_CHANNEL_3_IN_LO = 0x2C,
|
||||||
|
SI_POLL = 0x30,
|
||||||
|
SI_COM_CSR = 0x34,
|
||||||
|
SI_STATUS_REG = 0x38,
|
||||||
|
SI_EXI_CLOCK_COUNT = 0x3C,
|
||||||
|
};
|
||||||
|
|
||||||
|
// SI Channel Output
|
||||||
|
union USIChannelOut
|
||||||
|
{
|
||||||
|
u32 Hex;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned OUTPUT1 : 8;
|
||||||
|
unsigned OUTPUT0 : 8;
|
||||||
|
unsigned CMD : 8;
|
||||||
|
unsigned : 8;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// SI Channel Input High u32
|
||||||
|
union USIChannelIn_Hi
|
||||||
|
{
|
||||||
|
u32 Hex;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned INPUT3 : 8;
|
||||||
|
unsigned INPUT2 : 8;
|
||||||
|
unsigned INPUT1 : 8;
|
||||||
|
unsigned INPUT0 : 6;
|
||||||
|
unsigned ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
|
||||||
|
unsigned ERRSTAT : 1; // 0: no error 1: error on last transfer
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// SI Channel Input Low u32
|
||||||
|
union USIChannelIn_Lo
|
||||||
|
{
|
||||||
|
u32 Hex;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned INPUT7 : 8;
|
||||||
|
unsigned INPUT6 : 8;
|
||||||
|
unsigned INPUT5 : 8;
|
||||||
|
unsigned INPUT4 : 8;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// SI Channel
|
||||||
|
struct SSIChannel
|
||||||
|
{
|
||||||
|
USIChannelOut m_Out;
|
||||||
|
USIChannelIn_Hi m_InHi;
|
||||||
|
USIChannelIn_Lo m_InLo;
|
||||||
|
ISIDevice* m_pDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
// SI Poll: Controls how often a device is polled
|
// SI Poll: Controls how often a device is polled
|
||||||
@ -136,26 +209,34 @@ union USIEXIClockCount
|
|||||||
};
|
};
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
CSIChannel *g_Channel; // Save the channel state here?
|
static SSIChannel g_Channel[NUMBER_OF_CHANNELS];
|
||||||
static USIPoll g_Poll;
|
static USIPoll g_Poll;
|
||||||
static USIComCSR g_ComCSR;
|
static USIComCSR g_ComCSR;
|
||||||
static USIStatusReg g_StatusReg;
|
static USIStatusReg g_StatusReg;
|
||||||
static USIEXIClockCount g_EXIClockCount;
|
static USIEXIClockCount g_EXIClockCount;
|
||||||
static u8 g_SIBuffer[128];
|
static u8 g_SIBuffer[128];
|
||||||
|
|
||||||
static void GenerateSIInterrupt(SIInterruptType _SIInterrupt);
|
void DoState(PointerWrap &p)
|
||||||
void RunSIBuffer();
|
{
|
||||||
void UpdateInterrupts();
|
// p.DoArray(g_Channel);
|
||||||
|
p.Do(g_Poll);
|
||||||
|
p.Do(g_ComCSR);
|
||||||
|
p.Do(g_StatusReg);
|
||||||
|
p.Do(g_EXIClockCount);
|
||||||
|
p.Do(g_SIBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
g_Channel = new CSIChannel[NUMBER_OF_CHANNELS];
|
// TODO: allow dynamic attaching/detaching of devices
|
||||||
|
|
||||||
for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
|
for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
|
||||||
{
|
{
|
||||||
g_Channel[i].m_ChannelId = i;
|
g_Channel[i].m_Out.Hex = 0;
|
||||||
g_Channel[i].AddDevice(SConfig::GetInstance().m_SIDevice[i], i);
|
g_Channel[i].m_InHi.Hex = 0;
|
||||||
|
g_Channel[i].m_InLo.Hex = 0;
|
||||||
|
|
||||||
|
AddDevice(SConfig::GetInstance().m_SIDevice[i], i);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Poll.Hex = 0;
|
g_Poll.Hex = 0;
|
||||||
@ -167,18 +248,11 @@ void Init()
|
|||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
{
|
{
|
||||||
delete [] g_Channel;
|
for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
|
||||||
g_Channel = 0;
|
{
|
||||||
}
|
delete g_Channel[i].m_pDevice;
|
||||||
|
g_Channel[i].m_pDevice = NULL;
|
||||||
void DoState(PointerWrap &p)
|
}
|
||||||
{
|
|
||||||
// p.DoArray(g_Channel);
|
|
||||||
p.Do(g_Poll);
|
|
||||||
p.Do(g_ComCSR);
|
|
||||||
p.Do(g_StatusReg);
|
|
||||||
p.Do(g_EXIClockCount);
|
|
||||||
p.Do(g_SIBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read32(u32& _uReturnValue, const u32 _iAddress)
|
void Read32(u32& _uReturnValue, const u32 _iAddress)
|
||||||
@ -193,19 +267,104 @@ void Read32(u32& _uReturnValue, const u32 _iAddress)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (shuffle2) these assignments are taken from EXI,
|
// registers
|
||||||
// the iAddr amounted to the same, so I'm guessing the rest are too :D
|
switch (_iAddress & 0x3FF)
|
||||||
unsigned int iAddr = _iAddress & 0x3FF;
|
{
|
||||||
unsigned int iRegister = (iAddr >> 2) % 5;
|
//////////////////////////////////////////////////////////////////////////
|
||||||
unsigned int iChannel = (iAddr >> 2) / 5;
|
// Channel 0
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
case SI_CHANNEL_0_OUT:
|
||||||
|
_uReturnValue = g_Channel[0].m_Out.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
if (iChannel < NUMBER_OF_CHANNELS)
|
case SI_CHANNEL_0_IN_HI:
|
||||||
g_Channel[iChannel].Read32(_uReturnValue, iAddr);
|
g_StatusReg.RDST0 = 0;
|
||||||
|
UpdateInterrupts();
|
||||||
|
_uReturnValue = g_Channel[0].m_InHi.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SI_CHANNEL_0_IN_LO:
|
||||||
|
g_StatusReg.RDST0 = 0;
|
||||||
|
UpdateInterrupts();
|
||||||
|
_uReturnValue = g_Channel[0].m_InLo.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Channel 1
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
case SI_CHANNEL_1_OUT:
|
||||||
|
_uReturnValue = g_Channel[1].m_Out.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SI_CHANNEL_1_IN_HI:
|
||||||
|
g_StatusReg.RDST1 = 0;
|
||||||
|
UpdateInterrupts();
|
||||||
|
_uReturnValue = g_Channel[1].m_InHi.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SI_CHANNEL_1_IN_LO:
|
||||||
|
g_StatusReg.RDST1 = 0;
|
||||||
|
UpdateInterrupts();
|
||||||
|
_uReturnValue = g_Channel[1].m_InLo.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Channel 2
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
case SI_CHANNEL_2_OUT:
|
||||||
|
_uReturnValue = g_Channel[2].m_Out.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SI_CHANNEL_2_IN_HI:
|
||||||
|
g_StatusReg.RDST2 = 0;
|
||||||
|
UpdateInterrupts();
|
||||||
|
_uReturnValue = g_Channel[2].m_InHi.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SI_CHANNEL_2_IN_LO:
|
||||||
|
g_StatusReg.RDST2 = 0;
|
||||||
|
UpdateInterrupts();
|
||||||
|
_uReturnValue = g_Channel[2].m_InLo.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Channel 3
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
case SI_CHANNEL_3_OUT:
|
||||||
|
_uReturnValue = g_Channel[3].m_Out.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SI_CHANNEL_3_IN_HI:
|
||||||
|
g_StatusReg.RDST3 = 0;
|
||||||
|
UpdateInterrupts();
|
||||||
|
_uReturnValue = g_Channel[3].m_InHi.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SI_CHANNEL_3_IN_LO:
|
||||||
|
g_StatusReg.RDST3 = 0;
|
||||||
|
UpdateInterrupts();
|
||||||
|
_uReturnValue = g_Channel[3].m_InLo.Hex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SI_POLL: _uReturnValue = g_Poll.Hex; return;
|
||||||
|
case SI_COM_CSR: _uReturnValue = g_ComCSR.Hex; return;
|
||||||
|
case SI_STATUS_REG: _uReturnValue = g_StatusReg.Hex; return;
|
||||||
|
|
||||||
|
case SI_EXI_CLOCK_COUNT: _uReturnValue = g_EXIClockCount.Hex; return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOG(SERIALINTERFACE, "(r32-unk): 0x%08x", _iAddress);
|
||||||
|
_dbg_assert_(SERIALINTERFACE,0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
_uReturnValue = 0xdeadbeef;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write32(const u32 _iValue, const u32 _iAddress)
|
void Write32(const u32 _iValue, const u32 _iAddress)
|
||||||
{
|
{
|
||||||
LOGV(SERIALINTERFACE, 3, "(w32): 0x%08x 0x%08x", _iValue, _iAddress);
|
LOGV(SERIALINTERFACE, 3, "(w32): 0x%08x 0x%08x", _iValue,_iAddress);
|
||||||
|
|
||||||
// SIBuffer
|
// SIBuffer
|
||||||
if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) ||
|
if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) ||
|
||||||
@ -215,12 +374,101 @@ void Write32(const u32 _iValue, const u32 _iAddress)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iAddr = _iAddress & 0x3FF;
|
// registers
|
||||||
int iRegister = (iAddr >> 2) % 5;
|
switch (_iAddress & 0x3FF)
|
||||||
int iChannel = (iAddr >> 2) / 5;
|
{
|
||||||
|
case SI_CHANNEL_0_OUT: g_Channel[0].m_Out.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_0_IN_HI: g_Channel[0].m_InHi.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_0_IN_LO: g_Channel[0].m_InLo.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_1_OUT: g_Channel[1].m_Out.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_1_IN_HI: g_Channel[1].m_InHi.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_1_IN_LO: g_Channel[1].m_InLo.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_2_OUT: g_Channel[2].m_Out.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_2_IN_HI: g_Channel[2].m_InHi.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_2_IN_LO: g_Channel[2].m_InLo.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_3_OUT: g_Channel[3].m_Out.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_3_IN_HI: g_Channel[3].m_InHi.Hex = _iValue; break;
|
||||||
|
case SI_CHANNEL_3_IN_LO: g_Channel[3].m_InLo.Hex = _iValue; break;
|
||||||
|
|
||||||
if (iChannel < NUMBER_OF_CHANNELS)
|
case SI_POLL:
|
||||||
g_Channel[iChannel].Write32(_iValue, iAddr);
|
g_Poll.Hex = _iValue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SI_COM_CSR:
|
||||||
|
{
|
||||||
|
USIComCSR tmpComCSR(_iValue);
|
||||||
|
|
||||||
|
g_ComCSR.CHANNEL = tmpComCSR.CHANNEL;
|
||||||
|
g_ComCSR.INLNGTH = tmpComCSR.INLNGTH;
|
||||||
|
g_ComCSR.OUTLNGTH = tmpComCSR.OUTLNGTH;
|
||||||
|
g_ComCSR.RDSTINTMSK = tmpComCSR.RDSTINTMSK;
|
||||||
|
g_ComCSR.TCINTMSK = tmpComCSR.TCINTMSK;
|
||||||
|
|
||||||
|
g_ComCSR.COMERR = 0;
|
||||||
|
|
||||||
|
if (tmpComCSR.RDSTINT) g_ComCSR.RDSTINT = 0;
|
||||||
|
if (tmpComCSR.TCINT) g_ComCSR.TCINT = 0;
|
||||||
|
|
||||||
|
// be careful: runsi-buffer after updating the INT flags
|
||||||
|
if (tmpComCSR.TSTART) RunSIBuffer();
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SI_STATUS_REG:
|
||||||
|
{
|
||||||
|
USIStatusReg tmpStatus(_iValue);
|
||||||
|
|
||||||
|
// just update the writable bits
|
||||||
|
g_StatusReg.NOREP0 = tmpStatus.NOREP0 ? 1 : 0;
|
||||||
|
g_StatusReg.COLL0 = tmpStatus.COLL0 ? 1 : 0;
|
||||||
|
g_StatusReg.OVRUN0 = tmpStatus.OVRUN0 ? 1 : 0;
|
||||||
|
g_StatusReg.UNRUN0 = tmpStatus.UNRUN0 ? 1 : 0;
|
||||||
|
|
||||||
|
g_StatusReg.NOREP1 = tmpStatus.NOREP1 ? 1 : 0;
|
||||||
|
g_StatusReg.COLL1 = tmpStatus.COLL1 ? 1 : 0;
|
||||||
|
g_StatusReg.OVRUN1 = tmpStatus.OVRUN1 ? 1 : 0;
|
||||||
|
g_StatusReg.UNRUN1 = tmpStatus.UNRUN1 ? 1 : 0;
|
||||||
|
|
||||||
|
g_StatusReg.NOREP2 = tmpStatus.NOREP2 ? 1 : 0;
|
||||||
|
g_StatusReg.COLL2 = tmpStatus.COLL2 ? 1 : 0;
|
||||||
|
g_StatusReg.OVRUN2 = tmpStatus.OVRUN2 ? 1 : 0;
|
||||||
|
g_StatusReg.UNRUN2 = tmpStatus.UNRUN2 ? 1 : 0;
|
||||||
|
|
||||||
|
g_StatusReg.NOREP3 = tmpStatus.NOREP3 ? 1 : 0;
|
||||||
|
g_StatusReg.COLL3 = tmpStatus.COLL3 ? 1 : 0;
|
||||||
|
g_StatusReg.OVRUN3 = tmpStatus.OVRUN3 ? 1 : 0;
|
||||||
|
g_StatusReg.UNRUN3 = tmpStatus.UNRUN3 ? 1 : 0;
|
||||||
|
|
||||||
|
// send command to devices
|
||||||
|
if (tmpStatus.WR)
|
||||||
|
{
|
||||||
|
g_StatusReg.WR = 0;
|
||||||
|
g_Channel[0].m_pDevice->SendCommand(g_Channel[0].m_Out.Hex);
|
||||||
|
g_Channel[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex);
|
||||||
|
g_Channel[2].m_pDevice->SendCommand(g_Channel[2].m_Out.Hex);
|
||||||
|
g_Channel[3].m_pDevice->SendCommand(g_Channel[3].m_Out.Hex);
|
||||||
|
|
||||||
|
g_StatusReg.WRST0 = 0;
|
||||||
|
g_StatusReg.WRST1 = 0;
|
||||||
|
g_StatusReg.WRST2 = 0;
|
||||||
|
g_StatusReg.WRST3 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SI_EXI_CLOCK_COUNT:
|
||||||
|
g_EXIClockCount.Hex = _iValue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x80:
|
||||||
|
LOG(SERIALINTERFACE, "WII something at 0xCD006480");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_dbg_assert_(SERIALINTERFACE,0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInterrupts()
|
void UpdateInterrupts()
|
||||||
@ -255,6 +503,27 @@ void GenerateSIInterrupt(SIInterruptType _SIInterrupt)
|
|||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoveDevice(int _iDeviceNumber)
|
||||||
|
{
|
||||||
|
if (g_Channel[_iDeviceNumber].m_pDevice != NULL)
|
||||||
|
{
|
||||||
|
delete g_Channel[_iDeviceNumber].m_pDevice;
|
||||||
|
g_Channel[_iDeviceNumber].m_pDevice = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddDevice(const TSIDevices _device, int _iDeviceNumber)
|
||||||
|
{
|
||||||
|
//_dbg_assert_(SERIALINTERFACE, _iDeviceNumber < NUMBER_OF_CHANNELS);
|
||||||
|
|
||||||
|
// delete the old device
|
||||||
|
RemoveDevice(_iDeviceNumber);
|
||||||
|
|
||||||
|
// create the new one
|
||||||
|
g_Channel[_iDeviceNumber].m_pDevice = SIDevice_Create(_device, _iDeviceNumber);
|
||||||
|
_dbg_assert_(SERIALINTERFACE, g_Channel[_iDeviceNumber].m_pDevice != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateDevices()
|
void UpdateDevices()
|
||||||
{
|
{
|
||||||
// Update channels
|
// Update channels
|
||||||
@ -283,9 +552,9 @@ void RunSIBuffer()
|
|||||||
else
|
else
|
||||||
outLength++;
|
outLength++;
|
||||||
|
|
||||||
#ifdef LOGGING
|
#ifdef LOGGING
|
||||||
int numOutput =
|
int numOutput =
|
||||||
#endif
|
#endif
|
||||||
g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength);
|
g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength);
|
||||||
|
|
||||||
LOGV(SERIALINTERFACE, 2, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput);
|
LOGV(SERIALINTERFACE, 2, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput);
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#define _SERIALINTERFACE_H
|
#define _SERIALINTERFACE_H
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
#include "SI_Device.h"
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
|
|
||||||
namespace SerialInterface
|
namespace SerialInterface
|
||||||
@ -29,6 +30,9 @@ void DoState(PointerWrap &p);
|
|||||||
|
|
||||||
void UpdateDevices();
|
void UpdateDevices();
|
||||||
|
|
||||||
|
void RemoveDevice(int _iDeviceNumber);
|
||||||
|
void AddDevice(const TSIDevices _device, int _iDeviceNumber);
|
||||||
|
|
||||||
void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress);
|
void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress);
|
||||||
void HWCALL Write32(const u32 _iValue, const u32 _iAddress);
|
void HWCALL Write32(const u32 _iValue, const u32 _iAddress);
|
||||||
|
|
||||||
|
@ -1,257 +0,0 @@
|
|||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, version 2.0.
|
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License 2.0 for more details.
|
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
|
||||||
// If not, see http://www.gnu.org/licenses/
|
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
|
||||||
// http://code.google.com/p/dolphin-emu/
|
|
||||||
|
|
||||||
#include "SI_Channel.h"
|
|
||||||
#include "SI.h"
|
|
||||||
#include "PeripheralInterface.h"
|
|
||||||
#include "../PowerPC/PowerPC.h"
|
|
||||||
|
|
||||||
#include "SI.cpp"
|
|
||||||
using namespace SerialInterface;
|
|
||||||
|
|
||||||
CSIChannel::CSIChannel()
|
|
||||||
{
|
|
||||||
m_Out.Hex = 0;
|
|
||||||
m_InHi.Hex = 0;
|
|
||||||
m_InLo.Hex = 0;
|
|
||||||
|
|
||||||
m_pDevice = SIDevice_Create(SI_DUMMY, m_ChannelId);
|
|
||||||
_dbg_assert_(SERIALINTERFACE, m_pDevice != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
CSIChannel::~CSIChannel()
|
|
||||||
{
|
|
||||||
RemoveDevice();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSIChannel::AddDevice(const TSIDevices _device, int _iDeviceNumber)
|
|
||||||
{
|
|
||||||
//_dbg_assert_(SERIALINTERFACE, _iSlot < NUM_DEVICES);
|
|
||||||
|
|
||||||
// delete the old device
|
|
||||||
RemoveDevice();
|
|
||||||
|
|
||||||
// create the new one
|
|
||||||
m_pDevice = SIDevice_Create(_device, _iDeviceNumber);
|
|
||||||
_dbg_assert_(SERIALINTERFACE, m_pDevice != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSIChannel::RemoveDevice()
|
|
||||||
{
|
|
||||||
if (m_pDevice != NULL)
|
|
||||||
{
|
|
||||||
delete m_pDevice;
|
|
||||||
m_pDevice = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSIChannel::Read32(u32& _uReturnValue, const u32 _iAddr)
|
|
||||||
{
|
|
||||||
// registers
|
|
||||||
switch (_iAddr)
|
|
||||||
{
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Channel 0
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
case SI_CHANNEL_0_OUT:
|
|
||||||
_uReturnValue = m_Out.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_CHANNEL_0_IN_HI:
|
|
||||||
g_StatusReg.RDST0 = 0;
|
|
||||||
UpdateInterrupts();
|
|
||||||
_uReturnValue = m_InHi.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_CHANNEL_0_IN_LO:
|
|
||||||
g_StatusReg.RDST0 = 0;
|
|
||||||
UpdateInterrupts();
|
|
||||||
_uReturnValue = m_InLo.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Channel 1
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
case SI_CHANNEL_1_OUT:
|
|
||||||
_uReturnValue = m_Out.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_CHANNEL_1_IN_HI:
|
|
||||||
g_StatusReg.RDST1 = 0;
|
|
||||||
UpdateInterrupts();
|
|
||||||
_uReturnValue = m_InHi.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_CHANNEL_1_IN_LO:
|
|
||||||
g_StatusReg.RDST1 = 0;
|
|
||||||
UpdateInterrupts();
|
|
||||||
_uReturnValue = m_InLo.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Channel 2
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
case SI_CHANNEL_2_OUT:
|
|
||||||
_uReturnValue = m_Out.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_CHANNEL_2_IN_HI:
|
|
||||||
g_StatusReg.RDST2 = 0;
|
|
||||||
UpdateInterrupts();
|
|
||||||
_uReturnValue = m_InHi.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_CHANNEL_2_IN_LO:
|
|
||||||
g_StatusReg.RDST2 = 0;
|
|
||||||
UpdateInterrupts();
|
|
||||||
_uReturnValue = m_InLo.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Channel 3
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
case SI_CHANNEL_3_OUT:
|
|
||||||
_uReturnValue = m_Out.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_CHANNEL_3_IN_HI:
|
|
||||||
g_StatusReg.RDST3 = 0;
|
|
||||||
UpdateInterrupts();
|
|
||||||
_uReturnValue = m_InHi.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_CHANNEL_3_IN_LO:
|
|
||||||
g_StatusReg.RDST3 = 0;
|
|
||||||
UpdateInterrupts();
|
|
||||||
_uReturnValue = m_InLo.Hex;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SI_POLL: _uReturnValue = g_Poll.Hex; return;
|
|
||||||
case SI_COM_CSR: _uReturnValue = g_ComCSR.Hex; return;
|
|
||||||
case SI_STATUS_REG: _uReturnValue = g_StatusReg.Hex; return;
|
|
||||||
|
|
||||||
case SI_EXI_CLOCK_COUNT: _uReturnValue = g_EXIClockCount.Hex; return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// (shuffle2) FIX!
|
|
||||||
//LOG(SERIALINTERFACE, "(r32-unk): 0x%08x", _iAddress);
|
|
||||||
_dbg_assert_(SERIALINTERFACE, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// error
|
|
||||||
_uReturnValue = 0xdeadbeef;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSIChannel::Write32(const u32 _iValue, const u32 iAddr)
|
|
||||||
{
|
|
||||||
// registers
|
|
||||||
switch (iAddr)
|
|
||||||
{
|
|
||||||
case SI_CHANNEL_0_OUT: m_Out.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_0_IN_HI: m_InHi.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_0_IN_LO: m_InLo.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_1_OUT: m_Out.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_1_IN_HI: m_InHi.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_1_IN_LO: m_InLo.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_2_OUT: m_Out.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_2_IN_HI: m_InHi.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_2_IN_LO: m_InLo.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_3_OUT: m_Out.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_3_IN_HI: m_InHi.Hex = _iValue; break;
|
|
||||||
case SI_CHANNEL_3_IN_LO: m_InLo.Hex = _iValue; break;
|
|
||||||
|
|
||||||
case SI_POLL:
|
|
||||||
g_Poll.Hex = _iValue;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SI_COM_CSR:
|
|
||||||
{
|
|
||||||
USIComCSR tmpComCSR(_iValue);
|
|
||||||
|
|
||||||
g_ComCSR.CHANNEL = tmpComCSR.CHANNEL;
|
|
||||||
g_ComCSR.INLNGTH = tmpComCSR.INLNGTH;
|
|
||||||
g_ComCSR.OUTLNGTH = tmpComCSR.OUTLNGTH;
|
|
||||||
g_ComCSR.RDSTINTMSK = tmpComCSR.RDSTINTMSK;
|
|
||||||
g_ComCSR.TCINTMSK = tmpComCSR.TCINTMSK;
|
|
||||||
|
|
||||||
g_ComCSR.COMERR = 0;
|
|
||||||
|
|
||||||
if (tmpComCSR.RDSTINT) g_ComCSR.RDSTINT = 0;
|
|
||||||
if (tmpComCSR.TCINT) g_ComCSR.TCINT = 0;
|
|
||||||
|
|
||||||
// be careful: RunSIBuffer after updating the INT flags
|
|
||||||
if (tmpComCSR.TSTART) RunSIBuffer();
|
|
||||||
UpdateInterrupts();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SI_STATUS_REG:
|
|
||||||
{
|
|
||||||
USIStatusReg tmpStatus(_iValue);
|
|
||||||
|
|
||||||
// just update the writable bits
|
|
||||||
g_StatusReg.NOREP0 = tmpStatus.NOREP0 ? 1 : 0;
|
|
||||||
g_StatusReg.COLL0 = tmpStatus.COLL0 ? 1 : 0;
|
|
||||||
g_StatusReg.OVRUN0 = tmpStatus.OVRUN0 ? 1 : 0;
|
|
||||||
g_StatusReg.UNRUN0 = tmpStatus.UNRUN0 ? 1 : 0;
|
|
||||||
|
|
||||||
g_StatusReg.NOREP1 = tmpStatus.NOREP1 ? 1 : 0;
|
|
||||||
g_StatusReg.COLL1 = tmpStatus.COLL1 ? 1 : 0;
|
|
||||||
g_StatusReg.OVRUN1 = tmpStatus.OVRUN1 ? 1 : 0;
|
|
||||||
g_StatusReg.UNRUN1 = tmpStatus.UNRUN1 ? 1 : 0;
|
|
||||||
|
|
||||||
g_StatusReg.NOREP2 = tmpStatus.NOREP2 ? 1 : 0;
|
|
||||||
g_StatusReg.COLL2 = tmpStatus.COLL2 ? 1 : 0;
|
|
||||||
g_StatusReg.OVRUN2 = tmpStatus.OVRUN2 ? 1 : 0;
|
|
||||||
g_StatusReg.UNRUN2 = tmpStatus.UNRUN2 ? 1 : 0;
|
|
||||||
|
|
||||||
g_StatusReg.NOREP3 = tmpStatus.NOREP3 ? 1 : 0;
|
|
||||||
g_StatusReg.COLL3 = tmpStatus.COLL3 ? 1 : 0;
|
|
||||||
g_StatusReg.OVRUN3 = tmpStatus.OVRUN3 ? 1 : 0;
|
|
||||||
g_StatusReg.UNRUN3 = tmpStatus.UNRUN3 ? 1 : 0;
|
|
||||||
|
|
||||||
// send command to devices
|
|
||||||
if (tmpStatus.WR)
|
|
||||||
{
|
|
||||||
g_StatusReg.WR = 0;
|
|
||||||
m_pDevice->SendCommand(m_Out.Hex);
|
|
||||||
m_pDevice->SendCommand(m_Out.Hex);
|
|
||||||
m_pDevice->SendCommand(m_Out.Hex);
|
|
||||||
m_pDevice->SendCommand(m_Out.Hex);
|
|
||||||
|
|
||||||
g_StatusReg.WRST0 = 0;
|
|
||||||
g_StatusReg.WRST1 = 0;
|
|
||||||
g_StatusReg.WRST2 = 0;
|
|
||||||
g_StatusReg.WRST3 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SI_EXI_CLOCK_COUNT:
|
|
||||||
g_EXIClockCount.Hex = _iValue;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x80:
|
|
||||||
LOG(SERIALINTERFACE, "WII something at 0xCD006480");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
_dbg_assert_(SERIALINTERFACE,0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,111 +0,0 @@
|
|||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, version 2.0.
|
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License 2.0 for more details.
|
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
|
||||||
// If not, see http://www.gnu.org/licenses/
|
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
|
||||||
// http://code.google.com/p/dolphin-emu/
|
|
||||||
#ifndef _SICHANNEL_H
|
|
||||||
#define _SICHANNEL_H
|
|
||||||
|
|
||||||
#include "Common.h"
|
|
||||||
|
|
||||||
#include "SI_Device.h"
|
|
||||||
|
|
||||||
class CSIChannel
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
// SI Internal Hardware Addresses
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
SI_CHANNEL_0_OUT = 0x00,
|
|
||||||
SI_CHANNEL_0_IN_HI = 0x04,
|
|
||||||
SI_CHANNEL_0_IN_LO = 0x08,
|
|
||||||
SI_CHANNEL_1_OUT = 0x0C,
|
|
||||||
SI_CHANNEL_1_IN_HI = 0x10,
|
|
||||||
SI_CHANNEL_1_IN_LO = 0x14,
|
|
||||||
SI_CHANNEL_2_OUT = 0x18,
|
|
||||||
SI_CHANNEL_2_IN_HI = 0x1C,
|
|
||||||
SI_CHANNEL_2_IN_LO = 0x20,
|
|
||||||
SI_CHANNEL_3_OUT = 0x24,
|
|
||||||
SI_CHANNEL_3_IN_HI = 0x28,
|
|
||||||
SI_CHANNEL_3_IN_LO = 0x2C,
|
|
||||||
SI_POLL = 0x30,
|
|
||||||
SI_COM_CSR = 0x34,
|
|
||||||
SI_STATUS_REG = 0x38,
|
|
||||||
SI_EXI_CLOCK_COUNT = 0x3C,
|
|
||||||
};
|
|
||||||
|
|
||||||
// SI Channel Output
|
|
||||||
union USIChannelOut
|
|
||||||
{
|
|
||||||
u32 Hex;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned OUTPUT1 : 8;
|
|
||||||
unsigned OUTPUT0 : 8;
|
|
||||||
unsigned CMD : 8;
|
|
||||||
unsigned : 8;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// SI Channel Input High u32
|
|
||||||
union USIChannelIn_Hi
|
|
||||||
{
|
|
||||||
u32 Hex;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned INPUT3 : 8;
|
|
||||||
unsigned INPUT2 : 8;
|
|
||||||
unsigned INPUT1 : 8;
|
|
||||||
unsigned INPUT0 : 6;
|
|
||||||
unsigned ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
|
|
||||||
unsigned ERRSTAT : 1; // 0: no error 1: error on last transfer
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// SI Channel Input Low u32
|
|
||||||
union USIChannelIn_Lo
|
|
||||||
{
|
|
||||||
u32 Hex;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned INPUT7 : 8;
|
|
||||||
unsigned INPUT6 : 8;
|
|
||||||
unsigned INPUT5 : 8;
|
|
||||||
unsigned INPUT4 : 8;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
public: // HAX
|
|
||||||
// SI Channel
|
|
||||||
USIChannelOut m_Out;
|
|
||||||
USIChannelIn_Hi m_InHi;
|
|
||||||
USIChannelIn_Lo m_InLo;
|
|
||||||
ISIDevice* m_pDevice;
|
|
||||||
|
|
||||||
//public:
|
|
||||||
// ChannelId for debugging
|
|
||||||
u32 m_ChannelId;
|
|
||||||
|
|
||||||
CSIChannel();
|
|
||||||
~CSIChannel();
|
|
||||||
|
|
||||||
void AddDevice(const TSIDevices _device, int _iSlot);
|
|
||||||
|
|
||||||
// Remove the device
|
|
||||||
void RemoveDevice();
|
|
||||||
|
|
||||||
void Read32(u32& _uReturnValue, const u32 _iRegister);
|
|
||||||
void Write32(const u32 _iValue, const u32 _iRegister);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -118,8 +118,7 @@ CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
|
|||||||
{
|
{
|
||||||
SPADStatus PadStatus;
|
SPADStatus PadStatus;
|
||||||
memset(&PadStatus, 0 ,sizeof(PadStatus));
|
memset(&PadStatus, 0 ,sizeof(PadStatus));
|
||||||
Common::PluginPAD* pad =
|
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber);
|
||||||
CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber);
|
|
||||||
pad->PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
|
pad->PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
|
||||||
|
|
||||||
_Hi = (u32)((u8)PadStatus.stickY);
|
_Hi = (u32)((u8)PadStatus.stickY);
|
||||||
@ -146,7 +145,7 @@ CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
|
|||||||
void
|
void
|
||||||
CSIDevice_GCController::SendCommand(u32 _Cmd)
|
CSIDevice_GCController::SendCommand(u32 _Cmd)
|
||||||
{
|
{
|
||||||
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(0);
|
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber);
|
||||||
UCommand command(_Cmd);
|
UCommand command(_Cmd);
|
||||||
|
|
||||||
switch(command.Command)
|
switch(command.Command)
|
||||||
|
Reference in New Issue
Block a user