55
66#include "dmac.h"
77
8+ // #define printf(fmt, ...)(0)
9+
810static inline uint128_t dmac_read_qword (struct ps2_dmac * dmac , uint32_t addr , int mem ) {
911 int spr = mem || (addr & 0x80000000 );
1012
@@ -14,6 +16,18 @@ static inline uint128_t dmac_read_qword(struct ps2_dmac* dmac, uint32_t addr, in
1416 return ps2_ram_read128 (dmac -> spr , addr & 0x3ff0 );
1517}
1618
19+ static inline void dmac_write_qword (struct ps2_dmac * dmac , uint32_t addr , int mem , uint128_t value ) {
20+ int spr = mem || (addr & 0x80000000 );
21+
22+ if (!spr ) {
23+ ee_bus_write128 (dmac -> bus , addr & 0xfffffff0 , value );
24+
25+ return ;
26+ }
27+
28+ ps2_ram_write128 (dmac -> spr , addr & 0x3ff0 , value );
29+ }
30+
1731struct ps2_dmac * ps2_dmac_create (void ) {
1832 return malloc (sizeof (struct ps2_dmac ));
1933}
@@ -196,7 +210,7 @@ static inline void dmac_process_source_tag(struct ps2_dmac* dmac, struct dmac_ch
196210 } break ;
197211 }
198212
199- // If TIE is set, then end transfer
213+ // If TIE and TAG.IRQ are set, then end transfer
200214 if ((c -> chcr & 0x80 ) && c -> tag .irq )
201215 c -> tag .end = 1 ;
202216}
@@ -493,107 +507,156 @@ void dmac_handle_gif_transfer(struct ps2_dmac* dmac) {
493507 }
494508 } while (!channel_is_done (& dmac -> gif ));
495509}
496-
497510void dmac_handle_ipu_from_transfer (struct ps2_dmac * dmac ) {
498- // printf("ee: ipu_to start data=%08x dir=%d mod=%d tte=%d madr=%08x qwc=%08x tadr=%08x\n",
499- // dmac->ipu_to.chcr,
500- // dmac->ipu_to.chcr & 1,
501- // (dmac->ipu_to.chcr >> 2) & 3,
502- // !!(dmac->ipu_to.chcr & 0x40),
503- // dmac->ipu_to.madr,
504- // dmac->ipu_to.qwc,
505- // dmac->ipu_to.tadr
506- // );
511+ if ((dmac -> ipu_from .chcr & 0x100 ) == 0 ) {
512+ // printf("dmac: ipu_from channel not started\n");
513+
514+ return ;
515+ }
507516
508- // dmac_set_irq (dmac, DMAC_IPU_TO) ;
517+ int mode = (dmac -> ipu_from . chcr >> 2 ) & 3 ;
509518
510- // dmac->ipu_to.chcr &= ~0x100;
519+ printf ("dmac: ipu_from start data=%08x dir=%d mod=%d tte=%d madr=%08x qwc=%08x tadr=%08x dreq=%d\n" ,
520+ dmac -> ipu_from .chcr ,
521+ dmac -> ipu_from .chcr & 1 ,
522+ (dmac -> ipu_from .chcr >> 2 ) & 3 ,
523+ !!(dmac -> ipu_from .chcr & 0x40 ),
524+ dmac -> ipu_from .madr ,
525+ dmac -> ipu_from .qwc ,
526+ dmac -> ipu_from .tadr ,
527+ dmac -> ipu_from .dreq
528+ );
511529
512- // return;
530+ if (mode != 0 ) {
531+ printf ("dmac: ipu_from mode %d not supported\n" , mode );
513532
514- do {
515- uint128_t tag = ee_bus_read128 (dmac -> bus , 0x10007000 );
533+ exit (1 );
534+
535+ return ;
536+ }
537+
538+ while (dmac -> ipu_from .dreq && dmac -> ipu_from .qwc ) {
539+ uint128_t q = ee_bus_read128 (dmac -> bus , 0x10007000 );
516540
517- dmac_process_dest_tag (dmac , & dmac -> ipu_from , tag );
541+ dmac_write_qword (dmac , dmac -> ipu_from .madr , 0 , q );
542+
543+ dmac -> ipu_from .madr += 16 ;
544+ dmac -> ipu_from .qwc -- ;
545+ }
546+
547+ if (dmac -> ipu_from .qwc == 0 ) {
548+ dmac_set_irq (dmac , DMAC_IPU_FROM );
549+
550+ dmac -> ipu_from .chcr &= ~0x100 ;
551+ dmac -> ipu_from .qwc = 0 ;
552+
553+ printf ("dmac: ipu_from channel done\n" );
554+ }
555+ }
556+ int dmac_transfer_ipu_to_qword (struct ps2_dmac * dmac ) {
557+ if ((dmac -> ipu_to .chcr & 0x100 ) == 0 ) {
558+ // printf("dmac: ipu_to channel not started\n");
559+
560+ return 0 ;
561+ }
562+
563+ if (!dmac -> ipu_to .dreq ) {
564+ // printf("dmac: ipu_to dreq cleared\n");
565+
566+ return 0 ;
567+ }
518568
519- printf ("ee: ipu_from tag qwc=%08lx id=%ld irq=%ld addr=%08lx mem=%ld data=%016lx end=%d tte=%d\n" ,
520- dmac -> ipu_to .tag .qwc ,
521- dmac -> ipu_to .tag .id ,
522- dmac -> ipu_to .tag .irq ,
523- dmac -> ipu_to .tag .addr ,
524- dmac -> ipu_to .tag .mem ,
525- dmac -> ipu_to .tag .data ,
526- dmac -> ipu_to .tag .end ,
527- (dmac -> ipu_to .chcr >> 7 ) & 1
528- );
569+ if (dmac -> ipu_to .tag .qwc ) {
570+ uint128_t q = dmac_read_qword (dmac , dmac -> ipu_to .madr , dmac -> ipu_to .tag .mem );
571+
572+ ee_bus_write128 (dmac -> bus , 0x10007010 , q );
573+
574+ dmac -> ipu_to .madr += 16 ;
575+ dmac -> ipu_to .tag .qwc -- ;
576+
577+ return 1 ;
578+ }
579+
580+ if (channel_is_done (& dmac -> ipu_to )) {
581+ printf ("dmac: ipu_to channel done\n" );
582+
583+ dmac_set_irq (dmac , DMAC_IPU_TO );
584+
585+ dmac -> ipu_to .chcr &= ~0x100 ;
586+ dmac -> ipu_to .qwc = 0 ;
529587
530588 exit (1 );
531-
532- for (int i = 0 ; i < dmac -> ipu_from .tag .qwc ; i ++ ) {
533- uint128_t q = ee_bus_read128 (dmac -> bus , 0x10007000 );
534589
535- ee_bus_write128 (dmac -> bus , dmac -> ipu_from .madr , q );
590+ return 0 ;
591+ }
536592
537- dmac -> ipu_from .madr += 16 ;
538- }
539- } while (!channel_is_done (& dmac -> ipu_from ));
593+ uint128_t tag = dmac_read_qword (dmac , dmac -> ipu_to .tadr , 0 );
540594
541- // exit(1 );
595+ dmac_process_source_tag ( dmac , & dmac -> ipu_to , tag );
542596
543- dmac_set_irq (dmac , DMAC_IPU_FROM );
597+ // printf("dmac: ipu_to tag qwc=%08lx id=%ld irq=%ld addr=%08lx mem=%ld data=%016lx end=%d tte=%d\n",
598+ // dmac->ipu_to.tag.qwc,
599+ // dmac->ipu_to.tag.id,
600+ // dmac->ipu_to.tag.irq,
601+ // dmac->ipu_to.tag.addr,
602+ // dmac->ipu_to.tag.mem,
603+ // dmac->ipu_to.tag.data,
604+ // dmac->ipu_to.tag.end,
605+ // (dmac->ipu_to.chcr >> 7) & 1
606+ // );
544607
545- dmac -> ipu_from .chcr &= ~0x100 ;
546- dmac -> ipu_from .qwc = 0 ;
608+ return 1 ;
547609}
548610void dmac_handle_ipu_to_transfer (struct ps2_dmac * dmac ) {
549- // printf("ee: ipu_to start data=%08x dir=%d mod=%d tte=%d madr=%08x qwc=%08x tadr=%08x\n",
550- // dmac->ipu_to.chcr,
551- // dmac->ipu_to.chcr & 1,
552- // (dmac->ipu_to.chcr >> 2) & 3,
553- // !!(dmac->ipu_to.chcr & 0x40),
554- // dmac->ipu_to.madr,
555- // dmac->ipu_to.qwc,
556- // dmac->ipu_to.tadr
557- // );
611+ if ((dmac -> ipu_to .chcr & 0x100 ) == 0 ) {
612+ // printf("dmac: ipu_to channel not started\n");
558613
559- dmac_set_irq (dmac , DMAC_IPU_TO );
614+ return ;
615+ }
560616
561- dmac -> ipu_to .chcr &= ~0x100 ;
617+ printf ("dmac: ipu_to start data=%08x dir=%d mod=%d tte=%d madr=%08x qwc=%08x tadr=%08x\n" ,
618+ dmac -> ipu_to .chcr ,
619+ dmac -> ipu_to .chcr & 1 ,
620+ (dmac -> ipu_to .chcr >> 2 ) & 3 ,
621+ !!(dmac -> ipu_to .chcr & 0x40 ),
622+ dmac -> ipu_to .madr ,
623+ dmac -> ipu_to .qwc ,
624+ dmac -> ipu_to .tadr
625+ );
626+
627+ while (dmac_transfer_ipu_to_qword (dmac )) {
628+ // Keep transferring until we run out of QWC or DREQ is cleared
629+ }
562630
563- return ;
631+ // while (dmac->ipu_to.dreq && dmac->ipu_to.qwc) {
632+ // uint128_t q = dmac_read_qword(dmac, dmac->ipu_to.madr, dmac->ipu_to.tag.mem);
564633
565- do {
566- uint128_t tag = dmac_read_qword (dmac , dmac -> ipu_to .tadr , 0 );
567-
568- dmac_process_source_tag (dmac , & dmac -> ipu_to , tag );
569-
570- // printf("ee: ipu_to tag qwc=%08lx id=%ld irq=%ld addr=%08lx mem=%ld data=%016lx end=%d tte=%d\n",
571- // dmac->ipu_to.tag.qwc,
572- // dmac->ipu_to.tag.id,
573- // dmac->ipu_to.tag.irq,
574- // dmac->ipu_to.tag.addr,
575- // dmac->ipu_to.tag.mem,
576- // dmac->ipu_to.tag.data,
577- // dmac->ipu_to.tag.end,
578- // (dmac->ipu_to.chcr >> 7) & 1
579- // );
580- // printf("ee: SIF1 tag madr=%08x\n", dmac->sif1.madr);
634+ // ee_bus_write128(dmac->bus, 0x10007010, q);
635+
636+ // dmac->ipu_to.madr += 16;
637+ // dmac->ipu_to.tag.qwc--;
638+ // }
581639
582- for (int i = 0 ; i < dmac -> ipu_to .tag .qwc ; i ++ ) {
583- uint128_t q = dmac_read_qword (dmac , dmac -> ipu_to .madr , dmac -> ipu_to .tag .mem );
640+ // if (dmac->ipu_to.tag.qwc == 0) {
641+ // if (channel_is_done(&dmac->ipu_to)) {
642+ // dmac_set_irq(dmac, DMAC_IPU_TO);
584643
585- ee_bus_write128 (dmac -> bus , 0x10007010 , q );
644+ // dmac->ipu_to.chcr &= ~0x100;
645+ // dmac->ipu_to.qwc = 0;
586646
587- dmac -> ipu_to .madr += 16 ;
588- }
589- } while (!channel_is_done (& dmac -> ipu_to ));
647+ // printf("dmac: ipu_to channel done\n");
590648
591- // exit(1);
649+ // return;
650+ // }
592651
593- dmac_set_irq (dmac , DMAC_IPU_TO );
652+ // uint128_t tag = dmac_read_qword (dmac, dmac->ipu_to.tadr, 0 );
594653
595- dmac -> ipu_to .chcr &= ~0x100 ;
596- dmac -> ipu_to .qwc = 0 ;
654+ // dmac_process_source_tag(dmac, &dmac->ipu_to, tag);
655+ // }
656+
657+ // if (!dmac->ipu_to.dreq) {
658+ // return;
659+ // }
597660}
598661void dmac_handle_sif0_transfer (struct ps2_dmac * dmac ) {
599662 // SIF FIFO is empty, keep waiting
@@ -656,7 +719,7 @@ void dmac_handle_sif0_transfer(struct ps2_dmac* dmac) {
656719
657720 // printf("ee: Writing %016lx %016lx to %08x\n", q.u64[1], q.u64[0], dmac->sif0.madr);
658721
659- ee_bus_write128 (dmac -> bus , dmac -> sif0 .madr , q );
722+ dmac_write_qword (dmac , dmac -> sif0 . madr , dmac -> sif0 .tag . mem , q );
660723
661724 dmac -> sif0 .madr += 16 ;
662725 }
@@ -747,7 +810,7 @@ void dmac_spr_from_interleave(struct ps2_dmac* dmac) {
747810
748811 // Note: When TQWC=0, it is set to QWC instead (undocumented)
749812 if (tqwc == 0 )
750- tqwc = dmac -> spr_to .qwc ;
813+ tqwc = dmac -> spr_from .qwc ;
751814
752815 while (dmac -> spr_from .qwc ) {
753816 for (int i = 0 ; i < tqwc && dmac -> spr_from .qwc ; i ++ ) {
@@ -762,9 +825,6 @@ void dmac_spr_from_interleave(struct ps2_dmac* dmac) {
762825 }
763826
764827 dmac -> spr_from .madr += sqwc * 16 ;
765-
766- if (dmac -> spr_from .qwc == 0 )
767- return ;
768828 }
769829}
770830void dmac_handle_spr_from_transfer (struct ps2_dmac * dmac ) {
@@ -785,7 +845,6 @@ void dmac_handle_spr_from_transfer(struct ps2_dmac* dmac) {
785845
786846 int mode = (dmac -> spr_from .chcr >> 2 ) & 3 ;
787847
788- // Interleave mode unimplemented yet
789848 if (mode == 2 ) {
790849 dmac_spr_from_interleave (dmac );
791850
@@ -869,9 +928,6 @@ void dmac_spr_to_interleave(struct ps2_dmac* dmac) {
869928 }
870929
871930 dmac -> spr_to .madr += sqwc * 16 ;
872-
873- if (dmac -> spr_to .qwc == 0 )
874- return ;
875931 }
876932}
877933void dmac_handle_spr_to_transfer (struct ps2_dmac * dmac ) {
@@ -968,7 +1024,7 @@ static inline void dmac_handle_channel_start(struct ps2_dmac* dmac, uint32_t add
9681024 case 0x9000 : dmac_handle_vif1_transfer (dmac ); return ;
9691025 case 0xA000 : dmac_handle_gif_transfer (dmac ); return ;
9701026 case 0xB000 : dmac_handle_ipu_from_transfer (dmac ); return ;
971- case 0xB400 : dmac_handle_ipu_to_transfer (dmac ); return ;
1027+ case 0xB400 : dmac -> ipu_to . dreq = 1 ; dmac_handle_ipu_to_transfer (dmac ); return ;
9721028 case 0xC000 : dmac_handle_sif0_transfer (dmac ); return ;
9731029 case 0xC400 : dmac_handle_sif1_transfer (dmac ); return ;
9741030 case 0xC800 : dmac_handle_sif2_transfer (dmac ); return ;
0 commit comments