diff --git a/pcsx2/Dmac.h b/pcsx2/Dmac.h index 8933968ebc..9eca759fd6 100644 --- a/pcsx2/Dmac.h +++ b/pcsx2/Dmac.h @@ -19,6 +19,29 @@ extern u8 *psH; // hw mem +// Useful enums for some of the fields. +enum pce_values +{ + PCE_NOTHING = 0, + PCE_RESERVED, + PCE_DISABLED, + PCE_ENABLED +}; + + +enum tag_id +{ + TAG_CNTS = 0, + TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end + TAG_CNT, // Transfer QWC following the tag. + TAG_NEXT, // Transfer QWC following tag. TADR = ADDR + TAG_REF, // Transfer QWC from ADDR field + TAG_REFS, // Transfer QWC from ADDR field (Stall Control) + TAG_CALL, // Transfer QWC following the tag, save succeeding tag + TAG_RET, // Transfer QWC following the tag, load next tag + TAG_END // Transfer QWC following the tag +}; + enum mfd_type { NO_MFD = 0, @@ -55,15 +78,38 @@ enum TransferMode // --- DMA --- // +// Doing double duty as both the top 32 bits *and* the lower 32 bits of a chain tag. +// Theoretically should probably both be in a u64 together, but with the way the +// code is layed out, this is easier for the moment. + +union tDMA_TAG { + struct { + u32 QWC : 16; + u32 reserved2 : 10; + u32 PCE : 2; + u32 ID : 3; + u32 IRQ : 1; + }; + struct { + u32 ADDR : 31; + u32 SPR : 1; + }; + u32 _u32; + + tDMA_TAG(u32 val) { _u32 = val; } + u16 upper() { return (_u32 >> 16); } + u16 lower() { return (u16)_u32; } +}; + union tDMA_CHCR { struct { - u32 DIR : 1; + u32 DIR : 1; // Direction: 0 - to memory, 1 - from memory. VIF1 & SIF2 only. u32 reserved1 : 1; u32 MOD : 2; - u32 ASP : 2; - u32 TTE : 1; - u32 TIE : 1; - u32 STR : 1; + u32 ASP : 2; // ASP1 & ASP2; Address stack pointer. 0, 1, or 2 addresses. + u32 TTE : 1; // Tag Transfer Enable. 0 - Disable / 1 - Enable. + u32 TIE : 1; // Tag Interrupt Enable. 0 - Disable / 1 - Enable. + u32 STR : 1; // Start. 0 while stopping DMA, 1 while it's running. u32 reserved2 : 7; u32 TAG : 16; }; @@ -143,6 +189,8 @@ union tDMA_QWC { wxString desc() { return wxsFormat(L"QWC: 0x%x", _u32); } }; +static __forceinline void throwBusError(const char *s); + struct DMACh { tDMA_CHCR chcr; u32 null0[3]; @@ -157,9 +205,39 @@ struct DMACh { u32 asr1; u32 null5[11]; u32 sadr; + + void chcrTransfer(tDMA_TAG* ptag) + { + chcr.TAG = ptag[0].upper(); + } + + void qwcTransfer(tDMA_TAG* ptag) + { + qwc = ptag[0].QWC; + } + + bool transfer(const char *s, tDMA_TAG* ptag) + { + //chcrTransfer(ptag); + + if (ptag == NULL) // Is ptag empty? + { + throwBusError(s); + return false; + } + chcrTransfer(ptag); + + qwcTransfer(ptag); + return true; + } + + void unsafeTransfer(tDMA_TAG* ptag) + { + chcrTransfer(ptag); + qwcTransfer(ptag); + } }; - enum INTCIrqs { INTC_GS = 0, @@ -227,12 +305,12 @@ enum DMAInter union tDMAC_CTRL { struct { - u32 DMAE : 1; - u32 RELE : 1; - u32 MFD : 2; - u32 STS : 2; - u32 STD : 2; - u32 RCYC : 3; + u32 DMAE : 1; // 0/1 - disables/enables all DMAs + u32 RELE : 1; // 0/1 - cycle stealing off/on + u32 MFD : 2; // Memory FIFO drain channel (mfd_type) + u32 STS : 2; // Stall Control source channel (sts type) + u32 STD : 2; // Stall Control drain channel (std_type) + u32 RCYC : 3; // Release cycle (8/16/32/64/128/256) u32 reserved1 : 21; }; u32 _u32; @@ -346,6 +424,7 @@ union tDMAC_STADR { wxString desc() { return wxsFormat(L"Stadr: 0x%x", _u32); } }; + struct DMACregisters { tDMAC_CTRL ctrl; @@ -407,6 +486,12 @@ struct INTCregisters #define dmacRegs ((DMACregisters*)(PS2MEM_HW+0xE000)) #define intcRegs ((INTCregisters*)(PS2MEM_HW+0xF000)) +static __forceinline void throwBusError(const char *s) +{ + Console.Error("%s BUSERR", s); + dmacRegs->stat.BEIS = true; +} + // Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits) static __forceinline void *dmaGetAddr(u32 addr) { u8 *ptr; diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index 652b1547e2..11dd49fda7 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -1351,9 +1351,9 @@ static __forceinline bool IPU1chain(int &totalqwc) if (ipu1dma->qwc > 0) { int qwc = ipu1dma->qwc; - u32 *pMem; + tDMA_TAG *pMem; - pMem = (u32*)dmaGetAddr(ipu1dma->madr); + pMem = (tDMA_TAG*)dmaGetAddr(ipu1dma->madr); if (pMem == NULL) { @@ -1361,7 +1361,7 @@ static __forceinline bool IPU1chain(int &totalqwc) return true; } - qwc = FIFOto_write(pMem, qwc); + qwc = FIFOto_write((u32*)pMem, qwc); ipu1dma->madr += qwc<< 4; ipu1dma->qwc -= qwc; totalqwc += qwc; @@ -1375,10 +1375,9 @@ static __forceinline bool IPU1chain(int &totalqwc) return false; } -// Remind me to give this a better name. --arcum42 -static __forceinline bool IncreaseTadr(u32 tag) +static __forceinline bool ipuDmacPartialChain(tDMA_TAG tag) { - switch (Tag::Id(tag)) + switch (tag.ID) { case TAG_REFE: // refe ipu1dma->tadr += 16; @@ -1393,13 +1392,13 @@ static __forceinline bool IncreaseTadr(u32 tag) extern void gsInterrupt(); -static __forceinline bool ipuDmacSrcChain(DMACh *tag, u32 *ptag) +static __forceinline bool ipuDmacSrcChain(DMACh *tag, tDMA_TAG *ptag) { - switch (Tag::Id(ptag)) + switch (ptag->ID) { case TAG_REFE: // refe // do not change tadr - tag->madr = ptag[1]; + tag->madr = ptag[1].ADDR; return true; break; @@ -1411,11 +1410,11 @@ static __forceinline bool ipuDmacSrcChain(DMACh *tag, u32 *ptag) case TAG_NEXT: // next tag->madr = tag->tadr + 16; - tag->tadr = ptag[1]; + tag->tadr = ptag[1].ADDR; break; case TAG_REF: // ref - tag->madr = ptag[1]; + tag->madr = ptag[1].ADDR; tag->tadr += 16; break; @@ -1444,7 +1443,7 @@ static __forceinline void flushGIF() int IPU1dma() { - u32 *ptag; + tDMA_TAG *ptag; bool done = false; int ipu1cycles = 0, totalqwc = 0; @@ -1483,15 +1482,15 @@ int IPU1dma() else { // Chain mode. - u32 tag = ipu1dma->chcr._u32; // upper bits describe current tag + tDMA_TAG tag = ipu1dma->chcr._u32; // upper bits describe current tag - if (ipu1dma->chcr.TIE && Tag::IRQ(tag)) + if (ipu1dma->chcr.TIE && tag.IRQ) { - ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + ptag = (tDMA_TAG*)dmaGetAddr(ipu1dma->tadr); - IncreaseTadr(tag); + ipuDmacPartialChain(tag); - Tag::UpperTransfer(ipu1dma, ptag); + ipu1dma->chcrTransfer(ptag); IPU_LOG("IPU dmaIrq Set"); IPU_INT_TO(totalqwc * BIAS); @@ -1499,7 +1498,7 @@ int IPU1dma() return totalqwc; } - if (IncreaseTadr(tag)) + if (ipuDmacPartialChain(tag)) { IPU_INT_TO((1 + totalqwc)*BIAS); return totalqwc; @@ -1530,19 +1529,19 @@ int IPU1dma() else { // Chain Mode & ipu1dma->qwc is 0 - ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR + ptag = (tDMA_TAG*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR // Transfer the tag. - if (!(Tag::Transfer("IPU1", ipu1dma, ptag))) return totalqwc; + if (!ipu1dma->transfer("IPU1", ptag)) return totalqwc; ipu1cycles += 1; // Add 1 cycles from the QW read for the tag done = ipuDmacSrcChain(ipu1dma, ptag); IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x", - ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC); + ptag[1]._u32, ptag[0]._u32, ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC); - g_nDMATransfer.DOTIE1 = (ipu1dma->chcr.TIE && Tag::IRQ(ptag)); + g_nDMATransfer.DOTIE1 = (ipu1dma->chcr.TIE && ptag->IRQ); if (ipu1dma->qwc == 0) { @@ -1555,12 +1554,12 @@ int IPU1dma() if (done) { - ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + ptag = (tDMA_TAG*)dmaGetAddr(ipu1dma->tadr); - IncreaseTadr(ptag[0]); + ipuDmacPartialChain(ptag[0]); // Transfer the last of ptag into chcr. - Tag::UpperTransfer(ipu1dma, ptag); + ipu1dma->chcrTransfer(ptag); } IPU_INT_TO(ipu1cycles + totalqwc * BIAS); // Should it be (ipu1cycles + totalqwc) * BIAS? @@ -1574,7 +1573,7 @@ int IPU1dma() if (IPU1chain(totalqwc)) return totalqwc; } - IncreaseTadr(ptag[0]); + ipuDmacPartialChain(ptag[0]); } else { @@ -1655,7 +1654,7 @@ int IPU0dma() { int readsize; static int totalsize = 0; - void* pMem; + tDMA_TAG* pMem; if ((!(ipu0dma->chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0)) return 0; @@ -1665,8 +1664,9 @@ int IPU0dma() IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx", ipu0dma->chcr._u32, ipu0dma->madr, ipu0dma->qwc); - pxAssert((ipu0dma->chcr._u32 & 0xC) == 0); - pMem = (u32*)dmaGetAddr(ipu0dma->madr); + pxAssert(ipu0dma->chcr.MOD == NORMAL_MODE); + + pMem = (tDMA_TAG*)dmaGetAddr(ipu0dma->madr); readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC); totalsize+=readsize; @@ -1700,7 +1700,7 @@ int IPU0dma() //This broke vids in Digital Devil Saga //Note that interrupting based on totalsize is just guessing.. IPU_INT_FROM(totalsize*BIAS ); - totalsize=0; + totalsize = 0; } return readsize; diff --git a/pcsx2/Tags.h b/pcsx2/Tags.h index 3cc93fe074..ced5d01b7e 100644 --- a/pcsx2/Tags.h +++ b/pcsx2/Tags.h @@ -14,139 +14,54 @@ */ // This is meant to be a collection of generic functions dealing with tags. +// It's now going to be mostly depreciated for Dmac.h. + #include "Dmac.h" -enum pce_values -{ - PCE_NOTHING = 0, - PCE_RESERVED, - PCE_DISABLED, - PCE_ENABLED -}; - - -enum tag_id -{ - TAG_CNTS = 0, - TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end - TAG_CNT, // Transfer QWC following the tag. - TAG_NEXT, // Transfer QWC following tag. TADR = ADDR - TAG_REF, // Transfer QWC from ADDR field - TAG_REFS, // Transfer QWC from ADDR field (Stall Control) - TAG_CALL, // Transfer QWC following the tag, save succeeding tag - TAG_RET, // Transfer QWC following the tag, load next tag - TAG_END // Transfer QWC following the tag -}; - -enum d_ctrl_flags -{ - CTRL_DMAE = 0x1, // 0/1 - disables/enables all DMAs - CTRL_RELE = 0x2, // 0/1 - cycle stealing off/on - CTRL_MFD = 0xC, // Memory FIFO drain channel (mfd_type) - CTRL_STS = 0x30, // Stall Control source channel (sts type) - CTRL_STD = 0xC0, // Stall Control drain channel (std_type) - CTRL_RCYC = 0x100 // Release cycle (8/16/32/64/128/256) - // When cycle stealing is on, the release cycle sets the period to release - // the bus to EE. -}; - -enum chcr_flags -{ - CHCR_DIR = 0x1, // Direction: 0 - to memory, 1 - from memory. VIF1 & SIF2 only. - CHCR_MOD1 = 0x4, - CHCR_MOD2 = 0x8, - CHCR_MOD = 0xC, // MOD1 & MOD2; Holds which of the Transfer modes above is used. - CHCR_ASP1 = 0x10, - CHCR_ASP2 = 0x20, - CHCR_ASP = 0x30, // ASP1 & ASP2; Address stack pointer. 0, 1, or 2 addresses. - CHCR_TTE = 0x40, // Tag Transfer Enable. 0 - Diable / 1 - Enable. - CHCR_TIE = 0x80, // Tag Interrupt Enable. 0 - Diable / 1 - Enable. - CHCR_STR = 0x100 // Start. 0 while stopping DMA, 1 while it's running. -}; - -// Doing double duty as both the top 32 bits *and* the lower 32 bits of a chain tag. -// Theoretically should probably both be in a u64 together, but with the way the -// code is layed out, this is easier for the moment. -union tDMA_TAG { - struct { - u32 QWC : 16; - u32 reserved2 : 10; - u32 PCE : 2; - u32 ID : 3; - u32 IRQ : 1; - }; - struct { - u32 ADDR : 31; - u32 SPR : 1; - }; - u32 _u32; - - tDMA_TAG(u32 val) { _u32 = val; } -}; - +// Transfer functions using u32. Eventually should be phased out for the tDMA_TAG functions. namespace Tag { - // Transfer functions, static __forceinline void UpperTransfer(DMACh *tag, u32* ptag) { - // Transfer upper part of tag to CHCR bits 31-15 - tag->chcr.TAG = ((*ptag) >> 16); + tag->chcrTransfer((tDMA_TAG*)ptag); } static __forceinline void LowerTransfer(DMACh *tag, u32* ptag) { - //QWC set to lower 16bits of the tag - tag->qwc = (u16)ptag[0]; + tag->qwcTransfer((tDMA_TAG*)ptag); } static __forceinline bool Transfer(const char *s, DMACh *tag, u32* ptag) { - if (ptag == NULL) // Is ptag empty? - { - Console.Error("%s BUSERR", s); - UpperTransfer(tag, ptag); - - // Set BEIS (BUSERR) in DMAC_STAT register - dmacRegs->stat.BEIS = true; - return false; - } - else - { - UpperTransfer(tag, ptag); - LowerTransfer(tag, ptag); - return true; - } + tag->transfer(s, (tDMA_TAG*)ptag); } static __forceinline void UnsafeTransfer(DMACh *tag, u32* ptag) { - UpperTransfer(tag, ptag); - LowerTransfer(tag, ptag); - } - - // Untested - static __forceinline pce_values PCE(u32 *tag) - { - return (pce_values)((tag[0] >> 22) & 0x3); + tag->unsafeTransfer((tDMA_TAG*)ptag); } +} +// Misc Tag functions, soon to be obsolete. +namespace Tag +{ static __forceinline tag_id Id(u32* tag) { - return (tag_id)((tag[0] >> 28) & 0x7); + return (tag_id)(((tDMA_TAG)tag[0]).ID); } static __forceinline tag_id Id(u32 tag) { - return (tag_id)((tag >> 28) & 0x7); + return (tag_id)(((tDMA_TAG)tag).ID); } static __forceinline bool IRQ(u32 *tag) { - return !!(tag[0] >> 31); + return !!((tDMA_TAG)tag[0]).IRQ; } static __forceinline bool IRQ(u32 tag) { - return !!(tag >> 31); + return !!((tDMA_TAG)tag).IRQ; } }