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

📄 dma.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	curr.byte_cnt = len;

	dma_length = len;

	(void)DMA_Poke_Desp( LOCALA, Global_eumbbard, channel, &cdar );
	cdar.snen = snoop;
	cdar.ctt = type;
	
	if ( ( stat = DMA_Bld_Desp( LOCALA, Global_eumbbard, channel, cdar )) 
			!= DMASUCCESS ||
		 ( stat = DMA_Bld_Curr( LOCALA, Global_eumbbard, channel, curr )) 
			!= DMASUCCESS ||	    
	     ( stat = DMA_Set_Mode( LOCALA, Global_eumbbard, channel, md )) 
			!= DMASUCCESS ||
		 ( stat = DMA_Start( LOCALA, Global_eumbbard, channel, len )) 
			!= DMASUCCESS )
	{
		if ( stat == DMACHNBUSY )
		{
			PRINT( "dev DMA: channel %d busy.\n", channel );
		}
		else
		{
			PRINT( "dev DMA: invalid channel %d request.\n", channel );
		}
		semGive(dmaTaskSemId);
		return DMA_ERROR;
	}
		semTake(dmaSemId,WAIT_FOREVER);
/* Since we are interested at the DMA performace right now,
   we are going to do as less as possible to burden the
   603e core.

   if you have epic enabled or don't care the return from
   DMA operation, you can just return SUCCESS.

   if you don't have epic enabled and care the DMA result,
   you can use the polling method below.

   Note: I'll attempt to activate the code for handling polling.
 */

#if 0
	/* if steering interrupt to local processor, let it handle results */
	if ( int_steer == DMA_INT_STEER_LOCAL )
	{
	    return DMA_SUCCESS;
	}

	/* polling since interrupt goes to PCI */
	do
	{
		stat = DMA_ISR( Global_eumbbard, channel, dma_error_func, 
			dma_error_func, dma_error_func, dma_error_func );
	}
	while ( stat == DMANOEVENT );
#endif
	semGive(dmaTaskSemId);
    return DMA_SUCCESS;
}

/* DMA library internal functions */

/**
 * Note:
 *
 * In all following functions, the host (KAHLUA) processor has a
 * choice of accessing on board local DMA (LOCALA),
 * or DMA on a distributed KAHLUA (REMOTE). In either case,
 * the caller shall pass the configured embedded utility memory
 * block base address relative to the DMA. If LOCALA DMA is used,
 * this parameter shall be EUMBBAR, if REMOTE is used, the
 * parameter shall be the corresponding PCSRBAR.
 **/
    
/**************************************************************
 * function: DMA_Get_Stat
 *
 * description: return the content of status register of 
 *              the given DMA channel
 *
 *              if error, reserved0 field all 1s.
 **************************************************************/
static
DMAStatus DMA_Get_Stat( LOCATION host, unsigned int eumbbar, 
                        unsigned int channel, DMA_SR *stat )
{
  union {
    unsigned int tmp;
    DMA_SR status;
  } s;
   
  if (( channel != 0 && channel != 1) || stat == 0 )
  {
    return DMAINVALID;
  }

  s.tmp = load_runtime_reg( eumbbar, 
    dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG] );
#ifdef DMADBG0
  PRINT( "%s(%d): %s DMA %d (0x%08x) stat = 0x%08x\n", __FILE__, __LINE__,
    ( host == LOCALA ? "local" : "remote" ), channel, 
    dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG], s.tmp );
#endif
   
  *stat = s.status;
  return DMASUCCESS;
}

/**************************************************************
 * function: DMA_Get_Mode
 *
 * description: return the content of mode register of the 
 *              given DMA channel 
 *
 *              if error, return DMAINVALID, otherwise return
 *              DMASUCCESS
 **************************************************************/
static
DMAStatus DMA_Get_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR *mode )
{
    unsigned int tmp;
   if (( channel != 0 && channel != 1 )|| mode == 0 )
   {
     return DMAINVALID;
   }

    tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG] );

#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) mode = 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG], tmp );
#endif
   
	 mode->reserved0 = (tmp & 0xfff00000) >> 20;
	 mode->irqs      = (tmp & 0x00080000) >> 19;
	 mode->pde       = (tmp & 0x00040000) >> 18;
	 mode->dahts     = (tmp & 0x00030000) >> 16;
     mode->sahts     = (tmp & 0x0000c000) >> 14;
	 mode->dahe      = (tmp & 0x00002000) >> 13;
	 mode->sahe      = (tmp & 0x00001000) >> 12;
	 mode->prc       = (tmp & 0x00000c00) >> 10;
	 mode->reserved1 = (tmp & 0x00000200) >> 9;
	 mode->eie       = (tmp & 0x00000100) >> 8;
	 mode->eotie     = (tmp & 0x00000080) >> 7;
	 mode->reserved2 = (tmp & 0x00000070) >> 4;
	 mode->dl        = (tmp & 0x00000008) >> 3;
	 mode->ctm       = (tmp & 0x00000004) >> 2;
	 mode->cc        = (tmp & 0x00000002) >> 1;
	 mode->cs        = (tmp & 0x00000001);

   return DMASUCCESS;
}

/**************************************************************
 * function: DMA_Set_Mode
 *
 * description: Set a new mode to a given DMA channel 
 *
 * note: It is not a good idea of changing the DMA mode during
 *       the middle of a transaction.
 **************************************************************/
static
DMAStatus DMA_Set_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR mode )
{
    unsigned int tmp;
   if ( channel != 0 && channel != 1 )
   {
	   return DMAINVALID;
   }

   tmp = ( mode.reserved0 & 0xfff ) << 20;
   tmp |= ( ( mode.irqs  & 0x1 ) << 19);
   tmp |= ( ( mode.pde   & 0x1 ) << 18 );
   tmp |= ( ( mode.dahts & 0x3 ) << 16 );
   tmp |= ( ( mode.sahts & 0x3 ) << 14 );
   tmp |= ( ( mode.dahe  & 0x1 ) << 13 );
   tmp |= ( ( mode.sahe  & 0x1 ) << 12 );
   tmp |= ( ( mode.prc   & 0x3 ) << 10 );
   tmp |= ( ( mode.reserved1 & 0x1 ) << 9 );
   tmp |= ( ( mode.eie   & 0x1 ) << 8 );
   tmp |= ( ( mode.eotie & 0x1 ) << 7 );
   tmp |= ( ( mode.reserved2 & 0x7 ) << 4 );
   tmp |= ( ( mode.dl    & 0x1 ) << 3 );
   tmp |= ( ( mode.ctm   & 0x1 ) << 2 );
   tmp |= ( ( mode.cc    & 0x1 ) << 1 ) ;
   tmp |= ( mode.cs    & 0x1 );
   
   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], tmp );
   return DMASUCCESS;
}

/************************************************************
 * function: DMA_Start
 * 
 * description: start a given DMA channel transaction
 *              return DMASUCCESS if success otherwise return
 *              DMAStatus value
 *
 * note: this function will clear DMA_MR(CC) first, then
 *       set DMA_MR(CC).
 ***********************************************************/
static
DMAStatus DMA_Start( LOCATION host, unsigned int eumbbar, unsigned int channel, 
			int len)
{
   DMA_SR stat;
   unsigned int mode;
   
   if ( channel != 0 && channel != 1 )
   {
	   return DMAINVALID;
   }

   if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS )
   {
		   return DMAINVALID;
   }
   
   if ( stat.cb == 1 )
   {
	   /* DMA is not free */
	   return DMACHNBUSY;
   }
   
   mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] );
   /* clear DMA_MR(CS) */
   mode &= 0xfffffffe;
/*PRINT("Starting DMA......  \n");*/
   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );

   /* set DMA_MR(CS), after DMA_MR[CS] is set, DMA starts transferring data */
   mode |= CS;
   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); 

  /* decrementer_write(0x7fffffff);*/
/*************************************************************************/
/****************** Pause and then return to command line*****************/
/*delay(0x100000);
PRINT("Pause complete .....\n");*/
/*************************************************************************/

/*************************************************************************/
/*********** Poll the Status register (Impacts performance)***************/
/*
   DMA_Get_Stat( host, eumbbar, channel, &stat );
   while (stat.cb == 1)       
   {
     DMA_Get_Stat( host, eumbbar, channel, &stat );
   }     
PRINT("Polling complete .....\n");
*/
/*************************************************************************/
   
   return DMASUCCESS;
}

static
DMAStatus DMA_ReStart( LOCATION host, unsigned int eumbbar, unsigned int channel, 
			int len)
{
	 DMA_SR stat;
	 unsigned int mode;
	  if ( channel != 0 && channel != 1 )
   {
	   return DMAINVALID;
   }

   if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS )
   {
		   return DMAINVALID;
   }
	 mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] );
	mode |= CC;
   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); 
	return DMASUCCESS;	
		}
	
#if 0
extern 
DMA_Status DMA_Initialize( /*int (*p)(char *,...)*/void)
{
  /* establish the pointer, if there is one, to the application's "printf" */
 /* app_print = p;*/

  /* If this is the first call, get the embedded utilities memory block
   * base address.  I'm not sure what to do about error handling here:
   * if a non-zero value is returned, accept it.
   */
  if ( Global_eumbbard == 0)
     Global_eumbbard = get_eumbbar();
  if ( Global_eumbbard == 0)
  {
    PRINT( "DMA_Initialize: can't find EUMBBAR\n" );
    return DMA_ERROR;
  }

  return DMA_SUCCESS;
}
/***********************************************************
 * function: DMA_Halt
 *
 * description: halt the current dma transaction on the specified
 *              channel.
 *              return DMASUCCESS if success otherwise return DMAINVALID
 *
 * note: if the specified DMA channel is idle, nothing happens
 *************************************************************/
static
DMAStatus DMA_Halt( LOCATION host, unsigned int eumbbar, unsigned int channel )
{
   unsigned int mode;
   if ( channel != 0 && channel != 1 )
   {
	   return DMAINVALID;
   }

   mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG]);

   /* clear DMA_MR(CS) */
   mode &= 0xfffffffe;
   store_runtime_reg(eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
   return DMASUCCESS;
}

/*************************************************************
 * function: DMA_Chn_Cnt
 *
 * description: set the DMA_MR(CC) bit for a given channel
 *              that is in chaining mode. 
 *              return DMASUCCESS if successfule, otherwise return
 *              DMAINVALID.
 *
 * note: if the given channel is not in chaining mode, nothing
 *       happen.
 *
 *************************************************************/
static
DMAStatus DMA_Chn_Cnt( LOCATION host, unsigned int eumbbar, unsigned int channel )
{
	DMA_MR mode;    
	if ( channel != 0 && channel != 1 )
	{
		return DMAINVALID;
	}

	if ( DMA_Get_Mode( host, eumbbar, channel, &mode ) != DMASUCCESS )
	{
			return DMAINVALID;
	}
	
	if ( mode.ctm == 0 )
	{
		/* either illegal mode or not chaining mode */
		return DMAINVALID;
	}

	mode.cc = 1;
	return DMA_Set_Mode( host, eumbbar, channel, mode );
}
#endif

/**************************************************************
 * function: DMA_Bld_Desp
 *
 * description: set current descriptor address register
 *              according to the desp for a given channel
 *
 *              if the given channel is busy return DMACHNBUSY
 *              and no change made, otherwise return DMASUCCESS.
 *
 * note:
 **************************************************************/
static
DMAStatus DMA_Bld_Desp( LOCATION host,
						   unsigned int eumbbar,
						   unsigned int channel,
						   DMA_CDAR     desp )
{
	DMA_SR status;
	unsigned int temp;
	
	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;
	}

	temp = /*(*/ desp.cda /*& 0x7ffffff ) << 5*/;
	temp |= (( desp.snen & 0x1 ) << 4 );
	temp |= (( desp.eosie & 0x1 ) << 3 );
	temp |= (( desp.ctt   & 0x3 ) << 1 );
    temp |= ( desp.eotd  & 0x1 );

    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
	
#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) cdar := 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
#endif

	return DMASUCCESS;
}

/**************************************************************
 * function: DMA_Poke_Desp
 *
 * description: poke the current descriptor address register
 *              for a given channel
 *
 *              return DMASUCCESS if no error
 *
 * note: Due to the undeterministic parallellism of DMA operation,
 *       the value returned by this function shall be taken as
 *       the most recently used descriptor when the last time
 *       DMA starts a chaining mode operation.
 **************************************************************/
static
DMAStatus DMA_Poke_Desp( LOCATION host,
						    unsigned int eumbbar,
						    unsigned int channel,
						    DMA_CDAR     *desp )
{
	unsigned int cdar;
	if (( channel != 0 && channel != 1) || desp == 0 )
	{
			return DMAINVALID;
	}

    cdar = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG] );

#ifdef DMADBG0
   PRINT( "%s(%d): %s DMA %d (0x%08x) cdar : 0x%08x\n", __FILE__, __LINE__,
		  ( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], cdar );
#endif

	
	desp->cda   = ( cdar & 0xffffffe0 ) >> 5;
	desp->snen  = ( cdar & 0x00000010 ) >> 4;
	desp->eosie = ( cdar & 0x00000008 ) >> 3;
	desp->ctt   = ( cdar & 0x00000006 ) >> 1;
	desp->eotd  = ( cdar & 0x00000001 );

	return DMASUCCESS;
}

/**************************************************************
 * function: DMA_Bld_Curr

⌨️ 快捷键说明

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