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

📄 dma.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
 *
 * description: set current src, dest, byte count registers
 *              according to the desp for a given channel
 *              return DMASUCCESS if no error.
 *
 * note:
 **************************************************************/
static
DMAStatus DMA_Bld_Curr( LOCATION host,
					   unsigned int eumbbar,
					   unsigned int channel,
					   DMA_CURR     desp )
{
	DMA_SR status;	
	if ( channel != 0 && channel != 1 )
	{
		/* channel number out of range */
		return DMAINVALID;
	}

	if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
	{
		 return DMAINVALID;
	}
	
	if ( status.cb == 1  )
	{
		/* channel busy */
		return DMACHNBUSY;
	}
	
	desp.byte_cnt &= 0x03ffffff; /* upper 6-bits are 0s */

    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG], desp.src_addr );
#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) src := 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.src_addr );
#endif
	
    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG], desp.dest_addr );
#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) dest := 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.dest_addr );
#endif
	
    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG], desp.byte_cnt );
#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) count := 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt );
#endif
	

	return DMASUCCESS;

}

#if 0
/**************************************************************
 * function: DMA_Poke_Curr
 *
 * description: poke the current src, dest, byte count registers
 *              for a given channel.
 *
 *              return DMASUCCESS if no error
 *
 * note:        Due to the undeterministic parallelism, in chaining
 *              mode, the value returned by this function shall
 *              be taken as reference when the query is made rather
 *              than the absolute snapshot when the value is returned.
 **************************************************************/
static
DMAStatus DMA_Poke_Curr( LOCATION host,
					    unsigned int eumbbar,
					    unsigned int channel,
					    DMA_CURR*    desp )
{
	if ( channel != 0 && channel != 1 || desp == 0 )
	{
			return DMAINVALID;
	}

	desp->src_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG] );
#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) src : 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->src_addr );
#endif
	
	desp->dest_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG] );
#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) dest : 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->dest_addr );
#endif
	
    desp->byte_cnt = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG] );
#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) count : 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt );
#endif
	

	return DMASUCCESS;
}

/**************************************************/
/*  Delay routine				  */
/**************************************************/
void delay(deciseconds)
int     deciseconds;
{

int     j,k;

k = 0xfffff;

for(j=0;j<deciseconds;j++)
        {
        while(k)
                {
                k = k-1;
                }
        }
return;
}           
/**************************************************/
/*****************************************************************
 * function: dma_error_func
 *
 * description: display the error information
 *
 * note: This seems like a highly convoluted way to handle messages,
 * but I'll leave it as it was in device.c when I moved it into the
 * DMA library source.
 ****************************************************************/
static
DMAStatus dma_error_func( unsigned int eumbbar, unsigned int chn, DMAStatus err)
{
	unsigned char *msg[] =
		{
			"Local Memory Error",
			"PCI Error",			
			"Channel Busy", 
			"End-of-Segment Interrupt",
			"End-of-Chain/Direct Interrupt",
		};

	   if ( err >= DMALMERROR && err <= DMAEOCAINT )
	   {
	     PRINT( "DMA Status: channel %d  %s\n", chn, msg[err-DMASUCCESS-1] );
	   }
	
	   return err;

}

/*************************************************************
 * function: DMA_ISR
 *
 * description: DMA interrupt service routine
 *              return DMAStatus value based on
 *              the status
 *
 *************************************************************/
static
DMAStatus DMA_ISR( unsigned int eumbbar,
				  unsigned int channel,
				  DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ),
				  DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ),
				  DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ),
				  DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus ))
{

	DMA_SR stat;
	DMAStatus rval = DMANOEVENT;
    unsigned int temp;
	
	if ( channel != 0 && channel != 1 )
	{
		return DMAINVALID;
	}
	
	if ( DMA_Get_Stat( LOCALA, eumbbar, channel, &stat ) != DMASUCCESS )
	{
			return DMAINVALID;
	}

	if ( stat.lme == 1 )
	{
		/* local memory error */
		rval = DMALMERROR;
		if ( lme_func != 0 )
		{
		  rval = (*lme_func)(eumbbar, channel, DMALMERROR );
	    }
		
	}
	else if ( stat.pe == 1 )
	{
        /* PCI error */
		rval = DMAPERROR;
		if ( pe_func != 0 )
		{
		  rval = (*pe_func)(eumbbar, channel, DMAPERROR );
	    }

	}
	else if ( stat.eosi == 1 )
	{
		/* end-of-segment interrupt */
		rval = DMAEOSINT;
		if ( eosi_func != 0 )
		{
		  rval = (*eosi_func)(eumbbar, channel, DMAEOSINT );
	    }
	}
	else
	{
		/* End-of-chain/direct interrupt */
		rval = DMAEOCAINT;
		if ( eocai_func != 0 )
		{
		  rval = (*eocai_func)(eumbbar, channel, DMAEOCAINT );
	    }
	}

    temp = ( stat.reserved0 & 0xffffff ) << 8;
   	temp |= ( ( stat.lme       & 0x1 ) << 7 );  /* write one to clear */
	temp |= ( ( stat.reserved1 & 0x3 ) << 5 );
    temp |= ( ( stat.pe        & 0x1 ) << 4 );  /* write one to clear */	
    temp |= ( ( stat.reserved2 & 0x1 ) << 3 );
	temp |= ( ( stat.cb        & 0x1 ) << 2 );  /* write one to clear */
    temp |= ( ( stat.eosi      & 0x1 ) << 1 );  /* write one to clear */
    temp |= ( stat.eocai & 0x1 );               /* write one to clear */
	
    store_runtime_reg( eumbbar, dma_reg_tb[LOCALA][channel*NUM_DMA_REG + DMA_SR_REG], temp );

#ifdef DMADBG0
	PRINT( "%s(%d): DMA channel %d SR := 0x%08x\n", __FILE__, __LINE__, channel, temp );
#endif
	
	return rval;
}
#endif

void DMA0ISR(void)
{

   DMA_SR stat;
   DMA_MR mode;
	DMA_CHAIN_QUEUE *qu;  
  /* unsigned int xTime;*/
	qu = (DMA_CHAIN_QUEUE *)pDMAQueue;
  /* if(runled12%2)	*/
	/*led12(0);
	else
	led12(1);*/
	/*GTPRINT("\n I am in interrupt",0,0,0,0,0,0);*/
	/*runled12++;*/
   /*DMA_Get_Stat_Epic( LOCAL, get_eumbbar(), 0, &stat ) ;*/
   DMA_Get_Stat( LOCALA, get_eumbbar(), 0, &stat ) ;
	DMA_Get_Mode( LOCALA, get_eumbbar(), 0, &mode );
   
/* Check the  DMA status register to see if the DMA transaction was OK, if not
 * status register PE bit 4 was set.  If so, print an appropriate message and
 * clear the bit.  Write a 1 to stat.pe to clear it.
 * Leave everything else in the register unchanged.
 * Subsequent DMA transactions do not work until the stat.pe bit is cleared.
 * We might want to do the same thing for the Local Memory Error bit as well.
 */
  
   if (stat.pe == 1)
   {
     union {
       DMA_SR stat;
       unsigned int temp;
     } s;
     GTPRINT("PCI Error on DMA transfer.\n",0,0,0,0,0,0);
     s.stat = stat;
     GTPRINT("DMA Status is : 0x%x.\n",s.temp,0,0,0,0,0);
     s.temp &= 0xffffff6c; /* leave rest of status register unchanged */
     s.stat.pe = 1;        /* clear the pe bit by writing 1 to it */
     store_runtime_reg( get_eumbbar(),0x1104, s.temp );
   }
     if (mode.ctm==0)
   {
    if ( stat.eosi == 1 )
   {
	
	/*union {
       DMA_SR stat;
       unsigned int temp;
     } s;
	s.stat = stat;*/
    /* GTPRINT("DMA Status is : 0x%x,intnum:%d\n",s.temp,intnum,0,0,0,0);
	GTPRINT("segment interrupt ......",0,0,0,0,0,0);*/
        dma_chain_deq(qu);
        store_runtime_reg( get_eumbbar(),0x1104, 0x2 );
   }
   if ( stat.eocai == 1 )
   {
	 /*union {
       DMA_SR stat;
       unsigned int temp;
     } s;
      dma_chain_deq(qu);
      s.stat = stat;*/
    /* GTPRINT("DMA Status is : 0x%x,intnum:%d\n",s.temp,intnum,0,0,0,0);
	GTPRINT("DMA end Interupt ......",0,0,0,0,0,0);*/
	/*GTPRINT("Clearing Interupt\n",0,0,0,0,0,0);*/
        store_runtime_reg( get_eumbbar(),0x1104, 0x1 );
   /*semGive(dmaSemId);*/
   }
  }
  if (mode.ctm ==1)
  {
  	  if ( stat.eocai == 1 )
   {
	/*GTPRINT("Direct Mode Interupt ......",0,0,0,0,0,0);
	GTPRINT("Clearing Interupt\n",0,0,0,0,0,0);*/
        store_runtime_reg( get_eumbbar(),0x1104, 1 );
   }
   semGive(dmaSemId);
   }
  
}

STATUS Initdma(/*DMA_INTERRUPT_STEER int_steer*/void)
{


	/*int ret ;*/
	DMA_CHAIN_QUEUE *qu;	


	pDMADesp = (UINT32 *) (((UINT32) DMAdespArray + 8) & 0xfffffff8);
	pDMAQueue = DMAQueueArray;


	if (initnum==0)
	{
		(void)intConnect(INUM_TO_IVEC(DMA0_INT_LVL),(VOIDFUNCPTR)DMA0ISR,NULL);
	/*if(ret == ERROR)
	{
		#ifdef DMADBG0	
		PRINT("BSP:can't connect dma int! \n");	
		#endif
		return (ERROR);
	}*/
	intEnable(DMA0_INT_LVL);
	
	
	
	  if ( Global_eumbbard == 0)
     Global_eumbbard = get_eumbbar();
  if ( Global_eumbbard == 0)
  {
    PRINT( "DMA_Initialize: can't find EUMBBAR\n" );
    return (ERROR);
  }
  
	
	dmaTaskSemId = semBCreate ( SEM_Q_PRIORITY,SEM_FULL);
	if(dmaTaskSemId ==NULL)
	{
	#ifdef DMADBG0
		PRINT("BSP:can't create dma task sem for send! \n");	
	#endif
		return (ERROR);
	}
	
	dmaSemId = semBCreate ( SEM_Q_PRIORITY ,SEM_EMPTY);
	if(dmaSemId ==NULL)
	{
		#ifdef DMADBG0	
		PRINT("BSP:can't create dma sem for send! \n");	
		#endif
		return (ERROR);
	}
	

	
	/*qu = (QUEUE *)0x2080000;
    qu->q=(DMA_DESP *)0x2000000;*/
    qu = (DMA_CHAIN_QUEUE *)pDMAQueue;
    qu->q=(DMA_DESP *)pDMADesp;
    qu->f = qu->r = 0;
		
	initnum=1;
	}   
 return OK;	
    
}


static STATUS dma_chain_enq(DMA_CHAIN_QUEUE *qu,DMA_DESP *cdesp)
{
	if((qu->r+1)%(n0+1)==qu->f)
	return (ERROR);
	else{
	qu->q[qu->r].src_addr = cdesp->src_addr;
	qu->q[qu->r].dest_addr = cdesp->dest_addr;
	qu->q[qu->r].next_desp = cdesp->next_desp;
	qu->q[qu->r].byte_cnt = cdesp->byte_cnt;
	qu->q[qu->r].reserved0 = 0;
        qu->q[qu->r].reserved1 = 0;
        qu->q[qu->r].reserved2 = 0;
        qu->q[qu->r].reserved3 = 0;
	qu->r = (qu->r+1)%(n0+1);
return OK;
}
}
static void dma_chain_deq(DMA_CHAIN_QUEUE *qu)
{
	if(qu->r==qu->f)
	{}
	else
	qu->f = (qu->f+1)%(n0+1);
}
	
unsigned long dmacwrite(unsigned int *src,unsigned int *dst,unsigned int *len,unsigned int num)
{
	
	int rc;
	rc = DMA_chaining_transfer(0,1,src,dst,len,num,0,1);
	return (rc);

}


unsigned long dmacread(unsigned int *src,unsigned int *dst,unsigned int *len,unsigned int num)
{
	int rc;
	
	rc = DMA_chaining_transfer(0,2,src,dst,len,num,0,1);
		
	return(rc);
}

unsigned long dmadwrite(unsigned int src,unsigned int dst,unsigned int len)
{
	
	int rc;
	rc = DMA_direct_transfer(0,1,(unsigned long )src,(unsigned long )dst,(unsigned long)len,0,1);
	
	return (rc);

}


unsigned long dmadread(unsigned int src,unsigned int dst,unsigned int len)
{
	int rc;
	
	rc = DMA_direct_transfer(0,2,(unsigned long )src,(unsigned long )dst,(unsigned long )len,0,1);
		
	return(rc);
}

⌨️ 快捷键说明

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