📄 spi4_rx.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 + -