/*====================================================================================================================*/
/* Project      = AUTOSAR Renesas X2x MCAL Components                                                                 */
/* Module       = Eth_ETNDE_LLDriver.c                                                                                */
/* SW-VERSION   = 1.5.4                                                                                               */
/*====================================================================================================================*/
/*                                                     COPYRIGHT                                                      */
/*====================================================================================================================*/
/* (c) 2021,2022 Renesas Electronics Corporation. All rights reserved.                                                */
/*====================================================================================================================*/
/* Purpose:                                                                                                           */
/* This file contains ETNDE specific operations of Eth Driver Component.                                              */
/*                                                                                                                    */
/*====================================================================================================================*/
/*                                                                                                                    */
/* Unless otherwise agreed upon in writing between your company and Renesas Electronics Corporation the following     */
/* shall apply!                                                                                                       */
/*                                                                                                                    */
/* Warranty Disclaimer                                                                                                */
/*                                                                                                                    */
/* There is no warranty of any kind whatsoever granted by Renesas. Any warranty is expressly disclaimed and excluded  */
/* by Renesas, either expressed or implied, including but not limited to those for non-infringement of intellectual   */
/* property, merchantability and/or fitness for the particular purpose.                                               */
/*                                                                                                                    */
/* Renesas shall not have any obligation to maintain, service or provide bug fixes for the supplied Product(s) and/or */
/* the Application.                                                                                                   */
/*                                                                                                                    */
/* Each User is solely responsible for determining the appropriateness of using the Product(s) and assumes all risks  */
/* associated with its exercise of rights under this Agreement, including, but not limited to the risks and costs of  */
/* program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and             */
/* unavailability or interruption of operations.                                                                      */
/*                                                                                                                    */
/* Limitation of Liability                                                                                            */
/*                                                                                                                    */
/* In no event shall Renesas be liable to the User for any incidental, consequential, indirect, or punitive damage    */
/* (including but not limited to lost profits) regardless of whether such liability is based on breach of contract,   */
/* tort, strict liability, breach of warranties, failure of essential purpose or otherwise and even if advised of the */
/* possibility of such damages. Renesas shall not be liable for any services or products provided by third party      */
/* vendors, developers or consultants identified or referred to the User by Renesas in connection with the Product(s) */
/* and/or the Application.                                                                                            */
/*                                                                                                                    */
/*====================================================================================================================*/
/* Environment:                                                                                                       */
/*              Devices:        X2x                                                                                   */
/*====================================================================================================================*/

/***********************************************************************************************************************
**                                              Revision Control History                                              **
***********************************************************************************************************************/
/*
 * 1.5.4: 03/08/2022    : Change the setting of the maximum size of received frames from each queue to each MAC
 * 1.5.3: 11/04/2022    : Update QA-C comments
 * 1.5.0: 07/10/2021    : Initial Version
 */
/**********************************************************************************************************************/

/***********************************************************************************************************************
**                                                  Include Section                                                   **
***********************************************************************************************************************/
#include "Eth.h"
#include "Eth_ETNDE_Ram.h"
#include "Eth_ETNDE_LLDriver.h"
#if (ETH_USING_MACRO == ETH_MACRO_ETND)
#include "Eth_ETND_LLDriver.h"
#else
#include "Eth_ETNE_LLDriver.h"
#endif

#include "EthIf_Cbk.h"

#if (ETH_CRITICAL_SECTION_PROTECTION == STD_ON)
/* Included for the declaration of the critical section protection functions */
#include "SchM_Eth.h"
#endif
#if (ETH_ETHSWITCH_MANAGEMENT_SUPPORT == STD_ON)
#include "EthSwt_Cbk.h"
#endif

/***********************************************************************************************************************
**                                                Version Information                                                 **
***********************************************************************************************************************/
/* AUTOSAR release version information */
#define ETH_ETNDE_C_AR_RELEASE_MAJOR_VERSION ETH_AR_RELEASE_MAJOR_VERSION_VALUE
#define ETH_ETNDE_C_AR_RELEASE_MINOR_VERSION ETH_AR_RELEASE_MINOR_VERSION_VALUE
#define ETH_ETNDE_C_AR_RELEASE_REVISION_VERSION ETH_AR_RELEASE_REVISION_VERSION_VALUE

/* File version information */
#define ETH_ETNDE_C_SW_MAJOR_VERSION    ETH_SW_MAJOR_VERSION_VALUE
#define ETH_ETNDE_C_SW_MINOR_VERSION    ETH_SW_MINOR_VERSION_VALUE

/***********************************************************************************************************************
**                                                   Version Check                                                    **
***********************************************************************************************************************/
#if (ETH_ETNDE_AR_RELEASE_MAJOR_VERSION != ETH_ETNDE_C_AR_RELEASE_MAJOR_VERSION)
#error "Eth_ETNDE_LLDriver.c : Mismatch in Release Major Version"
#endif
#if (ETH_ETNDE_AR_RELEASE_MINOR_VERSION != ETH_ETNDE_C_AR_RELEASE_MINOR_VERSION)
#error "Eth_ETNDE_LLDriver.c : Mismatch in Release Minor Version"
#endif
#if (ETH_ETNDE_AR_RELEASE_REVISION_VERSION != ETH_ETNDE_C_AR_RELEASE_REVISION_VERSION)
#error "Eth_ETNDE_LLDriver.c : Mismatch in Release Revision Version"
#endif

#if (ETH_ETNDE_SW_MAJOR_VERSION != ETH_ETNDE_C_SW_MAJOR_VERSION)
#error "Eth_ETNDE_LLDriver.c : Mismatch in Software Major Version"
#endif
#if (ETH_ETNDE_SW_MINOR_VERSION != ETH_ETNDE_C_SW_MINOR_VERSION)
#error "Eth_ETNDE_LLDriver.c : Mismatch in Software Minor Version"
#endif

/***********************************************************************************************************************
**                                               Coding Rule Violations                                               **
***********************************************************************************************************************/
/* Message (1:1532)    : The function '%1s' is only referenced in one translation unit - but not the one in which it  */
/*                       is defined.                                                                                  */
/* Rule                : CERTCCM DCL19, MISRA C:2012 Rule-8.7                                                         */
/* JV-01 Justification : This is accepted, due to the specific coding rule, function of each hardware unit is         */
/*                       implemented in separated files for this hardware unit. Could not be static function.         */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:3432)    : Simple macro argument expression is not parenthesized.                                       */
/* Rule                : MISRA C:2012 Rule-20.7                                                                       */
/* JV-01 Justification : Compiler keyword (macro) is defined and used followed AUTOSAR standard rule. It is accepted. */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:0316)    : Cast from a pointer to void to a pointer to object type.                                     */
/* Rule                : MISRA C:2012 Rule-11.5                                                                       */
/* JV-01 Justification : Typecasting from void* is necessary to hide internal types from the header files which are   */
/*                       exposed to user.                                                                             */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:2844)    : Possible: Dereference of an invalid pointer value.                                           */
/* Rule                : CERTCCM ARR30                                                                                */
/* JV-01 Justification : To prevent overhead and excessive nesting of condition statements, this pointer has been     */
/*                       tested valid with many test cases, so there is no problem with the current implementation.   */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:2824)    : Possible: Arithmetic operation on NULL pointer.                                              */
/* Rule                : CERTCCM EXP34                                                                                */
/* JV-01 Justification : To prevent overhead and excessive nesting of condition statements, this pointer has been     */
/*                       tested valid with many test cases, so there is no problem with the current implementation.   */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:2814)    : Possible: Dereference of NULL pointer.                                                       */
/* Rule                : CERTCCM EXP34                                                                                */
/* JV-01 Justification : To prevent overhead and excessive nesting of condition statements, this pointer has been     */
/*                       tested valid with many test cases, so there is no problem with the current implementation.   */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:0306)    : Cast between a pointer to object and an integral type.                                       */
/* Rule                : CERTCCM INT36, MISRA C:2012 Rule-11.4                                                        */
/* JV-01 Justification : Typecasting is done as per the register size or hardware specific structure.                 */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:0759)    : An object of union type has been defined.                                                    */
/* Rule                : MISRA C:2012 Rule-19.2                                                                       */
/* JV-01 Justification : Data access of larger data types is used to achieve better throughput.                       */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (1:3383)    : Cannot identify wraparound guard for unsigned arithmetic expression.                         */
/* Rule                : CERTCCM INT30                                                                                */
/* JV-01 Justification : Wraparound can't be occur in this unsigned integer arithmetic so there is no need to add a   */
/*                       wraparound guard here.                                                                       */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (1:1503)    : The function '%1s' is defined but is not used within this project.                           */
/* Rule                : CERTCCM MSC07, MISRA C:2012 Rule-2.1                                                         */
/* JV-01 Justification : This is accepted, due to the module's API is exported for user's usage.                      */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:3469)    : This usage of a function-like macro looks like it could be replaced by an equivalent         */
/*                       function call.                                                                               */
/* Rule                : MISRA C:2012 Dir-4.9                                                                         */
/* JV-01 Justification : To prevent overhead and speed up the processing, there is no need to call a function here    */
/*                       for such a small operation.                                                                  */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (1:3384)    : Cannot identify wraparound guard for dependent unsigned arithmetic expression.               */
/* Rule                : CERTCCM INT30                                                                                */
/* JV-01 Justification : Wraparound can't be occur in this unsigned integer arithmetic so there is no need to add a   */
/*                       wraparound guard here.                                                                       */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (6:2877)    : This loop will never be executed more than once.                                             */
/* Rule                : CERTCCM MSC07, MISRA C:2012 Dir-4.1                                                          */
/* JV-01 Justification : This loop will only be executed at least once, depends on user configuration.                */
/*       Verification  : This is Hardware Specification, X2x only provides 1 Unit. So it is not having any impact.    */
/**********************************************************************************************************************/
/* Message (3:3206)    : The parameter '%s' is not used in this function.                                             */
/* Rule                : CERTCCM MSC07, MSC13, MISRA C:2012 Rule-2.7                                                  */
/* JV-01 Justification : This is done as per implementation requirement                                               */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:3678)    : The object referenced by '%1s' is not modified through it, so '%1s' could be declared with   */
/*                       type '%2s'.                                                                                  */
/* Rule                : MISRA C:2012 Rule-8.13                                                                       */
/* JV-01 Justification : The object addressed by this pointer change so it can not be of type "pointer to const"      */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:2934)    : Possible: Computing an invalid pointer value.                                                */
/* Rule                : CERTCCM ARR30, ARR37, ARR38, EXP08                                                           */
/* JV-01 Justification : To prevent overhead and excessive nesting of condition statements, this pointer has been     */
/*                       tested valid with many test cases, so there is no problem with the current implementation.   */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (6:3305)    : Pointer cast to stricter alignment.                                                          */
/* Rule                : CERTCCM EXP36, EXP39, MISRA C:2012 Rule-11.3                                                 */
/* JV-01 Justification : It is an implementation required to manage heap memory. There is no problem because the      */
/*                       4-byte alignment boundary is guaranteed by the implementation of the heap memory operation   */
/*                       algorithm.                                                                                   */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:0310)    : Casting to different object pointer type.                                                    */
/* Rule                : CERTCCM EXP11, EXP39, MISRA C:2012 Rule-11.3                                                 */
/* JV-01 Justification : There is no problem because it is as designed.                                               */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:0488)    : Performing pointer arithmetic.                                                               */
/* Rule                : CERTCCM EXP08, MISRA C:2012 Rule-18.4                                                        */
/* JV-01 Justification : This implementation is required for heap memory allocation algorithm                         */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (1:1505)    : The function '%1s' is only referenced in the translation unit where it is defined.           */
/* Rule                : CERTCCM DCL19, MISRA C:2012 Rule-8.7                                                         */
/* JV-01 Justification : This is accepted, due to following coding rule, internal function can be defined in other C  */
/*                       source files                                                                                 */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (2:0771)    : More than one 'break' statement has been used to terminate this iteration statement.         */
/* Rule                : MISRA C:2012 Rule-15.4                                                                       */
/* JV-01 Justification : There is no problem with this implementation, and the correct behavior of the ETH Driver is  */
/*                       confirmed. However, this implementation will be improved in the next ECODE update.           */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (4:5087)    : Use of #include directive after code fragment.                                               */
/* Rule                : MISRA C:2012 Rule-20.1                                                                       */
/* JV-01 Justification : This is done as per Memory Requirement, (MEMMAP003 - Specification of Memory Mapping).       */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/
/* Message (4:4322)    : An expression of 'essentially enum' type (ETag_Eth_RxExtStatusType) is being cast to a       */
/*                       different enum type, 'ETag_Eth_RxStatusType'.                                                */
/* Rule                : MISRA C:2012 Rule-10.5                                                                       */
/* JV-01 Justification : It is confirmed that no data loss occurs during the type casting process, so it is accepted. */
/*       Verification  : However, part of the code is verified manually and it is not having any impact.              */
/**********************************************************************************************************************/

/***********************************************************************************************************************
**                                                    Global Data                                                     **
***********************************************************************************************************************/

/***********************************************************************************************************************
**                                                Function Definitions                                                **
***********************************************************************************************************************/
#define ETH_START_SEC_PRIVATE_CODE
#include "Eth_MemMap.h"

STATIC FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_RxDescLearning(
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs,
  CONST(uint32, AUTOMATIC) LulEntryNum,
  CONST(uint32, AUTOMATIC) LulChainAddr);

#if (ETH_GLOBAL_TIME_SUPPORT == STD_ON)
STATIC FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_TasAdminLearning(
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONST(uint32, AUTOMATIC) LulCtrlAddress,
  CONSTP2CONST(Eth_TASEntryType, AUTOMATIC, ETH_APPL_DATA) LpCtrlConfig);
#endif

STATIC FUNC(void, ETH_PRIVATE_CODE) Eth_RxCallEthIf(
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONSTP2CONST(Eth_RxFrameType, AUTOMATIC, ETH_APPL_DATA) LpFrame);

#if (ETH_UPDATE_PHYS_ADDR_FILTER == STD_ON)
STATIC FUNC(boolean, ETH_PRIVATE_CODE) Eth_IsRxFrameValid(
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONSTP2CONST(Eth_RxFrameType, AUTOMATIC, ETH_APPL_DATA) LpRxFrame);
#endif

STATIC FUNC(void, ETH_PRIVATE_CODE) Eth_WaitNanoSec(CONST(uint32, AUTOMATIC) LulNanosec);

/***********************************************************************************************************************
** Function Name         : Eth_HwDisableController (ETNDE)
**
** Service ID            : N/A
**
** Description           : Changes the state of an ETNDE controller as DOWN
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : E_OK : Success
**                         E_NOT_OK : Failure
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpCtrlConfigPtr, Eth_GaaTxBufferTotal,
**                         Eth_GaaTxBufferMgrTable, Eth_GaaCtrlStat,
**                         Eth_GstETND_Regs
**
** Function(s) invoked   : Eth_ETHA_ModeSetting, Eth_ReleaseTxBuffer,
**                         Eth_MHD_ModeSetting
**
** Registers Used        : TCC
**
** Reference ID          : ETH_DUD_ACT_309
** Reference ID          : ETH_DUD_ACT_309_GBL001, ETH_DUD_ACT_309_GBL002, ETH_DUD_ACT_309_GBL003
** Reference ID          : ETH_DUD_ACT_309_GBL004, ETH_DUD_ACT_309_GBL005, ETH_DUD_ACT_309_GBL006
** Reference ID          : ETH_DUD_ACT_309_GBL007, ETH_DUD_ACT_309_GBL008, ETH_DUD_ACT_309_GBL009
** Reference ID          : ETH_DUD_ACT_309_GBL010, ETH_DUD_ACT_309_GBL011, ETH_DUD_ACT_309_GBL012
** Reference ID          : ETH_DUD_ACT_309_GBL013, ETH_DUD_ACT_309_GBL014, ETH_DUD_ACT_309_GBL015
** Reference ID          : ETH_DUD_ACT_309_GBL016, ETH_DUD_ACT_309_GBL017, ETH_DUD_ACT_309_GBL018
** Reference ID          : ETH_DUD_ACT_309_GBL019, ETH_DUD_ACT_309_GBL020, ETH_DUD_ACT_309_GBL021
** Reference ID          : ETH_DUD_ACT_309_GBL022, ETH_DUD_ACT_309_GBL023, ETH_DUD_ACT_309_GBL024
** Reference ID          : ETH_DUD_ACT_309_GBL025
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_HwDisableController(                                                         /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx)
{
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  P2VAR(Eth_ExtDescType, AUTOMATIC, ETH_APPL_DATA) LpTxDescChain;                                                       /* PRQA S 3432 # JV-01 */
  P2VAR(Eth_ExtDescWithTsType, AUTOMATIC, ETH_APPL_DATA) LpRxDescChain;                                                 /* PRQA S 3432 # JV-01 */
  uint32 LulCntI;
  uint32 LulCntJ;
  Std_ReturnType LucResult;

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */

  /* Set to CONFIG mode to enable MDIO communication.  */
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  LucResult = Eth_MHD_ModeSetting(LulCtrlIdx, ETH_ETND_MHD_DISABLE_MODE);
  LucResult |= Eth_MHD_ModeSetting(LulCtrlIdx, ETH_ETND_MHD_CONFIG_MODE);
  #else
  LucResult = Eth_ETHA_ModeSetting(LulCtrlIdx, ETH_ETNE_ETHA_DISABLE_MODE);
  LucResult |= Eth_ETHA_ModeSetting(LulCtrlIdx, ETH_ETNE_ETHA_CONFIG_MODE);
  #endif

  #if (ETH_GLOBAL_TIME_SUPPORT == STD_ON)
  /* TAS algorithm stop */
  if (ETH_ENABLE == LpHwUnitConfig->stTASConfig.enTasEnable)                                                            /* PRQA S 2814 # JV-01 */
  {
    #if (ETH_USING_MACRO == ETH_MACRO_ETND)
    /* TAS disable */
    Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTCC = ETH_ETNDE_TCC_DISABLE;                                              /* PRQA S 2844 # JV-01 */
    #else
    /* TAS disable */
    Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTCC = ETH_ETNDE_TCC_DISABLE;
    #endif
  }
  #endif

  /* Reset all Buffer Locks or pending Transmit */
  if (E_OK == LucResult)
  {
    for (LulCntI = 0UL; LulCntI < Eth_GaaTxBufferTotal[LulCtrlIdx]; LulCntI++)                                          /* PRQA S 2844 # JV-01 */
    {
      if (NULL_PTR != Eth_GaaTxBufferMgrTable[LulCtrlIdx][LulCntI].pBufferHdr)                                          /* PRQA S 2844, 2824 # JV-01, JV-01 */
      {
        Eth_ReleaseTxBuffer(LulCtrlIdx, Eth_GaaTxBufferMgrTable[LulCtrlIdx][LulCntI].pBufferHdr->ulbufIdx);             /* PRQA S 2814 # JV-01 */
      } /* else: No action required */
    }

    for (LulCntI = 0UL; LulCntI < (uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfTxQueue; LulCntI++)
    {
      /* Reset Tx descriptor */
      LpTxDescChain = Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc[LulCntI];                                       /* PRQA S 2844, 2824 # JV-01, JV-01 */
      for (LulCntJ = 0UL; LulCntJ < Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pBufTxCnt[LulCntI]; LulCntJ++)
      {
        /* Set frame empty type */
        LpTxDescChain->stHeader.ulDie   = (uint32)0UL;                                                                  /* PRQA S 2814 # JV-01 */
        LpTxDescChain->stHeader.ulAxie  = (uint32)0UL;
        LpTxDescChain->stHeader.ulDse   = (uint32)0UL;
        LpTxDescChain->stHeader.ulInfo0 = (uint32)0UL;
        LpTxDescChain->stHeader.ulDs    = (uint32)0UL;
        LpTxDescChain->ulDptr           = 0UL;
        LpTxDescChain->ulInfo1[0]       = 0UL;
        LpTxDescChain->ulInfo1[1]       = 0UL;
        LpTxDescChain->stHeader.ulDt    = (uint32)ETH_DESC_FEMPTY;

        /* Next descriptor */
        LpTxDescChain++;                                                                                                /* PRQA S 2824 # JV-01 */
        while ((LpTxDescChain->stHeader.ulDt == ETH_DESC_LEMPTY) || (LpTxDescChain->stHeader.ulDt == ETH_DESC_LINK))    /* PRQA S 2814 # JV-01 */
        {
          LpTxDescChain->stHeader.ulDt = (uint32)ETH_DESC_LINK;                                                         /* PRQA S 2814 # JV-01 */
          LpTxDescChain = (P2VAR(Eth_ExtDescType, AUTOMATIC, ETH_APPL_DATA))LpTxDescChain->ulDptr;                      /* PRQA S 0306, 3432 # JV-01, JV-01 */
        }
      }

      Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc[LulCntI] = LpTxDescChain;

      Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pBufTxCnt[LulCntI] = 0UL;
    }

    for (LulCntI = 0UL; LulCntI < (uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfRxQueue; LulCntI++)
    {
      /* Reset Rx descriptor */
      LpRxDescChain = Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc[LulCntI];
      while (LpRxDescChain->stHeader.ulDt != ETH_DESC_FEMPTY)                                                           /* PRQA S 2814 # JV-01 */
      {
        LpRxDescChain->stHeader.ulDie   = (uint32)ETH_RX_DESC_DIE_ENABLE;                                               /* PRQA S 2814 # JV-01 */
        LpRxDescChain->stHeader.ulAxie  = (uint32)0UL;
        LpRxDescChain->stHeader.ulDse   = (uint32)0UL;
        LpRxDescChain->stHeader.ulInfo0 = (uint32)0UL;
        LpRxDescChain->stHeader.ulDs    = LpHwUnitConfig->stRxConfig.ulMaxFrameSize;                                    /* PRQA S 2824 # JV-01 */
        LpRxDescChain->ulInfo1[0]       = 0UL;
        LpRxDescChain->ulInfo1[1]       = 0UL;
        LpRxDescChain->ulTsns           = 0UL;
        LpRxDescChain->ulTss            = 0UL;
        LpRxDescChain->stHeader.ulDt    = (uint32)ETH_DESC_FEMPTY;

        /* Next descriptor */
        LpRxDescChain++;                                                                                                /* PRQA S 2824 # JV-01 */
        while ((LpRxDescChain->stHeader.ulDt == ETH_DESC_LEMPTY) || (LpRxDescChain->stHeader.ulDt == ETH_DESC_LINK))    /* PRQA S 2814 # JV-01 */
        {
          LpRxDescChain->stHeader.ulDt = (uint32)ETH_DESC_LINK;                                                         /* PRQA S 2814 # JV-01 */
          LpRxDescChain = (P2VAR(Eth_ExtDescWithTsType, AUTOMATIC, ETH_APPL_DATA))LpRxDescChain->ulDptr;                /* PRQA S 0306, 3432 # JV-01, JV-01 */
        }
      }
      Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc[LulCntI] = LpRxDescChain;
    }
  }
  else
  {
    Eth_GaaCtrlStat[LulCtrlIdx].enMode = ETH_MODE_ACTIVE;                                                               /* PRQA S 2844 # JV-01 */
  }

  return LucResult;
}

/***********************************************************************************************************************
** Function Name         : Eth_HwEnableController (ETNDE)
**
** Service ID            : N/A
**
** Description           : Changes the state of an ETNDE controller as ACTIVE
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : E_OK : Success
**                         E_NOT_OK : Failure
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GaaETNE_ETHARegs, Eth_GaaCtrlStat, Eth_GaaDemEventLinkVerificationFailed
**                         Eth_GstETND_Regs, Eth_GpETNE_MFWDRegs
**
** Function(s) invoked   : Eth_ETHA_ModeSetting, Eth_MHD_ModeSetting, Eth_TasAdminLearning
**
** Registers Used        : MRMAC0, MRMAC1, TASFE, TACST0, TACST1, TACST2, TAEN, MRAFC
**
** Reference ID          : ETH_DUD_ACT_310
** Reference ID          : ETH_DUD_ACT_310_ERR001
** Reference ID          : ETH_DUD_ACT_310_REG001, ETH_DUD_ACT_310_REG002
** Reference ID          : ETH_DUD_ACT_310_REG003, ETH_DUD_ACT_310_REG004
** Reference ID          : ETH_DUD_ACT_310_REG005, ETH_DUD_ACT_310_REG006
** Reference ID          : ETH_DUD_ACT_310_REG007, ETH_DUD_ACT_310_REG008
** Reference ID          : ETH_DUD_ACT_310_REG009
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_HwEnableController(CONST(uint32, AUTOMATIC) LulCtrlIdx)                      /* PRQA S 1532 # JV-01 */
{
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2VAR(volatile Eth_ETNDE_RMACRegType, AUTOMATIC, REGSPACE) LpRmacRegs =
    &Eth_GstETND_Regs.pES[LulCtrlIdx]->stRMACSys.stRMAC;                                                                /* PRQA S 2844 # JV-01 */
  #else
  CONSTP2VAR(volatile Eth_ETNDE_RMACRegType, AUTOMATIC, REGSPACE) LpRmacRegs =
    &Eth_GstETNE_Regs.pEA[LulCtrlIdx]->stRMACSys.stRMAC;
  #endif
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  TickType LulTickStart;
  TickType LulTickElap;

  #if (ETH_GLOBAL_TIME_SUPPORT == STD_ON)
  uint32 LulQIdx;
  uint32 LulCfgIdx;
  uint32 LulRegIdx;
  uint32 LulTASCfgAddr;
  float64 LdbStartupTime;
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2CONST(volatile Eth_ETNDE_GPTMARegType, AUTOMATIC, REGSPACE) LpGptmaRegs = Eth_GstETND_Regs.pGPTMA;
  #else
  CONSTP2CONST(volatile Eth_ETNDE_GPTMARegType, AUTOMATIC, REGSPACE) LpGptmaRegs = Eth_GstETNE_Regs.pGPTMA;
  #endif
  #endif

  Std_ReturnType LucResult;

  LucResult = E_OK;

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */


  /* Set MAC address */
  /* When MAC address is 01-23-45-67-89-AB, set 0x0123 */
  LpRmacRegs->ulMRMAC0 = Eth_GaaCtrlStat[LulCtrlIdx].stMacAddr.ulH32 >> 16UL;                                           /* PRQA S 2814, 2844 # JV-01, JV-01 */
  /* When MAC address is 01-23-45-67-89-AB, set 0x456789AB */
  LpRmacRegs->ulMRMAC1 =
    (Eth_GaaCtrlStat[LulCtrlIdx].stMacAddr.ulH32 << 16UL) | Eth_GaaCtrlStat[LulCtrlIdx].stMacAddr.ulL16;

  #if (ETH_UPDATE_PHYS_ADDR_FILTER == STD_ON)
  if (ETH_TRUE == Eth_GaaCtrlStat[LulCtrlIdx].blPromiscuous)
  {
    /* Promiscuous receive mode */
    LpRmacRegs->ulMRAFC |= ETH_ETNDE_PROMISCUOUS_MODE;
  }
  else
  {
    /* Normal receive mode */
    LpRmacRegs->ulMRAFC &= ~ETH_ETNDE_PROMISCUOUS_MODE;
  }
  #endif

  #if (ETH_GLOBAL_TIME_SUPPORT == STD_ON)
  /* TAS algorithm start */
  if (ETH_ENABLE == LpHwUnitConfig->stTASConfig.enTasEnable)                                                            /* PRQA S 2814 # JV-01 */
  {
    LulTASCfgAddr = 0UL;
    for (LulQIdx = 0; LulQIdx < ETH_TAS_QUEUE_NUM; LulQIdx++)
    {
      /* Entry number setting */
      LulRegIdx = LulQIdx / ETH_ETNDE_TAEN_POSITION;
      #if (ETH_USING_MACRO == ETH_MACRO_ETND)
      Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTAEN[LulRegIdx] |=
        LpHwUnitConfig->stTASConfig.aaNumberOfTasTable[LulQIdx] <<
        ((LulQIdx % ETH_ETNDE_TAEN_POSITION) * ETH_ETNDE_TAEN_OFFSET);                                                  /* PRQA S 3384 # JV-01 */
      #else
      Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTAEN[LulRegIdx] |=
        LpHwUnitConfig->stTASConfig.aaNumberOfTasTable[LulQIdx] <<
        ((LulQIdx % ETH_ETNDE_TAEN_POSITION) * ETH_ETNDE_TAEN_OFFSET);
      #endif

      for (LulCfgIdx = 0; LulCfgIdx < LpHwUnitConfig->stTASConfig.aaNumberOfTasTable[LulQIdx]; LulCfgIdx++)
      {
        /* TAS admin control list table learning */
        LucResult = Eth_TasAdminLearning(LulCtrlIdx, LulTASCfgAddr,
                                         LpHwUnitConfig->stTASConfig.aaTasAdminTable[LulQIdx] + LulCfgIdx);             /* PRQA S 0488, 2824 # JV-01, JV-01 */
        if (E_NOT_OK == LucResult)
        {
          /* Failed learning */
          break;
        } /* else: No action required */

        LulTASCfgAddr++;                                                                                                /* PRQA S 3383 # JV-01 */
      }

      if (E_NOT_OK == LucResult)
      {
        /* Failed learning */
        break;
      } /* else: No action required */
    }

    LdbStartupTime = ETH_GET_TAS_STARTUP_TIME(LpGptmaRegs);

    #if (ETH_USING_MACRO == ETH_MACRO_ETND)
    /* Skip first entry setting */
    Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTASFE = 0UL;
    /* Cycle start time setting */
    Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTACST0 = ETH_CALC_TAS_TACST0(LdbStartupTime);
    Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTACST1 = ETH_CALC_TAS_TACST1(LdbStartupTime);
    Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTACST2 = ETH_CALC_TAS_TACST2(LdbStartupTime);
    /* TAS enable */
    Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTCC = ETH_ETNDE_TCC_ENABLE;
    #else
    /* Skip first entry setting */
    Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTASFE = 0UL;
    /* Cycle start time setting */
    Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTACST0 = ETH_CALC_TAS_TACST0(LdbStartupTime);
    Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTACST1 = ETH_CALC_TAS_TACST1(LdbStartupTime);
    Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTACST2 = ETH_CALC_TAS_TACST2(LdbStartupTime);
    /* TAS enable */
    Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTCC = ETH_ETNDE_TCC_ENABLE;
    #endif
  } /* else: No action required */
  #endif

  /* Link Verification */
  /* Set Preemption auto response and Link Verification Timer */
  LpRmacRegs->ulMLVC = ETH_ETNDE_MLVC_PASE_MASK | LpHwUnitConfig->stMACConfig.ulLVTimer;
  /* Request Link Verification (HW will clear this bit after completing link verification) */
  LpRmacRegs->ulMLVC |= ETH_ETNDE_MLVC_PLV_MASK;
  /* Wait until completing Link Verification */
  LulTickStart = 0UL;
  (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
  do
  {
    LulTickElap = Eth_GetTimeOutValue(LulTickStart);
  } while (0UL != (LpRmacRegs->ulMLVC & ETH_ETNDE_MLVC_PLV_MASK) &&
    (LulTickElap <= ETH_TIMEOUT_COUNT));

  if (0UL == (LpRmacRegs->ulMLVC & ETH_ETNDE_MLVC_PSE_MASK))
  {
    Eth_DemConfigCheck(Eth_GaaDemEventLinkVerificationFailed[LulCtrlIdx], DEM_EVENT_STATUS_FAILED);
  } /* else: No action required */

  if (ETH_TIMEOUT_COUNT < LulTickElap)
  {
    LucResult = E_NOT_OK;
  } /* else: No action required */

  if (E_OK == LucResult)
  {
    /* Set EAMC mode to OPERATION */
    #if (ETH_USING_MACRO == ETH_MACRO_ETND)
    LucResult = Eth_MHD_ModeSetting(LulCtrlIdx, ETH_ETND_MHD_DISABLE_MODE);
    LucResult |= Eth_MHD_ModeSetting(LulCtrlIdx, ETH_ETND_MHD_OPERATION_MODE);
    #else
    LucResult = Eth_ETHA_ModeSetting(LulCtrlIdx, ETH_ETNE_ETHA_DISABLE_MODE);
    LucResult |= Eth_ETHA_ModeSetting(LulCtrlIdx, ETH_ETNE_ETHA_OPERATION_MODE);
    #endif
  } /* else: No action required */

  return LucResult;
}

/***********************************************************************************************************************
** Function Name         : Eth_HwTransmit (ETNDE)
**
** Service ID            : N/A
**
** Description           : Initiates a transmission on an ETNDE controller.
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                         LulBufIdx      : index of a tx buffer
**                         LulLenByte     : byte length of a payload
**                         LblConfirmation: Whether TxConfirmation is required when a transmission finished
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : E_OK : Success
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpCtrlConfigPtr, Eth_GpETNE_MFWDRegs,
**                         Eth_GaaTxBufferMgrTable, Eth_GaaCtrlStat
**                         Eth_GstETND_Regs
**
** Function(s) invoked   : ETH_ENTER_CRITICAL_SECTION, ETH_EXIT_CRITICAL_SECTION
**
** Registers Used        : TRCR
**
** Reference ID          : ETH_DUD_ACT_311
** Reference ID          : ETH_DUD_ACT_311_CRT001, ETH_DUD_ACT_311_CRT002
** Reference ID          : ETH_DUD_ACT_311_CRT003, ETH_DUD_ACT_311_CRT004
** Reference ID          : ETH_DUD_ACT_311_GBL001, ETH_DUD_ACT_311_GBL002, ETH_DUD_ACT_311_GBL003
** Reference ID          : ETH_DUD_ACT_311_GBL004, ETH_DUD_ACT_311_GBL005, ETH_DUD_ACT_311_GBL006
** Reference ID          : ETH_DUD_ACT_311_GBL007, ETH_DUD_ACT_311_GBL008, ETH_DUD_ACT_311_GBL009
** Reference ID          : ETH_DUD_ACT_311_GBL010, ETH_DUD_ACT_311_GBL011, ETH_DUD_ACT_311_GBL012
** Reference ID          : ETH_DUD_ACT_311_GBL013
** Reference ID          : ETH_DUD_ACT_311_REG001
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_HwTransmit(                                                                  /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONST(uint32, AUTOMATIC) LulBufIdx,
  CONST(uint32, AUTOMATIC) LulLenByte, CONST(boolean, AUTOMATIC) LblConfirmation)
{
  P2VAR(Eth_ExtDescType, AUTOMATIC, ETH_APPL_DATA) LpDataDesc;                                                          /* PRQA S 3432 # JV-01 */
  P2VAR(Eth_BufHandlerType, AUTOMATIC, ETH_APPL_DATA) LpBufHandlerPtr;                                                  /* PRQA S 3432 # JV-01 */
  Eth_TxCtrlInfo0  LunTxCtrlInfo0;                                                                                      /* PRQA S 0759 # JV-01 */
  Eth_TxCtrlInfo1  LunTxCtrlInfo1;                                                                                      /* PRQA S 0759 # JV-01 */
  
  #if (ETH_USING_MACRO == ETH_MACRO_ETNE)
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;
  #endif

  ETH_ENTER_CRITICAL_SECTION(ETH_RAM_DATA_PROTECTION);

  /* Get Tx buffer handler */
  Eth_GaaTxBufferMgrTable[LulCtrlIdx][LulBufIdx].blTxOngoing = ETH_TRUE;                                                /* PRQA S 2844, 2824 # JV-01, JV-01 */
  LpBufHandlerPtr = Eth_GaaTxBufferMgrTable[LulCtrlIdx][LulBufIdx].pBufferHdr;

  ETH_EXIT_CRITICAL_SECTION(ETH_RAM_DATA_PROTECTION);

  /* Set Tx request length */
  LpBufHandlerPtr->ulTxLength = (uint32)ETH_HEADER_SIZE + LulLenByte;                                                   /* PRQA S 2814, 3383 # JV-01, JV-01 */

  /* Set Tx confirmation flag */
  LpBufHandlerPtr->blTxConfirm = LblConfirmation;

  /* Get next free descriptor */
  LpDataDesc = Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppNextTxDesc[LpBufHandlerPtr->ucPriority];                          /* PRQA S 2844, 2824 # JV-01, JV-01 */

  LunTxCtrlInfo0.ulWord = 0UL;
  LunTxCtrlInfo1.ulWord = 0UL;
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  /* Justify typecast to smaller datatype */
  LunTxCtrlInfo0.stTxCtrl.ulTsun = (uint8)(LpBufHandlerPtr->ulbufIdx);
  if (ETH_TRUE == LpBufHandlerPtr->blbenableTS)
  {
    LunTxCtrlInfo0.stTxCtrl.ulTxc = (uint32)ETH_TX_DESC_TCX_ENABLE;
    LunTxCtrlInfo0.stTxCtrl.ulTn = (uint32)ETH_TX_DESC_TN_DOMAIN;
  } /* else: No action required */

  LunTxCtrlInfo1.stTxCtrl.ulTfl = LpBufHandlerPtr->ulTxLength;
  #else
  LunTxCtrlInfo0.stTxCtrl.ulFmt = (uint32)ETH_TX_DESC_TYPE_DIRECT;

  /* Justify typecast to smaller datatype */
  LunTxCtrlInfo1.stTxCtrl.ulTsun = (uint8)(LpBufHandlerPtr->ulbufIdx + (LulCtrlIdx * ETH_TX_DESCR_TSUN_OFFSET));
  if (ETH_TRUE == LpBufHandlerPtr->blbenableTS)
  {
    LunTxCtrlInfo1.stTxCtrl.ulTxc = (uint32)ETH_TX_DESC_TCX_ENABLE;
    LunTxCtrlInfo1.stTxCtrl.ulTn = (uint32)ETH_TX_DESC_TN_DOMAIN;
  } /* else: No action required */
  #endif

  /* Build the descriptor */
  LpDataDesc->stHeader.ulDie = (uint32)ETH_TX_DESC_DIE_ENABLE;                                                          /* PRQA S 2814 # JV-01 */
  LpDataDesc->stHeader.ulInfo0 = LunTxCtrlInfo0.ulWord;
  LpDataDesc->stHeader.ulDs = LpBufHandlerPtr->ulTxLength;
  LpDataDesc->ulDptr = LpBufHandlerPtr->ulbufAddr;
  LpDataDesc->ulInfo1[0] = LunTxCtrlInfo1.ulWord;
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  LpDataDesc->ulInfo1[1] = 0UL;
  #else
  LpDataDesc->ulInfo1[1] = LpHwUnitConfig->ulEthPortId + 1UL;
  #endif
  /* Do not move this process due to descriptor exclusive control */
  LpDataDesc->stHeader.ulDt = (uint32)ETH_DESC_FSINGLE;

  /* Set next descriptor */
  LpDataDesc++;                                                                                                         /* PRQA S 2824 # JV-01 */
  while ((LpDataDesc->stHeader.ulDt == ETH_DESC_LEMPTY) || (LpDataDesc->stHeader.ulDt == ETH_DESC_LINK))                /* PRQA S 2814 # JV-01 */
  {
    LpDataDesc->stHeader.ulDt = (uint32)ETH_DESC_LINK;                                                                  /* PRQA S 2814 # JV-01 */
    LpDataDesc = (P2VAR(Eth_ExtDescType, AUTOMATIC, ETH_APPL_DATA)) LpDataDesc->ulDptr;                                 /* PRQA S 0306, 3432 # JV-01, JV-01 */
  }

  Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppNextTxDesc[LpBufHandlerPtr->ucPriority] = LpDataDesc;

  ETH_ENTER_CRITICAL_SECTION(ETH_RAM_DATA_PROTECTION);

  /* Increase the number of buffer of current Tx queue */
  Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pBufTxCnt[LpBufHandlerPtr->ucPriority]++;                                        /* PRQA S 2844, 2824, 3383 # JV-01, JV-01, JV-01 */

  ETH_EXIT_CRITICAL_SECTION(ETH_RAM_DATA_PROTECTION);

  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  /* Transmit start request 0-7 */
  Eth_GstETND_Regs.pES[LulCtrlIdx]->stAXIBMI.ulTRCR[0] |= (uint32)(1UL << ((uint32)LpBufHandlerPtr->ucPriority));       /* PRQA S 2844 # JV-01 */
  #else
  /* Transmit start request 0-15 */
  Eth_GstETNE_Regs.pAXIBMI->ulTRCR[0] |=
    (uint32)(1UL << ((uint32)LpBufHandlerPtr->ucPriority +
    (LulCtrlIdx * (uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfTxQueue)));
  #endif

  return E_OK;
}

/***********************************************************************************************************************
** Function Name         : Eth_HwTxConfirmation (ETNDE)
**
** Service ID            : N/A
**
** Description           : Performs transmission processing, notifies the upper layer
**                         of transmission completion and releases the Tx buffer.
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GaaCtrlStat, Eth_GstBroadcastAddr,
**                         Eth_GaaTxBufferMgrTable, Eth_GpCtrlConfigPtr
**
** Function(s) invoked   : EthIf_TxConfirmation, EthSwt_EthTxFinishedIndication,
**                         ETH_ENTER_CRITICAL_SECTION, ETH_EXIT_CRITICAL_SECTION,
**                         Eth_ReleaseTxBuffer
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_312
** Reference ID          : ETH_DUD_ACT_312_CRT001, ETH_DUD_ACT_312_CRT002
** Reference ID          : ETH_DUD_ACT_312_GBL001, ETH_DUD_ACT_312_GBL002, ETH_DUD_ACT_312_GBL003
** Reference ID          : ETH_DUD_ACT_312_GBL004, ETH_DUD_ACT_312_GBL005, ETH_DUD_ACT_312_GBL006
** Reference ID          : ETH_DUD_ACT_312_GBL007, ETH_DUD_ACT_312_GBL008, ETH_DUD_ACT_312_GBL009
** Reference ID          : ETH_DUD_ACT_312_GBL010, ETH_DUD_ACT_312_GBL011, ETH_DUD_ACT_312_GBL012
** Reference ID          : ETH_DUD_ACT_312_GBL013, ETH_DUD_ACT_312_GBL014, ETH_DUD_ACT_312_GBL015
***********************************************************************************************************************/
FUNC(void, ETH_PRIVATE_CODE) Eth_HwTxConfirmation(CONST(uint32, AUTOMATIC) LulCtrlIdx)                                  /* PRQA S 1532 # JV-01 */
{
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  uint32 LulQIdx;
  uint32 LulCnt;
  uint32 LulTxCnt;
  uint32 LulBufIdx;

  P2VAR(Eth_ExtDescType, AUTOMATIC, ETH_APPL_DATA) LpDataDesc;                                                          /* PRQA S 3432 # JV-01 */
  P2CONST(Eth_BufHandlerType, AUTOMATIC, ETH_APPL_DATA) LpBufHandlerPtr;
  #if (ETH_GET_TX_STATS_API == STD_ON)
  Eth_MacAddressType LstMacAddr;
  #endif

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */

  /* Check the status of the tx descriptor */
  for (LulQIdx = 0UL; LulQIdx < (uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfTxQueue; LulQIdx++)                     /* PRQA S 2814 # JV-01 */
  {
    /* Get on-transmit count */
    LulTxCnt = Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pBufTxCnt[LulQIdx];                                                 /* PRQA S 2844, 2824 # JV-01, JV-01 */
    if (0UL == LulTxCnt)
    {
      /* Skip because the transmit is not completed */
      continue;
    } /* else: No action required */

    LpDataDesc = Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc[LulQIdx];
    for (LulCnt = 0UL; LulCnt < LulTxCnt; LulCnt++)                                                                     /* PRQA S 0771 # JV-01 */
    {
      if (ETH_DESC_FEMPTY != LpDataDesc->stHeader.ulDt)                                                                 /* PRQA S 2814 # JV-01 */
      {
        /* Transmit not completed yet */
        break;
      } /* else: No action required */

      /* Get Tx buffer handler */
      #if (ETH_USING_MACRO == ETH_MACRO_ETND)
      LulBufIdx = (LpDataDesc->stHeader.ulInfo0 & ETH_TX_DESCR_TSUN_MASK) >> 4UL;
      #else
      LulBufIdx = ((Eth_TxCtrlInfo1Type *)&LpDataDesc->ulInfo1[0])->ulTsun - (LulCtrlIdx * ETH_TX_DESCR_TSUN_OFFSET);
      #endif
      LpBufHandlerPtr = Eth_GaaTxBufferMgrTable[LulCtrlIdx][LulBufIdx].pBufferHdr;                                      /* PRQA S 2844, 2824 # JV-01, JV-01 */

      #if (ETH_GLOBAL_TIME_SUPPORT == STD_ON)
      if ((ETH_TRUE == LpBufHandlerPtr->blbenableTS) && (ETH_INVALID == LpBufHandlerPtr->enTimeQual))                   /* PRQA S 2814 # JV-01 */
      {
        /* Transmit not completed yet */
        break;
      } /* else: No action required */
      #endif

      #if (ETH_GET_TX_STATS_API == STD_ON)
      Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulTxNumberOfOctets += LpBufHandlerPtr->ulTxLength;                         /* PRQA S 2844, 3383 # JV-01, JV-01 */
      ETH_PACK_ADDRESS_FROM_8(((uint8 *)LpBufHandlerPtr->ulbufAddr), LstMacAddr);                                       /* PRQA S 2824, 3469, 0306 # JV-01, JV-01, JV-01 */
      if ((0UL == ETH_COMPARE_MAC(LstMacAddr, Eth_GstBroadcastAddr)) ||                                                 /* PRQA S 3469 # JV-01 */
          (0UL != ETH_CHECK_MULTICAST(LstMacAddr)))                                                                     /* PRQA S 3469 # JV-01 */
      {
        Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulTxNUcastPkts++;                                                        /* PRQA S 2844, 3383 # JV-01, JV-01 */
      }
      else
      {
        Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulTxUniCastPkts++;                                                       /* PRQA S 3383 # JV-01 */
      }
      #endif

      /* Check whether the transmission confirmation was enabled */
      if (ETH_TRUE == LpBufHandlerPtr->blTxConfirm)
      {
        /* Call the callback function */
        /* Since the maximum value of controller index is 1, casting to uint8 does no problem. */
        EthIf_TxConfirmation((uint8)LulCtrlIdx, (Eth_BufIdxType)LpBufHandlerPtr->ulbufIdx, E_OK);
      } /* else: No action required */

      #if (ETH_ETHSWITCH_MANAGEMENT_SUPPORT == STD_ON)
      /* Indication for a finished transmit process for a specific Ethernet frame. */
      /* Since the maximum value of controller index is 1, casting to uint8 does no problem. */
      (void)EthSwt_EthTxFinishedIndication((uint8)LulCtrlIdx, (Eth_BufIdxType)LpBufHandlerPtr->ulbufIdx);
      #endif

      ETH_ENTER_CRITICAL_SECTION(ETH_RAM_DATA_PROTECTION);

      /* Release the tx buffer resource */
      Eth_ReleaseTxBuffer(LulCtrlIdx, LulBufIdx);

      /* Clear tx descriptor */
      LpDataDesc->stHeader.ulDie   = (uint32)0UL;
      LpDataDesc->stHeader.ulAxie  = (uint32)0UL;
      LpDataDesc->stHeader.ulDse   = (uint32)0UL;
      LpDataDesc->stHeader.ulInfo0 = (uint32)0UL;
      LpDataDesc->stHeader.ulDs    = (uint32)0UL;
      LpDataDesc->ulDptr           = 0UL;
      LpDataDesc->ulInfo1[0]       = 0UL;
      LpDataDesc->ulInfo1[1]       = 0UL;

      /* Decrease the number of on-transmission buffer of current Tx queue */
      Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pBufTxCnt[LulQIdx]--;                                                        /* PRQA S 2844, 2824, 3383 # JV-01, JV-01, JV-01 */

      ETH_EXIT_CRITICAL_SECTION(ETH_RAM_DATA_PROTECTION);

      /* Update start descriptor */
      LpDataDesc++;                                                                                                     /* PRQA S 2824 # JV-01 */
      while ((ETH_DESC_LEMPTY == LpDataDesc->stHeader.ulDt) || (ETH_DESC_LINK == LpDataDesc->stHeader.ulDt))            /* PRQA S 2814 # JV-01 */
      {
        LpDataDesc->stHeader.ulDt = (uint32)ETH_DESC_LINK;                                                              /* PRQA S 2814 # JV-01 */
        LpDataDesc = (P2VAR(Eth_ExtDescType, AUTOMATIC, ETH_APPL_DATA))LpDataDesc->ulDptr;                              /* PRQA S 0306, 3432 # JV-01, JV-01 */
      }
      Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc[LulQIdx] = LpDataDesc;
    }
  }
}

/***********************************************************************************************************************
** Function Name         : Eth_HwReceive (ETNDE)
**
** Service ID            : N/A
**
** Description           : Performs reception processing in polling mode.
**                         When polling mode:
**                           Receive one frame and indicate it EthIf
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                         LulFifoIdx     : Index of a Fifo
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : When polling mode:
**                           ETH_NOT_RECEIVED : there was no received frame
**                           ETH_RECEIVED     : there was one received frame
**                           ETH_RECEIVED_MORE_DATA_AVAILABLE:
**                                 there were more than one received frames
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpETNE_MFWDRegs, Eth_GstETND_Regs
**                         Eth_GpCtrlConfigPtr
**
** Function(s) invoked   : Eth_RxQueueProcess
**
** Registers Used        : RDISi
**
** Reference ID          : ETH_DUD_ACT_313
** Reference ID          : ETH_DUD_ACT_313_REG001
***********************************************************************************************************************/
FUNC(Eth_RxStatusType, ETH_PRIVATE_CODE) Eth_HwReceive(                                                                 /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONST(uint32, AUTOMATIC) LulFifoIdx)
{
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs =
    &Eth_GstETND_Regs.pES[LulCtrlIdx]->stAXIBMI;                                                                        /* PRQA S 2844 # JV-01 */
  #else
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs = Eth_GstETNE_Regs.pAXIBMI;
  #endif
  uint32 LulRxQueueMax;
  uint32 LulTargetRxIntStat;
  Eth_ExtRxStatusType LenRetValue;

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */
  LulRxQueueMax = (uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfRxQueue;                                              /* PRQA S 2814 # JV-01 */

  /* Get descriptor interrupt status */
  LulTargetRxIntStat = ETH_GET_RX_INT_STAT(LulCtrlIdx, LulFifoIdx, LpAxiRegs->stRXDI[0].ulRDISi, LulRxQueueMax);        /* PRQA S 2814 # JV-01 */

  /* Clear descriptor interrupt status */
  LpAxiRegs->stRXDI[0].ulRDISi = LulTargetRxIntStat;

  /* Receive the specified queue */
  do
  {
    LenRetValue = Eth_RxQueueProcess(LulCtrlIdx, LulFifoIdx);
  } while (ETH_EXT_NOT_RECEIVED_MORE_DATA_AVAILABLE == LenRetValue);

  return (Eth_RxStatusType)LenRetValue;                                                                                 /* PRQA S 4322 # JV-01 */
}

#if (ETH_CTRL_ENABLE_RX_POLLING == STD_ON)
/***********************************************************************************************************************
** Function Name         : Eth_HwCheckFifoIndex (ETNDE)
**
** Service ID            : N/A
**
** Description           : Check the validity of the FIFO index specified
**                         in the Eth_Receive.
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                         LulFifoIdx     : the FIFO index
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : LucReturnValue E_OK / E_NOT_OK
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpCtrlConfigPtr
**
** Function(s) invoked   : None
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_328
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_HwCheckFifoIndex(                                                            /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONST(uint32, AUTOMATIC) LulFifoIdx)
{
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  Std_ReturnType LucReturnValue;

  LucReturnValue = E_OK;

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */

  /* Validity check for the FIFO index */
  if ((uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfRxQueue <= LulFifoIdx)                                            /* PRQA S 2814 # JV-01 */
  {
    LucReturnValue = E_NOT_OK;
  } /* else: No action required */

  return LucReturnValue;
}
#endif /* (ETH_CTRL_ENABLE_RX_POLLING == STD_ON) */

#if (ETH_CTRL_ENABLE_MII == STD_ON)
/***********************************************************************************************************************
** Function Name         : Eth_HwReadMii (ETNDE)
**
** Service ID            : N/A
**
** Description           : Read data from the PHY management interface
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                         LucTrcvIdx     : Index of the transceiver on the MII
**                         LucRegIdx      : Index of the transceiver register on the MII
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : LusRetData (Read data from PHY)
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpCtrlConfigPtr, Eth_GaaETNE_ETHARegs,
**                         Eth_GstETND_Regs
**
** Function(s) invoked   : None
**
** Registers Used        : MPIC, MPSM, MMIS1
**
** Reference ID          : ETH_DUD_ACT_314
** Reference ID          : ETH_DUD_ACT_314_REG001, ETH_DUD_ACT_314_REG002
** Reference ID          : ETH_DUD_ACT_314_REG003, ETH_DUD_ACT_314_REG004
** Reference ID          : ETH_DUD_ACT_314_REG005, ETH_DUD_ACT_314_REG006
***********************************************************************************************************************/
FUNC(uint16, ETH_PRIVATE_CODE) Eth_HwReadMii(                                                                           /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONST(uint8, AUTOMATIC) LucTrcvIdx, CONST(uint8, AUTOMATIC) LucRegIdx)
{
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2VAR(volatile Eth_ETNDE_RMACRegType, AUTOMATIC, REGSPACE) LpRmacRegs =
    &Eth_GstETND_Regs.pES[LulCtrlIdx]->stRMACSys.stRMAC;                                                                /* PRQA S 2844 # JV-01 */
  #else
  CONSTP2VAR(volatile Eth_ETNDE_RMACRegType, AUTOMATIC, REGSPACE) LpRmacRegs =
    &Eth_GstETNE_Regs.pEA[LulCtrlIdx]->stRMACSys.stRMAC;
  #endif
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  TickType LulTickStart;
  TickType LulTickElap;
  uint16 LusRetData;

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */

  /* Configure MPIC register */
  LpRmacRegs->ulMPIC |=                                                                                                 /* PRQA S 2814 # JV-01 */
          (uint32)(((uint32)LpHwUnitConfig->stPHYConfig.enPSMCaptureTime << 28UL) |  /* Capture time    */              /* PRQA S 2814 # JV-01 */
          ((uint32)LpHwUnitConfig->stPHYConfig.enPSMHoldTime << 24UL) |              /* Hold time       */
          (LpHwUnitConfig->stPHYConfig.ulPSMClockSelection   << 16UL));              /* Clock Selection */

  /* Write PRA, PDA to the MPSM register and set read access direction */
  LpRmacRegs->ulMPSM = (uint32)(((uint32)LucTrcvIdx << 3UL) | ((uint32)LucRegIdx << 8UL));

  /* Enable PHY register access bit */
  LpRmacRegs->ulMPSM = (uint32)(((uint32)LucTrcvIdx << 3UL) | ((uint32)LucRegIdx << 8UL) |
                       ETH_ETNDE_MPSM_READ_OPERATION); /* Read access */

  /* Wait until MPSM.PSME returns to 0 */
  LulTickStart = 0UL;
  (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
  do
  {
    LulTickElap = Eth_GetTimeOutValue(LulTickStart);
  } while (((LpRmacRegs->ulMPSM & ETH_ETNDE_PHY_CONFIG_REGISTER_MASK) != 0UL) && (LulTickElap <= ETH_TIMEOUT_COUNT));

  if (ETH_TIMEOUT_COUNT < LulTickElap)
  {
    LusRetData = (uint16)0x0UL;
  }
  else
  {
    /* Get read data as return value */
    LusRetData = (uint16)(LpRmacRegs->ulMPSM >> 16UL);
  }

  /* Clear interrupt (MMIS1.PRACS = 1) */
  LpRmacRegs->ulMMIS1 |= ETH_ETNDE_PHY_CONFIG_REGISTER_MASK;

  /* Disable Station Management Clock */
  LpRmacRegs->ulMPIC &= ETH_ETNDE_MPIC_PSMCS_MASK;

  return LusRetData;
}

/***********************************************************************************************************************
** Function Name         : Eth_HwWriteMii (ETNDE)
**
** Service ID            : N/A
**
** Description           : Write data to the PHY management interface
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                         LucTrcvIdx     : Index of the transceiver on the MII
**                         LucRegIdx      : Index of the transceiver register on the MII
**                         LusRegVal      : Value to be written into the indexed
**                                          register
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : LucResult (E_OK / E_NOT_OK)
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpCtrlConfigPtr, Eth_GaaETNE_ETHARegs,
**                         Eth_GstETND_Regs
**
** Function(s) invoked   : None
**
** Registers Used        : MPIC, MPSM, MMIS1
**
** Reference ID          : ETH_DUD_ACT_315
** Reference ID          : ETH_DUD_ACT_315_REG001, ETH_DUD_ACT_315_REG002
** Reference ID          : ETH_DUD_ACT_315_REG003, ETH_DUD_ACT_315_REG004
** Reference ID          : ETH_DUD_ACT_315_REG005, ETH_DUD_ACT_315_REG006
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_HwWriteMii(                                                                  /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONST(uint8, AUTOMATIC) LucTrcvIdx,
  CONST(uint8, AUTOMATIC) LucRegIdx, CONST(uint16, AUTOMATIC) LusRegVal)
{
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2VAR(volatile Eth_ETNDE_RMACRegType, AUTOMATIC, REGSPACE) LpRmacRegs =
    &Eth_GstETND_Regs.pES[LulCtrlIdx]->stRMACSys.stRMAC;                                                                /* PRQA S 2844 # JV-01 */
  #else
  CONSTP2VAR(volatile Eth_ETNDE_RMACRegType, AUTOMATIC, REGSPACE) LpRmacRegs =
    &Eth_GstETNE_Regs.pEA[LulCtrlIdx]->stRMACSys.stRMAC;
  #endif
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  Std_ReturnType LucResult;
  TickType LulTickStart;
  TickType LulTickElap;

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */

  /* Configure MPIC register */
  LpRmacRegs->ulMPIC |=                                                                                                 /* PRQA S 2814 # JV-01 */
          (uint32)(((uint32)LpHwUnitConfig->stPHYConfig.enPSMCaptureTime << 28UL) |  /* Capture time    */              /* PRQA S 2814 # JV-01 */
          ((uint32)LpHwUnitConfig->stPHYConfig.enPSMHoldTime << 24UL) |              /* Hold time       */
          (LpHwUnitConfig->stPHYConfig.ulPSMClockSelection   << 16UL));              /* Clock Selection */

  /* Write PRA, PDA to the MPSM register and and set write access direction */
  LpRmacRegs->ulMPSM = (uint32)(((uint32)LusRegVal << 16UL) | ((uint32)LucTrcvIdx << 3UL) |
                       ((uint32)LucRegIdx << 8UL) | ETH_ETNDE_MPSM_WRITE_DATA_SET);  /* Write operation */

  /* Enable PHY register access bit */
  LpRmacRegs->ulMPSM = (uint32)(((uint32)LusRegVal << 16UL) | ((uint32)LucTrcvIdx << 3UL) |
                       ((uint32)LucRegIdx << 8UL) | ETH_ETNDE_MPSM_WRITE_OPERATION); /* Data write */

  /* Wait until MPSM.PSME returns to 0 */
  LulTickStart = 0UL;
  (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
  do
  {
    LulTickElap = Eth_GetTimeOutValue(LulTickStart);
  } while (((LpRmacRegs->ulMPSM & ETH_ETNDE_PHY_CONFIG_REGISTER_MASK) != 0UL) && (LulTickElap <= ETH_TIMEOUT_COUNT));

  if (ETH_TIMEOUT_COUNT < LulTickElap)
  {
    LucResult = E_NOT_OK;
  }
  else
  {
    LucResult = E_OK;
  }

  /* Clear interrupt (MMIS1.PRACS = 1) */
  LpRmacRegs->ulMMIS1 |= ETH_ETNDE_PHY_CONFIG_REGISTER_MASK;

  /* Disable Station Management Clock */
  LpRmacRegs->ulMPIC &= ETH_ETNDE_MPIC_PSMCS_MASK;

  return LucResult;
}
#endif /* (ETH_CTRL_ENABLE_MII == STD_ON) */

#if (ETH_GET_COUNTER_VALUES_API == STD_ON)
/***********************************************************************************************************************
** Function Name         : Eth_HwGetCounterValues (ETNDE)
**
** Service ID            : N/A
**
** Description           : Get drop frame counts for each error factor
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx: Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : LpCounterPtr: Drop frame counter information
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GaaETNE_ETHARegs, Eth_GstETND_Regs, Eth_GaaCtrlStat
**
** Function(s) invoked   : None
**
** Registers Used        : RBOEC
**
** Reference ID          : ETH_DUD_ACT_316
***********************************************************************************************************************/
FUNC(void, ETH_PRIVATE_CODE) Eth_HwGetCounterValues(                                                                    /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONSTP2VAR(Eth_CounterType, AUTOMATIC, ETH_APPL_DATA) LpCounterPtr)                                                   /* PRQA S 3432 # JV-01 */
{
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2CONST(volatile Eth_ETNDE_RMACSRegType, AUTOMATIC, REGSPACE) LpRmacsRegs =
    &Eth_GstETND_Regs.pES[LulCtrlIdx]->stRMACSys;                                                                       /* PRQA S 2844 # JV-01 */
  #else
  CONSTP2CONST(volatile Eth_ETNDE_RMACSRegType, AUTOMATIC, REGSPACE) LpRmacsRegs =
    &Eth_GstETNE_Regs.pEA[LulCtrlIdx]->stRMACSys;
  #endif
  /* Statistics Available */
  LpCounterPtr->DropPktBufOverrun = LpRmacsRegs->ulRBOEC;                                                               /* PRQA S 2814 # JV-01 */
  LpCounterPtr->DropPktCrc        = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulDropPktCrc;
  LpCounterPtr->UndersizePkt      = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulUndersizePkt;
  LpCounterPtr->OversizePkt       = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulOversizePkt;
  LpCounterPtr->AlgnmtErr         = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulAlgnmtErr;
  LpCounterPtr->SqeTestErr  = ETH_NOT_AVAILABLE;
  LpCounterPtr->DiscInbdPkt = ETH_NOT_AVAILABLE;
  LpCounterPtr->ErrInbdPkt  = ETH_NOT_AVAILABLE;
  LpCounterPtr->DiscOtbdPkt = ETH_NOT_AVAILABLE;
  LpCounterPtr->ErrOtbdPkt  = ETH_NOT_AVAILABLE;
  LpCounterPtr->SnglCollPkt = ETH_NOT_AVAILABLE;
  LpCounterPtr->MultCollPkt = ETH_NOT_AVAILABLE;
  LpCounterPtr->DfrdPkt     = ETH_NOT_AVAILABLE;
  LpCounterPtr->LatCollPkt  = ETH_NOT_AVAILABLE;
  LpCounterPtr->HwDepCtr0   = ETH_NOT_AVAILABLE;
  LpCounterPtr->HwDepCtr1   = ETH_NOT_AVAILABLE;
  LpCounterPtr->HwDepCtr2   = ETH_NOT_AVAILABLE;
  LpCounterPtr->HwDepCtr3   = ETH_NOT_AVAILABLE;
}
#endif /* (ETH_GET_COUNTER_VALUES_API == STD_ON) */

#if (ETH_GET_RX_STATS_API == STD_ON)
/***********************************************************************************************************************
** Function Name         : Eth_HwGetRxStats (ETNDE)
**
** Service ID            : N/A
**
** Description           : Get Rx statistics information
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : LpRxStats: Rx statistics counter information
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GaaCtrlStat, Eth_GaaETNE_ETHARegs, Eth_GstETND_Regs
**
** Function(s) invoked   : None
**
** Registers Used        : RBFC, RMFC
**
** Reference ID          : ETH_DUD_ACT_317
***********************************************************************************************************************/
FUNC(void, ETH_PRIVATE_CODE) Eth_HwGetRxStats(                                                                          /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONSTP2VAR(Eth_RxStatsType, AUTOMATIC, ETH_APPL_DATA) LpRxStats)                 /* PRQA S 3432 # JV-01 */
{
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2CONST(volatile Eth_ETNDE_RMACSRegType, AUTOMATIC, REGSPACE) LpRmacsRegs =
    &Eth_GstETND_Regs.pES[LulCtrlIdx]->stRMACSys;                                                                       /* PRQA S 2844 # JV-01 */
  #else
  CONSTP2CONST(volatile Eth_ETNDE_RMACSRegType, AUTOMATIC, REGSPACE) LpRmacsRegs =
    &Eth_GstETNE_Regs.pEA[LulCtrlIdx]->stRMACSys;
  #endif
  /* Rx Drop Events */
  LpRxStats->RxStatsDropEvents = ETH_NOT_AVAILABLE;                                                                     /* PRQA S 2814 # JV-01 */

  /* Rx Stats Fragments */
  LpRxStats->RxStatsFragments  = ETH_NOT_AVAILABLE;

  /* Rx Stats Jabbers */
  LpRxStats->RxStatsJabbers    = ETH_NOT_AVAILABLE;

  /* Rx Stats Collisions */
  LpRxStats->RxStatsCollisions = ETH_NOT_AVAILABLE;

  /* Rx Octet Counter */
  LpRxStats->RxStatsOctets = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsOctets;                                    /* PRQA S 2844 # JV-01 */

  /* Rx Packet Counter */
  LpRxStats->RxStatsPkts = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts;

  /* Rx Broadcast Counter */
  LpRxStats->RxStatsBroadcastPkts = LpRmacsRegs->ulRBFC;                                                                /* PRQA S 2814 # JV-01 */

  /* Rx 64 Octets */
  LpRxStats->RxStatsPkts64Octets = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts64Octets;

  /* Rx 65-127 Octets */
  LpRxStats->RxStatsPkts65to127Octets = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts65to127Octets;

  /* Rx 128-255 Octets */
  LpRxStats->RxStatsPkts128to255Octets = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts128to255Octets;

  /* Rx 256-511 Octets */
  LpRxStats->RxStatsPkts256to511Octets = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts256to511Octets;

  /* Rx 512-1023 Octets */
  LpRxStats->RxStatsPkts512to1023Octets = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts512to1023Octets;

  /* Rx 1024-1518 Octets */
  LpRxStats->RxStatsPkts1024to1518Octets = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts1024to1518Octets;

  /* Rx unicast frames */
  LpRxStats->RxUnicastFrames = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxUnicastFrames;

  /* Multicast Frame Counter */
  LpRxStats->RxStatsMulticastPkts = LpRmacsRegs->ulRMFC;

  /* Crc + Alignment Error Counter  */
  LpRxStats->RxStatsCrcAlignErrors = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsCrcAlignErrors;

  /* Too Short Frames Counter */
  LpRxStats->RxStatsUndersizePkts = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsUndersizePkts;

  /* Too Long Frames Counter  */
  LpRxStats->RxStatsOversizePkts = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsOversizePkts;
}
#endif /* (ETH_GET_RX_STATS_API == STD_ON) */

#if (ETH_GET_TX_STATS_API == STD_ON)
/***********************************************************************************************************************
** Function Name         : Eth_HwGetTxStats (ETNDE)
**
** Service ID            : N/A
**
** Description           : Get Tx statistics information
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : LpTxStats: Tx statistics counter information
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GaaCtrlStat
**
** Function(s) invoked   : None
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_318
***********************************************************************************************************************/
FUNC(void, ETH_PRIVATE_CODE) Eth_HwGetTxStats(                                                                          /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONSTP2VAR(Eth_TxStatsType, AUTOMATIC, ETH_APPL_DATA) LpTxStats)                 /* PRQA S 3432 # JV-01 */
{
  /* Tx Octet Counter */
  LpTxStats->TxNumberOfOctets = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulTxNumberOfOctets;                              /* PRQA S 2814, 2844 # JV-01, JV-01 */

  /* Tx Not Unicast Packet Counter */
  LpTxStats->TxNUcastPkts = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulTxNUcastPkts;

  /* Tx Unicast Packet Counter */
  LpTxStats->TxUniCastPkts = Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulTxUniCastPkts;
}
#endif /* (ETH_GET_TX_STATS_API == STD_ON) */

#if (ETH_GET_TX_ERROR_COUNTER_VALUES_API == STD_ON)
/***********************************************************************************************************************
** Function Name         : Eth_HwGetTxErrorCounterValues (ETNDE)
**
** Service ID            : N/A
**
** Description           : Get error statuses
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : LpTxErrorCounterValues: Tx error counter information
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : None
**
** Function(s) invoked   : None
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_319
***********************************************************************************************************************/
FUNC(void, ETH_PRIVATE_CODE) Eth_HwGetTxErrorCounterValues(                                                             /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONSTP2VAR(Eth_TxErrorCounterValuesType, AUTOMATIC, ETH_APPL_DATA) LpTxErrorCounterValues)                            /* PRQA S 3432 # JV-01 */
{
  (void)LulCtrlIdx;

  /* This HW is cannot get Tx error statistics */
  LpTxErrorCounterValues->TxDroppedNoErrorPkts = ETH_NOT_AVAILABLE;                                                     /* PRQA S 2814 # JV-01 */
  LpTxErrorCounterValues->TxDroppedErrorPkts   = ETH_NOT_AVAILABLE;
  LpTxErrorCounterValues->TxDeferredTrans      = ETH_NOT_AVAILABLE;
  LpTxErrorCounterValues->TxSingleCollision    = ETH_NOT_AVAILABLE;
  LpTxErrorCounterValues->TxLateCollision      = ETH_NOT_AVAILABLE;
  LpTxErrorCounterValues->TxExcessiveCollison  = ETH_NOT_AVAILABLE;
}
#endif /* (ETH_GET_TX_ERROR_COUNTER_VALUES_API == STD_ON) */

/***********************************************************************************************************************
** Function Name         : Eth_HwMainFunction (ETNDE)
**
** Service ID            : N/A
**
** Description           : Check receive errors and report DEM if exist
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : None
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GaaETNE_ETHARegs, Eth_GaaDemEventRxFramesLost, Eth_GaaDemEventCRC,
**                         Eth_GaaDemEventUnderSizeFrame, Eth_GaaDemEventOverSizeFrame,
**                         Eth_GaaDemEventAlignment, Eth_GstETND_Regs, Eth_GaaCtrlStat
**
** Function(s) invoked   : Eth_DemConfigCheck
**
** Registers Used        : RPEFC, RFMEFC, RUEFC, ROEFC, RNEFC
**
** Reference ID          : ETH_DUD_ACT_320
** Reference ID          : ETH_DUD_ACT_320_ERR001, ETH_DUD_ACT_320_ERR002
** Reference ID          : ETH_DUD_ACT_320_ERR003, ETH_DUD_ACT_320_ERR004
** Reference ID          : ETH_DUD_ACT_320_ERR005
***********************************************************************************************************************/
FUNC(void, ETH_PRIVATE_CODE) Eth_HwMainFunction(void)                                                                   /* PRQA S 1532 # JV-01 */
{
  /* Report Extended DEM (if any) */
  uint32 LulCtrlIdx;
  uint32 LulAutoClearCounter;
  P2CONST(volatile Eth_ETNDE_RMACSRegType, AUTOMATIC, REGSPACE) LpRmacsRegs;

  for (LulCtrlIdx = 0UL; LulCtrlIdx < (uint32)ETH_TOTAL_CTRL_CONFIG; LulCtrlIdx++)                                      /* PRQA S 2877 # JV-01 */
  {
    #if (ETH_USING_MACRO == ETH_MACRO_ETND)
    LpRmacsRegs = &Eth_GstETND_Regs.pES[LulCtrlIdx]->stRMACSys;
    #else
    LpRmacsRegs = &Eth_GstETNE_Regs.pEA[LulCtrlIdx]->stRMACSys;
    #endif

    /* Read RPEFC - Rx Frame Lost Counter */
    if (0UL < LpRmacsRegs->ulRPEFC)                                                                                     /* PRQA S 2814 # JV-01 */
    {
      /* Call DEM */
      Eth_DemConfigCheck(Eth_GaaDemEventRxFramesLost[LulCtrlIdx], DEM_EVENT_STATUS_PREFAILED);
    } /* else: No action required */

    /* Read RFMEFC - FCS/mCRC Error Counter */
    LulAutoClearCounter = LpRmacsRegs->ulRFMEFC;
    #if (ETH_GET_RX_STATS_API == STD_ON)
    Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsCrcAlignErrors += LulAutoClearCounter;
    #endif
    #if (ETH_GET_COUNTER_VALUES_API == STD_ON)
    Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulDropPktCrc += LulAutoClearCounter;
    #endif
    if (0UL < LulAutoClearCounter)
    {
      /* Call DEM */
      Eth_DemConfigCheck(Eth_GaaDemEventCRC[LulCtrlIdx], DEM_EVENT_STATUS_PREFAILED);
    } /* else: No action required */

    /* Read RUEFC - Too Short Frame Counter */
    LulAutoClearCounter = LpRmacsRegs->ulRUEFC;
    #if (ETH_GET_RX_STATS_API == STD_ON)
    Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsUndersizePkts += LulAutoClearCounter;
    #endif
    #if (ETH_GET_COUNTER_VALUES_API == STD_ON)
    Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulUndersizePkt += LulAutoClearCounter;
    #endif
    if (0UL < LulAutoClearCounter)
    {
      /* Call DEM */
      Eth_DemConfigCheck(Eth_GaaDemEventUnderSizeFrame[LulCtrlIdx], DEM_EVENT_STATUS_PREFAILED);
    } /* else: No action required */

    /* Read ROEFC - Too Long Frames Counter */
    LulAutoClearCounter = LpRmacsRegs->ulROEFC;
    #if (ETH_GET_RX_STATS_API == STD_ON)
    Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsOversizePkts += LulAutoClearCounter;
    #endif
    #if (ETH_GET_COUNTER_VALUES_API == STD_ON)
    Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulOversizePkt += LulAutoClearCounter;
    #endif
    if (0UL < LulAutoClearCounter)
    {
      /* Call DEM */
      Eth_DemConfigCheck(Eth_GaaDemEventOverSizeFrame[LulCtrlIdx], DEM_EVENT_STATUS_PREFAILED);
    } /* else: No action required */

    /* Read RNEFC - Frame Alignment Error Counter */
    LulAutoClearCounter = LpRmacsRegs->ulRNEFC;
    #if (ETH_GET_RX_STATS_API == STD_ON)
    Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsCrcAlignErrors += LulAutoClearCounter;
    #endif
    #if (ETH_GET_COUNTER_VALUES_API == STD_ON)
    Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulAlgnmtErr += LulAutoClearCounter;
    #endif
    if (0UL < LulAutoClearCounter)
    {
      /* Call DEM */
      Eth_DemConfigCheck(Eth_GaaDemEventAlignment[LulCtrlIdx], DEM_EVENT_STATUS_PREFAILED);
    } /* else: No action required */
  }
}

#if (ETH_GLOBAL_TIME_SUPPORT == STD_ON)
/***********************************************************************************************************************
** Function Name         : Eth_HwGetCurrentTime
**
** Service ID            : NA
**
** Description           : Return TimeStamp from the HW register
**                         previously started.
**                       : It returns adjusted gPTP timer value (TCSS = 01)
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : LpTimeQualPtr  : Quality of the HW TimeStamp returned
**                       : LpTimeStampPtr : Current TimeStamp value
**
** Return parameter      : LucReturnValue E_OK / E_NOT_OK
**
** Preconditions         : Component Requires previous controller
**                         initialization using Eth_ControllerInit..
**
** Global Variable(s)    : Eth_GpETNE_MFWDRegs, Eth_GstETND_Regs
**
** Function(s) invoked   : None
**
** Registers Used        : TME, GCTt0, GCTt1, GCTt2
**
** Reference ID          : ETH_DUD_ACT_321
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_HwGetCurrentTime(                                                            /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx,                                                                                  /* PRQA S 3206 # JV-01 */
  CONSTP2VAR(Eth_TimeStampQualType, AUTOMATIC, ETH_APPL_DATA) LpTimeQualPtr,                                            /* PRQA S 3432 # JV-01 */
  CONSTP2VAR(Eth_TimeStampType, AUTOMATIC, ETH_APPL_DATA) LpTimeStampPtr)                                               /* PRQA S 3432 # JV-01 */
{
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2CONST(volatile Eth_ETNDE_GPTMARegType, AUTOMATIC, REGSPACE) LpGptmaRegs = Eth_GstETND_Regs.pGPTMA;
  #else
  CONSTP2CONST(volatile Eth_ETNDE_GPTMARegType, AUTOMATIC, REGSPACE) LpGptmaRegs = Eth_GstETNE_Regs.pGPTMA;
  #endif
  Std_ReturnType LucReturnValue;

  /* R-Switch should use only one gPTP timer domain */

  /* gPTP timer status check */
  if (0UL != (LpGptmaRegs->ulTME & ETH_GPTP_TIMER_DOMAIN_MASK))                                                         /* PRQA S 2814, 2844 # JV-01, JV-01 */
  {
    *LpTimeQualPtr = ETH_VALID;                                                                                         /* PRQA S 2814 # JV-01 */
    LucReturnValue = E_OK;
  }
  else
  {
    *LpTimeQualPtr = ETH_INVALID;
    LucReturnValue = E_NOT_OK;
  }

  /* Get the nanosecond part of the GPTP timer */
  LpTimeStampPtr->nanoseconds = LpGptmaRegs->stGptpCfg[ETH_GPTP_TIMER_DOMAIN].ulGCTt0;                                  /* PRQA S 2814 # JV-01 */
  /* Get the lower 32 bit of second part of the GPTP timer */
  LpTimeStampPtr->seconds = LpGptmaRegs->stGptpCfg[ETH_GPTP_TIMER_DOMAIN].ulGCTt1;
  /* Get the upper 16 bit of second part of the GPTP timer */
  LpTimeStampPtr->secondsHi = (uint16)LpGptmaRegs->stGptpCfg[ETH_GPTP_TIMER_DOMAIN].ulGCTt2;

  return LucReturnValue;
}

/***********************************************************************************************************************
** Function Name         : Eth_HwGetEgressTimeStamp
**
** Service ID            : NA
**
** Description           : Read TimeStamp from a message just transmitted
**                         if tag match with Buf idx
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant for the same Ctrl ,
**                         Re-entrant for different
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                       : LulBufIdx      : Index of the message buffer
**
** InOut Parameters      : None
**
** Output Parameters     : LpTimeQualPtr  : Quality of the Read TS
**                       : LpTimeStampPtr : Value passed above
**
** Return parameter      : None
**
** Preconditions         : Component Requires previous controller
**                         initialization using Eth_ControllerInit..
**
** Global Variable(s)    : Eth_GaaTxBufferMgrTable
**
** Function(s) invoked   : None
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_322
***********************************************************************************************************************/
FUNC(void, ETH_PRIVATE_CODE) Eth_HwGetEgressTimeStamp(                                                                  /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONST(Eth_BufIdxType, AUTOMATIC) LulBufIdx,
  CONSTP2VAR(Eth_TimeStampQualType, AUTOMATIC, ETH_APPL_DATA) LpTimeQualPtr,                                            /* PRQA S 3432 # JV-01 */
  CONSTP2VAR(Eth_TimeStampType, AUTOMATIC, ETH_APPL_DATA) LpTimeStampPtr)                                               /* PRQA S 3432 # JV-01 */
{
  P2CONST(Eth_BufHandlerType, AUTOMATIC, ETH_APPL_DATA) LpTxBufferNode;

  /* Get Tx buffer handler from the Tx buffer manager table */
  LpTxBufferNode = (Eth_BufHandlerType *)Eth_GaaTxBufferMgrTable[LulCtrlIdx][LulBufIdx].pBufferHdr;                     /* PRQA S 2824, 2844 # JV-01, JV-01 */

  *LpTimeQualPtr = LpTxBufferNode->enTimeQual;                                                                          /* PRQA S 2814 # JV-01 */

  *LpTimeStampPtr = LpTxBufferNode->stTimeStamp;                                                                        /* PRQA S 2814 # JV-01 */
}

/***********************************************************************************************************************
** Function Name         : Eth_HwGetIngressTimeStamp
**
** Service ID            : NA
**
** Description           : Read TimeStamp from a message received and
**                         store in Autosar Format
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant for the same Ctrl ,
**                         Re-entrant for different
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                         LpDataPtr      : Pointer to the message buffer,
**                                          where Application expects ingress time stamping
**
** InOut Parameters      : None
**
** Output Parameters     : LpTimeQualPtr  : Quality of the Time Stamp
**                       : LpTimeStampPtr : TS read from the Rx Descriptor.
**
** Return parameter      : None
**
** Preconditions         : Component Requires previous controller
**                         initialization using Eth_ControllerInit..
**
** Global Variables Used : Eth_GaaRxFrame
**
** Function(s) invoked   : None
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_323
***********************************************************************************************************************/
FUNC(void, ETH_PRIVATE_CODE) Eth_HwGetIngressTimeStamp(                                                                 /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONSTP2CONST(Eth_DataType, AUTOMATIC, ETH_APPL_DATA) LpDataPtr,
  CONSTP2VAR(Eth_TimeStampQualType, AUTOMATIC, ETH_APPL_DATA) LpTimeQualPtr,                                            /* PRQA S 3432 # JV-01 */
  CONSTP2VAR(Eth_TimeStampType, AUTOMATIC, ETH_APPL_DATA) LpTimeStampPtr)                                               /* PRQA S 3432 # JV-01 */
{
  P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA) LpCompPtr;                                                              /* PRQA S 3432, 3678 # JV-01, JV-01 */

  /* Read TimeStamp from the rxframe.Timestamp */
  LpCompPtr = (Eth_DataType *)(Eth_GaaRxFrame[LulCtrlIdx].ulEthTypeAddr + (uint32)ETH_ETHERTYPE_SIZE);                  /* PRQA S 0306, 2844, 3383 # JV-01, JV-01, JV-01 */
  if (LpCompPtr == LpDataPtr)
  {
    LpTimeStampPtr->nanoseconds = Eth_GaaRxFrame[LulCtrlIdx].ulTsns;                                                    /* PRQA S 2814 # JV-01 */
    LpTimeStampPtr->seconds = Eth_GaaRxFrame[LulCtrlIdx].ulTss;
    LpTimeStampPtr->secondsHi = 0U;
    /* TimeStamp is valid  */
    *LpTimeQualPtr = ETH_VALID;                                                                                         /* PRQA S 2814 # JV-01 */
  }
  else
  {
    LpTimeStampPtr->nanoseconds = 0UL;
    LpTimeStampPtr->seconds = 0UL;
    LpTimeStampPtr->secondsHi = 0U;
    /* TimeStamp is invalid  */
    *LpTimeQualPtr = ETH_INVALID;
  }
}

/***********************************************************************************************************************
** Function Name         : Eth_HwSetIncrementTimeForGptp
**
** Service ID            : NA
**
** Description           : Set a value to GTI and issue a load request
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant for the same Ctrl ,
**                         Re-entrant for different
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                         LulIncVal      : New increment value for the gPTP timer
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : E_OK - GTIVt update success
**
** Preconditions         : Component Requires previous controller
**                         initialization using Eth_ControllerInit..
**
** Global Variable(s)    : Eth_GpETNE_MFWDRegs, Eth_GstETND_Regs
**
** Function(s) invoked   : None
**
** Registers Used        : GTIVt
**
** Reference ID          : ETH_DUD_ACT_324
** Reference ID          : ETH_DUD_ACT_324_REG001
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_HwSetIncrementTimeForGptp(                                                   /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONST(uint32, AUTOMATIC) LulIncVal)                                              /* PRQA S 3206 # JV-01 */
{
  /* R-Switch should use only one gPTP timer domain */
  #if (ETH_USING_MACRO == ETH_MACRO_ETND) 
  Eth_GstETND_Regs.pGPTMA->stGptpCfg[ETH_GPTP_TIMER_DOMAIN].ulGTIVt = LulIncVal;
  #else
  Eth_GstETNE_Regs.pGPTMA->stGptpCfg[ETH_GPTP_TIMER_DOMAIN].ulGTIVt = LulIncVal;
  #endif

  return E_OK;
}

/***********************************************************************************************************************
** Function Name         : Eth_HwSetOffsetTimeForGptp
**
** Service ID            : NA
**
** Description           : Adjust gPTP with an given delta
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant for the same Ctrl,
**                         Re-entrant for different
**
** Input Parameters      : LulCtrlIdx     : Index of a controller
**                       : LpTimeOffsetPtr: Delta TimeStamp
**
** InOut Parameters      : None
**
** Output Parameters     : E_OK - gPTP Request is completed w/o timeout
**                       : E_NOT_OK - gPTP Request not completed due to timeout
**
** Return parameter      : LucReturnValue - E_OK / E_NOT_OK
**
** Preconditions         : Component Requires previous controller
**                         initialization using Eth_ControllerInit.
**
** Global Variable(s)    : Eth_GpETNE_MFWDRegs, Eth_GstETND_Regs
**
** Function(s) invoked   : None
**
** Registers Used        : GTOVt0, GTOVt1, GTOVt2
**
** Reference ID          : ETH_DUD_ACT_325
** Reference ID          : ETH_DUD_ACT_325_REG001
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_HwSetOffsetTimeForGptp(                                                      /* PRQA S 1532 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx,                                                                                  /* PRQA S 3206 # JV-01 */
  CONSTP2CONST(Eth_TimeStampType, AUTOMATIC, ETH_APPL_DATA) LpTimeOffsetPtr)
{
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2VAR(volatile Eth_ETNDE_GPTPCFGRegType, AUTOMATIC, REGSPACE) LpGptpRegs =
    &Eth_GstETND_Regs.pGPTMA->stGptpCfg[ETH_GPTP_TIMER_DOMAIN];
  #else
  CONSTP2VAR(volatile Eth_ETNDE_GPTPCFGRegType, AUTOMATIC, REGSPACE) LpGptpRegs =
    &Eth_GstETNE_Regs.pGPTMA->stGptpCfg[ETH_GPTP_TIMER_DOMAIN];
  #endif

  /* R-Switch should use only one gPTP timer domain */
  /* Set the upper 16 bit of second part of the GPTP timer GTOVt1 (t = 0 to PTPTN-1) */
  LpGptpRegs->ulGTOVt2 = (uint32)LpTimeOffsetPtr->secondsHi;                                                            /* PRQA S 2814 # JV-01 */

  /* Set the lower 32 bit of second part of the GPTP timer GTOVt1 (t = 0 to PTPTN-1) */
  LpGptpRegs->ulGTOVt1 = LpTimeOffsetPtr->seconds;

  /* Set the nanosecond part of the GPTP timer GTOVt0 (t = 0 to PTPTN-1) */
  if (LpTimeOffsetPtr->nanoseconds > ETH_GPTP_OFFSET_NANOSEC_MAXVALUE)
  {
    /* The upper limit is 0x3B9AC9FF */
    LpGptpRegs->ulGTOVt0 = ETH_GPTP_OFFSET_NANOSEC_MAXVALUE;
  }
  else
  {
    LpGptpRegs->ulGTOVt0 = LpTimeOffsetPtr->nanoseconds;
  }

  return E_OK;
}

/***********************************************************************************************************************
** Function Name         : Eth_TsDescConfig
**
** Service ID            : NA
**
** Description           : Create timestamp descriptor chain & learning descriptor.
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : None
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpETNE_MFWDRegs, Eth_GaaDescTsChain, Eth_GaaDescTsChainTable
**                         Eth_GaaTsDescTotal
**
** Function(s) invoked   : None
**
** Registers Used        : TSSs, TSAs
**
** Reference ID          : ETH_DUD_ACT_334
** Reference ID          : ETH_DUD_ACT_334_GBL001, ETH_DUD_ACT_334_GBL002
** Reference ID          : ETH_DUD_ACT_334_GBL003, ETH_DUD_ACT_334_GBL004
** Reference ID          : ETH_DUD_ACT_334_GBL005, ETH_DUD_ACT_334_GBL006
** Reference ID          : ETH_DUD_ACT_334_GBL007, ETH_DUD_ACT_334_GBL008
** Reference ID          : ETH_DUD_ACT_334_GBL009, ETH_DUD_ACT_334_GBL010
** Reference ID          : ETH_DUD_ACT_334_GBL011
** Reference ID          : ETH_DUD_ACT_334_REG001, ETH_DUD_ACT_334_REG002
***********************************************************************************************************************/
#if (ETH_USING_MACRO == ETH_MACRO_ETND)
FUNC(void, ETH_PRIVATE_CODE) Eth_TsDescConfig(CONST(uint32, AUTOMATIC) LulCtrlIdx)                                      /* PRQA S 1532 # JV-01 */
#else
FUNC(void, ETH_PRIVATE_CODE) Eth_TsDescConfig(void)
#endif
{
  P2VAR(Eth_ExtDescWithTsType, AUTOMATIC, ETH_APPL_DATA) LpDescTsChain;                                                 /* PRQA S 3432 # JV-01 */
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs =
    &Eth_GstETND_Regs.pES[LulCtrlIdx]->stAXIBMI;                                                                        /* PRQA S 2844 # JV-01 */
  #else
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs = Eth_GstETNE_Regs.pAXIBMI;
  #endif
  uint32 LulCnt;

  /* TS descriptor chain setting */
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  for (LulCnt = 0UL; LulCnt < Eth_GaaTsDescTotal[LulCtrlIdx]; LulCnt++)                                                 /* PRQA S 2844 # JV-01 */
  #else
  for (LulCnt = 0UL; LulCnt < (uint32)ETH_MAX_TS_DESCRIPTOR; LulCnt++)
  #endif
  {
    #if (ETH_USING_MACRO == ETH_MACRO_ETND)
    LpDescTsChain = &Eth_GaaDescTsChainTable[LulCtrlIdx][LulCnt];                                                       /* PRQA S 2844, 2824 # JV-01, JV-01 */
    #else
    LpDescTsChain = &Eth_GaaDescTsChain[LulCnt];
    #endif
    
    /* Set frame empty type */
    LpDescTsChain->stHeader.ulDie = (uint32)ETH_TS_DESC_DIE_ENABLE;                                                     /* PRQA S 2814 # JV-01 */
    LpDescTsChain->stHeader.ulAxie = (uint32)0UL;
    LpDescTsChain->stHeader.ulDse = (uint32)0UL;
    LpDescTsChain->stHeader.ulInfo0 = (uint32)0UL;
    LpDescTsChain->stHeader.ulDs = (uint32)0UL;
    LpDescTsChain->ulDptr = 0UL;
    LpDescTsChain->ulInfo1[0] = 0UL;
    LpDescTsChain->ulInfo1[1] = 0UL;
    LpDescTsChain->ulTsns = 0UL;
    LpDescTsChain->ulTss = 0UL;
    LpDescTsChain->stHeader.ulDt = (uint32)ETH_DESC_FEMPTY_ND;
  }
  /* Set link type for cyclic descriptor */
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  LpDescTsChain = &Eth_GaaDescTsChainTable[LulCtrlIdx][LulCnt];
  #else
  LpDescTsChain = &Eth_GaaDescTsChain[LulCnt];
  #endif
  LpDescTsChain->stHeader.ulDie   = (uint32)0UL;                                                                        /* PRQA S 2814 # JV-01 */
  LpDescTsChain->stHeader.ulAxie  = (uint32)0UL;
  LpDescTsChain->stHeader.ulDse   = (uint32)0UL;
  LpDescTsChain->stHeader.ulInfo0 = (uint32)0UL;
  LpDescTsChain->stHeader.ulDs    = (uint32)0UL;
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  LpDescTsChain->ulDptr = (uint32)&Eth_GaaDescTsChainTable[LulCtrlIdx][0];                                              /* PRQA S 0306 # JV-01 */
  #else
  LpDescTsChain->ulDptr = (uint32)&Eth_GaaDescTsChain[0];
  #endif
  LpDescTsChain->ulInfo1[0] = 0UL;
  LpDescTsChain->ulInfo1[1] = 0UL;
  LpDescTsChain->ulTsns = 0UL;
  LpDescTsChain->ulTss = 0UL;
  LpDescTsChain->stHeader.ulDt = (uint32)ETH_DESC_LINK;

  /* Learning Ts descriptor table */
  LpAxiRegs->stTSD[0].ulTSSs = ETH_ETNDE_TSS_CONFIG;                                                                    /* PRQA S 2814 # JV-01 */
  LpAxiRegs->stTSD[0].ulTSAs = LpDescTsChain->ulDptr;
}

/***********************************************************************************************************************
** Function Name         : Eth_TasAdminLearning
**
** Service ID            : NA
**
** Description           : Learning TAS admin control list table
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LulCtrlIdx : Index of a controller
**                       : LulCtrlAddress : TAS admin control address.
**                       : LpCtrlConfig : TAS admin control information.
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : E_OK - Succeeded in learning TAS admin control.
**                         E_NOT_OK - Failed in learning TAS admin control.
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GstETND_Regs, Eth_GaaETNE_ETHARegs
**
** Function(s) invoked   : GetCounterValue, Eth_GetTimeOutValue
**
** Registers Used        : TACLL0, TACLL1, TACLL2
**
** Reference ID          : ETH_DUD_ACT_347
** Reference ID          : ETH_DUD_ACT_347_REG001, ETH_DUD_ACT_347_REG002
***********************************************************************************************************************/
STATIC FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_TasAdminLearning(
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONST(uint32, AUTOMATIC) LulCtrlAddress,
  CONSTP2CONST(Eth_TASEntryType, AUTOMATIC, ETH_APPL_DATA) LpCtrlConfig)
{
  TickType LulTickStart;
  TickType LulTickElap;
  Std_ReturnType LucResult;

  /* Tx Descriptor Address Table learning */
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTACLL0 =                                                                    /* PRQA S 2844 # JV-01 */
    (uint32)(((uint32)LpCtrlConfig->enGateState << 28UL) | LpCtrlConfig->ulTimeInterval);                               /* PRQA S 2814 # JV-01 */
  Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTACLL1 = LulCtrlAddress;
  Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTACLL2 = ETH_ETNDE_TACLL2_LEARNING;
  #else
  Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTACLL0 =
    ((LpCtrlConfig->enGateState << 28UL) | LpCtrlConfig->ulTimeInterval);
  Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTACLL1 = LulCtrlAddress;
  Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTACLL2 = ETH_ETNDE_TACLL2_LEARNING;
  #endif

  LulTickStart = 0UL;
  (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
  do
  {
    LulTickElap = Eth_GetTimeOutValue(LulTickStart);
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  } while ((0UL != (Eth_GstETND_Regs.pES[LulCtrlIdx]->stMHD.ulTACLL2 & ETH_ETNDE_TACLL2_LEARNING)) &&
           (LulTickElap <= ETH_TIMEOUT_COUNT));
  #else
  } while ((0UL != (Eth_GstETNE_Regs.pEA[LulCtrlIdx]->ulTACLL2 & ETH_ETNDE_TACLL2_LEARNING)) &&
           (LulTickElap <= ETH_TIMEOUT_COUNT));
  #endif

  if (ETH_TIMEOUT_COUNT < LulTickElap)
  {
    LucResult = E_NOT_OK;
  }
  else
  {
    LucResult = E_OK;
  }

  return LucResult;
}
#endif /* (ETH_GLOBAL_TIME_SUPPORT == STD_ON) */

/***********************************************************************************************************************
** Function Name         : Eth_SGMIIInit (ETNDE)
**
** Service ID            : N/A
**
** Description           : Initialize SGMII for ETND/ETNE HWUnit
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non Reentrant
**
** Input Parameters      : LulCtrlIdx : Index of a controller
**                       : LenBypassMode : Bypass mode
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GstETNE_Regs, Eth_GstETND_Regs
**
** Function(s) invoked   : None
**
** Registers Used        : ulETNDEzSGSRST, ulETNDEzSGSDS, ulETNDEzSGCLKSEL, ulETNDEzSGRCIE, ulETNDEzSGINTM
**
** Reference ID          : ETH_DUD_ACT_326,
** Reference ID          : ETH_DUD_ACT_326_REG001, ETH_DUD_ACT_326_REG002
** Reference ID          : ETH_DUD_ACT_326_REG003, ETH_DUD_ACT_326_REG004
** Reference ID          : ETH_DUD_ACT_326_REG005, ETH_DUD_ACT_326_REG006
** Reference ID          : ETH_DUD_ACT_326_REG007
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_SGMIIInit(
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONST(Eth_OptionType, AUTOMATIC) LenBypassMode)
{
  uint8 LucRegVal;
  Std_ReturnType LucResult;
  TickType LulTickStart;
  TickType LulTickElap;

  LucResult = E_OK;

  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2VAR(volatile Eth_ETNDE_SGMIIRegType, AUTOMATIC, REGSPACE) LpSgmiiRegs = Eth_GstETND_Regs.pSGMII;
  (void)LulCtrlIdx;
  #else
  CONSTP2VAR(volatile Eth_ETNDE_SGMIIRegType, AUTOMATIC, REGSPACE) LpSgmiiRegs = Eth_GstETNE_Regs.pSGMII[LulCtrlIdx];
  #endif

  /* Execute SW-Reset on SGMII interface */
  LpSgmiiRegs->ulETNDEzSGSRST = ETH_ETNDE_SGSRST_SRST;
  LpSgmiiRegs->ulETNDEzSGSRST = 0UL;

  /* Wait 4us */
  Eth_WaitNanoSec(ETH_ETNDE_WAIT_FOR_SGMII);

  /* Wait until the power supply for the SGMII SerDes is turned on */
  /* (ETNB1SGSDS.PWS[1:0] == 11B) */
  LulTickStart = 0UL;
  (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
  do
  {
    LulTickElap = Eth_GetTimeOutValue(LulTickStart);
    LucRegVal = LpSgmiiRegs->stPWRCTL.ulETNDEzSGSDS & ETH_ETNDE_SGSDS_PWS_ON;
  } while ((LucRegVal != ETH_ETNDE_SGSDS_PWS_ON) && (LulTickElap <= ETH_TIMEOUT_COUNT));

  if (ETH_TIMEOUT_COUNT < LulTickElap)
  {
    /* Timeout */
    LucResult = E_NOT_OK;
  } /* else: No action required */


  /* Select the reference clock */
  /* Set the reference clock, enable the clock input and wait until it is stable, if applicable */
  /* This setting is allowed only when MOSC is 20 MHz. */
  LpSgmiiRegs->stPWRCTL.ulETNDEzSGCLKSEL = ETH_ETNDE_SGCLKSEL_SEL;

  /* Wait until the reference clock which is supplied by the external
    oscillator or the internal MainOSC becomes stable */

  /* Enable the reference clock input */
  LpSgmiiRegs->stPWRCTL.ulETNDEzSGRCIE = ETH_ETNDE_SGRCIE_RCIE;

  /* Wait until the SerDes startup is completed */
  LulTickStart = 0UL;
  (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
  do
  {
    LulTickElap = Eth_GetTimeOutValue(LulTickStart);
    LucRegVal = LpSgmiiRegs->stPWRCTL.ulETNDEzSGSDS & ETH_ETNDE_SGSDS_SUC;
  } while ((LucRegVal != (uint32)ETH_ETNDE_SGSDS_SUC) && (LulTickElap <= ETH_TIMEOUT_COUNT));

  if (ETH_TIMEOUT_COUNT < LulTickElap)
  {
    /* Timeout */
    LucResult = E_NOT_OK;
  } /* else: No action required */

  if (ETH_ENABLE == LenBypassMode)
  {
    /* Manual set the operation mode */
    switch (Eth_GpEthConfigPtr[LulCtrlIdx].enEthSpeed)
    {
    case ETH_MAC_LAYER_SPEED_10M:
      /* Set operation mode to 10base */
      LpSgmiiRegs->ulETNDEzSGOPMC = ETH_ETNDE_SGOPMC_10M;
      break;
    case ETH_MAC_LAYER_SPEED_100M:
      /* Set operation mode to 100base */
      LpSgmiiRegs->ulETNDEzSGOPMC = ETH_ETNDE_SGOPMC_100M;
      break;
    default:
      /* Set operation mode to 1000base */
      LpSgmiiRegs->ulETNDEzSGOPMC = ETH_ETNDE_SGOPMC_1G;
      break;
    }
  } /* else: No action required */

  /* Enable Ready Interrupt */
  LpSgmiiRegs->ulETNDEzSGINTM = (uint32)~(ETH_ETNDE_SGINTM_URDYIM | ETH_ETNDE_SGINTM_RDYIM);

  return LucResult;
}

/***********************************************************************************************************************
** Function Name         : Eth_WaitNanoSec
**
** Service ID            : NA
**
** Description           : Wait for the specified nanosecond.
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LulNanosec     : Waiting time (nano sec)
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : None
**
** Preconditions         : None
**
** Global Variable(s)    : None
**
** Function(s) invoked   : None
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_327
***********************************************************************************************************************/
STATIC FUNC(void, ETH_PRIVATE_CODE) Eth_WaitNanoSec(CONST(uint32, AUTOMATIC) LulNanosec)
{
  CONST(uint32, AUTOMATIC) LulCycle = ETH_NS2HZ(LulNanosec) + 1UL;
  volatile uint32 LulCount;

  for (LulCount = 0UL; LulCount < LulCycle; LulCount++)
  {
    /* No action required */
  }
}

/***********************************************************************************************************************
** Function Name         : Eth_TxDescLearning
**
** Service ID            : NA
**
** Description           : Learning tx descriptor chain table
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LpAxiRegs : AXIBMI registers.
**                       : LulEntryNum : Table entry number.
**                       : LulChainAddr : Tx descriptor chain address.
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : E_OK - Succeeded in learning Tx descriptor.
**                         E_NOT_OK - Failed in learning Tx descriptor.
**
** Preconditions         : None
**
** Global Variable(s)    : None
**
** Function(s) invoked   : GetCounterValue, Eth_GetTimeOutValue
**
** Registers Used        : TATLS0, TATLS1, TATLR
**
** Reference ID          : ETH_DUD_ACT_337
** Reference ID          : ETH_DUD_ACT_337_REG001, ETH_DUD_ACT_337_REG002
** Reference ID          : ETH_DUD_ACT_337_REG003, ETH_DUD_ACT_337_REG004
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_TxDescLearning(
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs,
  CONST(uint32, AUTOMATIC) LulEntryNum,
  CONST(uint32, AUTOMATIC) LulChainAddr)
{
  TickType LulTickStart;
  TickType LulTickElap;
  Std_ReturnType LucResult;

  /* Tx Descriptor Address Table learning */
  LpAxiRegs->ulTATLS0 = ETH_ETNDE_TATLS0_CONFIG | (LulEntryNum << 24UL);                                                /* PRQA S 2814 # JV-01 */
  LpAxiRegs->ulTATLS1 = LulChainAddr;
  LpAxiRegs->ulTATLR = ETH_ETNDE_TATLR_LEARNING;

  LulTickStart = 0UL;
  (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
  do
  {
    LulTickElap = Eth_GetTimeOutValue(LulTickStart);
  } while ((0UL != (LpAxiRegs->ulTATLR & ETH_ETNDE_TATLR_LEARNING)) && (LulTickElap <= ETH_TIMEOUT_COUNT));

  if ((ETH_TIMEOUT_COUNT < LulTickElap) || (0UL != (LpAxiRegs->ulTATLR & ETH_ETNDE_TATLR_FAILED)))
  {
    LucResult = E_NOT_OK;
  }
  else
  {
    LucResult = E_OK;
  }

  return LucResult;
}

/***********************************************************************************************************************
** Function Name         : Eth_RxDescLearning
**
** Service ID            : NA
**
** Description           : Learning rx descriptor chain table
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LpAxiRegs : AXIBMI registers.
**                       : LulEntryNum : Table entry number.
**                       : LulChainAddr : Rx descriptor chain address.
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : E_OK - Succeeded in learning Rx descriptor.
**                         E_NOT_OK - Failed in learning Rx descriptor.
**
** Preconditions         : None
**
** Global Variable(s)    : None
**
** Function(s) invoked   : GetCounterValue, Eth_GetTimeOutValue
**
** Registers Used        : RATLS0, RATLS1, RATLR
**
** Reference ID          : ETH_DUD_ACT_338
** Reference ID          : ETH_DUD_ACT_338_REG001, ETH_DUD_ACT_338_REG002
** Reference ID          : ETH_DUD_ACT_338_REG003, ETH_DUD_ACT_338_REG004
***********************************************************************************************************************/
STATIC FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_RxDescLearning(
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs,
  CONST(uint32, AUTOMATIC) LulEntryNum,
  CONST(uint32, AUTOMATIC) LulChainAddr)
{
  TickType LulTickStart;
  TickType LulTickElap;
  Std_ReturnType LucResult;

  /* Rx Descriptor Address Table learning */
  LpAxiRegs->ulRATLS0 = ETH_ETNDE_RATLS0_CONFIG | (LulEntryNum << 24UL);                                                /* PRQA S 2814 # JV-01 */
  LpAxiRegs->ulRATLS1 = LulChainAddr;
  LpAxiRegs->ulRATLR = ETH_ETNDE_RATLR_LEARNING;

  LulTickStart = 0UL;
  (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
  do
  {
    LulTickElap = Eth_GetTimeOutValue(LulTickStart);
  } while ((0UL != (LpAxiRegs->ulRATLR & ETH_ETNDE_RATLR_LEARNING)) && (LulTickElap <= ETH_TIMEOUT_COUNT));

  if ((ETH_TIMEOUT_COUNT < LulTickElap) || (0UL != (LpAxiRegs->ulRATLR & ETH_ETNDE_RATLR_FAILED)))
  {
    LucResult = E_NOT_OK;
  }
  else
  {
    LucResult = E_OK;
  }

  return LucResult;
}

/***********************************************************************************************************************
** Function Name         : Eth_TxRxDescConfig
**
** Service ID            : NA
**
** Description           : Create descriptor chain & learning descriptor.
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LulCtrlIdx : Index of a controller
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : E_OK - Success in learning Tx/Rx descriptor.
**                         E_NOT_OK - Faile in learning Tx/Rx descriptor.
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpCtrlConfigPtr, Eth_GaaHeap, Eth_GaaCtrlStat,
**                         Eth_GstETND_Regs, Eth_GpETNE_MFWDRegs
**
** Function(s) invoked   : Eth_Util_RamAlloc, Eth_TxDescLearning,
**                         Eth_RxDescLearning
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_339
** Reference ID          : ETH_DUD_ACT_339_GBL001, ETH_DUD_ACT_339_GBL002,
** Reference ID          : ETH_DUD_ACT_339_GBL003, ETH_DUD_ACT_339_GBL004
***********************************************************************************************************************/
FUNC(Std_ReturnType, ETH_PRIVATE_CODE) Eth_TxRxDescConfig(CONST(uint32, AUTOMATIC) LulCtrlIdx)                          /* PRQA S 1532 # JV-01 */
{
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  P2VAR(Eth_ExtDescType, AUTOMATIC, ETH_APPL_DATA) LpDescChain;                                                         /* PRQA S 3432 # JV-01 */
  P2VAR(Eth_ExtDescWithTsType, AUTOMATIC, ETH_APPL_DATA) LpDescTsChain;                                                 /* PRQA S 3432 # JV-01 */
  P2VAR(uint8, AUTOMATIC, ETH_APPL_DATA) LpRxBuffer;                                                                    /* PRQA S 3432, 3678 # JV-01, JV-01 */
  uint32 LulTxQueueMax;
  uint32 LulRxQueueMax;
  uint32 LulRxBufferIndex;
  uint32 LulCntI;
  uint32 LulCntJ;
  Std_ReturnType LucResult;

  LucResult = E_OK;

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */
  LulTxQueueMax = (uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfTxQueue;                                              /* PRQA S 2814 # JV-01 */
  LulRxQueueMax = (uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfRxQueue;

  Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pBufTxCnt = (P2VAR(uint32, AUTOMATIC, ETH_APPL_DATA))                            /* PRQA S 2844, 0316, 3432 # JV-01, JV-01, JV-01 */
    Eth_Util_RamAlloc(&Eth_GaaHeap[LulCtrlIdx], sizeof(uint32) * LulTxQueueMax);                                        /* PRQA S 2934, 3383 # JV-01, JV-01 */

  Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pTxAllocCnt = (P2VAR(uint32, AUTOMATIC, ETH_APPL_DATA))                          /* PRQA S 2844, 0316, 3432 # JV-01, JV-01, JV-01 */
    Eth_Util_RamAlloc(&Eth_GaaHeap[LulCtrlIdx], sizeof(uint32) * LulTxQueueMax);                                        /* PRQA S 2934, 3383 # JV-01, JV-01 */

  Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc = (P2VAR(Eth_ExtDescType *, AUTOMATIC, ETH_APPL_DATA))              /* PRQA S 2844, 0316, 3432 # JV-01, JV-01, JV-01 */
    Eth_Util_RamAlloc(&Eth_GaaHeap[LulCtrlIdx], sizeof(Eth_ExtDescType *) * LulTxQueueMax);                             /* PRQA S 2934, 3383 # JV-01, JV-01 */

  Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppNextTxDesc = (P2VAR(Eth_ExtDescType *, AUTOMATIC, ETH_APPL_DATA))              /* PRQA S 2844, 0316, 3432 # JV-01, JV-01, JV-01 */
    Eth_Util_RamAlloc(&Eth_GaaHeap[LulCtrlIdx], sizeof(Eth_ExtDescType *) * LulTxQueueMax);                             /* PRQA S 2934, 3383 # JV-01, JV-01 */

  Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc = (P2VAR(Eth_ExtDescWithTsType *, AUTOMATIC, ETH_APPL_DATA))        /* PRQA S 2844, 0316, 3432 # JV-01, JV-01, JV-01 */
    Eth_Util_RamAlloc(&Eth_GaaHeap[LulCtrlIdx], sizeof(Eth_ExtDescWithTsType *) * LulRxQueueMax);                       /* PRQA S 2934, 3383 # JV-01, JV-01 */

  if ((NULL_PTR == Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pBufTxCnt) ||
      (NULL_PTR == Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pTxAllocCnt) ||
      (NULL_PTR == Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc) ||
      (NULL_PTR == Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppNextTxDesc) ||
      (NULL_PTR == Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc))
  {
    LucResult = E_NOT_OK;
  } /* else: No action required */

  /* Create Tx descriptor */
  for (LulCntI = 0UL; (LulCntI < LulTxQueueMax) && (E_OK == LucResult); LulCntI++)
  {
    Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pBufTxCnt[LulCntI] = 0UL;                                                      /* PRQA S 2844, 2824 # JV-01, JV-01 */
    Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.pTxAllocCnt[LulCntI] = 0UL;

    LpDescChain = (P2VAR(Eth_ExtDescType, AUTOMATIC, ETH_APPL_DATA))                                                    /* PRQA S 0316, 3432 # JV-01, JV-01 */
      Eth_Util_RamAlloc(&Eth_GaaHeap[LulCtrlIdx],                                                                       /* PRQA S 2934 # JV-01 */
                        (LpHwUnitConfig->stQueueConfig.pTxQueueConfig[LulCntI].ulQueueBufs + ETH_CYCLIC_DESC_NUM)       /* PRQA S 2824, 3383 # JV-01, JV-01 */
                        * ETH_EXT_DESC_SIZE);                                                                           /* PRQA S 3384 # JV-01 */

    if (NULL_PTR == LpDescChain)
    {
      LucResult = E_NOT_OK;
      break;
    } /* else: No action required */

    /* Store the head Tx descriptor address */
    Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppNextTxDesc[LulCntI] = LpDescChain;                                           /* PRQA S 2844, 2824 # JV-01, JV-01 */
    Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc[LulCntI] = LpDescChain;

    /* Set descriptor chain */
    for (LulCntJ = 0UL; LulCntJ < LpHwUnitConfig->stQueueConfig.pTxQueueConfig[LulCntI].ulQueueBufs; LulCntJ++)
    {
      /* Set frame empty type */
      LpDescChain->stHeader.ulDie   = (uint32)0UL;
      LpDescChain->stHeader.ulAxie  = (uint32)0UL;
      LpDescChain->stHeader.ulDse   = (uint32)0UL;
      LpDescChain->stHeader.ulInfo0 = (uint32)0UL;
      LpDescChain->stHeader.ulDs    = (uint32)0UL;
      LpDescChain->ulDptr           = 0UL;
      LpDescChain->ulInfo1[0]       = 0UL;
      LpDescChain->ulInfo1[1]       = 0UL;
      LpDescChain->stHeader.ulDt    = (uint32)ETH_DESC_FEMPTY;

      /* Next data descriptor */
      LpDescChain++;
    }
    /* Set link type for cyclic descriptor */
    LpDescChain->stHeader.ulDie   = (uint32)0UL;                                                                        /* PRQA S 2814 # JV-01 */
    LpDescChain->stHeader.ulAxie  = (uint32)0UL;
    LpDescChain->stHeader.ulDse   = (uint32)0UL;
    LpDescChain->stHeader.ulInfo0 = (uint32)0UL;
    LpDescChain->stHeader.ulDs    = (uint32)0UL;
    LpDescChain->ulDptr           = (uint32)Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc[LulCntI];                 /* PRQA S 0306 # JV-01 */
    LpDescChain->ulInfo1[0]       = 0UL;
    LpDescChain->ulInfo1[1]       = 0UL;
    LpDescChain->stHeader.ulDt    = (uint32)ETH_DESC_LINK;
  }

  /* Create Rx descriptor */
  LulRxBufferIndex = 0UL;
  for (LulCntI = 0UL; (LulCntI < LulRxQueueMax) && (E_OK == LucResult); LulCntI++)
  {
    LpDescTsChain = (P2VAR(Eth_ExtDescWithTsType, AUTOMATIC, ETH_APPL_DATA))                                            /* PRQA S 0316, 3432 # JV-01, JV-01 */
      Eth_Util_RamAlloc(&Eth_GaaHeap[LulCtrlIdx],                                                                       /* PRQA S 2934 # JV-01 */
                        (LpHwUnitConfig->stQueueConfig.pRxQueueConfig[LulCntI].ulQueueBufs + ETH_CYCLIC_DESC_NUM)       /* PRQA S 2824, 3383 # JV-01, JV-01 */
                        * ETH_EXT_DESC_TS_SIZE);                                                                        /* PRQA S 3384 # JV-01 */

    if (NULL_PTR == LpDescTsChain)
    {
      LucResult = E_NOT_OK;
      break;
    } /* else: No action required */

    /* Store the head Rx descriptor address */
    Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc[LulCntI] = LpDescTsChain;                                         /* PRQA S 2844, 2824 # JV-01, JV-01 */

    /* Set Rx descriptor chain */
    for (LulCntJ = 0UL; LulCntJ < LpHwUnitConfig->stQueueConfig.pRxQueueConfig[LulCntI].ulQueueBufs; LulCntJ++)
    {
      LpRxBuffer = (P2VAR(uint8, AUTOMATIC, ETH_APPL_DATA))                                                             /* PRQA S 0316, 3432 # JV-01, JV-01 */
        Eth_Util_RamAlloc(&Eth_GaaHeap[LulCtrlIdx],                                                                     /* PRQA S 2934 # JV-01 */
          LpHwUnitConfig->stRxConfig.ulMaxFrameSize + (uint32)sizeof(Eth_BufIdxType) + ETH_RX_DPTR_OFFSET);             /* PRQA S 3383 # JV-01 */

      if (NULL_PTR == LpRxBuffer)
      {
        /* Allocation memory error due to lack of resources */
        LucResult = E_NOT_OK;
        break;
      } /* else: No action required */

      /* Add receive buffer index */
      *(P2VAR(Eth_BufIdxType, AUTOMATIC, ETH_APPL_DATA))LpRxBuffer = LulRxBufferIndex;                                  /* PRQA S 3305, 0310, 3432 # JV-01, JV-01, JV-01 */
      LulRxBufferIndex++;                                                                                               /* PRQA S 3383 # JV-01 */

      /* Set frame empty type */
      LpDescTsChain->stHeader.ulDie   = (uint32)ETH_RX_DESC_DIE_ENABLE;
      LpDescTsChain->stHeader.ulAxie  = (uint32)0UL;
      LpDescTsChain->stHeader.ulDse   = (uint32)0UL;
      LpDescTsChain->stHeader.ulInfo0 = (uint32)0UL;
      LpDescTsChain->stHeader.ulDs    = LpHwUnitConfig->stRxConfig.ulMaxFrameSize;
      LpDescTsChain->ulDptr           = (uint32)(LpRxBuffer + (uint32)sizeof(Eth_BufIdxType) + ETH_RX_DPTR_OFFSET);     /* PRQA S 0306, 0488 # JV-01, JV-01 */
      LpDescTsChain->ulInfo1[0]       = 0UL;
      LpDescTsChain->ulInfo1[1]       = 0UL;
      LpDescTsChain->ulTsns           = 0UL;
      LpDescTsChain->ulTss            = 0UL;
      LpDescTsChain->stHeader.ulDt    = (uint32)ETH_DESC_FEMPTY;

      /* Next data descriptor */
      LpDescTsChain++;
    }
    /* Set link type for cyclic descriptor */
    LpDescTsChain->stHeader.ulDie   = (uint32)0UL;                                                                      /* PRQA S 2814 # JV-01 */
    LpDescTsChain->stHeader.ulAxie  = (uint32)0UL;
    LpDescTsChain->stHeader.ulDse   = (uint32)0UL;
    LpDescTsChain->stHeader.ulInfo0 = (uint32)0UL;
    LpDescTsChain->stHeader.ulDs    = (uint32)0UL;
    LpDescTsChain->ulDptr           = (uint32)Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc[LulCntI];               /* PRQA S 0306, 2844, 2824 # JV-01, JV-01, JV-01 */
    LpDescTsChain->ulInfo1[0]       = 0UL;
    LpDescTsChain->ulInfo1[1]       = 0UL;
    LpDescTsChain->ulTsns           = 0UL;
    LpDescTsChain->ulTss            = 0UL;
    LpDescTsChain->stHeader.ulDt    = (uint32)ETH_DESC_LINK;
  }

  if (E_OK == LucResult)
  {
    /* Learning Tx descriptor table */
    for (LulCntI = 0UL; LulCntI < LulTxQueueMax; LulCntI++)
    {
      #if (ETH_USING_MACRO == ETH_MACRO_ETND)
      LucResult |= Eth_TxDescLearning(&Eth_GstETND_Regs.pES[LulCtrlIdx]->stAXIBMI,                                      /* PRQA S 2844 # JV-01 */
                                      LulCntI,
                                      (uint32)Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc[LulCntI]);              /* PRQA S 0306, 2844, 2824 # JV-01, JV-01, JV-01 */
      #else
      LucResult |= Eth_TxDescLearning(Eth_GstETNE_Regs.pAXIBMI,
                                      LulCntI + (LulCtrlIdx * LulTxQueueMax),
                                      (uint32)Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadTxDesc[LulCntI]);
      #endif
    }

    /* Learning Rx descriptor table */
    for (LulCntI = 0UL; LulCntI < LulRxQueueMax; LulCntI++)
    {
      #if (ETH_USING_MACRO == ETH_MACRO_ETND)
      LucResult |= Eth_RxDescLearning(&Eth_GstETND_Regs.pES[LulCtrlIdx]->stAXIBMI,
                                      LulCntI,
                                      (uint32)Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc[LulCntI]);              /* PRQA S 0306, 2844, 2824 # JV-01, JV-01, JV-01 */
      #else
      LucResult |= Eth_RxDescLearning(Eth_GstETNE_Regs.pAXIBMI,
                                      LulCntI + (LulCtrlIdx * LulRxQueueMax),
                                      (uint32)Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc[LulCntI]);
      #endif
    }
  } /* else: No action required */

  return LucResult;
}

/***********************************************************************************************************************
** Function Name         : Eth_RxQueueProcess
**
** Service ID            : NA
**
** Description           : Process Receive Queue.
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LulCtrlIdx  - Instance number
**                       : LulFifoIdx - Rx queue index
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : When polling mode:
**                           ETH_EXT_NOT_RECEIVED : there was no received frame
**                           ETH_EXT_RECEIVED     : there was one received frame
**                           ETH_EXT_RECEIVED_MORE_DATA_AVAILABLE:
**                                 there were more than one received frames
**                           ETH_EXT_NOT_RECEIVED_MORE_DATA_AVAILABLE:
**                                 there was no received, but there are still receive frames.
**
** Preconditions         : None
**
** Global Variable(s)    : Eth_GpETNE_MFWDRegs, Eth_GstETND_Regs,
**                         Eth_GaaCtrlStat, Eth_GaaRxFrame,
**                         Eth_GpCtrlConfigPtr
**
** Function(s) invoked   : Eth_IsRxFrameValid, EthSwt_EthRxProcessFrame,
**                         Eth_RxCallEthIf, EthSwt_EthRxFinishedIndication,
**                         GetCounterValue, Eth_GetTimeOutValue,
**                         Eth_RxDescLearning
**
** Registers Used        : RFEISi, RATS, RATSR2
**
** Reference ID          : ETH_DUD_ACT_329
** Reference ID          : ETH_DUD_ACT_329_GBL001, ETH_DUD_ACT_329_GBL002
** Reference ID          : ETH_DUD_ACT_329_GBL003, ETH_DUD_ACT_329_GBL004
** Reference ID          : ETH_DUD_ACT_329_GBL005, ETH_DUD_ACT_329_GBL006
** Reference ID          : ETH_DUD_ACT_329_GBL007, ETH_DUD_ACT_329_GBL008
** Reference ID          : ETH_DUD_ACT_329_GBL009
** Reference ID          : ETH_DUD_ACT_329_REG001, ETH_DUD_ACT_329_REG002
***********************************************************************************************************************/
FUNC(Eth_ExtRxStatusType, ETH_PRIVATE_CODE) Eth_RxQueueProcess(                                                         /* PRQA S 1505 # JV-01 */
  CONST(uint32, AUTOMATIC) LulCtrlIdx, CONST(uint32, AUTOMATIC) LulFifoIdx)
{
  P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA) LpHwUnitConfig;
  #if (ETH_USING_MACRO == ETH_MACRO_ETND)
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs =
    &Eth_GstETND_Regs.pES[LulCtrlIdx]->stAXIBMI;                                                                        /* PRQA S 2844 # JV-01 */
  #else
  CONSTP2VAR(volatile Eth_ETNDE_AXIBMIRegType, AUTOMATIC, REGSPACE) LpAxiRegs = Eth_GstETNE_Regs.pAXIBMI;
  #endif
  P2VAR(Eth_ExtDescWithTsType, AUTOMATIC, ETH_APPL_DATA) LpDataDesc;                                                    /* PRQA S 3432 # JV-01 */
  P2VAR(Eth_ExtDescWithTsType, AUTOMATIC, ETH_APPL_DATA) LpTempDesc;                                                    /* PRQA S 3432 # JV-01 */
  uint32 LulRxQueueMax;
  #if (ETH_UPDATE_PHYS_ADDR_FILTER == STD_ON)
  boolean LblRxFrameValid;
  #endif
  TickType LulTickStart;
  TickType LulTickElap;
  uint32 LulIntStat;
  Eth_ExtRxStatusType LenRetValue;
  #if (ETH_GET_RX_STATS_API == STD_ON)
  uint32 LulLengthWithFCS;
  #endif

  #if (ETH_ETHSWITCH_MANAGEMENT_SUPPORT == STD_ON)
  Eth_BufIdxType LulBufIdx;
  P2VAR(uint8, AUTOMATIC, ETH_APPL_DATA) LpDataPtr;                                                                     /* PRQA S 3432 # JV-01 */
  boolean LblIsMgmtFrameOnlyPtr;
  uint16 LusLength;
  Std_ReturnType LucReturnValue;
  #endif

  LenRetValue = ETH_EXT_NOT_RECEIVED;

  LpHwUnitConfig =
    (P2CONST(Eth_ETNDEConfigType, AUTOMATIC, ETH_APPL_DATA))Eth_GpCtrlConfigPtr[LulCtrlIdx].pHwUnitConfig;              /* PRQA S 0316 # JV-01 */
  LulRxQueueMax = (uint32)LpHwUnitConfig->stQueueConfig.ucNumberOfRxQueue;                                              /* PRQA S 2814 # JV-01 */

  /* Get descriptor for read */
  LpDataDesc = Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc[LulFifoIdx];                                           /* PRQA S 2844, 2824 # JV-01, JV-01 */
  LpTempDesc = LpDataDesc;

  if (ETH_DESC_FSINGLE == LpDataDesc->stHeader.ulDt)                                                                    /* PRQA S 2814 # JV-01 */
  {
    /* Set Rx descriptor info */
    Eth_GaaRxFrame[LulCtrlIdx].ulFrameAddr   = LpDataDesc->ulDptr;                                                      /* PRQA S 2844 # JV-01 */
    Eth_GaaRxFrame[LulCtrlIdx].ulEthTypeAddr = LpDataDesc->ulDptr + ETH_SRC_DST_ADDRESS_SIZE;                           /* PRQA S 2844, 3383 # JV-01, JV-01 */
    Eth_GaaRxFrame[LulCtrlIdx].ulFrameLength = LpDataDesc->stHeader.ulDs;                                               /* PRQA S 2844 # JV-01 */
    Eth_GaaRxFrame[LulCtrlIdx].ulTsns        = LpDataDesc->ulTsns;                                                      /* PRQA S 2844 # JV-01 */
    Eth_GaaRxFrame[LulCtrlIdx].ulTss         = LpDataDesc->ulTss;                                                       /* PRQA S 2844 # JV-01 */

    /* Set descriptor to be read next */
    LpDataDesc++;                                                                                                       /* PRQA S 2824 # JV-01 */
    while ((LpDataDesc->stHeader.ulDt == ETH_DESC_LINK) || (LpDataDesc->stHeader.ulDt == ETH_DESC_LEMPTY))              /* PRQA S 2814 # JV-01 */
    {
      LpDataDesc->stHeader.ulDt = (uint32)ETH_DESC_LINK;                                                                /* PRQA S 2814 # JV-01 */
      LpDataDesc = (P2VAR(Eth_ExtDescWithTsType, AUTOMATIC, ETH_APPL_DATA))LpDataDesc->ulDptr;                          /* PRQA S 0306, 3432 # JV-01, JV-01 */
    }

    Eth_GaaCtrlStat[LulCtrlIdx].stHwStat.ppHeadRxDesc[LulFifoIdx] = LpDataDesc;

    #if (ETH_UPDATE_PHYS_ADDR_FILTER == STD_ON)
    /* check whether received frame is valid or not */
    LblRxFrameValid = Eth_IsRxFrameValid(LulCtrlIdx, &Eth_GaaRxFrame[LulCtrlIdx]);                                      /* PRQA S 2934 # JV-01 */
    if (ETH_TRUE == LblRxFrameValid)
    #endif
    {
      if (ETH_DESC_FSINGLE == LpDataDesc->stHeader.ulDt)                                                                /* PRQA S 2814 # JV-01 */
      {
        /* More frames are available */
        LenRetValue = ETH_EXT_RECEIVED_MORE_DATA_AVAILABLE;
      }
      else
      {
        /* Frame valid - Update status */
        LenRetValue = ETH_EXT_RECEIVED;
      }

      #if (ETH_GET_RX_STATS_API == STD_ON)
      Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts++;                                                           /* PRQA S 2844, 3383 # JV-01, JV-01 */
      LulLengthWithFCS = Eth_GaaRxFrame[LulCtrlIdx].ulFrameLength + ETH_FCS_LENGTH;                                     /* PRQA S 2844, 3383 # JV-01, JV-01 */
      Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsOctets += LulLengthWithFCS;                                       /* PRQA S 2844, 3383 # JV-01, JV-01 */
      if (LulLengthWithFCS <= 64UL)
      {
        /* Since the receive data size that does not include padding data is set in the receive descriptor,
           frames of 64 or less are collected by the statistical counter. */
        Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts64Octets++;                                                 /* PRQA S 2844, 3383 # JV-01, JV-01 */
      }
      else if (LulLengthWithFCS <= 127UL)
      {
        Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts65to127Octets++;                                            /* PRQA S 3383 # JV-01 */
      }
      else if (LulLengthWithFCS <= 255UL)
      {
        Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts128to255Octets++;                                           /* PRQA S 3383 # JV-01 */
      }
      else if (LulLengthWithFCS <= 511UL)
      {
        Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts256to511Octets++;                                           /* PRQA S 3383 # JV-01 */
      }
      else if (LulLengthWithFCS <= 1023UL)
      {
        Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts512to1023Octets++;                                          /* PRQA S 3383 # JV-01 */
      }
      else
      {
        /* When VLAN tag is supported, the maximum data size is 1522. */
        /* The maximum frame size that HW can receive is set to 1522. */
        Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxStatsPkts1024to1518Octets++;                                         /* PRQA S 3383 # JV-01 */
      }
      #endif

      #if (ETH_ETHSWITCH_MANAGEMENT_SUPPORT == STD_ON)
      LulBufIdx = *(P2VAR(Eth_BufIdxType, AUTOMATIC, ETH_APPL_DATA))                                                    /* PRQA S 2814, 0306, 3432 # JV-01, JV-01, JV-01 */
        (Eth_GaaRxFrame[LulCtrlIdx].ulFrameAddr - sizeof(Eth_BufIdxType) - ETH_RX_DPTR_OFFSET);                         /* PRQA S 3383, 3384 # JV-01, JV-01 */

      LpDataPtr = (P2VAR(uint8, AUTOMATIC, ETH_APPL_DATA))Eth_GaaRxFrame[LulCtrlIdx].ulEthTypeAddr;                     /* PRQA S 0306, 3432 # JV-01, JV-01 */
      /* Since the maximum value of buffer size is 1518, casting to uint16 does no problem. */
      LusLength = (uint16)(Eth_GaaRxFrame[LulCtrlIdx].ulFrameLength - ETH_HEADER_SIZE);                                 /* PRQA S 3383 # JV-01 */
      LblIsMgmtFrameOnlyPtr = ETH_FALSE;
      /* Since the maximum value of controller index is 1, casting to uint8 does no problem. */
      LucReturnValue = EthSwt_EthRxProcessFrame((uint8)LulCtrlIdx, LulBufIdx, &LpDataPtr,
                                                &LusLength, &LblIsMgmtFrameOnlyPtr);
      if (E_OK == LucReturnValue)
      {
        Eth_GaaRxFrame[LulCtrlIdx].ulEthTypeAddr = (uint32)LpDataPtr;                                                   /* PRQA S 0306, 2844 # JV-01, JV-01 */
        Eth_GaaRxFrame[LulCtrlIdx].ulFrameLength = (uint32)(LusLength + ETH_HEADER_SIZE);                               /* PRQA S 2844, 3383 # JV-01, JV-01 */

        if (ETH_FALSE == LblIsMgmtFrameOnlyPtr)
        {
          /* Call EthIf if the Frame Received is valid */
          Eth_RxCallEthIf(LulCtrlIdx, &Eth_GaaRxFrame[LulCtrlIdx]);                                                     /* PRQA S 2934 # JV-01 */
        }
        else
        {
          /* Must not be the Rx processed */
          /* Since the maximum value of controller index is 1, casting to uint8 does no problem. */
          (void)EthSwt_EthRxFinishedIndication((uint8)LulCtrlIdx, LulBufIdx);
        }
      }
      else
      {
        /* Normal operation if E_NOT_OK */
        Eth_RxCallEthIf(LulCtrlIdx, &Eth_GaaRxFrame[LulCtrlIdx]);                                                       /* PRQA S 2934 # JV-01 */
      }
      #else
      /* Call EthIf if the Frame Received is valid */
      Eth_RxCallEthIf(LulCtrlIdx, &Eth_GaaRxFrame[LulCtrlIdx]);                                                         /* PRQA S 2934 # JV-01 */
      #endif
    }
    #if (ETH_UPDATE_PHYS_ADDR_FILTER == STD_ON)
    else
    {
      /* Frame Invalid - E.g. Multicast to be discarded */
      /* No Call of EthIf */
      if (ETH_DESC_FSINGLE == LpDataDesc->stHeader.ulDt)
      {
        /* Not received, but more frames are available */
        LenRetValue = ETH_EXT_NOT_RECEIVED_MORE_DATA_AVAILABLE;
      } /* else: No action required */
    }
    #endif

    /* Reset Rx descriptor */
    LpTempDesc->stHeader.ulDie   = (uint32)ETH_RX_DESC_DIE_ENABLE;                                                      /* PRQA S 2814 # JV-01 */
    LpTempDesc->stHeader.ulAxie  = (uint32)0UL;
    LpTempDesc->stHeader.ulDse   = (uint32)0UL;
    LpTempDesc->stHeader.ulInfo0 = (uint32)0UL;
    LpTempDesc->stHeader.ulDs    = LpHwUnitConfig->stRxConfig.ulMaxFrameSize;                                           /* PRQA S 2824 # JV-01 */
    LpTempDesc->ulInfo1[0]       = 0UL;
    LpTempDesc->ulInfo1[1]       = 0UL;
    LpTempDesc->ulTsns           = 0UL;
    LpTempDesc->ulTss            = 0UL;
    /* Do not move this process due to descriptor exclusive control */
    LpTempDesc->stHeader.ulDt    = (uint32)ETH_DESC_FEMPTY;

    /* Get rx descriptor full interrupt status */
    LulIntStat = ETH_GET_RX_FULL_INT_STAT(LulCtrlIdx, LulFifoIdx, LpAxiRegs->stRXDFEI[0].ulRFEISi, LulRxQueueMax);      /* PRQA S 2814 # JV-01 */
    if (0UL != LulIntStat)
    {
      /* Searching rx descriptor chain table */
      LpAxiRegs->ulRATS = LulFifoIdx + (LulCtrlIdx * LulRxQueueMax);                                                    /* PRQA S 3383 # JV-01 */
      LpAxiRegs->ulRATSR2 = ETH_ETNDE_RATSR2_SEARCHING;

      /* Rx Descriptor Address Table searching waiting */
      LulTickStart = 0UL;
      (void)GetCounterValue(ETH_OS_COUNTER_ID, &LulTickStart);
      do
      {
        LulTickElap = Eth_GetTimeOutValue(LulTickStart);
      } while ((0UL != LpAxiRegs->ulRATSR2) && (LulTickElap <= ETH_TIMEOUT_COUNT));

      if (ETH_TIMEOUT_COUNT >= LulTickElap)
      {
        /* Clear rx descriptor full interrupt status */
        LpAxiRegs->stRXDFEI[LulCtrlIdx].ulRFEISi = LulIntStat;                                                          /* PRQA S 2844 # JV-01 */

        /* Re-learning rx descriptor chain table */
        (void)Eth_RxDescLearning(LpAxiRegs, LpAxiRegs->ulRATS, (uint32)LpTempDesc);                                     /* PRQA S 0306 # JV-01 */
      } /* else: No action required */
    } /* else: No action required */
  } /* else: No action required */

  return LenRetValue;
}

#if (ETH_UPDATE_PHYS_ADDR_FILTER == STD_ON)
/***********************************************************************************************************************
** Function Name         : Eth_IsRxFrameValid
**
** Service ID            : NA
**
** Description           : Compare Mac Address Frame just received with
**                         Broadcast and Controller Mac Address.
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LpRxFrame. Pointer to the Frame just received
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : LblPass
**                         True : Frame DA is Broadcast or
**                         matches with the Source Address of this Controller
**                         False : Otherwise
**
** Preconditions         : None
**
** Global Variables Used : Eth_GaaCtrlStat, Eth_GstBroadcastAddr,
**                         Eth_GaaAddressFilters
**
** Function(s) invoked   : None
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_332
***********************************************************************************************************************/
STATIC FUNC(boolean, ETH_PRIVATE_CODE) Eth_IsRxFrameValid(
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONSTP2CONST(Eth_RxFrameType, AUTOMATIC, ETH_APPL_DATA) LpRxFrame)
{
  Eth_MacAddressType LstDstAddress;
  boolean LblPass;
  uint32 LulFilterIdx;
  uint32 LulRemainBits;

  LblPass = ETH_FALSE;
  ETH_PACK_ADDRESS_FROM_8(((P2VAR(uint8, AUTOMATIC, ETH_APPL_DATA))LpRxFrame->ulFrameAddr), LstDstAddress);             /* PRQA S 0306, 3432, 3469, 2824, 2814 # JV-01, JV-01, JV-01, JV-01, JV-01 */

  /* Check whether promiscuous mode, broadcast, own unicast, multicast address is not registed */
  if ((ETH_TRUE == Eth_GaaCtrlStat[LulCtrlIdx].blPromiscuous) ||                                                        /* PRQA S 2844 # JV-01 */
      (0UL == ETH_COMPARE_MAC(LstDstAddress, Eth_GstBroadcastAddr)) ||                                                  /* PRQA S 3469 # JV-01 */
      (0UL == ETH_COMPARE_MAC(LstDstAddress, Eth_GaaCtrlStat[LulCtrlIdx].stMacAddr)))                                   /* PRQA S 3469 # JV-01 */
  {
    LblPass = ETH_TRUE;
  }
  else
  {
    /* Otherwise, do the filter operation */

    /* To skip empty filters efficiently, copy active bits to the local var */
    LulRemainBits = Eth_GaaCtrlStat[LulCtrlIdx].ulActiveFilterBits;
    LulFilterIdx = 0UL;
    /* Loop until any filter hits or pass all active filters */
    while (0UL != LulRemainBits)
    {
      if ((0UL != (LulRemainBits & (1UL << LulFilterIdx))) &&
          (0UL == ETH_COMPARE_MAC(LstDstAddress, Eth_GaaAddressFilters[LulCtrlIdx][LulFilterIdx])))                     /* PRQA S 2844, 3469 # JV-01, JV-01 */
      {
        LblPass = ETH_TRUE;
        break;
      } /* else: No action required */

      /* Clear the compared filter bit */
      LulRemainBits &= ~(1UL << LulFilterIdx);
      LulFilterIdx++;                                                                                                   /* PRQA S 3383 # JV-01 */
    }
  }

  return LblPass;
}
#endif  /* (ETH_UPDATE_PHYS_ADDR_FILTER == STD_ON) */

/***********************************************************************************************************************
** Function Name         : Eth_RxCallEthIf
**
** Service ID            : NA
**
** Description           : Wrapper for the Callback to the Eth Interface
**                         for each frame received
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Non-Reentrant
**
** Input Parameters      : LulCtrlIdx - Controller / Channel Index
**                       : LpFrame - Address of the Received Frame in URAM
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : None
**
** Preconditions         : NA
**
** Global Variables Used : Eth_GstBroadcastAddr, Eth_GaaCtrlStat
**
** Function(s) invoked   : EthIf_RxIndication, EthSwt_EthRxFinishedIndication,
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_330
** Reference ID          : ETH_DUD_ACT_330_GBL001
***********************************************************************************************************************/
STATIC FUNC(void, ETH_PRIVATE_CODE) Eth_RxCallEthIf(
  CONST(uint32, AUTOMATIC) LulCtrlIdx,
  CONSTP2CONST(Eth_RxFrameType, AUTOMATIC, ETH_APPL_DATA) LpFrame)
{
  boolean LblBroadcast;
  P2CONST(Eth_DataType, AUTOMATIC, ETH_APPL_DATA) LpFrameType;
  Eth_FrameType LddFrameType;
  Eth_MacAddressType LstMacAddr;
  #if (ETH_ETHSWITCH_MANAGEMENT_SUPPORT == STD_ON)
  Eth_BufIdxType LulBufIdx;
  #endif
  P2CONST(Eth_EtherFrameType, AUTOMATIC, ETH_APPL_DATA) LstEtherFrame;

  LstEtherFrame = (P2CONST(Eth_EtherFrameType, AUTOMATIC, ETH_APPL_DATA)) LpFrame->ulFrameAddr;                         /* PRQA S 0306, 2814 # JV-01, JV-01 */
  ETH_PACK_ADDRESS_FROM_8(LstEtherFrame->ucDstAddr, LstMacAddr);                                                        /* PRQA S 2814, 3469 # JV-01, JV-01 */

  if (0UL == ETH_COMPARE_MAC(LstMacAddr, Eth_GstBroadcastAddr))                                                         /* PRQA S 3469 # JV-01 */
  {
    LblBroadcast = ETH_TRUE;
  }
  else
  {
    LblBroadcast = ETH_FALSE;
    #if (ETH_GET_RX_STATS_API == STD_ON)
    if (0UL == ETH_CHECK_MULTICAST(LstMacAddr))                                                                         /* PRQA S 3469 # JV-01 */
    {
      /* Unicast frame */
      Eth_GaaCtrlStat[LulCtrlIdx].stTxRxStat.ulRxUnicastFrames++;                                                       /* PRQA S 2844, 3383 # JV-01, JV-01 */
    } /* else: No action required */
    #endif
  }

  LpFrameType = (const Eth_DataType *)LpFrame->ulEthTypeAddr;                                                           /* PRQA S 0306 # JV-01 */
  LddFrameType = (Eth_FrameType)((uint32)LpFrameType[0] << ETH_BYTE_BITS);                                              /* PRQA S 2824 # JV-01 */
  LddFrameType |= (Eth_FrameType)LpFrameType[1];

  /* Since the maximum value of Controller Index is 1, casting to uint8 does no problem. */
  EthIf_RxIndication((uint8)LulCtrlIdx, LddFrameType, LblBroadcast, LstEtherFrame->ucSrcAddr,
    LpFrameType + ETH_ETHERTYPE_SIZE, (uint16)(LpFrame->ulFrameLength - ETH_HEADER_SIZE));                              /* PRQA S 0488, 3383 # JV-01, JV-01 */

  #if (ETH_ETHSWITCH_MANAGEMENT_SUPPORT == STD_ON)
  LulBufIdx = *(P2VAR(Eth_BufIdxType, AUTOMATIC, ETH_APPL_DATA))                                                        /* PRQA S 0306, 2814, 3432 # JV-01, JV-01, JV-01 */
    (LpFrame->ulFrameAddr - sizeof(Eth_BufIdxType) - ETH_RX_DPTR_OFFSET);                                               /* PRQA S 3383, 3384 # JV-01, JV-01 */
  (void)EthSwt_EthRxFinishedIndication((uint8)LulCtrlIdx, LulBufIdx);
  #endif
}

/***********************************************************************************************************************
** Function Name         : Eth_GetTimeOutValue
**
** Service ID            : NA
**
** Description           : This returns the elapsed timeout value of  Os timer
**
** Sync/Async            : Synchronous
**
** Reentrancy            : Reentrant
**
** Input Parameters      : LusTimeOutCount_Init
**
** InOut Parameters      : None
**
** Output Parameters     : None
**
** Return parameter      : LulTimeOutCount_Elapsed - TickType
**
** Preconditions         : None
**
** Global Variable(s)    : None
**
** Function(s) invoked   : GetCounterValue
**
** Registers Used        : None
**
** Reference ID          : ETH_DUD_ACT_331
***********************************************************************************************************************/
FUNC(TickType, ETH_PRIVATE_CODE) Eth_GetTimeOutValue(CONST(TickType, AUTOMATIC) LusTimeOutCount_Init)
{
  TickType LulTimeOutCount_Curr;
  TickType LulTimeOutCount_Elapsed;

  LulTimeOutCount_Curr = 0UL;

  /* Get the current tick value from OS Counter */
  (void)GetCounterValue((CounterType)ETH_OS_COUNTER_ID, &LulTimeOutCount_Curr);

  /* Check whether current time out exceeds inital time out value */
  if (LulTimeOutCount_Curr > LusTimeOutCount_Init)
  {
    /* Get elapsed time out count */
    LulTimeOutCount_Elapsed = LulTimeOutCount_Curr - LusTimeOutCount_Init;                                              /* PRQA S 3383 # JV-01 */
  }
  else
  {
    /* Get elapsed time out count */
    LulTimeOutCount_Elapsed = ((uint32)ETH_OS_COUNTER_MAX_VALUE - LusTimeOutCount_Init) + LulTimeOutCount_Curr;         /* PRQA S 3383 # JV-01 */
  }

  return LulTimeOutCount_Elapsed;
}

#define ETH_STOP_SEC_PRIVATE_CODE
#include "Eth_MemMap.h"

/***********************************************************************************************************************
**                                                    End of File                                                     **
***********************************************************************************************************************/
