Skip to content
Snippets Groups Projects
dma.h 2.22 KiB
Newer Older
#pragma once
#include <cstdint>

class ComponentManager;

namespace iop
{
	enum class TransferMode : uint32_t
		Burst,
		Slice,
		Linked_List,
		Chain
	};

	enum DMAChannels : uint32_t
	{
		MDECin,
		MDECout,
		SIF2,
		CDVD,
		SPU1,
		PIO,
		OTC,
		SPU2,
		DEV9,
		SIF0,
		SIF1,
		SIO2in,
		SIO2out
	};

	/* General info about DMA for each channel. */
	union DMAControlReg
	{
		uint32_t value;
		struct
		{
			uint32_t trans_dir : 1;
			uint32_t addr_step : 1;
			uint32_t : 6;
			uint32_t chop_enable : 1;
			TransferMode transfer_mode : 2;
			uint32_t : 5;
			uint32_t chop_dma : 3;
			uint32_t : 1;
			uint32_t chop_cpu : 3;
			uint32_t : 1;
			uint32_t enable : 1;
			uint32_t : 3;
			uint32_t trigger : 1;
			uint32_t : 3;
		};
	};

	/* Holds info about block size and count. */
	union DMABlockReg
	{
		uint32_t value;
		struct
		{
			uint16_t size; /* Block size in words. */
			uint16_t count; /* Only used in Request sync mode. */
		};
	};

	/* A DMA channel */
	struct DMAChannel
	{
		uint32_t base;
		DMABlockReg block_ctrl;
		DMAControlReg channel_ctrl;
		uint32_t tadr;
	union DICR
	{
		uint32_t value;
		struct
		{
			uint32_t completion : 7;
			uint32_t : 8;
			uint32_t force : 1;
			uint32_t enable : 7;
			uint32_t master_enable : 1;
			uint32_t flags : 7;
			uint32_t master_flag : 1;
		};
	};

	union DICR2
	{
		uint32_t value;
		struct
		{
			uint32_t tag : 13;
			uint32_t : 3;
			uint32_t mask : 6;
			uint32_t : 2;
			uint32_t flags : 6;
			uint32_t : 2;
	/* The standalone registers */
	struct DMAGlobals
	{
		uint32_t dpcr[2];
		DICR dicr;
		DICR2 dicr2;
		uint32_t pad1; /* Added so we can read the struct nicely using pointer arithmetic */
		uint32_t dmacen;
		uint32_t pad2;
		uint32_t dmacinten;
	};

	/* A class that manages all DMA routines. */
	class DMAController {
	public:
		DMAController(ComponentManager* manager);

		void tick();
		void transfer_finished(DMAChannels channel);

		void start(DMAChannels channel);
		void block_copy(DMAChannels channel);
		void list_copy(DMAChannels channel);

		uint32_t read(uint32_t address);
		void write(uint32_t address, uint32_t data);

	public:
		DMAChannel channels[13] = {};
		DMAGlobals globals = {};

		bool irq_pending = false;
		ComponentManager* manager = nullptr;