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

📄 dma1.c

📁 适合KS8695X
💻 C
📖 第 1 页 / 共 2 页
字号:
   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;
   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );

   /* set DMA_MR(CS) */
   mode |= CS;
   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
   return DMASUCCESS;
}

/***********************************************************
 * 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 );
}

/**************************************************************
 * 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 == LOCAL ? "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 == LOCAL ? "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
 *
 * 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 == LOCAL ? "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 == LOCAL ? "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 == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt );
#endif


	return DMASUCCESS;

}

/**************************************************************
 * 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 == LOCAL ? "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 == LOCAL ? "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 == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt );
#endif


	return DMASUCCESS;
}

/*****************************************************************
 * 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( LOCAL, 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[LOCAL][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;
}

⌨️ 快捷键说明

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