⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idma.c

📁 这是motorola公司的powerpc芯片上的嵌入式linux上的驱动程序和测试程序
💻 C
字号:
#include "bm8024.h"
#include "idma.h"
#include "ppc860cpm.h"
#include "ppc860siu.h"

volatile U32	immrValue;

U32		txBdIndex=0;
#define         TXBD_INDEX_INCREASE(index)    index = ((index + 1) % NO_IDMA_BD_TX)

#define	        BDRX_OFFSET		0x2c00
#define         BDTX_OFFSET		0x2c30


/*
* get immr register value
*/
U32 ImmrGet(void)
{
	unsigned long immr;

	asm( "mfspr %0,638": "=r"(immr) : );
	immr &= 0xFFFF0000;	
	
	return immr;
}

/*
* the entry of CPM's IDMA  initialization.
*/
void IDMA_Init(void)
{
	U32 		i,bd_offset;
	IDMA_PARAM 	*idmaBase;
	IDMA_BD 	*pIBD;

	immrValue = ImmrGet();
	
	
	/* set up port B pin 22, 23 as DACK , direction: output*/
	*PBPAR(immrValue) |= (PORTB_BIT23 | PORTB_BIT22);
	*PBDIR(immrValue) |= (PORTB_BIT23 | PORTB_BIT22);
	
	/* configure RISC controller configuration register*/
	*RCCR(immrValue) |= (RCCR_DR1M_LEVEL | RCCR_DR0M_LEVEL) | (0x02<<4);  /* fix the MPC850 bug */


	/* initialization IDMA1 buffer descriptor, not finished*/
	bd_offset = BDRX_OFFSET;
	
	pIBD = (IDMA_BD *)(immrValue + bd_offset);	            /*start of the dual-port RAM address for IDMA1 BD*/
	idmaBase = (IDMA_PARAM *)(immrValue + DPRAM_IDMA1_PARAM);   /*3CC0*/
	idmaBase->ibase = (U16)bd_offset;
	idmaBase->dcmr = (DCMR_SIZE_WORD | DCMR_SD_RP_WM | DCMR_SC_SINGLE);  /*read from peripheral , write to memory*/
	

	/* to ensure the CPM is ideal now.*/
	while(*CPCR(immrValue) & 0x0001)
	{
		/* wait for previous command complete */
	} 
			
	*CPCR(immrValue) = 0x0511;     /* initial IDMA1 channel	*/

	
	for(i=0; i<NO_IDMA_BD_RX; i++)		/* NO_IDMA_BD_RX = 0x01 */
	{
		pIBD[i].status = 0x0000;
		pIBD[i].dfcr = SOURCE_FUNC_CODE;
		pIBD[i].sfcr = DEST_FUNC_CODE;
		pIBD[i].len = 0;
		pIBD[i].sBuffer = 0;
		pIBD[i].dBuffer = 0;
	}

	pIBD[NO_IDMA_BD_RX-1].status |= BD_WRAP_BIT;      
	
	*IDMR1(immrValue) = (IDSRx_DONE | IDSRx_OB);
	*IDSR1(immrValue) = (IDSRx_DONE | IDSRx_OB | IDSRx_AD);

		
	
	/* initialization IDMA2 buffer descriptor	*/

	bd_offset = BDTX_OFFSET;
	
	pIBD = (IDMA_BD *)(immrValue + bd_offset);	/*start of the dual-port RAM address for IDMA2 BD*/
	
	idmaBase = (IDMA_PARAM *)(immrValue + DPRAM_IDMA2_PARAM);		/*3DC0*/
	
	idmaBase->ibase = (U16)bd_offset;
	idmaBase->dcmr = (DCMR_SIZE_WORD | DCMR_SD_RM_WP | DCMR_SC_DUAL);

	/* issue command via CPCR to initialize IDMA parameters	*/
	while(*CPCR(immrValue) & 0x0001)
	{
		/* wait for previous command complete	*/
	} 		
	*CPCR(immrValue) = 0x0551; /* initial IDMA2 channel	*/

	
	for(i=0; i<NO_IDMA_BD_TX; i++)	/*NO_IDMA_BD = 0x08 */
	{
		pIBD[i].status = 0x0000;
		pIBD[i].dfcr = SOURCE_FUNC_CODE;
		pIBD[i].sfcr = DEST_FUNC_CODE;
		pIBD[i].len = 0;
		pIBD[i].sBuffer = 0;
		pIBD[i].dBuffer = 0;
	}

    	pIBD[NO_IDMA_BD_TX-1].status |= BD_WRAP_BIT;      
    
	*IDMR2(immrValue) = (IDSRx_DONE | IDSRx_OB);
	*IDSR2(immrValue) = (IDSRx_DONE | IDSRx_OB | IDSRx_AD);


	/* 
	 set up port C pin 14, 15 as DREQ0, DREQ1
	*/
	
	*PCPAR(immrValue) &= ~(PORTC_BIT14 | PORTC_BIT15);
	*PCDIR(immrValue) &= ~(PORTC_BIT14 | PORTC_BIT15);
	*PCSO(immrValue)  |=  (PORTC_BIT14 | PORTC_BIT15);

}



int	setupWriteIDMA(U8 *sBuffer, U32 len ,U32 lastBufferFlag)
{

	IDMA_PARAM 	*idmaBase;
	IDMA_BD 	*pIBD;

	/* Wait for DMA channel*/
	if (lastBufferFlag)
		semTake (acdDmaRdySem, WAIT_FOREVER);
	
	idmaBase = (IDMA_PARAM *)(immrValue + DPRAM_IDMA2_PARAM);		
	pIBD = (IDMA_BD *)(immrValue + idmaBase->ibase);
	
	if (pIBD[txBdIndex].status & BD_READY_BIT)
		return IDMA_BUSY;
			
	if (len%4)  	
		len = 4*(len/4+1);	
	
	pIBD[txBdIndex].status |= BD_READY_BIT;
	if (lastBufferFlag)
		pIBD[txBdIndex].status |= BD_LAST_BIT;
	 
	pIBD[txBdIndex].len = len;
	pIBD[txBdIndex].sBuffer = sBuffer;

	TXBD_INDEX_INCREASE(txBdIndex);
	
	return IDMA_OK;
}


void	setupReadIDMA(U8 *dBuffer, U32 len)
{
	IDMA_BD 	*pIBD;
	IDMA_PARAM 	*idmaBase;
	U8 			status;

	/* Wait for DMA channel*/
	semTake (acdDmaRdySem, WAIT_FOREVER);	
	
	/* len must be 4 aligned */
	if (len%4)   	
      len = 4*(len/4 + 1);

     status = *IDSR1(immrValue);
    *IDSR1(immrValue) = status;		/**clear the IDSR bits by writing ones**/	    
	
	/*select IDMA1 channel*/
	idmaBase = (IDMA_PARAM *)(immrValue + DPRAM_IDMA1_PARAM) ;		/*3cc0*/
		
	idmaBase->dcmr = (DCMR_SIZE_WORD | DCMR_SD_RP_WM | DCMR_SC_SINGLE);
		
	pIBD = (IDMA_BD *)(immrValue + idmaBase->ibptr);
		
	pIBD[0].status |= 0x8800;
	pIBD[0].len = len;
	pIBD[0].dBuffer = dBuffer;		
}


U32 checkIDMADone(U32 channel)
{
	U32		count =0;
	volatile	U32	status_idma;   
	while(count++< MAX_RETRY)
	{
		if(channel == CHANNEL_IDMA1)
      		status_idma = *IDSR1(immrValue);
      	else
      		status_idma = *IDSR2(immrValue);
   
      	if (status_idma & 0x02)
      	{
      		/* Release for DMA channel*/
		semGive(acdDmaRdySem);    
      		return ACD_SUCCESS;        
      	}
   }
      
   /* Time out */
    semGive(acdDmaRdySem); 
	stopReadIDMA(channel);
    return ACD_ERROR;

}


void	stopReadIDMA(U32 channel)
{
 
	/* issue command via CPCR to initialize IDMA parameters*/
	while(*CPCR(immrValue) & 0x0001)
	{
		/* wait for previous command complete*/
	} 		

	if(channel == CHANNEL_IDMA1)
	   *CPCR(immrValue) = 0x0B11; /* stop IDAM1 channel*/
	else
       *CPCR(immrValue) = 0x0B51;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -