1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /******************************************************************************
4 *
5 *   Sony PlayStation 2 EE DMA controller device skeleton
6 *
7 *   To Do:
8 *     Everything
9 *
10 */
11 
12 #include "emu.h"
13 #include "ps2dma.h"
14 
15 #include "cpu/mips/mips3.h"
16 #include "cpu/mips/ps2vif1.h"
17 #include "video/ps2gif.h"
18 
19 DEFINE_DEVICE_TYPE(SONYPS2_DMAC, ps2_dmac_device, "ps2dmac", "PlayStation 2 EE DMAC")
20 
ps2_dmac_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)21 ps2_dmac_device::ps2_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
22 	: device_t(mconfig, SONYPS2_DMAC, tag, owner, clock)
23 	, device_execute_interface(mconfig, *this)
24 	, m_ee(*this, finder_base::DUMMY_TAG)
25 	, m_ram(*this, finder_base::DUMMY_TAG)
26 	, m_sif(*this, finder_base::DUMMY_TAG)
27 	, m_gs(*this, finder_base::DUMMY_TAG)
28 	, m_vu1(*this, finder_base::DUMMY_TAG)
29 	, m_icount(0)
30 {
31 }
32 
~ps2_dmac_device()33 ps2_dmac_device::~ps2_dmac_device()
34 {
35 }
36 
device_start()37 void ps2_dmac_device::device_start()
38 {
39 	set_icountptr(m_icount);
40 
41 	for (uint32_t channel = 0; channel < 10; channel++)
42 	{
43 		//save_item(NAME(m_channels[channel].m_priority), channel);
44 	}
45 
46 	save_item(NAME(m_icount));
47 	save_item(NAME(m_ctrl));
48 	save_item(NAME(m_mem_drain));
49 	save_item(NAME(m_enabled));
50 
51 	save_item(NAME(m_disable_mask));
52 
53 	save_item(NAME(m_istat));
54 	save_item(NAME(m_imask));
55 
56 	save_item(NAME(m_last_serviced));
57 
58 	for (uint32_t channel = 0; channel < 10; channel++)
59 	{
60 		save_item(NAME(m_channels[channel].m_chcr), channel);
61 		save_item(NAME(m_channels[channel].m_mode), channel);
62 		save_item(NAME(m_channels[channel].m_enabled), channel);
63 		save_item(NAME(m_channels[channel].m_end_tag), channel);
64 		save_item(NAME(m_channels[channel].m_end_irq), channel);
65 		save_item(NAME(m_channels[channel].m_ienable), channel);
66 		save_item(NAME(m_channels[channel].m_qwc), channel);
67 		save_item(NAME(m_channels[channel].m_addr), channel);
68 		save_item(NAME(m_channels[channel].m_tag_addr), channel);
69 	}
70 }
71 
device_reset()72 void ps2_dmac_device::device_reset()
73 {
74 	m_ctrl = 0;
75 	m_mem_drain = 0;
76 	m_enabled = false;
77 
78 	m_disable_mask = 0x1201;
79 
80 	m_istat = 0;
81 	m_imask = 0;
82 
83 	m_last_serviced = 0;
84 }
85 
execute_run()86 void ps2_dmac_device::execute_run()
87 {
88 	if (!m_enabled || (m_disable_mask & 0x10000))
89 	{
90 		m_icount = 0;
91 		return;
92 	}
93 
94 	while (m_icount > 0)
95 	{
96 		for (; m_last_serviced < 10 && m_icount > 0; m_last_serviced++, m_icount--)
97 		{
98 			if (!m_channels[m_last_serviced].enabled())
99 				continue;
100 
101 			switch (m_last_serviced)
102 			{
103 				case VIF1:
104 					transfer_vif1();
105 					break;
106 				case GIF:
107 					transfer_gif();
108 					break;
109 				case SIF0:
110 					transfer_sif0();
111 					break;
112 				case SIF1:
113 					transfer_sif1();
114 					break;
115 				default:
116 					logerror("%s: Attempting to service unimplemented DMA channel %d\n", machine().describe_context(), m_last_serviced);
117 					break;
118 			}
119 		}
120 		if (m_last_serviced == 10)
121 			m_last_serviced = 0;
122 	}
123 }
124 
transfer_vif1()125 void ps2_dmac_device::transfer_vif1()
126 {
127 	if (m_mem_drain)
128 	{
129 		logerror("%s: transfer_vif1: Not yet implemented: memory drain bit. HACK: Disabling channel.\n", machine().describe_context());
130 		transfer_finish(VIF1);
131 		return;
132 	}
133 
134 	channel_t &channel = m_channels[VIF1];
135 	const uint32_t count = channel.quadword_count();
136 	if (count)
137 	{
138 		//logerror("%s: DMAC VIF1 quadword count: %08x\n", machine().describe_context(), count);
139 		if (m_vu1->interface()->fifo_available(4))
140 		{
141 			uint32_t addr = channel.addr();
142 			if (BIT(addr, 31))
143 				addr -= 0x10000000;
144 			address_space &space = m_ee->space(AS_PROGRAM);
145 			uint32_t words[4] = { 0, 0, 0, 0 };
146 			for (int word = 0; word < 4; word++)
147 			{
148 				words[word] = space.read_dword(addr);
149 				addr += 4;
150 			}
151 			m_vu1->interface()->dma_write(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]);
152 			channel.set_addr(channel.addr() + 0x10);
153 			channel.set_quadword_count(count - 1);
154 		}
155 	}
156 	else if (channel.end_tag())
157 	{
158 		logerror("%s: DMAC VIF1 end tag\n", machine().describe_context());
159 		transfer_finish(VIF1);
160 	}
161 	else if (m_vu1->interface()->fifo_available(2))
162 	{
163 		logerror("%s: DMAC VIF1 following source tag\n", machine().describe_context());
164 		uint32_t tag_addr = channel.tag_addr();
165 		if (BIT(tag_addr, 31))
166 			tag_addr -= 0x10000000;
167 		address_space &space = m_ee->space(AS_PROGRAM);
168 		uint32_t words[4] = { 0, 0, 0, 0 };
169 		for (int word = 0; word < 4; word++)
170 		{
171 			words[word] = space.read_dword(tag_addr);
172 			tag_addr += 4;
173 		}
174 		m_vu1->interface()->tag_write(words);
175 		follow_source_tag(VIF1);
176 	}
177 }
178 
transfer_gif()179 void ps2_dmac_device::transfer_gif()
180 {
181 	if (m_mem_drain)
182 	{
183 		logerror("%s: Not yet implemented: memory drain bit. HACK: Disabling channel.\n", machine().describe_context());
184 		transfer_finish(GIF);
185 		return;
186 	}
187 
188 	channel_t &channel = m_channels[GIF];
189 	const uint32_t count = channel.quadword_count();
190 	if (count)
191 	{
192 		//logerror("%s: DMAC GIF quadword count: %08x\n", machine().describe_context(), count);
193 		uint32_t addr = channel.addr();
194 		if (BIT(addr, 31))
195 			addr -= 0x10000000;
196 		address_space &space = m_ee->space(AS_PROGRAM);
197 		uint32_t words[4] = { 0, 0, 0, 0 };
198 		for (int word = 0; word < 4; word++)
199 		{
200 			words[word] = space.read_dword(addr);
201 			addr += 4;
202 		}
203 		m_gs->interface()->write_path3(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]);
204 		channel.set_addr(channel.addr() + 0x10);
205 		channel.set_quadword_count(count - 1);
206 	}
207 	else if (channel.end_tag())
208 	{
209 		logerror("%s: DMAC GIF end tag\n", machine().describe_context());
210 		transfer_finish(GIF);
211 	}
212 	else
213 	{
214 		logerror("%s: DMAC GIF following source tag\n", machine().describe_context());
215 		follow_source_tag(GIF);
216 	}
217 }
218 
transfer_sif0()219 void ps2_dmac_device::transfer_sif0()
220 {
221 	channel_t &channel = m_channels[SIF0];
222 	const uint32_t count = channel.quadword_count();
223 	if (count)
224 	{
225 		if (m_sif->fifo_depth(0) >= 4)
226 		{
227 			//logerror("%s: SIF0 depth is %d\n", machine().describe_context(), m_sif->fifo_depth(0));
228 			uint32_t addr = channel.addr();
229 			if (BIT(addr, 31))
230 				addr -= 0x10000000;
231 			for (int word = 0; word < 4; word++)
232 			{
233 				const uint32_t data = m_sif->fifo_pop(0);
234 				//logerror("%s: SIF0 popping %08x -> %08x\n", machine().describe_context(), data, addr);
235 				m_ee->space(AS_PROGRAM).write_dword(addr, data);
236 				addr += 4;
237 			}
238 			channel.set_addr(channel.addr() + 0x10);
239 			channel.set_quadword_count(count - 1);
240 			//logerror("%s: SIF0 remaining count: %08x\n", machine().describe_context(), channel.quadword_count());
241 		}
242 	}
243 	else if (channel.end_tag())
244 	{
245 		//logerror("%s: SIF0 end tag, finishing transfer\n", machine().describe_context());
246 		transfer_finish(SIF0);
247 	}
248 	else if (m_sif->fifo_depth(0) >= 2)
249 	{
250 		const uint32_t hi = m_sif->fifo_pop(0);
251 		const uint32_t lo = m_sif->fifo_pop(0);
252 		const uint32_t tag = hi;
253 		//logerror("%s: SIF0 chaining tag, tag %08x %08x\n", machine().describe_context(), hi, lo);
254 		channel.set_addr(lo);
255 		channel.set_tag_addr(channel.tag_addr() + 0x10);
256 		channel.set_quadword_count(tag & 0x0000ffff);
257 		channel.set_chcr((channel.chcr() & 0x0000ffff) | (tag & 0xffff0000));
258 
259 		const uint8_t mode = (tag >> 28) & 7;
260 		if ((channel.irq_enable() && BIT(tag, 31)) || mode == ID_END)
261 		{
262 			channel.set_end_tag(true);
263 		}
264 	}
265 }
266 
transfer_sif1()267 void ps2_dmac_device::transfer_sif1()
268 {
269 	channel_t &channel = m_channels[SIF1];
270 	const uint32_t count = channel.quadword_count();
271 	if (count)
272 	{
273 		//logerror("%s: DMAC SIF1 quadword count: %08x\n", machine().describe_context(), count);
274 		if (m_sif->fifo_depth(1) < (ps2_sif_device::MAX_FIFO_DEPTH - 4))
275 		{
276 			uint32_t addr = channel.addr();
277 			if (BIT(addr, 31))
278 				addr -= 0x10000000;
279 			address_space &space = m_ee->space(AS_PROGRAM);
280 			for (int word = 0; word < 4; word++)
281 			{
282 				const uint32_t data = space.read_dword(addr);
283 				//logerror("%s: DMAC SIF1 Pushing %08x\n", machine().describe_context(), data);
284 				addr += 4;
285 				m_sif->fifo_push(1, data);
286 			}
287 			channel.set_addr(channel.addr() + 0x10);
288 			channel.set_quadword_count(count - 1);
289 		}
290 	}
291 	else if (channel.end_tag())
292 	{
293 		//logerror("%s: DMAC SIF1 end tag\n", machine().describe_context());
294 		transfer_finish(SIF1);
295 	}
296 	else
297 	{
298 		//logerror("%s: DMAC SIF1 following source tag\n", machine().describe_context());
299 		follow_source_tag(SIF1);
300 	}
301 }
302 
follow_source_tag(uint32_t chan)303 void ps2_dmac_device::follow_source_tag(uint32_t chan)
304 {
305 	channel_t &channel = m_channels[chan];
306 	uint32_t tag_addr = channel.tag_addr();
307 	if (BIT(tag_addr, 31))
308 		tag_addr -= 0x10000000;
309 	address_space &space = m_ee->space(AS_PROGRAM);
310 	const uint64_t hi = space.read_qword(tag_addr);
311 	const uint64_t lo = space.read_dword(tag_addr + 8);
312 	const uint32_t tag = (uint32_t)hi;
313 	const uint32_t addr = (uint32_t)(hi >> 32) & ~0xf;
314 	if (chan != GIF && chan != VIF1)
315 		logerror("Trying to follow tag: %08x|%08x %08x|%08x\n", (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
316 
317 	channel.set_chcr((channel.chcr() & 0x0000ffff) | (tag & 0xffff0000));
318 	channel.set_quadword_count(tag & 0x0000ffff);
319 	const uint32_t id = (tag >> 28) & 7;
320 	const bool irq = BIT(tag, 31);
321 
322 	switch (id)
323 	{
324 		case ID_CNT:
325 			channel.set_addr(channel.tag_addr() + 0x10);
326 			channel.set_tag_addr(channel.addr() + (channel.quadword_count() << 4));
327 			break;
328 		case ID_REFE:
329 			channel.set_end_tag(true);
330 			// Intentional fall-through
331 		case ID_REF:
332 			channel.set_addr(addr);
333 			channel.set_tag_addr(channel.tag_addr() + 0x10);
334 			break;
335 		case ID_REFS:
336 			// We don't handle stalls yet, just act the same as REF for now
337 			channel.set_addr(addr);
338 			channel.set_tag_addr(channel.tag_addr() + 0x10);
339 			break;
340 		case ID_NEXT:
341 			channel.set_addr(channel.tag_addr() + 0x10);
342 			channel.set_tag_addr(addr);
343 			break;
344 		case ID_END:
345 			channel.set_addr(channel.tag_addr() + 0x10);
346 			channel.set_end_tag(true);
347 			break;
348 		default:
349 			logerror("%s: Unknown DMAtag ID: %d\n", machine().describe_context(), id);
350 			break;
351 	}
352 
353 	if (irq && channel.irq_enable())
354 	{
355 		channel.set_end_tag(true);
356 	}
357 }
358 
transfer_finish(uint32_t chan)359 void ps2_dmac_device::transfer_finish(uint32_t chan)
360 {
361 	channel_t &channel = m_channels[chan];
362 	channel.set_chcr(channel.chcr() & ~0x100);
363 	m_istat |= (1 << chan);
364 	update_interrupts();
365 }
366 
update_interrupts()367 void ps2_dmac_device::update_interrupts()
368 {
369 	logerror("%s: update_interrupts: %d\n", machine().describe_context(), (m_istat & m_imask) ? 1 : 0);
370 	m_ee->set_input_line(MIPS3_IRQ1, (m_istat & m_imask) ? ASSERT_LINE : CLEAR_LINE);
371 }
372 
read(offs_t offset,uint32_t mem_mask)373 uint32_t ps2_dmac_device::read(offs_t offset, uint32_t mem_mask)
374 {
375 	uint32_t ret = 0;
376 	switch (offset)
377 	{
378 		case 0: /* D_CTRL */
379 			ret = m_ctrl;
380 			logerror("%s: dmac_r: D_CTRL (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
381 			break;
382 		case 2: /* D_STAT */
383 			ret = m_istat | (m_imask << 16);
384 			logerror("%s: dmac_r: D_STAT (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
385 			break;
386 		case 4: /* D_PCR */
387 			logerror("%s: dmac_r: D_PCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
388 			break;
389 		case 6: /* D_SQWC */
390 			logerror("%s: dmac_r: D_SQWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
391 			break;
392 		case 8: /* D_RBSR */
393 			logerror("%s: dmac_r: D_RBSR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
394 			break;
395 		case 10: /* D_RBOR */
396 			logerror("%s: dmac_r: D_RBOR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
397 			break;
398 		case 12: /* D_STADR */
399 			logerror("%s: dmac_r: D_STADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
400 			break;
401 		default:
402 			logerror("%s: dmac_r: Unknown offset %08x & %08x\n", machine().describe_context(), 0x1000e000 + (offset << 3), mem_mask);
403 			break;
404 	}
405 	return ret;
406 }
407 
write(offs_t offset,uint32_t data,uint32_t mem_mask)408 void ps2_dmac_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
409 {
410 	switch (offset)
411 	{
412 		case 0: /* D_CTRL */
413 			logerror("%s: dmac_w: D_CTRL = %08x & %08x\n", machine().describe_context(), data, mem_mask);
414 			logerror("%s:         ENABLE=%d MEM_DRAIN=%d\n", machine().describe_context(), BIT(data, 0), (data >> 2) & 3);
415 			m_ctrl = data;
416 			m_enabled = BIT(data, 0);
417 			m_mem_drain = (data >> 2) & 3;
418 			break;
419 		case 2: /* D_STAT */
420 			logerror("%s: dmac_w: D_STAT = %08x & %08x\n", machine().describe_context(), data, mem_mask);
421 			m_istat &= ~(data & 0x7fff);
422 			m_imask ^= (data >> 16) & 0x7fff;
423 			update_interrupts();
424 			break;
425 		case 4: /* D_PCR */
426 			logerror("%s: dmac_w: D_PCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
427 			break;
428 		case 6: /* D_SQWC */
429 			logerror("%s: dmac_w: D_SQWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
430 			break;
431 		case 8: /* D_RBSR */
432 			logerror("%s: dmac_w: D_RBSR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
433 			break;
434 		case 10: /* D_RBOR */
435 			logerror("%s: dmac_w: D_RBOR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
436 			break;
437 		case 12: /* D_STADR */
438 			logerror("%s: dmac_w: D_STADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
439 			break;
440 		default:
441 			logerror("%s: dmac_w: Unknown offset %08x = %08X & %08x\n", machine().describe_context(), 0x1000e000 + (offset << 3), data, mem_mask);
442 			break;
443 	}
444 }
445 
channel_r(offs_t offset,uint32_t mem_mask)446 uint32_t ps2_dmac_device::channel_r(offs_t offset, uint32_t mem_mask)
447 {
448 	uint32_t ret = 0;
449 	switch (offset + 0x8000/8)
450 	{
451 		case 0x8000/8: /* D0_CHCR */
452 			logerror("%s: dmac_channel_r: D0_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
453 			break;
454 		case 0x8010/8: /* D0_MADR */
455 			logerror("%s: dmac_channel_r: D0_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
456 			break;
457 		case 0x8020/8: /* D0_QWC */
458 			logerror("%s: dmac_channel_r: D0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
459 			break;
460 		case 0x8030/8: /* D0_TADR */
461 			logerror("%s: dmac_channel_r: D0_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
462 			break;
463 		case 0x8040/8: /* D0_ASR0 */
464 			logerror("%s: dmac_channel_r: D0_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
465 			break;
466 		case 0x8050/8: /* D0_ASR1 */
467 			logerror("%s: dmac_channel_r: D0_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
468 			break;
469 		case 0x9000/8: /* VIF1_CHCR */
470 			ret = m_channels[VIF1].chcr();
471 			//logerror("%s: dmac_channel_r: VIF1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
472 			break;
473 		case 0x9010/8: /* VIF1_MADR */
474 			ret = m_channels[VIF1].addr();
475 			logerror("%s: dmac_channel_r: VIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
476 			break;
477 		case 0x9020/8: /* VIF1_QWC */
478 			ret = m_channels[VIF1].quadword_count();
479 			logerror("%s: dmac_channel_r: VIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
480 			break;
481 		case 0x9030/8: /* VIF1_TADR */
482 			ret = m_channels[VIF1].tag_addr();
483 			logerror("%s: dmac_channel_r: VIF1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
484 			break;
485 		case 0x9040/8: /* VIF1_ASR0 */
486 			logerror("%s: dmac_channel_r: VIF1_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
487 			break;
488 		case 0x9050/8: /* VIF1_ASR1 */
489 			logerror("%s: dmac_channel_r: VIF1_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
490 			break;
491 		case 0xa000/8: /* GIF_CHCR */
492 			ret = m_channels[GIF].chcr();
493 			//logerror("%s: dmac_channel_r: GIF_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
494 			break;
495 		case 0xa010/8: /* GIF_MADR */
496 			ret = m_channels[GIF].addr();
497 			logerror("%s: dmac_channel_r: GIF_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
498 			break;
499 		case 0xa020/8: /* GIF_QWC */
500 			ret = m_channels[GIF].quadword_count();
501 			logerror("%s: dmac_channel_r: GIF_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
502 			break;
503 		case 0xa030/8: /* GIF_TADR */
504 			ret = m_channels[GIF].tag_addr();
505 			logerror("%s: dmac_channel_r: GIF_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
506 			break;
507 		case 0xa040/8: /* GIF_ASR0 */
508 			logerror("%s: dmac_channel_r: GIF_ASR0 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
509 			break;
510 		case 0xa050/8: /* GIF_ASR1 */
511 			logerror("%s: dmac_channel_r: GIF_ASR1 (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
512 			break;
513 		case 0xb000/8: /* D3_CHCR */
514 			logerror("%s: dmac_channel_r: D3_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
515 			break;
516 		case 0xb010/8: /* D3_MADR */
517 			logerror("%s: dmac_channel_r: D3_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
518 			break;
519 		case 0xb020/8: /* D3_QWC */
520 			logerror("%s: dmac_channel_r: D3_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
521 			break;
522 		case 0xb400/8: /* D4_CHCR */
523 			logerror("%s: dmac_channel_r: D4_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
524 			break;
525 		case 0xb410/8: /* D4_MADR */
526 			logerror("%s: dmac_channel_r: D4_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
527 			break;
528 		case 0xb420/8: /* D4_QWC */
529 			logerror("%s: dmac_channel_r: D4_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
530 			break;
531 		case 0xb430/8: /* D4_TADR */
532 			logerror("%s: dmac_channel_r: D4_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
533 			break;
534 		case 0xc000/8: /* SIF0_CHCR */
535 			ret = m_channels[SIF0].chcr();
536 			//logerror("%s: dmac_channel_r: SIF0_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
537 			break;
538 		case 0xc010/8: /* SIF0_MADR */
539 			ret = m_channels[SIF0].addr();
540 			//logerror("%s: dmac_channel_r: SIF0_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
541 			break;
542 		case 0xc020/8: /* SIF0_QWC */
543 			ret = m_channels[SIF0].quadword_count();
544 			//logerror("%s: dmac_channel_r: SIF0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
545 			break;
546 		case 0xc400/8: /* SIF1_CHCR */
547 			ret = m_channels[SIF1].chcr();
548 			//logerror("%s: dmac_channel_r: SIF1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
549 			break;
550 		case 0xc410/8: /* SIF1_MADR */
551 			ret = m_channels[SIF1].addr();
552 			//logerror("%s: dmac_channel_r: SIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
553 			break;
554 		case 0xc420/8: /* SIF1_QWC */
555 			ret = m_channels[SIF1].quadword_count();
556 			//logerror("%s: dmac_channel_r: SIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
557 			break;
558 		case 0xc430/8: /* SIF1_TADR */
559 			ret = m_channels[SIF1].tag_addr();
560 			//logerror("%s: dmac_channel_r: SIF1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
561 			break;
562 		case 0xc800/8: /* D7_CHCR */
563 			logerror("%s: dmac_channel_r: D7_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
564 			break;
565 		case 0xc810/8: /* D7_MADR */
566 			logerror("%s: dmac_channel_r: D7_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
567 			break;
568 		case 0xc820/8: /* D7_QWC */
569 			logerror("%s: dmac_channel_r: D7_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
570 			break;
571 		case 0xd000/8: /* D8_CHCR */
572 			logerror("%s: dmac_channel_r: D8_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
573 			break;
574 		case 0xd010/8: /* D8_MADR */
575 			logerror("%s: dmac_channel_r: D8_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
576 			break;
577 		case 0xd020/8: /* D8_QWC */
578 			logerror("%s: dmac_channel_r: D8_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
579 			break;
580 		case 0xd080/8: /* D8_SADR */
581 			logerror("%s: dmac_channel_r: D8_SADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
582 			break;
583 		case 0xd400/8: /* D9_CHCR */
584 			logerror("%s: dmac_channel_r: D9_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
585 			break;
586 		case 0xd410/8: /* D9_MADR */
587 			logerror("%s: dmac_channel_r: D9_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
588 			break;
589 		case 0xd420/8: /* D9_QWC */
590 			logerror("%s: dmac_channel_r: D9_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
591 			break;
592 		case 0xd430/8: /* D9_TADR */
593 			logerror("%s: dmac_channel_r: D9_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
594 			break;
595 		case 0xd480/8: /* D9_SADR */
596 			logerror("%s: dmac_channel_r: D9_SADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
597 			break;
598 		default:
599 			logerror("%s: dmac_channel_r: Unknown offset %08x & %08x\n", machine().describe_context(), 0x10008000 + (offset << 3), mem_mask);
600 			break;
601 	}
602 	return ret;
603 }
604 
channel_w(offs_t offset,uint32_t data,uint32_t mem_mask)605 void ps2_dmac_device::channel_w(offs_t offset, uint32_t data, uint32_t mem_mask)
606 {
607 	static char const *const mode_strings[4] = { "Normal", "Chain", "Interleave", "Undefined" };
608 
609 	switch (offset + 0x8000/8)
610 	{
611 		case 0x8000/8: /* D0_CHCR */
612 			logerror("%s: dmac_channel_w: D0_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
613 			break;
614 		case 0x8010/8: /* D0_MADR */
615 			logerror("%s: dmac_channel_w: D0_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
616 			break;
617 		case 0x8020/8: /* D0_QWC */
618 			logerror("%s: dmac_channel_w: D0_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
619 			break;
620 		case 0x8030/8: /* D0_TADR */
621 			logerror("%s: dmac_channel_w: D0_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
622 			break;
623 		case 0x8040/8: /* D0_ASR0 */
624 			logerror("%s: dmac_channel_w: D0_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
625 			break;
626 		case 0x8050/8: /* D0_ASR1 */
627 			logerror("%s: dmac_channel_w: D0_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
628 			break;
629 		case 0x9000/8: /* VIF1_CHCR */
630 			logerror("%s: dmac_channel_w: VIF1_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
631 			logerror("%s:                                   TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
632 			m_channels[VIF1].set_chcr(data);
633 			break;
634 		case 0x9010/8: /* VIF1_MADR */
635 			logerror("%s: dmac_channel_w: VIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
636 			m_channels[VIF1].set_addr(data);
637 			break;
638 		case 0x9020/8: /* VIF1_QWC */
639 			logerror("%s: dmac_channel_w: VIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
640 			m_channels[VIF1].set_quadword_count(data);
641 			break;
642 		case 0x9030/8: /* VIF1_TADR */
643 			logerror("%s: dmac_channel_w: VIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
644 			m_channels[VIF1].set_tag_addr(data);
645 			break;
646 		case 0x9040/8: /* VIF1_ASR0 */
647 			logerror("%s: dmac_channel_w: VIF1_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
648 			break;
649 		case 0x9050/8: /* VIF1_ASR1 */
650 			logerror("%s: dmac_channel_w: VIF1_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
651 			break;
652 		case 0xa000/8: /* GIF_CHCR */
653 			logerror("%s: dmac_channel_w: GIF_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
654 			logerror("%s:                                   TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
655 			m_channels[GIF].set_chcr(data);
656 			break;
657 		case 0xa010/8: /* GIF_MADR */
658 			logerror("%s: dmac_channel_w: GIF_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
659 			m_channels[GIF].set_addr(data);
660 			break;
661 		case 0xa020/8: /* GIF_QWC */
662 			logerror("%s: dmac_channel_w: GIF_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
663 			m_channels[GIF].set_quadword_count(data);
664 			break;
665 		case 0xa030/8: /* GIF_TADR */
666 			logerror("%s: dmac_channel_w: GIF_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
667 			m_channels[GIF].set_tag_addr(data);
668 			break;
669 		case 0xa040/8: /* GIF_ASR0 */
670 			logerror("%s: dmac_channel_w: GIF_ASR0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
671 			break;
672 		case 0xa050/8: /* GIF_ASR1 */
673 			logerror("%s: dmac_channel_w: GIF_ASR1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
674 			break;
675 		case 0xb000/8: /* D3_CHCR */
676 			logerror("%s: dmac_channel_w: D3_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
677 			break;
678 		case 0xb010/8: /* D3_MADR */
679 			logerror("%s: dmac_channel_w: D3_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
680 			break;
681 		case 0xb020/8: /* D3_QWC */
682 			logerror("%s: dmac_channel_w: D3_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
683 			break;
684 		case 0xb400/8: /* D4_CHCR */
685 			logerror("%s: dmac_channel_w: D4_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
686 			break;
687 		case 0xb410/8: /* D4_MADR */
688 			logerror("%s: dmac_channel_w: D4_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
689 			break;
690 		case 0xb420/8: /* D4_QWC */
691 			logerror("%s: dmac_channel_w: D4_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
692 			break;
693 		case 0xb430/8: /* D4_TADR */
694 			logerror("%s: dmac_channel_w: D4_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
695 			break;
696 		case 0xc000/8: /* SIF0_CHCR */
697 			//logerror("%s: dmac_channel_w: SIF0_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
698 			//logerror("%s:                                   TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
699 			m_channels[SIF0].set_chcr(data);
700 			break;
701 		case 0xc010/8: /* SIF0_MADR */
702 			//logerror("%s: dmac_channel_w: SIF0_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
703 			m_channels[SIF0].set_addr(data);
704 			break;
705 		case 0xc020/8: /* SIF0_QWC */
706 			//logerror("%s: dmac_channel_w: SIF0_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
707 			m_channels[SIF0].set_quadword_count(data);
708 			break;
709 		case 0xc400/8: /* D6_CHCR */
710 			//logerror("%s: dmac_channel_w: SIF1_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
711 			//logerror("%s:                                   TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
712 			m_channels[SIF1].set_chcr(data);
713 			break;
714 		case 0xc410/8: /* D6_MADR */
715 			//logerror("%s: dmac_channel_w: SIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
716 			m_channels[SIF1].set_addr(data);
717 			break;
718 		case 0xc420/8: /* D6_QWC */
719 			//logerror("%s: dmac_channel_w: SIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
720 			m_channels[SIF1].set_quadword_count(data);
721 			break;
722 		case 0xc430/8: /* D6_TADR */
723 			//logerror("%s: dmac_channel_w: SIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
724 			m_channels[SIF1].set_tag_addr(data);
725 			break;
726 		case 0xc800/8: /* D7_CHCR */
727 			logerror("%s: dmac_channel_w: D7_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
728 			break;
729 		case 0xc810/8: /* D7_MADR */
730 			logerror("%s: dmac_channel_w: D7_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
731 			break;
732 		case 0xc820/8: /* D7_QWC */
733 			logerror("%s: dmac_channel_w: D7_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
734 			break;
735 		case 0xd000/8: /* D8_CHCR */
736 			logerror("%s: dmac_channel_w: D8_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
737 			break;
738 		case 0xd010/8: /* D8_MADR */
739 			logerror("%s: dmac_channel_w: D8_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
740 			break;
741 		case 0xd020/8: /* D8_QWC */
742 			logerror("%s: dmac_channel_w: D8_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
743 			break;
744 		case 0xd080/8: /* D8_SADR */
745 			logerror("%s: dmac_channel_w: D8_SADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
746 			break;
747 		case 0xd400/8: /* D9_CHCR */
748 			logerror("%s: dmac_channel_w: D9_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
749 			break;
750 		case 0xd410/8: /* D9_MADR */
751 			logerror("%s: dmac_channel_w: D9_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
752 			break;
753 		case 0xd420/8: /* D9_QWC */
754 			logerror("%s: dmac_channel_w: D9_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
755 			break;
756 		case 0xd430/8: /* D9_TADR */
757 			logerror("%s: dmac_channel_w: D9_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
758 			break;
759 		case 0xd480/8: /* D9_SADR */
760 			logerror("%s: dmac_channel_w: D9_SADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
761 			break;
762 		default:
763 			logerror("%s: dmac_channel_w: Unknown offset %08x = %08x & %08x\n", machine().describe_context(), 0x10008000 + (offset << 3), data, mem_mask);
764 			break;
765 	}
766 }
767 
disable_mask_r(offs_t offset,uint32_t mem_mask)768 uint32_t ps2_dmac_device::disable_mask_r(offs_t offset, uint32_t mem_mask)
769 {
770 	uint32_t ret = m_disable_mask;
771 	logerror("%s: m_disable_mask = %08x & %08x\n", machine().describe_context(), ret, mem_mask);
772 	return ret;
773 }
774 
disable_mask_w(offs_t offset,uint32_t data,uint32_t mem_mask)775 void ps2_dmac_device::disable_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask)
776 {
777 	logerror("%s: m_disable_mask = %08x & %08x\n", machine().describe_context(), data, mem_mask);
778 	m_disable_mask = data;
779 }
780 
set_chcr(uint32_t data)781 void ps2_dmac_device::channel_t::set_chcr(uint32_t data)
782 {
783 	m_chcr = data;
784 	m_mode = (data >> 2) & 3;
785 	bool was_enabled = m_enabled;
786 	m_ienable = BIT(m_chcr, 7);
787 	m_enabled = BIT(m_chcr, 8);
788 	if (!was_enabled && m_enabled)
789 	{
790 		m_end_tag = m_mode == 0;
791 	}
792 	else
793 	{
794 		m_end_tag = false;
795 	}
796 }
797