s32 BlockTransWrite(u8 *iopaddr, u32 size, s32 chan) { s32 core = chan & 1; BlockTransBuff[core] = 0; BlockTransSize[core] = size; BlockTransAddr[core] = (u32)iopaddr; if(*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS) return -1; if(*SD_DMA_CHCR(core) & SD_DMA_START) return -1; *SD_CORE_ATTR(core) &= 0xFFCF; *SD_A_TSA_HI(core) = 0; *SD_A_TSA_LO(core) = 0; *U16_REGISTER(0x1B0+(core*1024)) = 1 << core; SetDmaWrite(core); *SD_DMA_ADDR(core) = (u32)iopaddr; *SD_DMA_MODE(core) = 0x10; *SD_DMA_SIZE(core) = (size/64)+((size&63)>0); *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU; return 0; }
s32 BlockTransWriteFrom(u8 *iopaddr, u32 size, s32 chan, u16 mode, u8 *startaddr) { s32 core = chan & 1; s32 offset; BlockTransBuff[core] = 0; BlockTransSize[core] = size; BlockTransAddr[core] = (u32)iopaddr; if(startaddr == 0) startaddr = iopaddr; offset = startaddr - iopaddr; if(offset > size) { if(mode & SD_TRANS_LOOP) { offset -= size; BlockTransBuff[core] = 1; } else { return -1; } } if(offset & 1023) offset += 1024; iopaddr += (BlockTransSize[core] * BlockTransBuff[core]) + offset; if(*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS) return -1; if(*SD_DMA_CHCR(core) & SD_DMA_START) return -1; *SD_CORE_ATTR(core) &= 0xFFCF; *SD_A_TSA_HI(core) = 0; *SD_A_TSA_LO(core) = 0; *U16_REGISTER(0x1B0+(core*1024)) = 1 << core; SetDmaWrite(core); *SD_DMA_ADDR(core) = (u32)iopaddr; *SD_DMA_MODE(core) = 0x10; *SD_DMA_SIZE(core) = (size/64)+((size&63)>0); *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU; return 0; }
s32 BlockTransRead(u8 *iopaddr, u32 size, s32 chan, s16 mode) { u32 i; s32 core = chan & 1; BlockTransBuff[core] = 0; BlockTransSize[core] = size; BlockTransAddr[core] = (u32)iopaddr; if(*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS) return -1; if(*SD_DMA_CHCR(core) & SD_DMA_START) return -1; *SD_CORE_ATTR(core) &= 0xFFCF; *SD_A_TSA_HI(core) = 0; *SD_A_TSA_LO(core) = ((mode & 0xF00) << 1) + 0x400; *U16_REGISTER(0x1AE + (core*1024)) = (mode & 0xF000) >> 11; i = 0x4937; while(i--); *U16_REGISTER(0x1B0+(core*1024)) = 4; SetDmaRead(core); *SD_DMA_ADDR(core) = (u32)iopaddr; *SD_DMA_MODE(core) = 0x10; *SD_DMA_SIZE(core) = (size/64)+((size&63)>0); *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_SPU2IOP; return 0; }
int TransInterrupt(void *data) { IntrData *intr = (IntrData*) data; s32 dir; s32 core; dir = ((intr->mode & 0x200) < 1); core = intr->mode & 0xFF; // Voice Transfer if((intr->mode & 0x100) == 0) { // SD_C_STATX(core) // If done elsewise, it doesn't work, havn't figured out why yet. volatile u16 *statx = U16_REGISTER(0x344 + (core * 1024)); if(!(*statx & 0x80)) while(!(*statx & 0x80)); *SD_CORE_ATTR(core) &= ~SD_CORE_DMA; if(*SD_CORE_ATTR(core) & 0x30) while((*SD_CORE_ATTR(core) & 0x30)); if(TransIntrHandlers[core]) goto intr_handler; if(TransIntrCallbacks[core]) goto IntrCallback; VoiceTransComplete[core] = 1; } else { // Block Transfer if(intr->mode & (SD_BLOCK_TRANS_LOOP << 8)) { // Switch buffers BlockTransBuff[core] = 1 - BlockTransBuff[core]; // Setup DMA & send *SD_DMA_ADDR(core) = (BlockTransSize[core] * BlockTransBuff[core])+BlockTransAddr[core]; *SD_DMA_SIZE(core) = (BlockTransSize[core]/64)+((BlockTransSize[core]&63)>0); *SD_DMA_CHCR(core) = SD_DMA_START | SD_DMA_CS | dir; } else { *SD_CORE_ATTR(core) &= ~SD_CORE_DMA; *SD_P_MMIX(core) &= 0xFF3F; *U16_REGISTER(0x1B0 + (core * 1024)) = 0; } if(TransIntrHandlers[core]) { intr_handler: TransIntrHandlers[core](core, intr->data); } else { if(TransIntrCallbacks[core]) { IntrCallback: TransIntrCallbacks[core](0); } } } if(dir == SD_DMA_DIR_SPU2IOP) FlushDcache(); return 1; }