ref: 69a1076197fd30228ab21b06961bc5d7b305ff79
parent: 9fc807ccb8c9aacbe22e81fbde9b052e1a9ebcee
author: allkern <lisandroaalarcon@gmail.com>
date: Sat Jul 22 07:46:45 EDT 2023
Implement CDROM DMA IRQs Fix DICR writing
--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -99,25 +99,15 @@
switch (offset) { case 0x70: log_error("DMA control write %08x", value); dma->dpcr = value; break; case 0x74: {- value &= 0x7fffffff;
+ // IRQ signal is read-only
+ value &= ~DICR_IRQSI;
- uint32_t irqf = (dma->dicr >> 24) & 0x7f;
- uint32_t irqfr = (value >> 24) & 0x7f;
+ // Reset flags
+ dma->dicr &= ~(value & DICR_FLAGS);
- dma->dicr &= ~0x7f000000;
-
- irqf &= ~irqfr;
- irqf &= 0x7f;
-
- dma->dicr |= irqf << 24;
-
- if (dma->dicr & 0x00008000) {- dma->dicr |= 0x80000000;
-
- psx_ic_irq(dma->ic, IC_DMA);
- }
-
- log_error("DMA irqc write %08x irqfr=%08x", value, irqfr);+ // Write other fields
+ dma->dicr &= DICR_FLAGS;
+ dma->dicr |= value & (~DICR_FLAGS);
} break;
default: {@@ -130,7 +120,9 @@
void psx_dma_write16(psx_dma_t* dma, uint32_t offset, uint16_t value) { switch (offset) { default: {- log_error("Unhandled 16-bit DMA write at offset %08x (%04x)", offset, value);+ log_fatal("Unhandled 16-bit DMA write at offset %08x (%04x)", offset, value);+
+ exit(1);
} break;
}
}
@@ -138,7 +130,9 @@
void psx_dma_write8(psx_dma_t* dma, uint32_t offset, uint8_t value) { switch (offset) { default: {- log_error("Unhandled 8-bit DMA write at offset %08x (%02x)", offset, value);+ log_fatal("Unhandled 8-bit DMA write at offset %08x (%02x)", offset, value);+
+ exit(1);
} break;
}
}
@@ -260,6 +254,13 @@
BCR_SIZE(cdrom)
);
+ log_fatal("DICR: force=%u, en=%02x, irqen=%u, flags=%02x",+ (dma->dicr >> 15) & 1,
+ (dma->dicr >> 16) & 0x7f,
+ (dma->dicr >> 23) & 1,
+ (dma->dicr >> 24) & 0x7f
+ );
+
uint32_t size = BCR_SIZE(cdrom) * BCR_BCNT(cdrom);
if (!size) {@@ -325,18 +326,6 @@
dma->otc.chcr = 0;
//dma->otc.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
dma->otc.bcr = 0;
-
- // if (dma->dicr & 0x00400000) {- // dma->dicr |= 0x40000000;
-
- // if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {- // dma->dicr |= 0x80000000;
-
- // psx_ic_irq(dma->ic, IC_DMA);
- // } else {- // dma->dicr &= 0x7fffffff;
- // }
- // }
}
void psx_dma_update(psx_dma_t* dma, int cyc) {@@ -344,23 +333,25 @@
dma->cdrom_irq_delay -= cyc;
if (dma->cdrom_irq_delay <= 0) {- if (dma->dicr & 0x00400000) {- dma->dicr |= 0x40000000;
+ if (dma->dicr & DICR_DMA3EN)
+ dma->dicr |= DICR_DMA3FL;
- if ((dma->dicr & 0x8000) || ((dma->dicr & 0x800000) && (dma->dicr & 0x7f000000))) {- dma->dicr |= 0x80000000;
-
- log_fatal("DMA IRQ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");-
- psx_ic_irq(dma->ic, IC_DMA);
- } else {- dma->dicr &= 0x7fffffff;
- }
- }
-
dma->cdrom_irq_delay = 0;
}
}
+
+ int prev_irq_signal = (dma->dicr & DICR_IRQSI) != 0;
+ int irq_on_flags = (dma->dicr & DICR_IRQEN) != 0;
+ int force_irq = (dma->dicr & DICR_FORCE) != 0;
+ int irq = (dma->dicr & DICR_FLAGS) != 0;
+
+ int irq_signal = force_irq || (irq && irq_on_flags);
+
+ if (irq_signal && !prev_irq_signal)
+ psx_ic_irq(dma->ic, IC_DMA);
+
+ dma->dicr &= ~DICR_IRQSI;
+ dma->dicr |= irq_signal << 31;
}
void psx_dma_destroy(psx_dma_t* dma) {--- a/psx/dev/dma.h
+++ b/psx/dev/dma.h
@@ -105,7 +105,34 @@
#define BCR_SIZE(c) (dma->c.bcr & 0xffff)
#define BCR_BCNT(c) ((dma->c.bcr >> 16) & 0xffff)
-#define DICR_FIRQ 0x00008000
-#define DICR_IRQE 0x00000000
+/*
+ 0-5 Unknown (read/write-able)
+ 6-14 Not used (always zero)
+ 15 Force IRQ (sets bit31) (0=None, 1=Force Bit31=1)
+ 16-22 IRQ Enable setting bit24-30 upon DMA0..DMA6 (0=None, 1=Enable)
+ 23 IRQ Enable setting bit31 when bit24-30=nonzero (0=None, 1=Enable)
+ 24-30 IRQ Flags for DMA0..DMA6 (Write 1 to reset) (0=None, 1=IRQ)
+ 31 IRQ Signal (0-to-1 triggers 1F801070h.bit3) (0=None, 1=IRQ) (R)
+*/
+
+#define DICR_FORCE 0x00008000
+#define DICR_FLGEN 0x007f0000
+#define DICR_IRQEN 0x00800000
+#define DICR_FLAGS 0x7f000000
+#define DICR_IRQSI 0x80000000
+#define DICR_DMA0EN 0x00010000
+#define DICR_DMA1EN 0x00020000
+#define DICR_DMA2EN 0x00040000
+#define DICR_DMA3EN 0x00080000
+#define DICR_DMA4EN 0x00100000
+#define DICR_DMA5EN 0x00200000
+#define DICR_DMA6EN 0x00400000
+#define DICR_DMA0FL 0x01000000
+#define DICR_DMA1FL 0x02000000
+#define DICR_DMA2FL 0x04000000
+#define DICR_DMA3FL 0x08000000
+#define DICR_DMA4FL 0x10000000
+#define DICR_DMA5FL 0x20000000
+#define DICR_DMA6FL 0x40000000
#endif
\ No newline at end of file
--
⑨