Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#pragma once
#include <cstdint>
namespace iop
{
enum class SyncType : uint32_t
{
Manual = 0,
Request = 1,
Linked_List = 2
};
enum DMAChannels : uint32_t
{
MDECin = 0x0,
MDECout = 0x1,
GPU = 0x2,
CDROM = 0x3,
SPU = 0x4,
PIO = 0x5,
OTC = 0x6
};
/* 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;
SyncType sync_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 block_size;
uint16_t block_count; /* Only used in Request sync mode. */
};
};
/* A DMA channel */
struct DMAChannel
{
uint32_t base;
DMABlockReg block;
DMAControlReg control;
};
/* DMA Interrupt Register. */
union DMAIRQReg
{
uint32_t value;
struct
{
uint32_t : 15;
uint32_t force : 1;
uint32_t enable : 7;
uint32_t master_enable : 1;
uint32_t flags : 7;
uint32_t master_flag : 1;
};
};
union ListPacket
{
uint32_t value;
struct
{
uint32_t next_addr : 24;
uint32_t size : 8;
};
};
/* A class that manages all DMA routines. */
class ComponentManager;
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:
uint32_t control;
DMAIRQReg irq;
DMAChannel channels[7];
bool irq_pending = false;
ComponentManager* manager;
};
}