@@ -69,6 +69,8 @@ v25_common_device::v25_common_device(const machine_config &mconfig, device_type
69
69
, m_p0_out(*this )
70
70
, m_p1_out(*this )
71
71
, m_p2_out(*this )
72
+ , m_dma_read(*this , 0xffff )
73
+ , m_dma_write(*this )
72
74
, m_prefetch_size(prefetch_size)
73
75
, m_prefetch_cycles(prefetch_cycles)
74
76
, m_chip_type(chip_type)
@@ -215,7 +217,6 @@ void v25_common_device::device_reset()
215
217
m_intm = 0 ;
216
218
m_halted = 0 ;
217
219
218
- m_TM0 = m_MD0 = m_TM1 = m_MD1 = 0 ;
219
220
m_TMC0 = m_TMC1 = 0 ;
220
221
221
222
for (int i = 0 ; i < 2 ; i++)
@@ -226,6 +227,10 @@ void v25_common_device::device_reset()
226
227
m_sce[i] = 0 ;
227
228
}
228
229
230
+ m_dmam[0 ] = m_dmam[1 ] = 0 ;
231
+ m_dma_channel = -1 ;
232
+ m_last_dma_channel = 0 ;
233
+
229
234
m_RAMEN = 1 ;
230
235
m_TB = 20 ;
231
236
m_PCK = 8 ;
@@ -483,6 +488,111 @@ void v25_common_device::external_int()
483
488
}
484
489
}
485
490
491
+ void v25_common_device::dma_process ()
492
+ {
493
+ uint16_t sar = m_internal_ram[m_dma_channel * 4 ];
494
+ uint16_t dar = m_internal_ram[m_dma_channel * 4 + 1 ];
495
+ uint16_t sarh_darh = m_internal_ram[m_dma_channel * 4 + 2 ];
496
+ uint8_t dmamode = BIT (m_dmam[m_dma_channel], 5 , 3 );
497
+ bool w = BIT (m_dmam[m_dma_channel], 4 );
498
+
499
+ uint32_t saddr = (BIT (dmamode, 0 ) ? 0 : (uint32_t (sarh_darh) & 0xff00 ) << 4 ) + sar;
500
+ uint32_t daddr = (BIT (dmamode, 1 ) ? 0 : (uint32_t (sarh_darh) & 0x00ff ) << 12 ) + dar;
501
+
502
+ switch (dmamode & 3 )
503
+ {
504
+ case 0 :
505
+ // Memory to memory transfer
506
+ if (w)
507
+ {
508
+ uint16_t data = v25_read_word (saddr);
509
+ v25_write_word (daddr, data);
510
+ }
511
+ else
512
+ {
513
+ uint8_t data = v25_read_byte (saddr);
514
+ v25_write_byte (daddr, data);
515
+ }
516
+ m_icount -= (w && m_program->addr_width () == 8 ) ? 8 : 4 ;
517
+ break ;
518
+
519
+ case 1 :
520
+ // I/O to memory transfer
521
+ if (w && m_program->addr_width () == 16 )
522
+ {
523
+ uint16_t data = m_dma_read[m_dma_channel](daddr);
524
+ v25_write_word (daddr, data);
525
+ }
526
+ else
527
+ {
528
+ uint8_t data = m_dma_read[m_dma_channel](daddr);
529
+ v25_write_byte (daddr, data);
530
+ if (w)
531
+ {
532
+ logerror (" Warning: V25 16-bit I/O to memory transfer\n " );
533
+ data = m_dma_read[m_dma_channel](daddr + 1 );
534
+ v25_write_byte (daddr + 1 , data);
535
+ m_icount -= 2 ;
536
+ }
537
+ }
538
+ m_icount -= 2 ;
539
+ break ;
540
+
541
+ case 2 :
542
+ // Memory to I/O transfer
543
+ if (w && m_program->addr_width () == 16 )
544
+ {
545
+ uint16_t data = v25_read_word (saddr);
546
+ m_dma_write[m_dma_channel](saddr, data);
547
+ }
548
+ else
549
+ {
550
+ uint8_t data = v25_read_byte (saddr);
551
+ m_dma_write[m_dma_channel](saddr, data);
552
+ if (w)
553
+ {
554
+ logerror (" Warning: V25 16-bit memory to I/O transfer\n " );
555
+ data = v25_read_byte (saddr + 1 );
556
+ m_dma_write[m_dma_channel](saddr + 1 , data);
557
+ m_icount -= 2 ;
558
+ }
559
+ }
560
+ m_icount -= 2 ;
561
+ break ;
562
+
563
+ default :
564
+ logerror (" Reserved DMA transfer mode\n " );
565
+ m_icount--;
566
+ break ;
567
+ }
568
+
569
+ // Update source and destination based on address control
570
+ uint8_t dmac = m_dmac[m_dma_channel];
571
+ if (BIT (dmac, 0 , 2 ) == 1 )
572
+ m_internal_ram[m_dma_channel * 4 ] = sar + (w ? 2 : 1 );
573
+ else if (BIT (dmac, 0 , 2 ) == 2 )
574
+ m_internal_ram[m_dma_channel * 4 ] = sar - (w ? 2 : 1 );
575
+ if (BIT (dmac, 4 , 2 ) == 1 )
576
+ m_internal_ram[m_dma_channel * 4 + 1 ] = dar + (w ? 2 : 1 );
577
+ else if (BIT (dmac, 4 , 2 ) == 2 )
578
+ m_internal_ram[m_dma_channel * 4 + 1 ] = dar - (w ? 2 : 1 );
579
+
580
+ // Update TC
581
+ uint16_t tc = --m_internal_ram[m_dma_channel * 4 + 3 ];
582
+ if (tc == 0 )
583
+ {
584
+ m_dmam[m_dma_channel] &= 0xf0 ; // disable channel
585
+ m_pending_irq |= m_dma_channel ? INTD1 : INTD0; // request interrupt
586
+ }
587
+
588
+ if (dmamode == 0 || dmamode > 4 || tc == 0 )
589
+ {
590
+ // Single step/single transfer modes (or end of burst)
591
+ m_last_dma_channel = m_dma_channel;
592
+ m_dma_channel = -1 ;
593
+ }
594
+ }
595
+
486
596
/* ***************************************************************************/
487
597
/* OPCODES */
488
598
/* ***************************************************************************/
@@ -570,6 +680,9 @@ void v25_common_device::device_start()
570
680
m_EO = 0 ;
571
681
m_E16 = 0 ;
572
682
683
+ m_TM0 = m_MD0 = m_TM1 = m_MD1 = 0 ;
684
+ m_dmac[0 ] = m_dmac[1 ] = 0 ;
685
+
573
686
for (i = 0 ; i < 4 ; i++)
574
687
m_timers[i] = timer_alloc (FUNC (v25_common_device::v25_timer_callback), this );
575
688
@@ -630,6 +743,10 @@ void v25_common_device::device_start()
630
743
save_item (NAME (m_scc));
631
744
save_item (NAME (m_brg));
632
745
save_item (NAME (m_sce));
746
+ save_item (NAME (m_dmac));
747
+ save_item (NAME (m_dmam));
748
+ save_item (NAME (m_dma_channel));
749
+ save_item (NAME (m_last_dma_channel));
633
750
save_item (NAME (m_RAMEN));
634
751
save_item (NAME (m_TB));
635
752
save_item (NAME (m_PCK));
@@ -790,6 +907,12 @@ void v25_common_device::execute_run()
790
907
}
791
908
792
909
while (m_icount>0 ) {
910
+ if (m_dma_channel != -1 )
911
+ {
912
+ dma_process ();
913
+ continue ;
914
+ }
915
+
793
916
/* Dispatch IRQ */
794
917
m_prev_ip = m_ip;
795
918
if (m_no_interrupt==0 && (m_pending_irq & m_unmasked_irq))
@@ -808,5 +931,13 @@ void v25_common_device::execute_run()
808
931
prev_ICount = m_icount;
809
932
(this ->*s_nec_instruction[fetchop ()])();
810
933
do_prefetch (prev_ICount);
934
+
935
+ if ((m_dmam[0 ] & 0x0c ) == 0x0c || (m_dmam[1 ] & 0x0c ) == 0x0c )
936
+ {
937
+ if ((m_dmam[1 - m_last_dma_channel] & 0x0c ) == 0x0c )
938
+ m_dma_channel = 1 - m_last_dma_channel;
939
+ else
940
+ m_dma_channel = m_last_dma_channel;
941
+ }
811
942
}
812
943
}
0 commit comments