 /*
   *  Object %name    : FVOS.c
   *  State           :  %state%
   *  Creation date   :  Wed Nov 17 17:39:24 2004
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief Secure Boot implemtation of hash queues
   *
   *  \version 
   *  \author yevgenys
   *  \remarks Copyright (C) 2004 by Discretix Technologies Ltd.
   *           All Rights reserved
   */
#include "DX_VOS_Mem.h"

#include "FVOS_Types.h"
#include "FVOS_API.h"
#include "FVOS_Config.h"
#include "FVOS_HwDefs.h"
#include "gen.h"
#include "FVOS_Error.h"

#ifndef DX_USE_BOARD_DMA_AREA
#include "rt_misc.h"
#endif

#ifdef DX_ARM_INTEGRATOR_DEBUG
#include "time.h"
#endif


/*-------------------------
  GLOBAL variables
--------------------------*/

/* counter for the gpr value */
DxUint32_t          g_GPRPollValue;


/* address of the SEP shared area */
DxUint32_t          g_FVOS_SharedAreaAddress;

/* the start address of the area where the DMA tables for synchronic symmetric operations are created */
DxUint32_t          g_FVOS_DMATableAreaAddress;

/* number of DMA tables already created during current API */
DxUint32_t          g_FVOS_DMATablesCreated;

/* the start address of the area where the DMA tables for flow operations are created */
DxUint32_t          g_FVOS_FLOWDMATableAreaAddress;

/* allocation offset */
DxUint32_t          g_FVOS_AllocOffset = 0;

/* static memory address */
DxUint32_t          g_FVOS_StaticMemoryAddr;

/* start address of memory region for allocations */
DxUint32_t          g_FVOS_AllocMemoryAddr;

/* start adress of the region for the system data (time, caller id etc) */
DxUint32_t          g_FVOS_SystemDataMemoryAreaAddress;

/* data for flows */
FVOS_FlowContext_t  g_FlowsContexts[FVOS_NUM_FLOWS];

#ifndef CRYS_DSM_FLAG
#ifndef DX_USE_BOARD_DMA_AREA
extern unsigned int  Image$$DATA_SECTION$$ZI$$Limit;
#ifndef DX_NO_WMDRM_SUPPORT
extern unsigned int  Image$$HEAP_FOR_DMA_SECTION$$Base;
extern unsigned int  Image$$STACK_FOR_DMA_SECTION$$Base;
#endif
#endif
#endif
#ifdef DX_USE_BOARD_DMA_AREA
DxUint32_t  outMemAddress;
DxUint32_t  outMemDataSize;
DxUint32_t  dmaOutputAddress;
DxUint8_t*  dmaInputDataArea_ptr;
DxUint8_t*  dmaOutputDataArea_ptr;
#endif

/*-------------------------
  DEFINES
--------------------------*/

#define DX_CSI                              0xFFFFFFFC 



/*-----------------------------
    prototypes
-------------------------------*/

/**
 * @brief     This function handles the send message to SEP command  
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleMsgReadyCmd(void);

/**
 * @brief     This function handles the send reply message to SEP command  
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleReplyMsgReadyCmd(void);

/**
 * @brief     This function handles the allocate memory from dynamic pool command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 *
 * @return     DxError_t:  
 *                        
 */    
static FVOS_Error_t FVOS_HandleAllocMemoryCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles the build DMa tables for symmetric action (AES,DES,HASH)
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */                                                
static FVOS_Error_t FVOS_HandleBuildSymDmaTablesCmd(FVOS_Cntrl_info_t* cmdData_ptr);
      
/**
 * @brief     This function handles the build DMA tables for flow
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleBuildFlowDmaTablesCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles the addition  DMA tables to a flow
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleAddFlowDmaTablesCmd(FVOS_Cntrl_info_t* cmdData_ptr);


/**
 * @brief     This function handles the addition of message for add flow command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleAddFlowTableMsgCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles the set flow id command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleSetFlowIdCmd(FVOS_Cntrl_info_t* cmdData_ptr);


/**
 * @brief     This function handles the free DMA resources command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleFreeDMAResources(void);

/**
 * @brief     This function handles write data command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleWriteDataCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles read data command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleReadDataCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles get static pool data command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleGetStaticPoolDataCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles convert static poll physical address to virtual command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleConverStaticPhysToVirtCmd(FVOS_Cntrl_info_t* cmdData_ptr);


/**
 * @brief     This function handles free flow resources command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleFreeFlowResourcesCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles the get time command
 *
 * @param[out] timeAddress_ptr - address of the stored time value
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleGetTimeCmd(FVOS_Cntrl_info_t* cmdData_ptr);


/**
 * @brief     This function handles check configuration command
 *
 * @param[out] timeAddress_ptr - address of the stored time value
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleCheckConfigurationCmd(FVOS_Cntrl_info_t* cmdData_ptr);



/**
 * @brief     This function handles the realloc cache and resident command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleReallocCacheResidentCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles the realloc command of the external cache
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleReallocExtCacheCmd(FVOS_Cntrl_info_t* cmdData_ptr);

/**
 * @brief     This function handles theSEP Init command 
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleSEPInitCmd(FVOS_Cntrl_info_t* cmdData_ptr);


/**
 * @brief     This function free the resources of the flow
 *
 * @param[in] flowId - flow id to free
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_FreeFlowResources(DxUint32_t flowId, DxBool_t is_call_from_terminate);

/**
 * @brief     This function constructs the lli table from the input of the array of physical addresses
 *            sizes for each physical buffer ,  and the number of physical buffer. Function uses the the VOS function for allocation of the
 *            memory needed for the 
 *
 *
 * @param[in] inputPhysicalBuffersArray - input physical buffers and their size
 * @param[out] firstInputLLITable_ptr - holds pointer to the first lli table in the list
 * @param[out] numEntriesInTable_ptr - number of entries in the first lli table 
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_PrepareInputDMATable(DxUint32_t   dataInAddr,
                                              DxUint32_t   dataInSize,
                                              DxUint32_t*  firstInputLLITable_ptr,
                                              DxUint32_t*  numEntriesInTable_ptr,
                                              DxUint32_t*  firstTableDataSize_ptr);


/**
 * @brief     This function creates tables for symmetric engines (AES,DES). The size of data in each
 *            table is modulud the operationBlockSize
 *
 *
 * @param[in] inputPhysicalBuffersArray - physical memory buffers for input
 * @param[in] outputPhysicalBuffersArray - physical memory buffers for output
 * @param[in] operationBlockSize - block size of the operation (AES or DES)
 * @param[out] firstInputLLITable_ptr - pointer to the first table in the list of input tables
 * @param[out] firstOutputLLITable_ptr - pointer to the first table in the list of output tables
 * @param[out] numInTableEntries_ptr - number of entries in the first input table
 * @param[out] numOutTableEntries_ptr - number of entries in the first output table
 * @param[out] firstTableDataSize_ptr - the size of data in the first table (input or output, since they must be equal)
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_PrepareInputOutputDMATables(DxUint32_t   dataInAddr,
                                                     DxUint32_t   dataOutAddr,
                                                     DxUint32_t   dataInSize,
                                                     DxUint32_t   operationBlockSize,
                                                     DxUint32_t*  firstInputLLITable_ptr,
                                                     DxUint32_t*  firstOutputLLITable_ptr,
                                                     DxUint32_t*  numInTableEntries_ptr,
                                                     DxUint32_t*  numOutTableEntries_ptr,
                                                     DxUint32_t*  firstTableDataSize_ptr);


/**
 * @brief     this functions handles the request from upper layer for construction of the first tables of the FLOW 
 *
 * @param[in] flowType - flow type (static or dynamic)
 * @param[in] buffersArrayAddr - array of input buffers
 * @param[in] buffersArraySize - size of input buffers array
 * @param[in] inputOutputFlag - flag if the created tables are for input or output data
 * @param[out] firstTableInfo_ptr - pointer to the LLI entry that will hold the data of the first table
 *
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_CreateFlowDMATables(DxUint32_t             flowType,
                                             DxUint32_t             buffersArrayAddr,
                                             DxUint32_t             buffersArraySize,
                                             FVOS_InputArrayFlag_t  inputOutputFlag,
                                             FVOS_LliEntry_t*       firstTableInfo_ptr);

/**
 * @brief     this functions constructs DMA table for the flow ( for input or for output )
 *            the first word of table holds the number of 
 *
 * @param[in] flowId - flow id
 * @param[in] flowType - flow type (static or dynamic)
 * @param[in] buffersArrayAddr - array of input buffers
 * @param[in] buffersArraySize - size of input buffers array
 * @param[out] firstTableInfo_ptr - pointer to the LLI entry that will hold the data of the first table
 * @param[out] lastTableInfo_ptr - pointer to the LLI entry that will hold the data of the last table 
 *
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_PrepareFlowDMATables(DxUint32_t        flowId,
                                              DxUint32_t        flowType,
                                              DxUint32_t        buffersArrayAddr,
                                              DxUint32_t        buffersArraySize,
                                              FVOS_LliEntry_t*  firstTableInfo_ptr,
                                              FVOS_LliEntry_t*  lastTableInfo_ptr);

/**
 * @brief     this functions constructs additional DMA tables for the flow ( for input or for output ), and if new message shoudl be created
 *            it set the flag and returns the data for the input and output tables
 *
 *
 * @param[in] flowId
 * @param[in] inputOutputFlag - flag if this input or output tables
 * @param[in] bufferArrayAddr - array of input/output buffers
 * @param[out] bufferArraySize - size of the buffers array
 * @param[out] firstInputTableInfo_ptr - pointer to the data of the first table (input or output)
 *
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_AddFlowDMATables(DxUint32_t        flowId,
                                          DxUint32_t        inputOutputFlag,
                                          DxUint32_t        bufferArrayAddr,
                                          DxUint32_t        bufferArraySize,
                                          FVOS_LliEntry_t*  firstTableInfo_ptr);

/**
 * @brief     this functions find flow context according to the id
 *
 * @param[in] flowId - flow id 
 * @param[out] flowContext_ptr - pointer to the returned context
 *
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_FindFlowContext(DxUint32_t flowId , FVOS_FlowContext_t** flowContext_ptr);

/**
 * @brief     this functions deallocates the tables starting from the first table
 *
 *
 * @param[in] firstTable_ptr - first table 
 *
 * @return     DxError_t:  
 *                        
 */
static void FVOS_DeallocateFlowTables(FVOS_LliEntry_t* firstTable_ptr);


/* function to be called as callback for NVS transactions */
extern FVOS_Error_t NVSTreadParser(void);



/*--------------------------
    FUNCTIONS
----------------------------*/

/**
 * @brief     This functionsconfigurates the FVOS - shared area address
 *
 * @param[in] sharedAreaAddr - address of the shared area
 * @return     DxError_t_t:  
 *                        
 */
FVOS_Error_t  FVOS_Config(DxUint32_t sharedAreaAddr)
{
  /* count */
  DxUint32_t  count;
  
  /*-------------------------
      CODE
  ----------------------------*/
  /* set the shared area */
  g_FVOS_SharedAreaAddress = sharedAreaAddr;
  
  /* set the static memory address at the end of the shared message area */
  g_FVOS_StaticMemoryAddr = sharedAreaAddr + FVOS_MESSAGE_MEMORY_SIZE_IN_BYTES;
  
  /* set the allocation memory address at the end of the static memory */
  g_FVOS_AllocMemoryAddr = g_FVOS_StaticMemoryAddr + FVOS_STATIC_MEMORY_SIZE_IN_BYTES;
  
  /* set the DMA tables start address at the end of the allocation memory area */
  g_FVOS_DMATableAreaAddress = g_FVOS_AllocMemoryAddr + FVOS_ALLOC_MEMORY_SIZE_IN_BYTES;
  
  /* set the area for the FLOW DMA tables */
  g_FVOS_FLOWDMATableAreaAddress = g_FVOS_DMATableAreaAddress + FVOS_SYM_DMA_MEMORY_SIZE_IN_BYTES;
  
  /* prepare the area for the flow dma tables */
  DX_VOS_MemSet((DxUint8_t*)g_FVOS_FLOWDMATableAreaAddress , 0 , FVOS_FLOW_DMA_MEMORY_SIZE_IN_BYTES);
  
  /* set the area for system data */
  g_FVOS_SystemDataMemoryAreaAddress = g_FVOS_FLOWDMATableAreaAddress + FVOS_FLOW_DMA_MEMORY_SIZE_IN_BYTES;
  
  g_FVOS_DMATablesCreated = 0;
  for(count = 0; count < FVOS_NUM_FLOWS; count++)
  {
    g_FlowsContexts[count].flowId = FVOS_FREE_FLOW_ID;
    g_FlowsContexts[count].inputTablesFlag = 0;
    g_FlowsContexts[count].outputTablesFlag = 0;
  }
  
#ifdef DX_USE_BOARD_DMA_AREA
  dmaInputDataArea_ptr = (DxUint8_t*)0xC2040000;
  dmaOutputDataArea_ptr = (DxUint8_t*)0xC2050000;
#endif

  return FVOS_OK;
}


/**
 * @brief     This functions resets the FVOS registers (IMR). In NoOS (polling), we do nothing
 *
 * @return      
 *                        
 */
void FVOS_Reset()
{
  return;
}

/**
 * @brief     This functions start the transaction to the SEP - this is the first function to be called during transaction to SEP
 *            In NoOS configuration no action needs to be performed
 * 
 * @return     DxError_t_t:  
 *                        
 */
FVOS_Error_t FVOS_StartTransaction()
{
  /* regVal */
  DxUint32_t      regVal;

  /*-----------------------------
      CODE
  ---------------------------------*/
  
  g_FVOS_AllocOffset = 0;
  
  /* read the current value of the GRP SEP register */
  FVOS_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR3_REG_ADDR , regVal);
  
  /*Check that GPR3 has legal value of working SEP*/
  if ((regVal != 0x4) &&  /* After cold boot */
      (regVal != 0x8) &&  /* After Warm boot */
  	  (regVal != 0x10))   /* After Cold Warm boot */
  {
  		return FVOS_SEP_IS_DISABLED_ERR;
  }
  	
  
  return FVOS_OK;
}

/**
 * @brief     This function end the transaction to SEP - this is the last function in the transaction
 *            In NoOS configuration no action needs to be performed
 *
 * @return     DxError_t_t:  
 *                        
 */
FVOS_Error_t FVOS_EndTransaction(DxUint32_t mappedAddr)
{
  /*-----------------------------
      CODE
  ---------------------------------*/
  
  return FVOS_OK;
}

/**
 * @brief     This function maps the shared message area to the application memory. It returns a pointer,
 *            trough which application can directly write message data into message shared area
 * 
 * @param[out] mappedAddr_ptr - the mapped address will be returned into this pointer
 *
 * @return     DxError_t_t:  
 *                        
 */
FVOS_Error_t FVOS_Mmap(DxUint32_t* mappedAddr_ptr)
{
  /*-----------------------------
      CODE
  ---------------------------------*/
  
  /* the message starts from the second word of the shared area, the first word is taken by the flows status word */
  *mappedAddr_ptr = g_FVOS_SharedAreaAddress + sizeof(DxUint32_t) * 2;
  
  return FVOS_OK;
}


/**
 * @brief     This function performs a number of commands according to the CMD paramater:
 *            1) Signal to SEP that the message is ready
 *            2) Allocate memory continues locked memory
 *            3) Read from the allocated memory
 *            4) Write into allocated memory
 * 
 * @param[in] commandId - the id of command to execute
 * @param[in] cmdData_ptr - pointer to the strucutre that contains the paramaters for command execution
 *
 * @return     DxError_t_t:  
 *                        
 */
FVOS_Error_t FVOS_Cntrl(FVOS_Cntrl_cmd_t commandId , FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* error */
  FVOS_Error_t    error;
  
  /*-----------------------------
      CODE
  ---------------------------------*/
  
  error = FVOS_OK;
  
  switch(commandId)
  {
    case FVOS_CNTRL_SEND_MSG_RDY_CMD:
      
      /* handle the send message to SEP command */      
      error = FVOS_HandleMsgReadyCmd();
      
      break;
    
    case FVOS_CNTRL_SEND_RPLY_MSG_RDY_CMD:
      
      /* handle the send reply message to SEP command */      
      error = FVOS_HandleReplyMsgReadyCmd();
     
      break;
      
    case FVOS_CNTRL_ALLOC_MEM_CMD:
      
      /* handle alloc memory from dynamic pool command */      
      error = FVOS_HandleAllocMemoryCmd(cmdData_ptr);
         
      break;
      
    case FVOS_CNTRL_BUILD_SYM_DMA_TABLES_CMD:
    
      /* handle the command */
      error = FVOS_HandleBuildSymDmaTablesCmd(cmdData_ptr);
      
      break;
      
    case FVOS_CNTRL_BUILD_FLOW_DMA_TABLES_CMD:
    
      /* handle the command */
      error = FVOS_HandleBuildFlowDmaTablesCmd(cmdData_ptr);
      
      break;
      
    case FVOS_CNTRL_ADD_FLOW_DMA_TABLES_CMD:
    
      /* handle the command */
      error = FVOS_HandleAddFlowDmaTablesCmd(cmdData_ptr);
                                   
      break;
      
    case FVOS_CNTRL_ADD_FLOW_TABLE_MSG_CMD:
    
      error = FVOS_HandleAddFlowTableMsgCmd(cmdData_ptr);
                             
      break;
      
    case FVOS_CNTRL_SET_FLOW_ID_IN_TABLES_CMD:
    
      error = FVOS_HandleSetFlowIdCmd(cmdData_ptr);
      
      break;
      
    case FVOS_CNTRL_FREE_DMA_RESOURSES:

      error = FVOS_HandleFreeDMAResources();
      /* no need for any action in the NoOS  */
      break;
    
    case FVOS_CNTRL_WRITE_DATA_CMD:
      
      error = FVOS_HandleWriteDataCmd(cmdData_ptr);
      
      break;
      
    case FVOS_CNTRL_READ_DATA_CMD:
      
      error = FVOS_HandleReadDataCmd(cmdData_ptr);
      
      break;
      
    case FVOS_CNTRL_GET_STATIC_POOL_ADDR:
      
      error = FVOS_HandleGetStaticPoolDataCmd(cmdData_ptr);
      
      break;
      
    case FVOS_CNTRL_CONV_STATIC_PHYS_TO_VIRT:
    
      error = FVOS_HandleConverStaticPhysToVirtCmd(cmdData_ptr);
    
      break;
    
    case FVOS_CNTRL_FREE_FLOW_RESOURSES:
    
      /* free FLOW DMA tables */
      error = FVOS_HandleFreeFlowResourcesCmd(cmdData_ptr);
      
      break;
      
    case FVOS_CNTRL_SEP_API_MODE:
    
      /* nothing needs to be done */
      break;
      
    case FVOS_CNTRL_GET_TIME:
    
      error = FVOS_HandleGetTimeCmd(cmdData_ptr);
      
      break;
    
    case FVOS_CHECK_CONFIGURATION:
    
      error = FVOS_HandleCheckConfigurationCmd(cmdData_ptr);
      
      break;
    
    case FVOS_READ_PHYS_REGISTER:
    
      FVOS_ReadRegister(cmdData_ptr->data.regDataOp.regVirtAddr,cmdData_ptr->data.regDataOp.regData);
      
      break;
    
    case FVOS_WRITE_PHYS_REGISTER:
    
      FVOS_WriteRegister(cmdData_ptr->data.regDataOp.regVirtAddr,cmdData_ptr->data.regDataOp.regData);
      
      break;
      
    case FVOS_REALLOC_CACHE_RESIDENT:
      
      error = FVOS_HandleReallocCacheResidentCmd(cmdData_ptr);
      
      break;

    case FVOS_REALLOC_EXT_CACHE_RESIDENT:
      
      error = FVOS_HandleReallocExtCacheCmd(cmdData_ptr);
      
      break;
      
    case FVOS_CNTRL_SEP_INIT:
      
      error = FVOS_HandleSEPInitCmd(cmdData_ptr);
      
      break;
      
    default:
      break;
  }
  
  return error;
}


/**
 * @brief     This function polls for the for the response from SEP
 *            Polling can be blocking or busy wait,and can be regulated by timeout
 * @param[in] Timeout - timeout for polling
 * @param[out] pollSource_ptr - the source of the poll interrupt (regular response, or MVS request from SEP
 * @return     DxError_t_t:  
 *                        
 */
FVOS_Error_t FVOS_Poll(DxUint32_t  timeout , DxUint32_t* pollSource_ptr)
{
  /* error */
  FVOS_Error_t    error;
  
  /* regVal */
  DxUint32_t      regVal;

  /*-----------------------
      CODE
  -------------------------*/
  
  error = FVOS_OK;
  
  /* update counter, minding the wrap around */
  g_GPRPollValue = (g_GPRPollValue + 1) & 0x3FFFFFFF;
        
  /* wait for incoming message notification */
  FVOS_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR2_REG_ADDR , regVal);
  while( (regVal & 0x3FFFFFFF) != g_GPRPollValue )
  {
    FVOS_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR2_REG_ADDR , regVal);
  }
        
  /* check if the callback bit is raised - if raised call the callback function */
  if(regVal & (1<<30))
  {
    *pollSource_ptr = FVOS_SEP_PRINTF;
    return error;
  }
  if(regVal >> 31)
  {
    *pollSource_ptr = FVOS_SEP_REQUEST;
  }
  else
  {
    *pollSource_ptr = FVOS_SEP_REPLY;
  }
  
  return error;
}

/*-------------------------------------
    Private functions
---------------------------------------*/

/**
 * @brief     This function handles the send message to SEP command  
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleMsgReadyCmd()
{
  /* read the current value of the GRP SEP register */
  FVOS_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR2_REG_ADDR , g_GPRPollValue);
      
  /* raise interrupt to SEP */
  FVOS_WriteRegister(GEN_HW_HOST_HOST_SEP_GPR0_REG_ADDR , 0x2);
  
  return FVOS_OK;
}

/**
 * @brief     This function handles the send reply message to SEP command  
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleReplyMsgReadyCmd()
{
  /* update counter, minding the wrap around */
  g_GPRPollValue = (g_GPRPollValue + 1) & 0x3FFFFFFF;    
  
  /* raise interrupt to SEP */
  FVOS_WriteRegister(GEN_HW_HOST_HOST_SEP_GPR2_REG_ADDR , g_GPRPollValue);
      
  return FVOS_OK;
}


/**
 * @brief     This function handles the allocate memory from dynamic pool command
 *
 * @param[in] allocSize - size to allocate
 * @param[out] fvosAddr_ptr - fvos address (virtual) of the allocated memory
 * @param[out] physAddr_ptr - physical address of the alloctaed memory 
 * 
 * @return     DxError_t:  
 *                        
 */    
static FVOS_Error_t FVOS_HandleAllocMemoryCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{

  /* error */
  FVOS_Error_t  error;
  
  /*-----------------------
      CODE
  --------------------------*/
  
  error = FVOS_OK;

  /* check that there is a space left for allocation */
  if( (g_FVOS_AllocOffset + cmdData_ptr->data.allocCmdData.allocSize) > FVOS_ALLOC_MEMORY_SIZE_IN_BYTES)
  {
    error = FVOS_ALLOCATE_FAIL_ERR;
    goto end_function;
  }
      
  cmdData_ptr->data.allocCmdData.virtAddr = g_FVOS_AllocMemoryAddr + g_FVOS_AllocOffset;      
  cmdData_ptr->data.allocCmdData.physAddr = cmdData_ptr->data.allocCmdData.virtAddr;
  g_FVOS_AllocOffset += cmdData_ptr->data.allocCmdData.allocSize;

end_function:

  return error;   
}

/**
 * @brief     This function handles the allocate memory from dynamic pool command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 *
 * @return     DxError_t:  
 *                        
 */    
static FVOS_Error_t FVOS_HandleBuildSymDmaTablesCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* error */
  FVOS_Error_t  error = FVOS_OK;
  
  /* build mode */
  DxUint32_t    buildMode = 3;

  /*--------------------------------
      CODE
  --------------------------------*/
  
  /* check if output table must be created */ 
  if(cmdData_ptr->data.buildSymDMATables.dataOutAddr == DX_NULL)
  {
    buildMode  &= ~(0x2);
  }
  
  /* check if output table should be CSI */
  if(cmdData_ptr->data.buildSymDMATables.dataOutAddr >= DX_CSI)
  {
    buildMode  &= ~(0x2);
    cmdData_ptr->data.buildSymDMATables.firstOutTableAddr = cmdData_ptr->data.buildSymDMATables.dataOutAddr;
    cmdData_ptr->data.buildSymDMATables.firstOutTableNumEntries = 2;
  }
  
  /* check if input table should be CSI */
  if(cmdData_ptr->data.buildSymDMATables.dataInAddr >= DX_CSI)
  {
    buildMode  &= ~(0x1);
    cmdData_ptr->data.buildSymDMATables.firstInTableAddr = cmdData_ptr->data.buildSymDMATables.dataInAddr;
    cmdData_ptr->data.buildSymDMATables.firstInTableNumEntries = 2;
  }
  
  switch(buildMode)
  {
    case 0x1:
      /* only input table should be created */
      error = FVOS_PrepareInputDMATable(cmdData_ptr->data.buildSymDMATables.dataInAddr,
                                        cmdData_ptr->data.buildSymDMATables.dataInSize,
                                        &cmdData_ptr->data.buildSymDMATables.firstInTableAddr,
                                        &cmdData_ptr->data.buildSymDMATables.firstInTableNumEntries,
                                        &cmdData_ptr->data.buildSymDMATables.firstTableDataSize); 
  
      break;
      
    case 0x2:
      /* only output table should be created */
      error = FVOS_PrepareInputDMATable(cmdData_ptr->data.buildSymDMATables.dataOutAddr,
                                        cmdData_ptr->data.buildSymDMATables.dataInSize,
                                        &cmdData_ptr->data.buildSymDMATables.firstOutTableAddr,
                                        &cmdData_ptr->data.buildSymDMATables.firstOutTableNumEntries,
                                        &cmdData_ptr->data.buildSymDMATables.firstTableDataSize);
      break;
      
    case 0x3:
      /* both tables should be created */
      error = FVOS_PrepareInputOutputDMATables(cmdData_ptr->data.buildSymDMATables.dataInAddr,
                                               cmdData_ptr->data.buildSymDMATables.dataOutAddr,
                                               cmdData_ptr->data.buildSymDMATables.dataInSize,
                                               cmdData_ptr->data.buildSymDMATables.blockSize,
                                               &cmdData_ptr->data.buildSymDMATables.firstInTableAddr,
                                               &cmdData_ptr->data.buildSymDMATables.firstOutTableAddr,
                                               &cmdData_ptr->data.buildSymDMATables.firstInTableNumEntries,
                                               &cmdData_ptr->data.buildSymDMATables.firstOutTableNumEntries,
                                               &cmdData_ptr->data.buildSymDMATables.firstTableDataSize);
      break;
      
    default:
      
      /* this is the case when CSI with hash - we must set the table size */
      cmdData_ptr->data.buildSymDMATables.firstTableDataSize = cmdData_ptr->data.buildSymDMATables.dataInSize;
      
      /* this is no error since it is possible that both input and output are for CSI, or we are working in CSI for HASH */
      break;
  }
  
  return error;
}


/**
 * @brief     This function handles the build DMA tables for flow
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleBuildFlowDmaTablesCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* error */
  FVOS_Error_t    error;
  
  /* data of the first table */
  FVOS_LliEntry_t firstTableData;
  
  /*--------------------
      CODE
  -----------------------*/

  
  error = FVOS_CreateFlowDMATables(cmdData_ptr->data.buildFlowDMATables.flowType,
                                   cmdData_ptr->data.buildFlowDMATables.buffersArrayAddr,
                                   cmdData_ptr->data.buildFlowDMATables.buffersArraySize,
                                   cmdData_ptr->data.buildFlowDMATables.inputOutputFlag,
                                   &firstTableData);
  /* update output params */                                  
  if(error == FVOS_OK)
  {
    cmdData_ptr->data.buildFlowDMATables.firstInTableAddr = firstTableData.physicalAddress;
    cmdData_ptr->data.buildFlowDMATables.firstInTableNumEntries = firstTableData.blockLength >> FVOS_NUM_ENTRIES_OFFSET_IN_BITS;
    cmdData_ptr->data.buildFlowDMATables.firstTableDataSize = firstTableData.blockLength & FVOS_TABLE_DATA_SIZE_MASK;
  }
  
  return error;
}

/**
 * @brief     This function handles the add DMA tables to a flow
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleAddFlowDmaTablesCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* error */
  FVOS_Error_t    error;
  
  /* data of the first table */
  FVOS_LliEntry_t firstTableData;
  
  /*--------------------
      CODE
  -----------------------*/

  
  error = FVOS_AddFlowDMATables(cmdData_ptr->data.addTables.flowId,
                                cmdData_ptr->data.addTables.inputOutputFlag,
                                cmdData_ptr->data.addTables.buffersArrayAddr,
                                cmdData_ptr->data.addTables.buffersArraySize,
                                &firstTableData);
  if(error == FVOS_OK)
  {
    /* set first table data */
    cmdData_ptr->data.addTables.firstTableAddr = firstTableData.physicalAddress;
    cmdData_ptr->data.addTables.firstTableNumEntries = firstTableData.blockLength >> FVOS_NUM_ENTRIES_OFFSET_IN_BITS;
    cmdData_ptr->data.addTables.firstTableDataSize = firstTableData.blockLength & FVOS_TABLE_DATA_SIZE_MASK;  
  }
  
  return error;
}

/**
 * @brief     This function handles the addition of message for add flow command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleAddFlowTableMsgCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* flow Id */
  DxUint32_t            flowId;
  
  /* error */
  FVOS_Error_t          error;

  /* count */
  DxUint32_t            count;
  
  /* flow register */
  volatile DxUint32_t   flowReg;
  
  /* flow status */
  volatile DxUint32_t   flowStatus;
 
  volatile DxUint32_t   ind;
  
  /*----------------
    CODE
  --------------------*/
  
  error = FVOS_OK;
  
  /* set flow id */
  flowId = cmdData_ptr->data.addTablesMessage.flowId;
  
  /* find the flow entry */
  for(count = 0; count < FVOS_NUM_FLOWS; count++)
  {
    if(g_FlowsContexts[count].flowId == flowId)
    {
      break;
    }
  }
  if(count >= FVOS_NUM_FLOWS )
  {
    error = FVOS_ILLEGAL_FLOW_ID_ERR;
    goto end_function;
  }
  
  /* add message to the flow data */
  g_FlowsContexts[count].messageSizeInBytes = cmdData_ptr->data.addTablesMessage.messageSizeInWords * sizeof(DxUint32_t);
  DX_VOS_FastMemCpy((DxUint8_t*)g_FlowsContexts[count].message , (DxUint8_t*)cmdData_ptr->data.addTablesMessage.messageAddress , g_FlowsContexts[count].messageSizeInBytes );
  
  /* wait till the SEP finished with its tables, and the added tables can be sent */
  flowStatus = 0;
  
  
  while( flowStatus != 0x1)
  {    
    DX_GEN_ReadRegister((DxUint32_t*)g_FVOS_SharedAreaAddress , flowReg);
    flowStatus = ((flowReg >> (flowId * 8)) & 0xFF);
  }

  /* This function free the resources of the flow */
  FVOS_FreeFlowResources(flowId, DX_FALSE); 
  
  /* NOTE: SEP is done working on all tables he had and got the new tables */
  /* we need to update Context data base for next time and to allow corect free operation */
  g_FlowsContexts[count].inputTablesInProcess = g_FlowsContexts[count].firstInputTable;
  g_FlowsContexts[count].outputTablesInProcess = g_FlowsContexts[count].firstOutputTable;
  
  g_FlowsContexts[count].inputTablesFlag = DX_FALSE;
  g_FlowsContexts[count].outputTablesFlag = DX_FALSE;
  
  /* now copy the message to the message shared area */
  DX_VOS_FastMemCpy( (DxUint8_t*)(g_FVOS_SharedAreaAddress + sizeof(DxUint32_t) * 2) , (DxUint8_t*)cmdData_ptr->data.addTablesMessage.messageAddress , (cmdData_ptr->data.addTablesMessage.messageSizeInWords * sizeof(DxUint32_t)) ); 
  
  /* signal the sep */
  DX_GEN_WriteRegister(GEN_HW_HOST_HOST_SEP_GPR0_REG_ADDR , 0x2);
  
  /* wait til SEP has read the message */
  flowStatus = 0;
  
  while( flowStatus != 0x2 && flowStatus != 0x4)  
  {
    DX_GEN_ReadRegister((DxUint32_t*)g_FVOS_SharedAreaAddress , flowReg);
    flowStatus = ((flowReg >> (flowId * 8)) & 0xFF);
  }

end_function:

  return error;
}

/**
 * @brief     This function handles the set flow id command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleSetFlowIdCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* pointer to the id ptr */
  FVOS_Error_t          error;
  
  /* table size in words */ 
  FVOS_FlowContext_t*   flowContext_ptr;
 
  /*------------------------
      CODE
  -------------------------*/
  
  error = FVOS_OK;
  
  error = FVOS_FindFlowContext(FVOS_DEFAULT_FLOW_ID , &flowContext_ptr);
  if(error != FVOS_OK)
  {
    error = FVOS_ILLEGAL_FLOW_ID_ERR;
    goto end_function;
  }
  
  /* flow id */
  flowContext_ptr->flowId = cmdData_ptr->data.setFlowId.flowId;
  
end_function:

  return error;
}

/**
 * @brief     This function handles the free DMA resources command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleFreeDMAResources()
{
  /*------------------------
      CODE
  --------------------------*/
#ifdef DX_USE_BOARD_DMA_AREA

  if(outMemAddress != 0)
  {
    /* copy data to the output memory */
    DX_VOS_FastMemCpy((DxUint8_t*)outMemAddress , (DxUint8_t*)dmaOutputAddress , outMemDataSize);
  }

#endif

  g_FVOS_DMATablesCreated = 0;

  

  return FVOS_OK;
}

/**
 * @brief     This function handles write data command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleWriteDataCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /*------------------
      CODE
  ---------------------*/
  
  DX_VOS_FastMemCpy((DxUint8_t*)cmdData_ptr->data.writeCmdData.destFvosAddr , (DxUint8_t*)cmdData_ptr->data.writeCmdData.srcAppAddr , cmdData_ptr->data.writeCmdData.dataSize);
    
  return FVOS_OK;
}

/**
 * @brief     This function handles read data command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleReadDataCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /*------------------------
      CODE
  ---------------------------*/
  
  DX_VOS_FastMemCpy((DxUint8_t*)cmdData_ptr->data.readCmdData.destAppAddr , (DxUint8_t*)cmdData_ptr->data.readCmdData.srcFvosAddr , cmdData_ptr->data.readCmdData.dataSize);
  
  return FVOS_OK;    
}

/**
 * @brief     This function handles get static pool data command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleGetStaticPoolDataCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /*----------------------------
      CODE
  -------------------------------*/
  
  /* set the addresses of the static memory */
  cmdData_ptr->data.staticPoolInfo.physAddr = g_FVOS_StaticMemoryAddr;
  cmdData_ptr->data.staticPoolInfo.fvosAddr = g_FVOS_StaticMemoryAddr;
  
  return FVOS_OK;
}

/**
 * @brief     This function handles convert static poll physical address to virtual command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleConverStaticPhysToVirtCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* set the addresses of the static memory */
  cmdData_ptr->data.convStatPhysToVirt.virtAddr = cmdData_ptr->data.convStatPhysToVirt.physAddr;
  
  return FVOS_OK;
}

/**
 * @brief     This function handles free flow resources command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */ 
static FVOS_Error_t FVOS_HandleFreeFlowResourcesCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /*-----------------------
      CODE
  -------------------------*/
  
  return FVOS_FreeFlowResources(cmdData_ptr->data.freeFlowResources.flowId, DX_TRUE);
    
}


/**
 * @brief     This function returns address of the stored time value 
 *
 * @param[out] timeAddress_ptr - address of the stored time value
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleGetTimeCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* time value */
  DxUint32_t    timeVal;
  
  /*-----------------
      CODE
  ---------------------*/
  
#ifdef DX_ARM_INTEGRATOR_DEBUG
  /* get the value from the RT clock */
  timeVal = time(DX_NULL); 
#endif

  if(timeVal == -1)
  {
    return FVOS_SYS_CALL_FAIL_ERR;
  }
  
  /* store the time at the beginning of the pool - first set the secure token */
  *(DxUint32_t*)g_FVOS_SystemDataMemoryAreaAddress = FVOS_TIME_VAL_TOKEN;
  
  /* set the time */
  *(DxUint32_t*)(g_FVOS_SystemDataMemoryAreaAddress + sizeof(DxUint32_t)) = timeVal;

  cmdData_ptr->data.getTime.timeAddress = g_FVOS_SystemDataMemoryAreaAddress;

  cmdData_ptr->data.getTime.timeValue = timeVal;
  
  return FVOS_OK;
}

/**
 * @brief     This function checks the configuration
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleCheckConfigurationCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /*------------------
      CODE
  ----------------------*/
  
  if(cmdData_ptr->data.checkConfigData.hostSharedAreaSize < (FVOS_FLOW_DMA_MEMORY_SIZE_IN_BYTES + FVOS_SYM_DMA_MEMORY_SIZE_IN_BYTES + FVOS_ALLOC_MEMORY_SIZE_IN_BYTES + FVOS_STATIC_MEMORY_SIZE_IN_BYTES + FVOS_MESSAGE_MEMORY_SIZE_IN_BYTES + FVOS_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES))
  {
    return FVOS_SHARED_AREA_UNSUFFICENT_SIZE_ERR;
  }
  
  return FVOS_OK;
}

/**
 * @brief     This function handles the realloc cache and resident command
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleReallocCacheResidentCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  DxUint32_t regVal;
  /*-----------------------------
      CODE
  --------------------------------*/
  
  /*Check that the CC_INIT was not called yet*/
  FVOS_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR3_REG_ADDR ,regVal );
  if((regVal == 0x4)||   /*cold boot finished*/
     (regVal == 0x8)||   /*warm boot finished*/
     (regVal == 0x10))   /*cold-warm boot finished*/  
  {
      return FVOS_CC_INIT_SECOND_CALL_ERR;	
  }
  cmdData_ptr->data.reallocCachResident.newCacheAddr = cmdData_ptr->data.reallocCachResident.cacheAddr;
  cmdData_ptr->data.reallocCachResident.newResidentAddr = cmdData_ptr->data.reallocCachResident.residentAddr;
  cmdData_ptr->data.reallocCachResident.newSharedAreaAddr = g_FVOS_SharedAreaAddress;
  cmdData_ptr->data.reallocCachResident.newBaseAddr = cmdData_ptr->data.reallocCachResident.baseAddr;
  cmdData_ptr->data.reallocCachResident.newDCacheAddr = cmdData_ptr->data.reallocCachResident.dcacheAddr;
   
  return  FVOS_OK;
}

/**
 * @brief     This function handles the realloc command of the external cache
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleReallocExtCacheCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /*-----------------------------
      CODE
  --------------------------------*/
  
  cmdData_ptr->data.reallocExtCache.newCacheAddr = cmdData_ptr->data.reallocExtCache.cacheAddr;
   
  return  FVOS_OK;
}

/**
 * @brief     This function handles theSEP Init command 
 *
 * @param[in/out] cmd - command structure wuth input/output argument
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_HandleSEPInitCmd(FVOS_Cntrl_info_t* cmdData_ptr)
{
  /* error */
  FVOS_Error_t  error;
  
  /* register value */
  DxUint32_t    regVal;
  
  /* counter */
  DxUint32_t    counter;
  
  /* pointer to message */
  DxUint32_t*   message_ptr;

  /*-----------------------
      CODE
  -------------------------*/
  
  error  = FVOS_OK;
  
  message_ptr = (DxUint32_t*)cmdData_ptr->data.sepInit.messageAddr;
  
  /* set the base address of the SRAM  */
  FVOS_WriteRegister(GEN_HW_SRAM_ADDR_REG_ADDR , cmdData_ptr->data.sepInit.SepSramAddr );

  for( counter = 0 ; counter < cmdData_ptr->data.sepInit.messageSizeInWords ; counter++ )
  { 
    /* write data to SRAM */
    FVOS_WriteRegister( GEN_HW_SRAM_DATA_REG_ADDR, message_ptr[counter] );
		
		/* wait for write complete */
    FVOS_WAIT_SRAM_WRITE_COMPLETE();
  }
 
  /* signal SEP */ 
  FVOS_WriteRegister(GEN_HW_HOST_HOST_SEP_GPR0_REG_ADDR ,0x1 );

  do
  {
    FVOS_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR3_REG_ADDR , regVal);
  }while(!(regVal & 0xFFFFFFFD));
  
  /* check the value */
  if(regVal == 0x1)
  {
    /* fatal error - read erro status from GPRO */
    FVOS_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR0_REG_ADDR , error); 
  }
  
  return error;
}


/**
 * @brief     This function free the resources of the flow
 *
 * @param[in] flowId - flow id to free
 * @param[in] is_call_from_terminate - 
 *               TRUE:  caller is terminate function
 *               FALSE: else - call from add buffer function
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_FreeFlowResources(DxUint32_t flowId, DxBool_t is_call_from_terminate)
{
  /* pointer to the id ptr */
  FVOS_Error_t          error;
  
  /* table size in words */ 
  FVOS_FlowContext_t*   flowContext_ptr;
 
  /*------------------------
      CODE
  -------------------------*/
  
  /* find the context */
  error = FVOS_FindFlowContext(flowId , &flowContext_ptr);
  if(error != FVOS_OK)
  {
    goto end_function;
  }
  
  /* when calling frmterminate with no Add operation => need to update internal params */
  /* inorder for deallication to work. */
  if(is_call_from_terminate)
  {
    /* deallocate input tables if needed */
    if(flowContext_ptr->inputTablesInProcess.physicalAddress != DX_NULL)
    {
      FVOS_DeallocateFlowTables(&flowContext_ptr->inputTablesInProcess);
    }
    
    /* deallocate output tables if needed */
    if(flowContext_ptr->outputTablesInProcess.physicalAddress != DX_NULL)
    {
      FVOS_DeallocateFlowTables(&flowContext_ptr->outputTablesInProcess);
    }
    
    /* free relevant g_FlowsContexts[flowid] location */
    DX_VOS_MemSet((DxUint8_t*)flowContext_ptr , 0 , sizeof(FVOS_FlowContext_t));
    
    /* setting data base flowid to free */
    flowContext_ptr->flowId = FVOS_FREE_FLOW_ID;
  }
  else
  {
    /* deallocate input tables if needed */
    if(flowContext_ptr->inputTablesFlag)
    {
      FVOS_DeallocateFlowTables(&flowContext_ptr->inputTablesInProcess);
    }
    
    /* deallocate output tables if needed */
    if(flowContext_ptr->outputTablesFlag)
    {
      FVOS_DeallocateFlowTables(&flowContext_ptr->outputTablesInProcess);
    }
  }
  
end_function:  
  return error;
}


/**
 * @brief     this functions handles the request from upper layer for construction of the first tables of the FLOW 
 *
 * @param[in] flowType - flow type (static or dynamic)
 * @param[in] buffersArrayAddr - array of input buffers
 * @param[in] buffersArraySize - size of input buffers array
 * @param[in] inputOutputFlag - flag if the created tables are for input or output data
 * @param[out] firstTableInfo_ptr - pointer to the LLI entry that will hold the data of the first table
 *
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_CreateFlowDMATables(DxUint32_t             flowType,
                                             DxUint32_t             buffersArrayAddr,
                                             DxUint32_t             buffersArraySize,
                                             FVOS_InputArrayFlag_t  inputOutputFlag,
                                             FVOS_LliEntry_t*       firstTableData_ptr)
{
  /* error */
  FVOS_Error_t            error;

  /* pointer to the flow context pointer */
  FVOS_FlowContext_t*     flowContext_ptr;

#ifdef DX_USE_BOARD_DMA_AREA    
  /* pointer to the buffers (virutal) */
  FVOS_FLOW_BufferData_t* buffers_ptr;
  
  /* copy address */
  DxUint8_t*              copyAddress;
  
  /* count */
  DxUint32_t              count;  
#endif
  
  /*----------------------
      CODE
  -------------------------*/

#ifdef DX_USE_BOARD_DMA_AREA  
  
  /* copy the flow input data into the DMA area */
  buffers_ptr = (FVOS_FLOW_BufferData_t*)buffersArrayAddr;
  
  if(inputOutputFlag == FVOS_InputArray)
  {
    copyAddress = dmaInputDataArea_ptr ;
  }
  else
  {
    copyAddress = dmaOutputDataArea_ptr ;
  }
  
  
  /* copy the buffers to the DMA area */
  for(count = 0; count < buffersArraySize; count++)
  {
    DX_VOS_FastMemCpy(copyAddress , buffers_ptr[count].buffer_ptr , buffers_ptr[count].bufferSize);
    buffers_ptr[count].buffer_ptr = copyAddress;
    copyAddress += buffers_ptr[count].bufferSize;
  }
  
  if(inputOutputFlag == FVOS_InputArray)
  {
    dmaInputDataArea_ptr = copyAddress ;
  }
  else
  {
    dmaOutputDataArea_ptr = copyAddress ;
  }
#endif
  
  /* if this is input buffer - then find free contex, if output - then find context with default id */
  if(inputOutputFlag == FVOS_InputArray)
  {
    /* find free flow context */
    error = FVOS_FindFlowContext(FVOS_FREE_FLOW_ID , &flowContext_ptr);
  }
  else
  {
    error = FVOS_FindFlowContext(FVOS_DEFAULT_FLOW_ID , &flowContext_ptr);
  }
  if(error != FVOS_OK)
  {
    goto end_function;
  }
  
  /* prepare dma tables */
  error = FVOS_PrepareFlowDMATables(FVOS_DEFAULT_FLOW_ID,
                                    flowType,
                                    buffersArrayAddr,
                                    buffersArraySize,
                                    firstTableData_ptr,
                                    DX_NULL);
  if(error != FVOS_OK)
  {
    goto end_function;
  }
  
  /* set the context */
  flowContext_ptr->flowId = FVOS_DEFAULT_FLOW_ID;
  
  if(inputOutputFlag == FVOS_InputArray)
  {
    flowContext_ptr->inputTablesInProcess = *firstTableData_ptr;
  }
  else
  {
    flowContext_ptr->outputTablesInProcess = *firstTableData_ptr;
  }
  
  
end_function:

  return error;
}


/**
 * @brief     this functions constructs DMA table for the flow ( for input or for output )
 *            the first word of table holds the number of 
 *
 * @param[in] flowId - flow id
 * @param[in] flowType - flow type (static or dynamic)
 * @param[in] buffersArrayAddr - array of input buffers
 * @param[in] buffersArraySize - size of input buffers array
 * @param[out] firstTableInfo_ptr - pointer to the LLI entry that will hold the data of the first table
 * @param[out] lastTableInfo_ptr - pointer to the LLI entry that will hold the data of the last table 
 *
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_PrepareFlowDMATables(DxUint32_t        flowId,
                                              DxUint32_t        flowType,
                                              DxUint32_t        buffersArrayAddr,
                                              DxUint32_t        buffersArraySize,
                                              FVOS_LliEntry_t*  firstTableInfo_ptr,
                                              FVOS_LliEntry_t*  lastTableInfo_ptr)
{
  /* count */
  DxUint32_t              count;
  
  /* lli entry ptr */
  FVOS_LliEntry_t*        lliEntry_ptr;
  
  /* info entry of the table before last */
  FVOS_LliEntry_t*        prevInfoEntry_ptr;
  
  /* pointer to the id ptr */
  DxUint32_t*             id_ptr;
  
  /* table size in words */
  DxUint32_t              tableSizeInWords;
  
  /* end address of the flow DMA area */
  DxUint32_t              flowDmaAreaEndAddr;
  
  /* pointer to the buffers (virtual) */
  FVOS_FLOW_BufferData_t* buffers_ptr;
  
  /* error */
  FVOS_Error_t            error;
  
  
  /*------------------------
      CODE
  --------------------------*/
  
  error = FVOS_OK;
  
  prevInfoEntry_ptr = DX_NULL;
  
  /* table size is the size of all entries + 1 word for id */
  tableSizeInWords = FVOS_FLOW_MAX_NUM_ENTRIES_IN_TABLE * (sizeof(FVOS_LliEntry_t) / sizeof(DxUint32_t)) + 1;
  flowDmaAreaEndAddr = g_FVOS_FLOWDMATableAreaAddress + FVOS_FLOW_DMA_MEMORY_SIZE_IN_BYTES;

  /* set the pointer */
  buffers_ptr = (FVOS_FLOW_BufferData_t*)buffersArrayAddr;
  
  /* init the output paramater */
  firstTableInfo_ptr->physicalAddress = 0xFFFFFFFF;

  /* set the pointer to the start address of DMA area */
  id_ptr = (DxUint32_t*)g_FVOS_FLOWDMATableAreaAddress;
  
  for(count = 0; count < buffersArraySize; count++)
  {
    /* find the space for the next table */
    while( (*id_ptr != 0) && ( (DxUint32_t)id_ptr < flowDmaAreaEndAddr ) )
    {
      id_ptr += tableSizeInWords;
    }
    
    if((DxUint32_t)id_ptr >= flowDmaAreaEndAddr)
    {
      error = FVOS_MEMORY_NOT_AVAILABLE_ERR;
      
      goto end_function_deallocate_tables;
    }
    
    /* set the DEFAULT id */
    *id_ptr = FVOS_DEFAULT_FLOW_ID;
     
    /* set the start pointer of the table */
    lliEntry_ptr = (FVOS_LliEntry_t*)(id_ptr + 1) ;
    
    /* set the address and size */
    lliEntry_ptr->physicalAddress = (DxUint32_t)buffers_ptr[count].buffer_ptr;
    lliEntry_ptr->blockLength = buffers_ptr[count].bufferSize;
    
    /* if this first table - set the output parameters */
    if(count == 0)
    {
      /* set the data of the first table */
      firstTableInfo_ptr->physicalAddress = (DxUint32_t)lliEntry_ptr;
      firstTableInfo_ptr->blockLength = (0x2 << FVOS_NUM_ENTRIES_OFFSET_IN_BITS) | (buffers_ptr[count].bufferSize);
    
      /* point to the info table that contains data of the table currently proccessed */
      prevInfoEntry_ptr = firstTableInfo_ptr;
      
      lliEntry_ptr++;
    }
    else
    {
      
      /* set the data in the previous table info entry */
      prevInfoEntry_ptr->physicalAddress = (DxUint32_t)lliEntry_ptr;
      /* NOTE: in No OS we have only 1 entry for each buffer (In|Out) => we mark 2 entries +1 for information entry */
      prevInfoEntry_ptr->blockLength = (0x1 << FVOS_INT_FLAG_OFFSET_IN_BITS) | (0x2 << FVOS_NUM_ENTRIES_OFFSET_IN_BITS) | (lliEntry_ptr->blockLength); 
    
      /* set the current entry to 0xFFFFFFFF, in case the next allocation fails */
      lliEntry_ptr++;
      
      lliEntry_ptr->physicalAddress = 0xffffffff;
    }
    
    /* set the pointer for info entry for this table */
    prevInfoEntry_ptr = lliEntry_ptr;
  }
  
  /* set the data of the last table */
  if(lastTableInfo_ptr != DX_NULL)
  {
    *lastTableInfo_ptr = *prevInfoEntry_ptr;
  }
  
  /* set the last info entry according to type */
  if(flowType)
  {
    /* flow is dynamic - set MSB bit in length for interrupt */
    prevInfoEntry_ptr->blockLength = (DxUint32_t)(0x1 << 31);
    prevInfoEntry_ptr->physicalAddress = 0xffffffff;
  }
  else
  {
    /* flow is static  - point to the beginning of the table */
    prevInfoEntry_ptr->physicalAddress = (DxUint32_t)firstTableInfo_ptr->physicalAddress;
    prevInfoEntry_ptr->blockLength = (DxUint32_t)(0x1 << 31) | (firstTableInfo_ptr->blockLength);
  }
  
  goto end_function;

end_function_deallocate_tables:

  /* deallocate all alocated tables */
  FVOS_DeallocateFlowTables(firstTableInfo_ptr);

end_function:
  
  return error; 
}


/**
 * @brief     this functions deallocates the tables starting from the first table
 *
 *
 * @param[in] firstTable_ptr - first table 
 *
 * @return     DxError_t:  
 *                        
 */
static void FVOS_DeallocateFlowTables(FVOS_LliEntry_t* firstTable_ptr)
{
  /* id poiner */
  DxUint32_t* id_ptr;
  
  /* number of entries */
  DxUint32_t  numEntries;
  
  /* for Static flow save first entry physical Address */
  DxUint32_t  firstEntryPhyAddr;
  DxBool_t    firstLoop;
  
  /*-------------------------------
      CODE
  ---------------------------------*/
  
  if(firstTable_ptr == DX_NULL)
  {
    goto end_function;
  }
    
  firstLoop = DX_TRUE;
  firstEntryPhyAddr = 0xFFFFFFFF;
  
  /* 2 conditions for Dynamic & Static flows */
  while((firstTable_ptr->physicalAddress != 0xFFFFFFFFUL) &&
        (firstTable_ptr->physicalAddress != firstEntryPhyAddr)
       )
  {
    if(firstLoop == DX_TRUE)
    {
      firstEntryPhyAddr = firstTable_ptr->physicalAddress;      
      firstLoop = DX_FALSE;
    }
    
    id_ptr = (DxUint32_t*)(firstTable_ptr->physicalAddress - sizeof(DxUint32_t));
    *id_ptr = 0;
    
    /* find the next table */
    numEntries = (DxUint32_t)((firstTable_ptr->blockLength >> FVOS_NUM_ENTRIES_OFFSET_IN_BITS) & FVOS_NUM_ENTRIES_MASK);
    
    firstTable_ptr = ((FVOS_LliEntry_t*)firstTable_ptr->physicalAddress) + (numEntries - 1);
  }
  
end_function:

  return;
}


/**
 * @brief     this functions constructs additional DMA tables for the flow ( for input or for output ), and if new message shoudl be created
 *            it set the flag and returns the data for the input and output tables
 *
 *
 * @param[in] flowId
 * @param[in] inputOutputFlag - flag if this input or output tables
 * @param[in] bufferArrayAddr - array of input/output buffers
 * @param[out] bufferArraySize - size of the buffers array
 * @param[out] firstInputTableInfo_ptr - pointer to the data of the first table (input or output)
 *
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_AddFlowDMATables(DxUint32_t        flowId,
                                          DxUint32_t        inputOutputFlag,
                                          DxUint32_t        bufferArrayAddr,
                                          DxUint32_t        bufferArraySize,
                                          FVOS_LliEntry_t*  firstTableInfo_ptr)
{
  
  /* count */
  DxUint32_t              count;
  
  /* first table address */
  FVOS_LliEntry_t         firstTableData;
  
  /* first table size */
  FVOS_LliEntry_t         lastTableData;
  
  /* num entries of the first table */
  DxUint32_t              numEntries;
  
  /* info entry */
  FVOS_LliEntry_t*        infoEntry_ptr;
  
  /* error */
  FVOS_Error_t            error;
  
#ifdef DX_USE_BOARD_DMA_AREA  
  /* pointer to the buffers (virutal) */
  FVOS_FLOW_BufferData_t* buffers_ptr;
  
  /* copy address */
  DxUint8_t*              copyAddress;
#endif  
  
  /*--------------------
      CODE
  ----------------------*/
  
  error = FVOS_OK;
  
#ifdef DX_USE_BOARD_DMA_AREA  
  
  /* copy the data int the DMA area */
  buffers_ptr = (FVOS_FLOW_BufferData_t*)bufferArrayAddr;
  
  if(inputOutputFlag == FVOS_InputArray)
  {
    copyAddress = dmaInputDataArea_ptr ;
  }
  else
  {
    copyAddress = dmaOutputDataArea_ptr ;
  }
  
  
  /* copy the buffers to the DMA area */
  for(count = 0; count < bufferArraySize; count++)
  {
    DX_VOS_FastMemCpy(copyAddress , buffers_ptr[count].buffer_ptr , buffers_ptr[count].bufferSize);
    buffers_ptr[count].buffer_ptr = copyAddress;
    copyAddress += buffers_ptr[count].bufferSize;
  }
  
  if(inputOutputFlag == FVOS_InputArray)
  {
    dmaInputDataArea_ptr = copyAddress ;
  }
  else
  {
    dmaOutputDataArea_ptr = copyAddress ;
  }
  
#endif 

  /* find the flow entry */
  for(count = 0; count < FVOS_NUM_FLOWS; count++)
  {
    if(g_FlowsContexts[count].flowId == flowId)
    {
      break;
    }
  }
  
  if(count >= FVOS_NUM_FLOWS )
  {
    error = FVOS_ILLEGAL_FLOW_ID_ERR;
    goto end_function;
  }
  
  /* prepare the tables for dynamic flow */
  error = FVOS_PrepareFlowDMATables(flowId ,
                                    1,
                                    bufferArrayAddr,
                                    bufferArraySize,
                                    &firstTableData,
                                    &lastTableData);
  if(error != FVOS_OK)
  {
    goto end_function;
  }
  
  if(inputOutputFlag)
  {
    /* this is the output table */
    if(g_FlowsContexts[count].outputTablesFlag)
    {
      /* output table already exists - update info entry of the last table */
      numEntries = (g_FlowsContexts[count].lastOutputTable.blockLength >> FVOS_NUM_ENTRIES_OFFSET_IN_BITS) & FVOS_NUM_ENTRIES_MASK;
      
      infoEntry_ptr = (FVOS_LliEntry_t*)(g_FlowsContexts[count].lastOutputTable.physicalAddress + (sizeof(FVOS_LliEntry_t) * (numEntries - 1)) );
      
      *infoEntry_ptr = firstTableData;
    }
    else
    {
      g_FlowsContexts[count].firstOutputTable = firstTableData;
      g_FlowsContexts[count].outputTablesFlag = 1;
    }
    
    /* update the data for the new last table */
    g_FlowsContexts[count].lastOutputTable = lastTableData;
    
    /* set the output parameters */
    *firstTableInfo_ptr = g_FlowsContexts[count].firstOutputTable;
  }
  else
  {
    /* this is input table */
    if(g_FlowsContexts[count].inputTablesFlag)
    {
      /* input  table already exists - update info entry of the last table */
      numEntries = (g_FlowsContexts[count].lastInputTable.blockLength >> FVOS_NUM_ENTRIES_OFFSET_IN_BITS) & FVOS_NUM_ENTRIES_MASK;
      
      infoEntry_ptr = (FVOS_LliEntry_t*)(g_FlowsContexts[count].lastInputTable.physicalAddress + (sizeof(FVOS_LliEntry_t) * (numEntries - 1)) );
      
      *infoEntry_ptr = firstTableData;
    }
    else
    {
      g_FlowsContexts[count].firstInputTable = firstTableData;
      g_FlowsContexts[count].inputTablesFlag = 1;
    }
    
    /* update the data for the new last table */
    g_FlowsContexts[count].lastInputTable = lastTableData;
    
    /* set the output parameters */
    *firstTableInfo_ptr = g_FlowsContexts[count].firstInputTable;
  }
  
end_function:
  
  return error; 
  
}


/**
 * @brief     this functions find flow context according to the id
 *
 * @param[in] flowId - flow id 
 * @param[out] flowContext_ptr - pointer to the returned context
 *
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_FindFlowContext(DxUint32_t flowId , FVOS_FlowContext_t** flowContext_ptr)
{
  /* count */
  DxUint32_t      count;
  
  /* error */
  FVOS_Error_t    error;
  
  /*-----------------------
      CODE
  ---------------------------*/
  
  error = 0;
  
  /* 
     always search for flow with id default first - in case we already started working on the flow
     there can be no situation when 2 flows are with default flag
  */  
  for(count = 0; count < FVOS_NUM_FLOWS ; count++)
  {
    if(g_FlowsContexts[count].flowId == flowId)
    {
      *flowContext_ptr = &g_FlowsContexts[count];
      break;
    }
  }
  
  if(count == FVOS_NUM_FLOWS)
  {
    /* no flow found  */
    error = FVOS_ILLEGAL_FLOW_ID_ERR;
  }
  
  return error;
}

/**
 * @brief     This function constructs the lli table from the input of the array of physical addresses
 *            sizes for each physical buffer ,  and the number of physical buffer. Function uses the the VOS function for allocation of the
 *            memory needed for the 
 *
 *
 * @param[in] inputPhysicalBuffersArray - input physical buffers and their size
 * @param[out] firstInputLLITable_ptr - holds pointer to the first lli table in the list
 * @param[out] numEntriesInTable_ptr - number of entries in the first lli table 
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_PrepareInputDMATable(DxUint32_t   dataInAddr,
                                              DxUint32_t   dataInSize,
                                              DxUint32_t*  firstInputLLITable_ptr,
                                              DxUint32_t*  numEntriesInTable_ptr,
                                              DxUint32_t*  firstTableDataSize_ptr)
{  
  /* lli entry ptr */
  FVOS_LliEntry_t*    lliEntryPtr;
  
  /* error */
  FVOS_Error_t        error;
  
  /* table size */
  DxUint32_t          tableSize;
  
  
  /*------------------------
      CODE
  --------------------------*/
  
#ifdef DX_USE_BOARD_DMA_AREA  
  /* copy the data to the board DMA area */
  DX_VOS_FastMemCpy((DxUint8_t*)0xc2000000 , (DxUint8_t*)dataInAddr, dataInSize);
  dataInAddr = 0xc2000000;
  outMemAddress = 0;
#endif
  
  /* init variables */
  error = FVOS_OK;
  
  /* in NoOs each table has only 2 entries */
  tableSize = sizeof(FVOS_LliEntry_t) * 2;
   
  lliEntryPtr = (FVOS_LliEntry_t*)(g_FVOS_DMATableAreaAddress + (g_FVOS_DMATablesCreated * tableSize));
  
  /* set the address and size */
  lliEntryPtr->physicalAddress = (DxUint32_t)dataInAddr;
  lliEntryPtr->blockLength = dataInSize;
      
  lliEntryPtr++;
  
  /* set the last info entry */ 
  lliEntryPtr->blockLength = 0x0;
  lliEntryPtr->physicalAddress = 0xffffffff;
  
  /* this is the first table - set the output paramater */
  *firstInputLLITable_ptr = g_FVOS_DMATableAreaAddress;
      
  /* num entries should include the last entry that points to the next table */
  *numEntriesInTable_ptr = 2;
      
  *firstTableDataSize_ptr = dataInSize;
  
  /* set number of already created tables */
  g_FVOS_DMATablesCreated += 1;
  
  return error;

}


/**
 * @brief     This function creates tables for symmetric engines (AES,DES). The size of data in each
 *            table is modulud the operationBlockSize
 *
 *
 * @param[in] inputPhysicalBuffersArray - physical memory buffers for input
 * @param[in] outputPhysicalBuffersArray - physical memory buffers for output
 * @param[in] operationBlockSize - block size of the operation (AES or DES)
 * @param[out] firstInputLLITable_ptr - pointer to the first table in the list of input tables
 * @param[out] firstOutputLLITable_ptr - pointer to the first table in the list of output tables
 * @param[out] numEntriesInTable_ptr - number of entries in the first input/output tables
 * 
 * @return     DxError_t:  
 *                        
 */
static FVOS_Error_t FVOS_PrepareInputOutputDMATables(DxUint32_t   dataInAddr,
                                                     DxUint32_t   dataOutAddr,
                                                     DxUint32_t   dataInSize,
                                                     DxUint32_t   operationBlockSize,
                                                     DxUint32_t*  firstInputLLITable_ptr,
                                                     DxUint32_t*  firstOutputLLITable_ptr,
                                                     DxUint32_t*  numInTableEntries_ptr,
                                                     DxUint32_t*  numOutTableEntries_ptr,
                                                     DxUint32_t*  firstTableDataSize_ptr)
{
  /* pointer to allocated LLI input table */
  FVOS_LliEntry_t*          inputLLITable_ptr;
  
  /* pointer to allocated LLI output table */
  FVOS_LliEntry_t*          outputLLITable_ptr;
  
  /* table size */
  DxUint32_t                tableSize;
  
  /* error */
  FVOS_Error_t              error = FVOS_OK;
  
  /*-------------------------------
    CODE
  --------------------------------*/

#ifdef DX_USE_BOARD_DMA_AREA  
  /* copy the data to the board DMA area */
  DX_VOS_FastMemCpy((DxUint8_t*)0xc2000000 , (DxUint8_t*)dataInAddr, dataInSize);
  dataInAddr = 0xc2000000;
  
  outMemAddress = dataOutAddr;
  outMemDataSize = dataInSize;
  dmaOutputAddress = dataInAddr + dataInSize;
  
  dataOutAddr = dataInAddr + dataInSize;
#endif
 
  /* in NoOs each table has only 2 entries */
  tableSize = sizeof(FVOS_LliEntry_t) * 2;
  
  /* allocate input and output tables */
  inputLLITable_ptr = (FVOS_LliEntry_t*)(g_FVOS_DMATableAreaAddress + (g_FVOS_DMATablesCreated * tableSize));
  outputLLITable_ptr = (FVOS_LliEntry_t*)( ((DxUint32_t)inputLLITable_ptr) + tableSize);
  
  /* set the fields for the output */
  *firstInputLLITable_ptr = (DxUint32_t)inputLLITable_ptr; 
  *firstOutputLLITable_ptr = (DxUint32_t)outputLLITable_ptr;
  
  
  /* set the input table parameters */
  inputLLITable_ptr->physicalAddress = (DxUint32_t)dataInAddr;
  inputLLITable_ptr->blockLength = dataInSize;
      
  inputLLITable_ptr++;
  
  /* set the last info entry */ 
  inputLLITable_ptr->blockLength = 0x0;
  inputLLITable_ptr->physicalAddress = 0xffffffff;
  
  /* set the output table parameters */
  outputLLITable_ptr->physicalAddress = (DxUint32_t)dataOutAddr;
  outputLLITable_ptr->blockLength = dataInSize;
      
  outputLLITable_ptr++;
  
  /* set the last info entry */ 
  outputLLITable_ptr->blockLength = 0x0;
  outputLLITable_ptr->physicalAddress = 0xffffffff;
  
  /* set the number of entries in the input/output table and the data size of the first table */
  *numInTableEntries_ptr = 2;
  *numOutTableEntries_ptr = 2;
  *firstTableDataSize_ptr = dataInSize;
  
  
  /* set the offset for the next table */
  g_FVOS_DMATablesCreated += 2;
  
  return error;
}


#if !defined(DX_USE_BOARD_DMA_AREA) && !defined (DSM_SIM)

/* scatter working stack initialization */
__value_in_regs struct __initial_stackheap __user_initial_stackheap(

        unsigned R0, unsigned SP, unsigned R2, unsigned SL)

{

    struct __initial_stackheap config;

    R0 = R0;

    R2 = R2;

    SL = SL;

    config.heap_base = ((unsigned int)&Image$$DATA_SECTION$$ZI$$Limit) +  (1024 * 16); // defined in heap.s

    config.stack_base = SP;   // inherit sp from the execution environment
    
#ifndef DX_NO_WMDRM_SUPPORT    
	/*These 2 sections are allocated at the end of the end of the DMA access area.*/
	/*The heap pointer is at the begining of the area (right after the cache) and */
	/*the stack pointer is at the end of the memory */
    config.heap_base = ((unsigned int)&Image$$HEAP_FOR_DMA_SECTION$$Base); 

    config.stack_base = ((unsigned int)&Image$$STACK_FOR_DMA_SECTION$$Base);
#endif
    return config;

}

#endif

/**
 * @brief     This function return the printf buffer used by the SEP,
 *            
 * 
 * @param[out] printfBuff_ptr - the mapped address will be returned into this pointer
 *
 * @return     DxError_t_t:  
 *                        
 */
FVOS_Error_t FVOS_GetPrintfBuffer(DxUint32_t* printfBuff_ptr)
{
  /*-----------------------------
      CODE
  ---------------------------------*/
  
  /* The printf buffer is located at the end of the shared area for the message (last 256 bytes from 6K) */
  *printfBuff_ptr = g_FVOS_SharedAreaAddress + 5888; /*5888 = 6K-256*/
  
  return FVOS_OK;
}
