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

📄 spi4_rx.c

📁 ixp2400的一个小程序
💻 C
字号:
//  Copyright (C) 2002-2003 Intel Corporation, All Rights Reserved.
//  Permission is hereby granted to merge this program code with 
//  other program material to create a derivative work.  This 
//  derivative work may be distributed in compiled object form only.
//  Any other publication of this program, in any form, without the 
//  explicit permission of the copyright holder is prohibited.
//
//  Send questions and comments to erik.j.johnson@intel.com, 
//  aaron.kunze@intel.com

//-------------------------------------------------------------------
// spi4_rx.c - Chapter 5
// Reassembles incomming packets from a single port on the
// SPI-4 interface using a single thread
//


// This file contains an implementation of the receive reassembly
// process using a single thread.  Incomming mpackets from a single
// port are assembled into complete packets.  Handles to these 
// packets are then placed on a scratch ring for processing.
//

//-------------------------------------------------------------------
// Include files
#include "ixp.h"
#include "spi4_rx.h"
#include "dl_buf.c"
#include "dl_meta.h"

extern dl_buf_handle_t			dlBufHandle;
extern __declspec(gp_reg) int 	dlNextBlock;
extern dl_meta_t				dlMeta;


#define RBUF_ELEM_SIZE 		128
/*#define RX_CONTROL_VAL		((1 << RX_EN_SPHY_BITPOS) | \
							 (1 << RBUF_ELE_SIZE_0_BITPOS))
*/
//control value of the rx for spi3,the ru_buf_size is 128,specifi rbuf_ele_size_0_bitpos as 1
#define RX_CONTROL_VAL			((0 << RX_EN_SPHY_BITPOS) | \
								  (01 << RBUF_ELE_SIZE_0_BITPOS) | \
								  (0 << RX_MPHY_LEVEL2) | \
							       (1 << RX_MPHY_EN) | \
								   (0 << RX_MPHY_MODE) | \
								   (0 << RX_MPHY_POLL_MODE) | \
								   (00 << RX_WIDTH) | \
								   (0 << RX_MODE)) 

//enable desired channels with the enable bitpos
#define RX_CONTROL_VAL_SECOND ((RX_CONTROL_VAL) | \
                               (1 << RX_EN_SPHY_BITPOS))

//value for the rx_up_control 
#define RX_UP_CONTROL_VAL ((1 << RX_UP_CPMODE) | \
                     	   (1 << RX_UP_DETIME)| \
						   ( 1 << RX_UP_PPMODE) )
//-------------------------------------------------------------------
// _spi4_rx_free_rbuf
//
//    Description:
//       Place the given RBUF element onto the RBUF freelist
//
//    Parameters:
//      Outputs: n/a
//      In/Outs: n.a
//      Inputs: in_elem	- The RBUF element number to free
//      Constants: n/a
//      Labels: n/a
//
//    Side effects: Writes the given element number into
//                  the MSF RBUF done address.  The RBUF
//                  should not be used after calling this macro
//
//    See also: n/a
//
__forceinline
static void _spi4_rx_free_rbuf(unsigned int in_elem)
{
	void* val_and_addr;

	// The element number is placed into the upper 16 
	// bits as required by the MSF fast_wr instruction
	val_and_addr = (void*)(MSF_RBUF_ELEMENT_DONE_ADDR | 
						   (in_elem << 16));
	msf_fast_write(val_and_addr);
}


//-------------------------------------------------------------------
// spi4_rx_init
//
//    Description:
//       Initialize the appropriate CSRs to receive packets on
//       the SPI4 interface.
//
//    Parameters:
//      Outputs: n/a
//      In/Outs: n/a
//      Inputs: n/a
//      Constants: n/a
//      Labels: n/a
//
//    Side effects: Writes to the MSF receive control and 
//                  port map CSRs
//
//    See also: n/a
//
void spi4_rx_init()
{
	void* addr; // Holds the address of the CSR being set
	__declspec(sram_write_reg) unsigned int rx_ctl;
	SIGNAL msf_rx_ctl_sig;

	//----------- Set the receive control CSR in the MSF.
	rx_ctl = RX_CONTROL_VAL;
	addr   = (void *)MSF_RX_CONTROL_ADDR;
	msf_write(&rx_ctl, addr, 1, ctx_swap, &msf_rx_ctl_sig);
	
	//set rx_up_control _* value
    rx_ctl= RX_UP_CONTROL_VAL;
	addr =(void *)MSF_RX_UP_CONTROL_0_ADDR;
    msf_write(&rx_ctl,addr,1,ctx_swap,&msf_rx_ctl_sig);
	
	addr =(void *)MSF_RX_UP_CONTROL_1_ADDR;
    msf_write(&rx_ctl,addr,1,ctx_swap,&msf_rx_ctl_sig);
	
	addr =(void *)MSF_RX_UP_CONTROL_2_ADDR;
    msf_write(&rx_ctl,addr,1,ctx_swap,&msf_rx_ctl_sig);
	
	addr =(void *)MSF_RX_UP_CONTROL_3_ADDR;   
    msf_write(&rx_ctl,addr,1,ctx_swap,&msf_rx_ctl_sig);
	
	//----------- Specify the Rx Calendar Length as one entry
	rx_ctl = 1;
	//addr   = (void *) MSF_RX_CALENDAR_LENGTH_ADDR;
	addr=(void *)MSF_RX_MPHY_POLL_LIMIT;
	msf_write(&rx_ctl, addr, 1, ctx_swap, &msf_rx_ctl_sig);

	//----------- Specify the RBUF SPI4 High Water Mark
	//               (should be read & mask & rewrite)
	rx_ctl = MST_HWM_CONTROL__RBUF_S_HWM__01;
	addr   = (void *)MSF_HWM_CONTROL_ADDR;
	msf_write(&rx_ctl, addr, 1, ctx_swap, &msf_rx_ctl_sig);

	//----------- Enable the MSF Rx flow control (should be read & mask)
 	rx_ctl = MSF_TRAIN_DATA__RSTAT_EN;
	//addr   = (void *)MSF_TRAIN_DATA_ADDR;
	addr=(void *)MSF_Rx_FIFO_Control_0;
	msf_write(&rx_ctl, addr, 1, ctx_swap, &msf_rx_ctl_sig);
	  
	//specify the RBUF elment by writing rbuf_element_done regester   .
	_spi4_rx_free_rbuf(0x00);
	
	//set the rx_en bitpos
	rx_ctl=	RX_CONTROL_VAL_SECOND;
	addr=(void *) MSF_RX_CONTROL_ADDR;
	msf_write(&rx_ctl,addr,1,ctx_swap,&msf_rx_ctl_sig);
} 

//-------------------------------------------------------------------
// _spi4_rx_get_mpacket
//
//    Description:
//       Add the thread into the receive thread freelist and wait
//		 for an mpacket to arrive
//
//    Parameters:
//      In/Outs: n/a
//      Inputs: n/a
//      Constants: n/a
//      Labels: n/a
//
//	  Returns:
//      The value of the SPI4 receive status words
//
//    Side effects: n/a
//    See also: n/a
//
__forceinline
static spi4_rsw_t _spi4_rx_get_mpacket()
{
	SIGNAL rx_complete_sig;
	__declspec(sram_read_reg) spi4_rsw_t rsw;
	// This union represents the fields written into
	// the thread freelist CSR
	union
	{
		struct
		{
			unsigned int	res			: 16,
							sig_no		: 4,
							me_no		: 5,
							thd			: 3,
							xfer_reg	: 4;
		} parts;
		unsigned int whole;		
	} rx_tfl;
	void* rx_tfl_addr_and_val;
	
	rx_tfl.whole = 0;

	// Add the wakeup signal when an mpacket arrives
	rx_tfl.parts.sig_no = __signal_number(&rx_complete_sig);

	// Add the microengine number to singal
	rx_tfl.parts.me_no = __ME();

	// Add the context to signal
	rx_tfl.parts.thd = ctx();

	// Add the transfer register address 
	// where the RSW words should be placed
	rx_tfl.parts.xfer_reg = __xfer_reg_number(&rsw);

	// Place the data into the upper 16 bits for
	// the fast_wr operation
	rx_tfl_addr_and_val = 
				(void*) (MSF_RX_THREAD_FREELIST_0_ADDR |
						 (rx_tfl.whole << 16));
	msf_fast_write(rx_tfl_addr_and_val);
	wait_for_all(&rx_complete_sig); // wait for an mpacket


	return (rsw);
}


//-------------------------------------------------------------------
// _spi4_rx_move_rbuf_to_dram
//
//    Description:
//       Transfer the given RBUF element into the given DRAM
// 		 address
//
//    Parameters:
//      Outputs: n/a 
//      In/Outs: n/a
//      Inputs: in_rbuf_elem - The RBUF element number to transfer
//              in_dram_addr - The address to transfer to RBUF
//							   into
//				in_size - The number of bytes to transfer
//				in_dram_sig	 - The signal to use for the transfer
//      Constants: n/a
//      Labels: n/a
//
//    Side effects: The given dual signal must be caught by the
//					calling routine.
//					The in_rbuf_elem_size must be between 1 and
//					128.  The number of bytes transfered will
//					be (in_rbuf_elem_size >> 3) << 3) since
//					the transfer must be an even number of quadwords
//    See also: n/a
//
__forceinline
static void _spi4_rx_move_rbuf_to_dram(
	unsigned int in_rbuf_elem, 
	void __declspec(dram) *in_dram_addr,
	unsigned int in_size, 
	SIGNAL_PAIR *in_dram_sig)
{
	dram_rbuf_tbuf_ind_t indir;
	unsigned int rbuf_addr;

	// Compute the RBUF address.  This is the base RBUF
	// address in the MSF plus the element number times
	// 64.  The multiplication by 64 comes from the fact
	// that the element number given in the RSW is divided 
	// by 64 
	rbuf_addr = MSF_RBUF_BASE_ADDR + (in_rbuf_elem << 6);

	// Override the rbuf addr
	indir.value = 0;
	indir.ov_buf_addr = 1;
	indir.buf_addr = rbuf_addr;

	// Override the transfer size
	indir.ov_ref_count = 1;
	indir.ref_count = ((in_size + 7) >> 3) - 1;

	dram_rbuf_read_ind(in_dram_addr,
					   16,
					   indir,
					   sig_done,
					   in_dram_sig);
}


//-------------------------------------------------------------------
// spi4_rx
//
//    Description:
//       Reassemble an incomming packet. 
//
//    Parameters:
//      Outputs: out_buffer_handle - a handle representing the
//               		properly reassembled packet
//               out_buffer_length - the length, in bytes, of the
//                  	reassembled packet
//      In/Outs: n/a
//      Inputs: n/a
//      Constants: n/a
//      Labels: n/a
//
//    Side effects:  
//		This routine requires that packets are arriving on only one 
//      port of the SPHY4 interface.  If this is not the case, 
//		mpackets from multiple ports will be intermixed into the 
//		one final packet.
//
//		This routine does not return until a packet is reassembled
//      without error.
//
//    See also: spi4_rx_init()
//
void spi4_rx()
{
	// A pointer into dram where 
	// the next mpacket should be placed
	__declspec(dram) unsigned char *cur_mpacket_addr;
	__declspec(sram_read_reg) dl_buf_handle_t alloc_handle;
	spi4_rsw_t rsw;
						  // The receive status words
	SIGNAL_PAIR rbuf_to_dram_sig;
	SIGNAL		buf_alloc_sig;

	dlBufHandle.value 	  = 0;
	dlMeta.bufferSize 	  = 0;

	while(1)
	{
		// Get the next mpacket
		rsw = _spi4_rx_get_mpacket();

		// Check for errors in the packet
		// These indicate that the current buffer, if any,
		// should be discarded
		if (rsw.w1.parts.err)
		{
			if (dlBufHandle.value != 0)
			{
				// Drop the packet
				Dl_BufDrop(dlBufHandle);
			}

			_spi4_rx_free_rbuf(rsw.w1.parts.element);
			dlBufHandle.value = 0;
			dlMeta.bufferSize = 0;
			continue;
		}
	
		// If this is the SOP, allocate a new buffer		
		if (rsw.w1.parts.sop)
		{
			if (dlBufHandle.value == 0)
			{
				Dl_BufAlloc(&alloc_handle,
							BUF_FREE_LIST0,
							BUF_POOL,
							&buf_alloc_sig,
							SIG_NONE,
							___);
				wait_for_all(&buf_alloc_sig);
				dlBufHandle = alloc_handle;

				if (dlBufHandle.value == 0)
				{
					// No more buffers
					_spi4_rx_free_rbuf(rsw.w1.parts.element);
					continue;
				}
			}
			cur_mpacket_addr = (__declspec(dram) unsigned char *)
				Dl_BufGetData(dlBufHandle);
		}
		else if (dlBufHandle.value == 0)
		{
			// An MOP or EOP mpacket was received 
			// without an SOP mpacket first
			_spi4_rx_free_rbuf(rsw.w1.parts.element);
			continue;
		}

		// Move the mpacket into DRAM
		_spi4_rx_move_rbuf_to_dram(
					rsw.w1.parts.element, 
					cur_mpacket_addr,
					rsw.w1.parts.byte_count, 
					&rbuf_to_dram_sig);

		// Update the buffer length
		dlMeta.bufferSize += rsw.w1.parts.byte_count;

		// Wait for the mpacket to move into DRAM
		__wait_for_all(&rbuf_to_dram_sig);

		_spi4_rx_free_rbuf(rsw.w1.parts.element);

		// If this is the EOP mpacket then return
		if (rsw.w1.parts.eop)
		{
			break;
		}

		// Update the reassembly pointer
		cur_mpacket_addr += rsw.w1.parts.byte_count;
	}
	dlNextBlock = SPI4_RX_NEXT_BLOCK;
}

⌨️ 快捷键说明

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