Newer
Older
#include <cpu/iop/dma.h>
#include <common/memory.h>
#include <fmt/color.h>
namespace iop
{
/* DMA Controller class implementation. */
DMAController::DMAController(ComponentManager* manager) :
manager(manager)
{
}
void DMAController::tick()
{
}
void DMAController::transfer_finished(DMAChannels dma_channel)
{
}
void DMAController::start(DMAChannels dma_channel)
{
DMAChannel& channel = channels[dma_channel];
/* Start linked list copy routine. */
switch (channel.channel_ctrl.transfer_mode)
case TransferMode::Linked_List:
list_copy(dma_channel); break;
default:
block_copy(dma_channel);
}
/* Complete the transfer. */
transfer_finished(dma_channel);
}
void DMAController::block_copy(DMAChannels dma_channel)
{
}
void DMAController::list_copy(DMAChannels dma_channel)
{
}
uint32_t DMAController::read(uint32_t address)
{
/* Get channel information from address. */
bool group = address & 0x100;
uint16_t channel_num = (address & 0x70) >> 4;
uint16_t offset = (address & 0xf) >> 2;
uint32_t* ptr = nullptr;
if (channel_num >= 0 && channel_num <= 6)
{
ptr = (uint32_t*)&channels[channel_num + group * 7] + offset;
}
ptr = (uint32_t*)&globals + 2 * offset + group;
}
else
{
fmt::print("[IOP DMA] Invalid channel number {:d}\n", channel_num);
std::abort();
fmt::print("[IOP DMA] Reading {:#x} from DMA channel {:d} at address {:#x}\n", *ptr, channel_num, address);
return *ptr;
void DMAController::write(uint32_t address, uint32_t data)
{
/* Get channel information from address. */
bool group = address & 0x100;
uint16_t channel_num = (address & 0x70) >> 4;
uint16_t offset = (address & 0xf) >> 2;
fmt::print("[IOP DMA] Writing {:#x} to DMA channel {:d} at address {:#x}\n", data, channel_num, address);
if (channel_num >= 0 && channel_num <= 6)
{
auto ptr = (uint32_t*)&channels[channel_num + group * 7] + offset;
*ptr = data;
}
auto ptr = (uint32_t*)&globals + 2 * offset + group;
*ptr = data;
if (offset == 4 && !group)
/* Handle special case for writing to DICR */
auto& irq = globals.dicr;
irq.master_flag = irq.force || (irq.master_enable && ((irq.enable & irq.flags) > 0));
else
{
fmt::print("[IOP DMA] Invalid channel number {:d}\n", channel_num);
std::abort();
}