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