//PVR-DMA
void do_pvr_dma()
{
	u32 chcr   = DMAC_CHCR(0).full;
	u32 dmaor  = DMAC_DMAOR.full;
	u32 dmatcr = DMAC_DMATCR(0);

	u32 src = SB_PDSTAR;
	u32 dst = SB_PDSTAP;
	u32 len = SB_PDLEN;

	if(0x8201 != (dmaor &DMAOR_MASK))
	{
		printf("\n!\tDMAC: DMAOR has invalid settings (%X) !\n", dmaor);
		return;
	}

	if (len & 0x1F)
	{
		printf("\n!\tDMAC: SB_C2DLEN has invalid size (%X) !\n", len);
		return;
	}

	if (SB_PDDIR)
	{
		//PVR -> System
/*		for (u32 i=0;i<len;i+=4)
		{
			u32 temp=ReadMem32_nommu(dst+i);
			WriteMem32_nommu(src+i,temp);
		}*/
		WriteMemBlock_nommu_dma(dst,src,len);
	}
	else
	{
		//System -> PVR
		//TODO : FIX THAT , to warp around on dmas :)
		//WriteMemBlock_nommu_ptr(dst,(u32*)GetMemPtr(src,len),len);
		WriteMemBlock_nommu_dma(dst,src,len);
	}

	DMAC_SAR(0) = (src + len);
	DMAC_CHCR(0).full &= 0xFFFFFFFE;
	DMAC_DMATCR(0) = 0x00000000;

	SB_PDST = 0x00000000;

	//TODO : *CHECKME* is that ok here ? the docs don't say here it's used [PVR-DMA , bit 11]
	asic_RaiseInterrupt(holly_PVR_DMA);
}
Example #2
0
void DMAC_Ch2St(void)
{
	u32 chcr   = DMAC_CHCR(2).full;
	u32 dmaor  = DMAC_DMAOR.full;
	u32 dmatcr = DMAC_DMATCR(2);

	u32 src    = DMAC_SAR(2);
	u32 dst    = SB_C2DSTAT;
	u32 len    = SB_C2DLEN ;

	if(0x8201 != (dmaor &DMAOR_MASK))
	{
		printf("\n!\tDMAC: DMAOR has invalid settings (%X) !\n", dmaor);
		return;
	}

	if (len & 0x1F)
	{
		printf("\n!\tDMAC: SB_C2DLEN has invalid size (%X) !\n", len);
		return;
	}

//	printf(">>\tDMAC: Ch2 DMA SRC=%X DST=%X LEN=%X\n", src, dst, len );

	// Direct DList DMA (Ch2)

	// Texture DMA 
	if((dst >= 0x10000000) && (dst <= 0x10FFFFFF))
	{
		u32 p_addr=src & RAM_MASK;
		//GetMemPtr perhaps ? it's not good to use the mem arrays directly 
		while(len)
		{
			if ((p_addr+len)>RAM_SIZE)
			{
				u32 *sys_buf=(u32 *)GetMemPtr(src,len);//(&mem_b[src&RAM_MASK]);
				u32 new_len=RAM_SIZE-p_addr;
				TAWrite(dst,sys_buf,(new_len/32));
				len-=new_len;
				src+=new_len;
			}
			else
			{
				u32 *sys_buf=(u32 *)GetMemPtr(src,len);//(&mem_b[src&RAM_MASK]);
				TAWrite(dst,sys_buf,(len/32));
				src+=len;
				break;
			}
		}
	}
	// If SB_C2DSTAT reg is inrange from 0x11000000 to 0x11FFFFE0,	 set 1 in SB_LMMODE0 reg.
	else if((dst >= 0x11000000) && (dst <= 0x11FFFFE0))
	{
		//printf(">>\tDMAC: TEX LNMODE0 Ch2 DMA SRC=%X DST=%X LEN=%X | LN(%X::%X)\n", src, dst, len, *pSB_LMMODE0, *pSB_LMMODE1 );

		dst=(dst&0xFFFFFF) |0xa4000000;
		u32 p_addr=src & RAM_MASK;
		while(len)
		{
			if ((p_addr+len)>RAM_SIZE)
			{
				u32 new_len=RAM_SIZE-p_addr;
				WriteMemBlock_nommu_dma(dst,src,new_len);
				len-=new_len;
				src+=new_len;
				dst+=new_len;
			}
			else
			{
				WriteMemBlock_nommu_dma(dst,src,len);
				src+=len;
				break;
			}
		}
	}
	// If SB_C2DSTAT reg is in range from 0x13000000 to 0x13FFFFE0, set 1 in SB_LMMODE1 reg.
	else if((dst >= 0x13000000) && (dst <= 0x13FFFFE0))
	{
		die(".\tPVR DList DMA LNMODE1\n\n");
		src+=len;
	}
	else 
	{ 
		printf("\n!\tDMAC: SB_C2DSTAT has invalid address (%X) !\n", dst); 
		src+=len;
	}

	// Setup some of the regs so it thinks we've finished DMA

	DMAC_SAR(2)        = (src);
	DMAC_CHCR(2).full &= 0xFFFFFFFE;
	DMAC_DMATCR(2)     = 0x00000000;

	SB_C2DST           = 0x00000000;
	SB_C2DLEN          = 0x00000000;
	SB_C2DSTAT         = (src );

	// The DMA end interrupt flag (SB_ISTNRM - bit 19: DTDE2INT) is set to "1."
	//-> fixed , holly_PVR_DMA is for different use now (fixed the interrupts enum too)
	asic_RaiseInterruptWait(holly_CH2_DMA);
}