
/*
   *  Object %name    : SEPDriver.h
   *  State           :  %state%
   *  Creation date   :  Wed Nov 17 17:39:24 2004
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief  Key Management h file (API and structures )
   *
   *  \version 
   *  \author yevgenys
   *  \remarks Copyright (C) 2004 by Discretix Technologies Ltd.
   *           All Rights reserved
   */
#include "DX_VOS_BaseTypes.h"
#include "DX_VOS_Sem.h"
#include "DX_VOS_Mem.h"
#include "error.h"
#include "SEPDriver.h"
#include "gen.h"
#include "FVOS_Types.h"
#include "FVOS_API.h"
#include "FVOS_Config.h"
#include "FVOS_Error.h"




/*------------------------------
    DEFINES
--------------------------------*/
#define SEPDRIVER_START_MESSAGE_TOKEN   0X02558808


/*--------------------------------------
  PROTOTYPES
---------------------------------------*/


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


/* address of the shared RAM */
DxUint32_t    g_SharedRamAddr;

/* function to be called as callback for NVS transactions */
#ifdef DX_NVS_SUPPORT
extern DxError_t  NVSHost_Parser(void);
#endif



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

/**
 * @brief       This function initializes the SEP Driver
 * 
 * @param[in] sharedRamAddress - start address of the shared Ram
 * @return     DxError_t:  
 *                        
 */
void SEPDriver_Init(DxUint32_t sharedRamAddress)
{
  /*----------------------
      CODE
  -----------------------*/
/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Config(sharedRamAddress);
/*lint -restore */

}


/**
 * @brief       This function check that the resident and the cache are not being overwritten by the 
 *              internal configuration of the SEPDriver and FVOS
 *
 * 
 * @param[in] HostSharedAreaSize - the size of the shared area
 *
 */
DxError_t SEPDriver_CheckInitParams(DxUint32_t    hostSharedAreaSize)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t checkConfigData;
  
  /*----------------------
      CODE
  -------------------------*/
  
  checkConfigData.data.checkConfigData.hostSharedAreaSize = hostSharedAreaSize;
  
  return FVOS_Cntrl(FVOS_CHECK_CONFIGURATION , &checkConfigData);
}


/**
 * @brief       This function start the message in the SRAM. It inserts the token and the total length of the message,
 *              and returns the offset into message from where to start writing the next paramater
 *
 * @param[out] messageOffset_ptr - offset of the next paramater to be written into the message
 *
 */
void SEPDriver_StartMessage(DxUint32_t*  messageOffset_ptr)
{
  
  /*---------------
     CODE
  ------------------*/
  
  /* write token into message and convert the endianness if needed */
  *(DxUint32_t*)g_SharedRamAddr = SEPDRIVER_START_MESSAGE_TOKEN; 
  
  /* set the next parameter offset - the first 2 words are token and messsage length */
  *messageOffset_ptr = sizeof(DxUint32_t) * 2;

}

/**
 * @brief       This function ends the message in the SRAM. It inserts CRS and then raises the interrupt to SEP
 *
 * @param[in] messageOffset - 
 *                  
 */
void SEPDriver_EndMessage(DxUint32_t   messageOffset)
{ 
  /* message length */
  DxUint32_t    messageLength;
  
  /*-----------------
    CODE
  -----------------*/
  
  /* length of message in words is the whole length + word of crc */
  messageLength = messageOffset / sizeof(DxUint32_t) + 1;
  
  /* insert the length in bytes into message */
  *(DxUint32_t*)(g_SharedRamAddr + 4) = messageLength;
  
  /* set 0 for temp CRC */
  *(DxUint32_t*)(g_SharedRamAddr + messageOffset) = 0;

/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Cntrl(FVOS_CNTRL_SEND_MSG_RDY_CMD , DX_NULL);
/*lint -restore */
  
}


/**
 * @brief       This function ends the reply message in the SRAM. It inserts CRS and then sets GPR2 to the value that SEP is polling on
 *              Reply message is the message sent from host to SEP as a result of SEP request (NVS)
 *
 * @param[in] messageOffset - 
 *
 */
void SEPDriver_EndReplyMessage(DxUint32_t   messageOffset)
{
  /* message length */
  DxUint32_t    messageLength;
  
  /*-----------------
    CODE
  -----------------*/
  
  /* length of message in words is the whole length + word of crc */
  messageLength = messageOffset / sizeof(DxUint32_t) + 1;
  
  /* insert the length in bytes into message */
  *(DxUint32_t*)(g_SharedRamAddr + 4) = messageLength;
  
  /* set 0 for temp CRC */
  *(DxUint32_t*)(g_SharedRamAddr + messageOffset) = 0;
  
/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Cntrl(FVOS_CNTRL_SEND_RPLY_MSG_RDY_CMD , DX_NULL);
/*lint -restore */

}

/**
 * @brief       This function start the incoming message from SEP. It checks the start token , the length and the CRC
 *
 * @param[out] messageOffset_ptr - offset of the next paramater to be read from the message
 *                        
 */
DxError_t SEPDriver_StartIncomingMessage(DxUint32_t*  messageOffset_ptr)
{
  /* opcode */
  DxUint32_t  token;

  /* message length */
  DxUint32_t  messageLength;
  
  /* get CRC */
  DxUint32_t  crc;
  
  /* error */
  DxError_t     error;
  /*---------------
     CODE
  ------------------*/
  
  error = DX_OK;
  
  /* get start token */
  token = *(DxUint32_t*)g_SharedRamAddr;
  
  if(token != SEPDRIVER_START_MESSAGE_TOKEN)
  {
    error = DX_FAILED_START_TOKEN_ERR;
    goto end_function;
  }
  
  /* get message length */
  messageLength = *(DxUint32_t*)(g_SharedRamAddr + sizeof(DxUint32_t));
  
  /* get CRC */
  crc = *(DxUint32_t*)(g_SharedRamAddr + (messageLength - 1) * sizeof(DxUint32_t));
  
  /* calculate and check CRC */
  *(DxUint32_t*)(g_SharedRamAddr + (messageLength - 1) * sizeof(DxUint32_t)) = 0;
  
end_function:

  /* set the offset */
  *messageOffset_ptr = sizeof(DxUint32_t) * 2; 

  return error;
}


/**
 * @brief       This function writes a a parameter into SHARED memory. Paramter can be either a word or an array of words or bytes
 *              If this is an array of bytes, then the bytesArrayFlag should be set, so that the parameter will be converted into little endian (if needed)
 *
 * @param[in] paramAddress - address pf the parameter to insert
 * @param[in] paramLengthInBytes - parameter length in bytes
 * @param[in] maxParamLengthInBytes - maximum number of bytes that this parameter should take in the message.Must be word alligned
 * @param[in/out] messageOffset_ptr - offset into message before and after insertion
 * @param[in] bytesArrayFlag - if this is byte array that should be converted
 *  
 * @return: Error - if the maxParamLengthInBytes is not word alligned                      
 */
DxError_t SEPDriver_WriteParamater(DxUint32_t   paramAddress,
                                   DxUint32_t   paramLengthInBytes,
                                   DxUint32_t   maxParamLengthInBytes,
                                   DxUint32_t*  messageOffset_ptr,
                                   DxUint32_t   bytesArrayFlag)
{
  /* paramater address */
  DxUint32_t  sramAddress;

  /*------------------
    CODE
  -------------------*/
  
  if( (maxParamLengthInBytes < paramLengthInBytes) || (maxParamLengthInBytes % sizeof(DxUint32_t)) )
  {
    return DX_PARAM_NOT_ALLIGNED_ERR;
  }
  
  /* set address to where to insert parameter */
  sramAddress = g_SharedRamAddr + *messageOffset_ptr;
  
  /* copy the data into shared ram */
  DX_VOS_FastMemCpy((DxUint8_t*)sramAddress , (DxUint8_t*)paramAddress , paramLengthInBytes);
  
  if(bytesArrayFlag)
  {
    DX_GEN_CHANGE_ENDIANNESS(sramAddress , ((paramLengthInBytes + 3) / sizeof(DxUint32_t)) );
  }
  
  /* update the message offset */
  *messageOffset_ptr += maxParamLengthInBytes;

  return DX_OK;
}


/**
 * @brief       This function reads a a parameter from SHARED memory. Paramter can be either a word or an array of words or bytes
 *              If this is an array of bytes, then the bytesArrayFlag should be set, so that the parameter will be converted into little endian (if needed)
 *
 * @param[in] paramAddress - address of the parameter to read
 * @param[in] paramLengthInBytes - parameter length in bytes
 * @param[in] maxParamLengthInBytes - maximum number of bytes that this parameter should take in the message.Must be word alligned
 * @param[in/out] messageOffset_ptr - offset into message before and after insertion
 * @param[in] bytesArrayFlag - if this is byte array that should be converted
 *
 * @return: Error - if the maxParamLengthInBytes is not word alligned  
 */
DxError_t SEPDriver_ReadParamater(DxUint32_t    paramAddress ,
                                  DxUint32_t    paramLengthInBytes,
                                  DxUint32_t    maxParamLengthInBytes,
                                  DxUint32_t*   messageOffset_ptr,
                                  DxUint32_t    bytesArrayFlag)
{
  /* address in the sram */
  DxUint32_t    sramAddress;
  
  /*------------------
    CODE
  -------------------*/
  
  if( (maxParamLengthInBytes < paramLengthInBytes) || (maxParamLengthInBytes % sizeof(DxUint32_t)) )
  {
    return DX_PARAM_NOT_ALLIGNED_ERR;
  }
  
  /* set address to where to insert parameter */
  sramAddress = g_SharedRamAddr + *messageOffset_ptr;
  
  if(bytesArrayFlag)
  {
    DX_GEN_CHANGE_ENDIANNESS(sramAddress , ((paramLengthInBytes + 3) / sizeof(DxUint32_t)) );
  }
  
  /* copy from user data */
  DX_VOS_FastMemCpy((DxUint8_t*)paramAddress , (DxUint8_t*)sramAddress , paramLengthInBytes);
  
  /* update next message offset */
  *messageOffset_ptr += maxParamLengthInBytes;

  return DX_OK;
}



/**
 * @brief       This function locks access to the SEP driver and though it to the SEP
 *
 * @param[in] 
 *
 * @return     DxError_t: 
 *
 */
DxError_t SEPDriver_Lock()
{
  /* error */
  DxError_t   error;

  /*---------------------
      CODE
  -----------------------*/

  error = DX_OK;
	
  /* start transaction */
  error = FVOS_StartTransaction();
  
  if (error == FVOS_SEP_IS_DISABLED_ERR)
  {
  		return DX_MNG_SEP_IS_DISABLE_ERR;
  }
  
  /* Cancelling lint warning - Ignoring return value of function */
  /*lint -save -e{534} */
  error = FVOS_Mmap(&g_SharedRamAddr);
  /*lint -restore */
	
  
  return error;
}

/**
 * @brief       This function unlocks access to the SEP driver and though it to the SEP
 *
 * @param[in] 
 *
 */
void SEPDriver_Unlock(void)
{
  /*------------------------
      CODE
  --------------------------*/

/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_EndTransaction(g_SharedRamAddr);
/*lint -restore */
}

/**
 * @brief       This function waits for response from SEP(either by polling , or by event )
 *
 * @param[in] type - the type of polling - event, polling
 * @param[in] eventId - id of event in case type is EVENT, otherwise 0.
 * @param[in] callbackFunc_ptr - call back function in case the type is polling with callback
 * @return     DxError_t:  
 *                        
 */
DxError_t SEPDriver_WaitForResponse(SEPDriver_PollingType_t type , 
                                    DxUint32_t              eventId,
                                    SEP_CallbackFunc        callbackFunc_ptr,
                                    DxUint32_t              timeOut)
{
  /* source for interrupt */
  DxUint32_t  intSource;  
  
  /* error */
  DxError_t   error;
  /*--------------
    CODE
  ----------------*/
  /* Eliminating compiler warnings: */
  type = type;
  eventId = eventId;
  callbackFunc_ptr = callbackFunc_ptr;
  
  error = DX_OK;
  
  while(1)
  {
    error = FVOS_Poll(timeOut , &intSource);
    
    /* if we failed on timeout - exit with appropriate error code */
    if(error == FVOS_TIMEOUT_ERR)
    {
      goto end_function;
    }
    
    /* if this is reply to the original HOST request  - exit the function with OK status */
    if(intSource == FVOS_SEP_REPLY)
    {
      goto end_function;
    }
    
    if(callbackFunc_ptr == DX_NULL)
    {
      #ifdef DX_NVS_SUPPORT
      /* this is NVS request from SEP - activate the function */
      error = NVSHost_Parser();
      if (error!=DX_OK)
      {
      	goto end_function;
      }
      	
      #endif
    }
    else
    {
      callbackFunc_ptr();
    }
  }
    

end_function:

  return error;
}

/**
 * @brief       This function builds the DMA tables for symmetric CRYS APIs
 *
 * @param[in] dataInAddr - start address of the input data
 * @param[in] dataOutAddr - start address of the input data. If it is 0, then no output tables will be generated
 * @param[in] dataInSize - size of input data in bytes.
 * @param[in] blockSize - virtual allocated address
 * @param[out] firstInTable_ptr - pointer to physical address of the first input table
 * @param[out] firstOutTable_ptr - pointer to physical address of the first output table
 * @param[out] firstInTableNumEntries_ptr - pointer to the number of entries in the first input table
 * @param[out] firstOutTableNumEntries_ptr - pointer to the number of entries in the first output table
 * @param[out] firstTableDataSize_ptr - pointer to the data in the first in table ( the same for input and output)
 * 
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_PrepareSymDMATables(DxUint32_t    dataInAddr,
                                        DxUint32_t    dataOutAddr,
                                        DxUint32_t    dataInSize,
                                        DxUint32_t    blockSize,
                                        DxUint32_t*   firstInTable_ptr,
                                        DxUint32_t*   firstOutTable_ptr,
                                        DxUint32_t*   firstInTableNumEntries_ptr,
                                        DxUint32_t*   firstOutTableNumEntries_ptr,
                                        DxUint32_t*   firstTableDataSize_ptr)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t tableData;
  
  /* error */
  DxError_t         error;
  
  /*---------------
      CODE
  -----------------*/
  
  error = DX_OK;
  
  /* prepare input data */
  tableData.data.buildSymDMATables.dataInAddr = dataInAddr;
  tableData.data.buildSymDMATables.dataInSize = dataInSize;
  tableData.data.buildSymDMATables.dataOutAddr = dataOutAddr;
  tableData.data.buildSymDMATables.blockSize = blockSize;
  
  error = FVOS_Cntrl(FVOS_CNTRL_BUILD_SYM_DMA_TABLES_CMD , &tableData);
  if(error != DX_OK)
  {
    goto end_function;
  }
  
  /* set the output variables */
  *firstInTable_ptr = tableData.data.buildSymDMATables.firstInTableAddr;
  *firstInTableNumEntries_ptr = tableData.data.buildSymDMATables.firstInTableNumEntries;
  
  /* check output table data if needed */
  if(firstOutTable_ptr != DX_NULL)
  {
    *firstOutTable_ptr = tableData.data.buildSymDMATables.firstOutTableAddr;
    *firstOutTableNumEntries_ptr = tableData.data.buildSymDMATables.firstOutTableNumEntries;
  }
  
  *firstTableDataSize_ptr = tableData.data.buildSymDMATables.firstTableDataSize;
  
end_function:

  return error;
}

/**
 * @brief       This function builds flow DMA table from the input buffer
 *
 * @param[in] flowType - static or dynamic
 * @param[in] bufferAddr - address of the input buffer (virtual)
 * @param[in] bufferLen - length of the input buffer
 * @param[in] inputOutputFlag - if the tables being built are for input or output
 * @param[out] firstLLITableAddr_ptr - physical address of the first DMA table
 * @param[out] numEntries_ptr - number of entries in the first DMA table
 * @param[out] tableDataSize_ptr - total data size in the first dma table 
 *
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_PrepareFlowDMATables(DxUint32_t                   flowType,   
                                         SEP_FLOW_BufferData_t*       buffersArray_ptr,
                                         DxUint32_t                   buffersArrayLen,
                                         SEPDriver_BufferDirection_t  inputOutputFlag,
                                         DxUint32_t*                  firstLLITableAddr_ptr,
                                         DxUint32_t*                  numEntries_ptr,
                                         DxUint32_t*                  tableDataSize_ptr)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t tableData;
  
  /* error */
  DxError_t         error;
  
  /*---------------
      CODE
  -----------------*/
  
  error = DX_OK;
  
  /* prepare input data */
  tableData.data.buildFlowDMATables.buffersArrayAddr = (DxUint32_t)buffersArray_ptr;
  tableData.data.buildFlowDMATables.buffersArraySize = buffersArrayLen;
  tableData.data.buildFlowDMATables.flowType = flowType;
  tableData.data.buildFlowDMATables.inputOutputFlag = (FVOS_InputArrayFlag_t)inputOutputFlag;
  
  error = FVOS_Cntrl(FVOS_CNTRL_BUILD_FLOW_DMA_TABLES_CMD , &tableData);
  if(error != DX_OK)
  {
    goto end_function;
  }
  
  /* set the output variables */
  *firstLLITableAddr_ptr = tableData.data.buildFlowDMATables.firstInTableAddr;
  *numEntries_ptr = tableData.data.buildFlowDMATables.firstInTableNumEntries;
  *tableDataSize_ptr = tableData.data.buildFlowDMATables.firstTableDataSize;
  
end_function:

  return error;
}

/**
 * @brief       This function prepares the tables for additional buffers for the flow
 *
 * @param[in] flowId - id of flow to whom this message belongs
 * @param[in] inputOutputFlag - if the prepared table are input or output
 * @param[in] buffersArray_ptr - virtual buffers array
 * @param[in] buffersArraySize - virtual buffers array size
 * @param[out] lliTableAddr_ptr - address of the first table of the added buffers
 * @param[out] numEntriesInTable_ptr - number of entries in the first table
 * @param[out] tableDataSize_ptr - data size in the first table
 *
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_AddFlowBuffers(DxUint32_t             flowId , 
                                   DxUint32_t             inputOutputFlag,
                                   SEP_FLOW_BufferData_t* buffersArray_ptr , 
                                   DxUint32_t             buffersArraySize,
                                   DxUint32_t*            lliTableAddr_ptr,
                                   DxUint32_t*            numEntriesInTable_ptr,
                                   DxUint32_t*            tableDataSize_ptr)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t addTablesData;
  
  /* error */
  DxError_t         error; 
  
  /*-------------------
      CODE
  -----------------------*/
  
  /* prepare paramaters for FVOS */
  addTablesData.data.addTables.buffersArrayAddr = (DxUint32_t)buffersArray_ptr;
  addTablesData.data.addTables.buffersArraySize = buffersArraySize;
  addTablesData.data.addTables.flowId = flowId;
  addTablesData.data.addTables.inputOutputFlag = inputOutputFlag;
  
  error = FVOS_Cntrl(FVOS_CNTRL_ADD_FLOW_DMA_TABLES_CMD , &addTablesData);
  if(error != DX_OK)
  {
    goto end_function;
  }
  
  /* set output params */
  *lliTableAddr_ptr = addTablesData.data.addTables.firstTableAddr;
  *numEntriesInTable_ptr = addTablesData.data.addTables.firstTableNumEntries;
  *tableDataSize_ptr = addTablesData.data.addTables.firstTableDataSize;
  
end_function:

  return error;
}

/**
 * @brief       This function construct the ADD BUFFERS TO FLOW message based on the message data and sends it to FVOs for storage
 *
 * @param[in] flowId - id of flow to whom this message belongs
 * @param[in] messageData_ptr - array of words that contains the data of message  - will be inserted as is into message
 * @param[in] messageSizeInWords - size of messageData_ptr in words
 *
 * @return     DxError_t:  
 *
 */
void SEPDriver_AddBufferMessage(DxUint32_t  flowId,
                                DxUint32_t* messageData_ptr,
                                DxUint32_t  messageSizeInWords)
{
  
  DxUint32_t        message[FVOS_MAX_ADD_MESSAGE_LENGTH_IN_WORDS];
  
  /* input alloc structure */
  FVOS_Cntrl_info_t addTablesMessage;
  
  /*-------------------
      CODE
  -----------------------*/
  
  /* start the message formatting */
  message[0] = SEPDRIVER_START_MESSAGE_TOKEN;
  message[1] = FVOS_MAX_ADD_MESSAGE_LENGTH_IN_WORDS;
  
  /* copy the message body */
  DX_VOS_FastMemCpy((DxUint8_t*)&message[2] , (DxUint8_t*)messageData_ptr , (messageSizeInWords * sizeof(DxUint32_t)) );
  message[FVOS_MAX_ADD_MESSAGE_LENGTH_IN_WORDS - 1] = 0;
  
  /* prepare paramaters for FVOS */
  addTablesMessage.data.addTablesMessage.messageAddress = (DxUint32_t)message;
  addTablesMessage.data.addTablesMessage.messageSizeInWords = FVOS_MAX_ADD_MESSAGE_LENGTH_IN_WORDS;
  addTablesMessage.data.addTablesMessage.flowId = flowId;
  
/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Cntrl(FVOS_CNTRL_ADD_FLOW_TABLE_MSG_CMD , &addTablesMessage);
/*lint -restore */
   
}

/**
 * @brief       This function sets the id for the tables which were created for the new flow, and had no id during creation 
 *
 * @param[in] flowId - flow id to set
 *
 * @return     DxError_t:  
 *
 */
void SEPDriver_SetFlowId(DxUint32_t flowId)
{
  /* input structure */
  FVOS_Cntrl_info_t tableData;
  
  /*-------------------
      CODE
  ---------------------*/
  
  tableData.data.setFlowId.flowId = flowId;
  
/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Cntrl(FVOS_CNTRL_SET_FLOW_ID_IN_TABLES_CMD , &tableData);
/*lint -restore */
  
}

/**
 * @brief       This function frees all SEP tables resources
 *
 * @param[in] flowId - flow id to set
 *
 * @return     DxError_t:  
 * 
 */
void SEPDriver_FreeFlowResources(DxUint32_t flowId)
{
  /* input structure */
  FVOS_Cntrl_info_t tableData;
  
  /*-------------------
      CODE
  ---------------------*/
  
  tableData.data.setFlowId.flowId = flowId;
  
/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Cntrl(FVOS_CNTRL_FREE_FLOW_RESOURSES , &tableData);
/*lint -restore */
  
}


/**
 * @brief       This function performs the needed clenup after the DMA action is finished.Depending on the enviroment
 *              it frees any dynamically allocted resources
 *
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_FreeDMATables(void)
{
  return FVOS_Cntrl(FVOS_CNTRL_FREE_DMA_RESOURSES , DX_NULL);
}

/**
 * @brief       This allocates a memory from the data pool according to the rquired length.
 *              It returns the virtual address and the physical address of the allocated memory
 *              The virtual address can be used later for reading or writing from the allocated memory
 *              the physical address is used for passing as argument to SEP
 *
 * @param[in] userDataInOut_ptr - user pointer to the data to be later written or read into
 * @param[in] sizeInBytes - size in bytes to allocated
 * @param[in] physAddr_ptr - physical allocated address.
 * @param[in] virtAddr_ptr - virtual allocated address
 * 
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_AllocateDataPoolMemory(DxUint8_t*       userDataInOut_ptr,
                                           DxUint32_t       sizeInBytes, 
                                           DxUint32_t*      physAddr_ptr,
                                           DxUint32_t*      virtAddr_ptr)
{
  /* error */
  FVOS_Error_t      error;
  
  /* input alloc structure */
  FVOS_Cntrl_info_t allocInfo;
  
  /*---------------
      CODE
  -----------------*/
  
  /* prepare input data */
  allocInfo.data.allocCmdData.allocSize = sizeInBytes;
  allocInfo.data.allocCmdData.appAddr = (DxUint32_t)userDataInOut_ptr;
  
  error = FVOS_Cntrl(FVOS_CNTRL_ALLOC_MEM_CMD , &allocInfo);
  if(error != FVOS_OK)
  {
    return error;
  }

  /* set output paramaters */
  *physAddr_ptr = allocInfo.data.allocCmdData.physAddr;
  *virtAddr_ptr = allocInfo.data.allocCmdData.virtAddr;
  
  return error;
}
                                           
/**
 * @brief       This functions writes data into the pre-allocated memory in the data pool. The address
 *              to write is defined by the virtAddr_ptr, and must be recieved previously from the SEPDriver_AllocateDataPoolMemory
 *              function
 *
 * @param[in] virtAddr_ptr - address in the data pool to write into
 * @param[in] dataIn_ptr - data to write.
 * @param[in] dataInSize - length in bytes of data to write
 * 
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_WriteToDataPoolMemory(DxUint32_t  virtAddr_ptr, 
                                          DxUint8_t*  dataIn_ptr,
                                          DxUint32_t  dataInSize)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t writeInfo;
  
  /*---------------
      CODE
  -----------------*/
  
  /* prepare input data */
  writeInfo.data.writeCmdData.srcAppAddr = (DxUint32_t)dataIn_ptr;
  writeInfo.data.writeCmdData.destFvosAddr = virtAddr_ptr;
  writeInfo.data.writeCmdData.dataSize = dataInSize;

  
  return FVOS_Cntrl(FVOS_CNTRL_WRITE_DATA_CMD , &writeInfo);
}
                                          
/**
 * @brief       This functions reads data from the pre-allocated memory in the data pool. The address
 *              to be read is defined by the virtAddr_ptr, and must be recieved previously from the SEPDriver_AllocateDataPoolMemory
 *              function
 *
 * @param[in] virtAddr_ptr - address in the data pool to read from
 * @param[in] dataIn_ptr - memory to read into.
 * @param[in] dataInSize - length in bytes of data to read
 * 
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_ReadFromDataPoolMemory(DxUint32_t  virtAddr_ptr, 
                                           DxUint8_t*  dataOut_ptr,
                                           DxUint32_t  dataOutSize)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t readInfo;
  
  /*---------------
      CODE
  -----------------*/
  
  /* prepare input data */
  readInfo.data.readCmdData.srcFvosAddr = virtAddr_ptr;
  readInfo.data.readCmdData.destAppAddr = (DxUint32_t)dataOut_ptr;
  readInfo.data.readCmdData.dataSize = dataOutSize;

  
  return FVOS_Cntrl(FVOS_CNTRL_READ_DATA_CMD , &readInfo);
}


/**
 * @brief       This function returns the memory address of the static pool. This pool is allocated during init of the Host
 *              and currently will be used by SEP and NVS for SST purposes
 *
 * @param[out] physMemoryAddr_ptr - physical address of the static pool
 * @param[out] fvosMemoryAddr_ptr - FVOS (virtual kernel) address of the static pool
 * 
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_GetStaticMemoryAddr(DxUint32_t* physMemoryAddr_ptr,
                                        DxUint32_t* fvosMemoryAddr_ptr)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t staticInfo;
  
  /*-------------------------
      CODE
  ----------------------------*/

/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */  
  FVOS_Cntrl(FVOS_CNTRL_GET_STATIC_POOL_ADDR , &staticInfo);
/*lint -restore */
    
  *physMemoryAddr_ptr = staticInfo.data.staticPoolInfo.physAddr;
  *fvosMemoryAddr_ptr = staticInfo.data.staticPoolInfo.fvosAddr;
  
  return DX_OK;
}

/**
 * @brief       This function returns virtual address that is mapped to the input physical address. Physical address must be in the address range of the static pool
 *
 * @param[in] physAddr - physical address in the static pool
 * @param[out] virtAddr_ptr - virtual address of the static pool
 * 
 * @return     DxError_t:  
 *
 */
DxError_t SEPDriver_StaticPhysAddrToVirt(DxUint32_t   physAddr,
                                         DxUint32_t*  virtAddr_ptr)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t staticInfo;
  
  /*-------------------------
      CODE
  ----------------------------*/

  /* prepare input data */
  staticInfo.data.convStatPhysToVirt.physAddr = physAddr;

/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */  
  FVOS_Cntrl(FVOS_CNTRL_CONV_STATIC_PHYS_TO_VIRT , &staticInfo);
/*lint -restore */
    
  *virtAddr_ptr = staticInfo.data.convStatPhysToVirt.virtAddr;
  
  return DX_OK;
  
}

/*
*   @brief This function set blocking mode of the access to SEP. If blocking  - then wait until semaphore is released,
*          if non-blocking - exit with appropriate error if the sempahore is currently taken
*          
*
*   @param[in] blockingMode - 1 - blocking mode, 0 - non-blocking mode. 
*
*   Returns:  Status of the operation.
*/
DxError_t SEPDriver_SetAPIBlockingMode(DxUint32_t blockingMode)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t setModeCmd;
  
  /*-------------------------
      CODE
  ----------------------------*/
  setModeCmd.data.setAPIMode.blockingMode = blockingMode;
/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Cntrl(FVOS_CNTRL_SEP_API_MODE , &setModeCmd);
/*lint -restore */
  
  return DX_OK; 
}



/*
*   @brief This function returns physical address where the RT time value is stored
*
*   @param[out] timeAddress_ptr - address where the RT time value is stored
*   @param[out] timeValue_ptr - RT time value stored
*
*   Returns:  Status of the operation.
*/
DxError_t SEPDriver_GetTime(DxUint32_t* timeAddress_ptr, DxUint32_t* timeValue_ptr)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t getTimeCmd;
  
  /*-------------------------
      CODE
  ----------------------------*/
  
  /* Cancelling lint warning - Ignoring return value of function */
  /*lint -save -e{534} */
  FVOS_Cntrl(FVOS_CNTRL_GET_TIME , &getTimeCmd);
  /*lint -restore */
  
  if(timeAddress_ptr != DX_NULL)
  {
  	*timeAddress_ptr = getTimeCmd.data.getTime.timeAddress;  	
  }
  
  if(timeValue_ptr != DX_NULL)
  {
  	*timeValue_ptr = getTimeCmd.data.getTime.timeValue;  	
  }
  
  return DX_OK; 
}


/**
 * @brief       This function calculates the check sum on the given data 
 *
 * @param[in] data- data to perfrom checksum on
 * @param[in] length - length of data
 *
 * @return  DxUint32_t  - Checksum 
 *                        
 */
DxUint32_t SEPDriver_CheckSumCalc(DxUint8_t *data, DxUint32_t length)
{
  DxUint32_t sum = 0;
	DxUint16_t *Tdata = (DxUint16_t *)data;

	while( length > 1 )  
	{
    /*  This is the inner loop */
    sum += *Tdata++;
    length -= 2;
  }
  /*  Add left-over byte, if any */
  if( length > 0 )
    sum += * (DxUint8_t *) Tdata;

  /*  Fold 32-bit sum to 16 bits */
  while (sum>>16)
    sum = (sum & 0xffff) + (sum >> 16);

	return (~sum &0xFFFF);
}


/**
 * @brief       This function reads value of giver register 
 *
 * @param[in] regVirtAddr - register address
 * @param[out] regData_ptr - buffer for the register data
 *
 * @return  DX_OK 
 *                        
 */
DxError_t SEPDriver_ReadRegister(DxUint32_t    regVirtAddr, DxUint32_t* regData_ptr)
{
  /* input alloc structure */
  FVOS_Cntrl_info_t regDataInfo;

  regDataInfo.data.regDataOp.regVirtAddr = regVirtAddr;
  regDataInfo.data.regDataOp.regData = 0x0;
/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Cntrl(FVOS_READ_PHYS_REGISTER , &regDataInfo);
/*lint -restore */
	
  if(regData_ptr != DX_NULL)
  {
  	*regData_ptr = regDataInfo.data.regDataOp.regData;	
  }
	
  return DX_OK; 
}


/**
 * @brief       This function writes a value to a specific register 
 *
 * @param[in] regVirtAddr - register address.
 * @param[out] regData - data to be written.
 *
 * @return  DX_OK 
 *                        
 */
DxError_t SEPDriver_WriteRegister(DxUint32_t    regVirtAddr, DxUint32_t regData)
{
  FVOS_Cntrl_info_t regDataInfo;
	
  regDataInfo.data.regDataOp.regVirtAddr = regVirtAddr;
  regDataInfo.data.regDataOp.regData = regData;
/* Cancelling lint warning - Ignoring return value of function */
/*lint -save -e{534} */
  FVOS_Cntrl(FVOS_WRITE_PHYS_REGISTER , &regDataInfo);
/*lint -restore */
	
  return DX_OK; 
}

/**
 * @brief       This function rellocates the cache and resident and returns new physical addresses for cache, resident and shared area 
 *
 * @param[in] baseAddr - current base address (virtual)
 * @param[in] cacheAddr - current cache address (virtual)
 * @param[in] cacheSizeInBytes - size of cache in bytes
 * @param[in] residentAddr - current resident address (virtual)
 * @param[in] residentSizeInBytes - size of resident in bytes
 * @param[in] dcacheAddr - current dcache address (virtual)
 * @param[in] dcacheSizeInBytes - dcache size in bytes
 * @param[out] newCacheAddr_ptr - pointer where new cache address (physical) will be returned
 * @param[out] newResidentAddr_ptr - pointer where new resident address (physical) will be returned
 * @param[out] newDCacheAddr_ptr - pointer where new dcache address (physical) will be returned
 * @param[out] newSharedAreaAddr_ptr - pointer where new shared area address (physical) will be returned
 * @param[out] newBaseAddr_ptr - pointer where new base address (physical) will be returned
 *
 * @return  DX_OK 
 *                        
 */
DxError_t SEPDRiver_ReallocCacheResident(DxUint32_t   baseAddr,
                                         DxUint32_t   cacheAddr,
                                         DxUint32_t   cacheSizeInBytes,
                                         DxUint32_t   residentAddr,
                                         DxUint32_t   residentSizeInBytes,
                                         DxUint32_t   extCacheAddr,
                                         DxUint32_t   extCacheSizeInBytes,                                         
                                         DxUint32_t   dcacheAddr,
                                         DxUint32_t   dcacheSizeInBytes,
                                         DxUint32_t*  newCacheAddr_ptr,
                                         DxUint32_t*  newResidentAddr_ptr,
                                         DxUint32_t*  newDCacheAddr_ptr,
                                         DxUint32_t*  newSharedAreaAddr_ptr,
                                         DxUint32_t*  newBaseAddr_ptr)
{
  /* error */
  DxError_t         error;
  
  /* control data */
  FVOS_Cntrl_info_t controlData;
  
  /*---------------------------
      CODE
  -------------------------------*/
  
  /* realloc the cache and resident if needed */
  controlData.data.reallocCachResident.baseAddr = baseAddr;
  controlData.data.reallocCachResident.cacheAddr = cacheAddr;
  controlData.data.reallocCachResident.cacheSize = cacheSizeInBytes;
  controlData.data.reallocCachResident.residentAddr = residentAddr;
  controlData.data.reallocCachResident.residentSize = residentSizeInBytes;
  controlData.data.reallocCachResident.dcacheAddr = dcacheAddr;
  controlData.data.reallocCachResident.extCacheAddr = extCacheAddr;
  controlData.data.reallocCachResident.extCacheSize = extCacheSizeInBytes;
  controlData.data.reallocCachResident.dcacheSize = dcacheSizeInBytes;
  
  error = FVOS_Cntrl(FVOS_REALLOC_CACHE_RESIDENT , &controlData);
  if(error == DX_OK)
  {
    *newCacheAddr_ptr = controlData.data.reallocCachResident.newCacheAddr;
    *newResidentAddr_ptr = controlData.data.reallocCachResident.newResidentAddr;
    *newSharedAreaAddr_ptr = controlData.data.reallocCachResident.newSharedAreaAddr;
    *newBaseAddr_ptr = controlData.data.reallocCachResident.newBaseAddr;
    *newDCacheAddr_ptr = controlData.data.reallocCachResident.newDCacheAddr;
  }
  
  return error;
}


/**
 * @brief       This function rellocates the external cache and returns its new physical addresses 
 *
 * @param[in] cacheAddr - current cache address (virtual)
 * @param[in] cacheSizeInBytes - size of cache in bytes
 * @param[out] newCacheAddr_ptr - pointer where new cache address (physical) will be returned
 *
 * @return  DX_OK 
 *                        
 */
DxError_t SEPDRiver_ReallocExtCache( DxUint32_t   cacheAddr,
                                     DxUint32_t   cacheSizeInBytes,
                                     DxUint32_t*  newCacheAddr_ptr )
{
  /* error */
  DxError_t         error;
  
  /* control data */
  FVOS_Cntrl_info_t controlData;
  
  /*---------------------------
      CODE
  -------------------------------*/
  
  /* realloc the cache and resident if needed */
  controlData.data.reallocExtCache.cacheAddr = cacheAddr;
  controlData.data.reallocExtCache.cacheSize = cacheSizeInBytes;
  
  error = FVOS_Cntrl(FVOS_REALLOC_EXT_CACHE_RESIDENT , &controlData);
  if(error == DX_OK)
  {
    *newCacheAddr_ptr = controlData.data.reallocExtCache.newCacheAddr;
  }
  
  return error;
}



/**
 * @brief       This function sends the already constructed init message to SEP and returns the result
 *
 * @param[in] messageAddr - address of message to send
 * @param[in] messageSizeInWords - message size in words
 *
 * @return  DX_OK 
 *                        
 */
DxError_t SEPDRiver_SendInitMessage(DxUint32_t   messageAddr,
                                    DxUint32_t   messageSizeInWords,
                                    DxUint32_t   SepSramAddr)
{
  /* control data */
  FVOS_Cntrl_info_t controlData;
  
  /*-----------------------------
      CODE
  -------------------------------*/
  
  controlData.data.sepInit.messageAddr = messageAddr;
  controlData.data.sepInit.messageSizeInWords = messageSizeInWords;
  controlData.data.sepInit.SepSramAddr = SepSramAddr;
  
  /* send the message to SEP */
  return FVOS_Cntrl(FVOS_CNTRL_SEP_INIT , &controlData); 
}


/**
 * @brief   This function sets the Token and the given op-code into the target message
 *
 * @param[in/out] messageOffset_ptr - offset into message before and after insertion
 * @param[in] opCode - the op-code to insert
 *
 * @return  DX_OK -in case of success
 *                        
 */
DxError_t SEPDriver_BuildMsgHeader(DxUint32_t* messageOffset_ptr, DxUint32 opCode)
{

  /* error */
  DxError_t  error = DX_OK;
  /* paramater address */
  DxUint32_t  *sramAddress = DX_NULL;

  if (messageOffset_ptr == DX_NULL)
  {
    error = DX_INVALID_PARAMETERS_ERR;
  	goto end_function;
  }

  /*------------------
    CODE
  -------------------*/
  
  /* lock access to the SEP */
  error = SEPDriver_Lock();
   
  if(error != DX_OK)
  {
    goto end_function;
  }
  
  /* ordinary start message */
  SEPDriver_StartMessage(messageOffset_ptr);

  /* set address to where to insert parameter */
  sramAddress = (DxUint32_t *)((DxUint8_t *)g_SharedRamAddr + *messageOffset_ptr);
  
  /* write op-code into message */
  *sramAddress = opCode; 
  
  /* set the next parameter offset */
  *messageOffset_ptr += sizeof(DxUint32_t);
  
end_function:
  
  return error;

}


/**
 * @brief   This function checks the Token and the given op-code against the target message
 *			received from the SeP.
 *
 * @param[in/out] messageOffset_ptr - offset into message before and after insertion
 * @param[in] opCode - the op-code to check
 *
 * @return  DX_OK -in case of success
 *                        
 */
DxError_t SEPDriver_CheckStatus(DxUint32_t* messageOffset_ptr, 
								DxUint32 opCode)
{
  /* error */
  DxError_t  error = DX_OK;
  /* local pointer for reading op-code + status */
  DxUint32_t message_ptr[2] = {0};
  
  if (messageOffset_ptr == DX_NULL)
  {
    error = DX_INVALID_PARAMETERS_ERR;
  	goto end_function;
  }
  
  /*------------------
     CODE
  ------------------*/
  
  /* ordinary start incoming message */
  error  = SEPDriver_StartIncomingMessage(messageOffset_ptr);
  if (error != DX_OK) 
  {
  	goto end_function;
  }
  	
  /* read opcode + status  */
  error = SEPDriver_ReadParamater((DxUint32_t)message_ptr,
                            sizeof(DxUint32_t) * 2,
                            sizeof(DxUint32_t) * 2,
                            messageOffset_ptr,
                            DX_FALSE);
                            
  if (error != DX_OK) 
  {
  	goto end_function;
  }

  /* check the opcode */
  if(message_ptr[0] != opCode)
  {
    error = DX_WRONG_OPCODE_FROM_SEP_ERR;
    goto end_function;
  }
   
  /* check status */
  if(message_ptr[1] != DX_OK)
  {
    error = message_ptr[1];
    goto end_function;
  }
                            
  	
end_function:
  
  return error;
  	
}

/*
  This function sets the caller id data into the caller id table according to the pid of the process
*/
DxError_t SEPDriver_SetCallerIdData(DxUint32_t  pid , 
                                    DxUint8_t*  callerId_ptr ,
                                    DxUint32_t  callerIdSizeInBytes)
{
  /* input structure */
  FVOS_Cntrl_info_t callerIdData;
  
  /*-------------------
      CODE
  ---------------------*/
  
  callerIdData.data.setCallerId.pid = pid;
  callerIdData.data.setCallerId.callerIdAddress = (DxUint32_t)callerId_ptr;
  callerIdData.data.setCallerId.callerIdSizeInBytes = callerIdSizeInBytes;
  
  /* Cancelling lint warning - Ignoring return value of function */
  /*lint -save -e{534} */
  return FVOS_Cntrl(FVOS_SET_CALLER_ID , &callerIdData); 
}

