2008-11-03 00:36:40 +00:00
|
|
|
#include <assert.h>
|
2017-02-11 15:00:24 -05:00
|
|
|
#include "string_format.h"
|
2008-11-03 00:36:40 +00:00
|
|
|
#include "Iop_DmacChannel.h"
|
|
|
|
#include "Iop_Dmac.h"
|
2021-05-25 10:41:11 +02:00
|
|
|
#include "Iop_Intc.h"
|
2019-02-06 13:34:51 -05:00
|
|
|
#include "../states/RegisterStateFile.h"
|
2008-11-03 00:36:40 +00:00
|
|
|
|
|
|
|
using namespace Iop;
|
|
|
|
using namespace Iop::Dmac;
|
|
|
|
|
2017-02-11 15:00:24 -05:00
|
|
|
#define STATE_REGS_XML_FORMAT ("iop_dmac/channel_%d.xml")
|
2018-04-30 21:01:23 +01:00
|
|
|
#define STATE_REGS_CHCR ("CHCR")
|
|
|
|
#define STATE_REGS_BCR ("BCR")
|
|
|
|
#define STATE_REGS_MADR ("MADR")
|
|
|
|
|
2021-05-25 10:41:11 +02:00
|
|
|
CChannel::CChannel(uint32 baseAddress, unsigned int number, unsigned int intrLine, CDmac& dmac)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_dmac(dmac)
|
|
|
|
, m_number(number)
|
2021-05-25 10:41:11 +02:00
|
|
|
, m_intrLine(intrLine)
|
2018-04-30 21:01:23 +01:00
|
|
|
, m_baseAddress(baseAddress)
|
2008-11-03 00:36:40 +00:00
|
|
|
{
|
2012-04-07 20:33:13 +00:00
|
|
|
Reset();
|
2008-11-03 00:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::Reset()
|
|
|
|
{
|
2012-04-07 20:33:13 +00:00
|
|
|
m_CHCR <<= 0;
|
|
|
|
m_BCR <<= 0;
|
|
|
|
m_MADR = 0;
|
2008-11-03 00:36:40 +00:00
|
|
|
}
|
|
|
|
|
2017-02-11 15:00:24 -05:00
|
|
|
void CChannel::LoadState(Framework::CZipArchiveReader& archive)
|
|
|
|
{
|
|
|
|
auto path = string_format(STATE_REGS_XML_FORMAT, m_number);
|
|
|
|
auto registerFile = CRegisterStateFile(*archive.BeginReadFile(path.c_str()));
|
|
|
|
m_CHCR <<= registerFile.GetRegister32(STATE_REGS_CHCR);
|
2018-04-30 21:01:23 +01:00
|
|
|
m_BCR <<= registerFile.GetRegister32(STATE_REGS_BCR);
|
|
|
|
m_MADR = registerFile.GetRegister32(STATE_REGS_MADR);
|
2017-02-11 15:00:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::SaveState(Framework::CZipArchiveWriter& archive)
|
|
|
|
{
|
|
|
|
auto path = string_format(STATE_REGS_XML_FORMAT, m_number);
|
2023-07-23 17:22:18 -04:00
|
|
|
auto registerFile = std::make_unique<CRegisterStateFile>(path.c_str());
|
2017-02-11 15:00:24 -05:00
|
|
|
registerFile->SetRegister32(STATE_REGS_CHCR, m_CHCR);
|
2018-04-30 21:01:23 +01:00
|
|
|
registerFile->SetRegister32(STATE_REGS_BCR, m_BCR);
|
2017-02-11 15:00:24 -05:00
|
|
|
registerFile->SetRegister32(STATE_REGS_MADR, m_MADR);
|
2023-07-23 17:22:18 -04:00
|
|
|
archive.InsertFile(std::move(registerFile));
|
2017-02-11 15:00:24 -05:00
|
|
|
}
|
|
|
|
|
2008-11-03 00:36:40 +00:00
|
|
|
void CChannel::SetReceiveFunction(const ReceiveFunctionType& receiveFunction)
|
|
|
|
{
|
|
|
|
m_receiveFunction = receiveFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::ResumeDma()
|
|
|
|
{
|
|
|
|
if(m_CHCR.tr == 0) return;
|
2021-04-01 17:22:33 -04:00
|
|
|
assert(m_CHCR.co == 1);
|
2008-11-03 00:36:40 +00:00
|
|
|
assert(m_receiveFunction);
|
|
|
|
uint32 address = m_MADR & 0x1FFFFFFF;
|
2021-04-01 17:22:33 -04:00
|
|
|
uint32 blocksTransfered = m_receiveFunction(m_dmac.GetRam() + address, m_BCR.bs * 4, m_BCR.ba, m_CHCR.dr);
|
2008-11-03 00:36:40 +00:00
|
|
|
assert(blocksTransfered <= m_BCR.ba);
|
|
|
|
m_BCR.ba -= blocksTransfered;
|
2013-03-06 04:42:17 +00:00
|
|
|
m_MADR += (m_BCR.bs * 4) * blocksTransfered;
|
2008-11-03 00:36:40 +00:00
|
|
|
|
|
|
|
if(m_BCR.ba == 0)
|
|
|
|
{
|
|
|
|
//Trigger interrupt
|
|
|
|
m_CHCR.tr = 0;
|
2021-05-25 10:41:11 +02:00
|
|
|
m_dmac.AssertLine(m_intrLine - CIntc::LINE_DMA_BASE);
|
2008-11-03 00:36:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CChannel::ReadRegister(uint32 address)
|
|
|
|
{
|
|
|
|
switch(address - m_baseAddress)
|
|
|
|
{
|
|
|
|
case REG_MADR:
|
|
|
|
return m_MADR;
|
|
|
|
break;
|
|
|
|
case REG_BCR:
|
|
|
|
return m_BCR;
|
|
|
|
break;
|
|
|
|
case REG_CHCR:
|
|
|
|
return m_CHCR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CChannel::WriteRegister(uint32 address, uint32 value)
|
|
|
|
{
|
|
|
|
switch(address - m_baseAddress)
|
|
|
|
{
|
|
|
|
case REG_MADR:
|
|
|
|
m_MADR = value;
|
|
|
|
break;
|
|
|
|
case REG_BCR:
|
|
|
|
m_BCR <<= value;
|
|
|
|
break;
|
2012-04-07 20:33:13 +00:00
|
|
|
case REG_BCR + 2:
|
|
|
|
//Not really cool...
|
|
|
|
m_BCR.ba = static_cast<uint16>(value);
|
|
|
|
break;
|
2008-11-03 00:36:40 +00:00
|
|
|
case REG_CHCR:
|
|
|
|
m_CHCR <<= value;
|
|
|
|
if(m_CHCR.tr)
|
|
|
|
{
|
|
|
|
ResumeDma();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|