summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/ps2dma.h
blob: a8a0f43476e4bf9350a9a0e02fd54705eab8e22c (plain) (blame)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
*   Sony PlayStation 2 EE DMA controller device skeleton
*
*   To Do:
*     Everything
*
*/

#ifndef DEVICES_MACHINE_PS2DMAC_H
#define DEVICES_MACHINE_PS2DMAC_H

#pragma once

#include "ps2sif.h"
#include "video/ps2gs.h"
#include "cpu/mips/ps2vu.h"

class ps2_dmac_device : public device_t, public device_execute_interface
{
public:
	template <typename T, typename U, typename V, typename W, typename X>
    ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&ee_tag, U &&ram_tag, V &&sif_tag, W &&gs_tag, X &&vu1_tag)
    	: ps2_dmac_device(mconfig, tag, owner, clock)
    {
		m_ee.set_tag(std::forward<T>(ee_tag));
		m_ram.set_tag(std::forward<U>(ram_tag));
		m_sif.set_tag(std::forward<V>(sif_tag));
		m_gs.set_tag(std::forward<W>(gs_tag));
		m_vu1.set_tag(std::forward<X>(vu1_tag));
	}

    ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	enum channel_type : uint32_t
	{
		VIF0 = 0,
		VIF1,
		GIF,
		IPU_OUT,
		IPU_IN,
		SIF0,
		SIF1,
		SIF2,
		SPR_OUT,
		SPR_IN
	};

	DECLARE_READ32_MEMBER(read);
	DECLARE_WRITE32_MEMBER(write);
	DECLARE_READ32_MEMBER(channel_r);
	DECLARE_WRITE32_MEMBER(channel_w);

	DECLARE_READ32_MEMBER(disable_mask_r);
	DECLARE_WRITE32_MEMBER(disable_mask_w);

protected:
    virtual void device_start() override;
    virtual void device_reset() override;
	virtual void execute_run() override;

    enum tag_id
    {
		ID_REFE = 0,
		ID_CNT,
		ID_NEXT,
		ID_REF,
		ID_REFS,
		ID_CALL,
		ID_RET,
		ID_END
	};

	class channel_t
	{
		friend class ps2_dmac_device;

	public:
		channel_t()
			: m_chcr(0), m_mode(0), m_enabled(false), m_end_tag(false), m_end_irq(false), m_ienable(false), m_addr(0), m_qwc(0)
		{
		}

		void set_chcr(uint32_t data);
		uint32_t chcr() const { return m_chcr; }
		uint32_t mode() const { return m_mode; }
		bool enabled() const { return m_enabled; }
		bool irq_enable() const { return m_ienable; }

		bool end_tag() const { return m_end_tag; }
		void set_end_tag(bool end_tag) { m_end_tag = end_tag; }

		bool end_irq() const { return m_end_irq; }
		void set_end_irq(bool end_irq) { m_end_irq = end_irq; }

		uint32_t addr() const { return m_addr; }
		void set_addr(uint32_t addr) { m_addr = addr; }

		uint32_t quadword_count() const { return m_qwc; }
		void set_quadword_count(uint32_t qwc) { m_qwc = qwc; }

		uint32_t tag_addr() const { return m_tag_addr; }
		void set_tag_addr(uint32_t tag_addr) { m_tag_addr = tag_addr; }

	protected:
		uint32_t m_chcr;
		uint32_t m_mode;
		bool m_enabled;
		bool m_end_tag;
		bool m_end_irq;
		bool m_ienable;

		uint32_t m_addr;
		uint32_t m_qwc;
		uint32_t m_tag_addr;
	};

	void transfer_vif1();
	void transfer_gif();
	void transfer_sif0();
	void transfer_sif1();
	void transfer_finish(uint32_t chan);
	void follow_source_tag(uint32_t channel);
	void update_interrupts();

	required_device<cpu_device> m_ee;
	required_shared_ptr<uint64_t> m_ram;
	required_device<ps2_sif_device> m_sif;
	required_device<ps2_gs_device> m_gs;
	required_device<sonyvu1_device> m_vu1;

	int m_icount;

	uint32_t m_ctrl;
	uint32_t m_mem_drain;
	bool m_enabled;

	uint32_t m_disable_mask;

	uint32_t m_istat;
	uint32_t m_imask;

	uint32_t m_last_serviced;
	channel_t m_channels[10];
};

DECLARE_DEVICE_TYPE(SONYPS2_DMAC, ps2_dmac_device)

#endif // DEVICES_MACHINE_PS2DMAC_H