/**
*   @file    Eth_Fec.c
*   @version 0.4.3
*
*    @brief            ENET controller interface
*    @details          Implementation of the ENET controller interface for
*                      the Ethernet driver
*
*   @addtogroup ETH_DRIVER
*   @{
*/
/*==================================================================================================
*   Project              : AUTOSAR 4.3 MCAL
*   Platform             : PA
*   Peripheral           : FEC
*   Dependencies         : 
*
*   Autosar Version      : 4.3.1
*   Autosar Revision     : ASR_REL_4_3_REV_0001
*   Autosar Conf.Variant :
*   SW Version           : 1.0.0
*   Build Version        : MPC5777C_MCAL_1_0_0_RTM_ASR_REL_4_3_REV_0001_20190315
*
*   (c) Copyright 2006-2016 Freescale Semiconductor, Inc. 
*       Copyright 2017-2019 NXP
*   All Rights Reserved.
==================================================================================================*/
/*==================================================================================================
==================================================================================================*/

#ifdef __cplusplus
extern "C"{
#endif

/**
* @page misra_violations MISRA-C:2012 violations
* 
* @section Eth_Fec_c_REF_1
* Violates MISRA 2012 Required Directive 4.10, Precautions shall be taken in order to prevent the contents
* of a header file being included more than once. This comes from the order of includes in the .c file
* and from include dependencies. As a safe approach, any file must include all its dependencies.
* Header files are already protected against double inclusions. The inclusion of Eth_Memmap.h is as
* per AUTOSAR requirement (SWS_MemMap_00003)
*
* @section [global]
*          Violates MISRA 2012 Required Rule 5.1, External identifiers shall be distinct.
*          The used compilers use more than 31 chars for identifiers.
*
* @section [global]
*          Violates MISRA 2012 Required Rule 5.2, Identifiers declared in the same scope and name space shall be distinct.
*          The used compilers use more than 31 chars for identifiers.
*
* @section [global]
*          Violates MISRA 2012 Required Rule 5.4, Macro identifiers shall be distinct.
*          The used compilers use more than 31 chars for identifiers.
*
* @section [global]
*          Violates MISRA 2012 Required Rule 5.5, Identifiers shall be distinct from macro names.
*          The used compilers use more than 31 chars for identifiers.
*
* @section Eth_Fec_c_REF_2
* Violates MISRA 2012 Advisory Rule 20.1, #include directives should only be preceded by preprocessor 
* directives or comments. AUTOSAR imposes the specification of the sections in which certain parts
* of the driver must be placed.
*
* @section Eth_Fec_c_REF_3
* Violates MISRA 2012 Advisory Rule 8.7,  Functions and objects should not be defined with external 
* linkage if they are referenced in only one translation unit.
*
* @section Eth_Fec_c_REF_4
* Violates MISRA 2012 Advisory Rule 11.4, A conversion should not be performed between a pointer to object
* and an integer type.
* The cast is used to access memory mapped registers.
*
* @section Eth_Fec_c_REF_5
* Violates MISRA 2012 Required Rule 11.6, A cast shall not be performed between pointer to void and an arithmetic type.
*
* @section Eth_Fec_c_REF_6
* Violates MISRA 2012 Required Rule 10.8, The value of a composite expression shall not be cast to a different essential 
* type category or a wider essential type.
*
* @section Eth_Fec_c_REF_7
* Violates MISRA 2012 Advisory Rule 20.1, #include directives should only be preceded by preprocessor 
* directives or comments. AUTOSAR imposes the specification of the sections in which certain parts
* of the driver must be placed.
*
* @section Eth_Fec_c_REF_8
* Violates MISRA 2012 Advisory Rule 2.5, A project should not contain unused macro declarations.
*
* @section Eth_Fec_c_REF_9
* Violates MISRA 2012 Required Rule 1.3, There shall be no occurrence of undefined or critical unspecified behaviour
*
* @section Eth_Fec_c_REF_10
* Violates MISRA 2012 Advisory Rule 8.9, An object should be defined at block scope if its identifier only appears
* in a single function.
*
* @section Eth_Fec_c_REF_11
* Violates MISRA 2012 Advisory Rule 18.4, The +, -, += and -= operators should not be applied to an expression of pointer
* type
*
* @section Eth_Fec_c_REF_12
* Violates MISRA 2012 Required Rule 8.4, A compatible declaration shall be visible when an object or function with 
* external linkage is defined.
*
* @section Eth_Fec_c_REF_13
* Violates MISRA 2012 Required Rule 14.3, Controlling expressions shall not be invariant.
*
* @section Eth_Fec_c_REF_14
* Violates MISRA 2012 Advisory Rule 11.5, A conversion should not be performed from pointer to void into pointer to object.
*
*
* @section Eth_Fec_c_REF_15
* Violates MISRA 2012 Required Rule 10.3, The value of an expression shall not be assigned to an object with a narrower
* essential type or of a different essential type category.
*
* @section Eth_Fec_c_REF_16
* Violates MISRA 2012 Mandatory Rule 9.1, The value of an object with automatic storage duration shall not be read before
* it has been set.
*
* @section Eth_Fec_c_REF_17
* Violates MISRA 2012 Required Rule 2.2, There shall be no dead code
*
* @section Eth_Fec_c_REF_18
* Violates MISRA 2012 Required Rule 7.2, A "U" or "u" sall be applied to all interger constants.
*/

/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "Eth.h" /* Includes also Eth_GeneralTypes.h, Eth_Cfg.h,
                    Eth_ComStack_Types.h, Dem.h, Det.h and Mcal.h */
#include "SchM_Eth.h" /* RTE module header for critical sections protection */
#include "Eth_Fec_Reg_Sys.h"
#include "Eth_Fec.h" /* Own interface */
#if STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API
    #include "EthSwt.h"
#endif
#include "StdRegMacros.h"   /* Macros for register access abstraction */
/* Note Soc_Ips.h is included through Reg_eSys.h - Mcal.h - Eth_Cfg.h - Eth.h */
#include "EthIf_Cbk.h" /* EthIf callbacks to be called from Eth driver */

#ifdef ETH_ENABLE_USER_MODE_SUPPORT
    #if (STD_ON == ETH_ENABLE_USER_MODE_SUPPORT)
        #ifdef MCAL_ETH_REG_PROT_AVAILABLE  
            #include "RegLockMacros.h"
        #endif
    #endif
#endif
/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/

#define ETH_VENDOR_ID_C                      43
#define ETH_MODULE_ID_C                      88
#define ETH_AR_RELEASE_MAJOR_VERSION_C       4
#define ETH_AR_RELEASE_MINOR_VERSION_C       3
#define ETH_AR_RELEASE_REVISION_VERSION_C    1
#define ETH_SW_MAJOR_VERSION_C               1
#define ETH_SW_MINOR_VERSION_C               0
#define ETH_SW_PATCH_VERSION_C               0

/*==================================================================================================
*                                     FILE VERSION CHECKS
==================================================================================================*/
/* Check if current file and ETH header file are of the same vendor */
#if(ETH_VENDOR_ID_C != ETH_VENDOR_ID)
    #error "Eth_Fec.c and ETH.h have different vendor ids"
#endif
/* Check if current file and ETH header file are of the same Autosar version */
#if ((ETH_AR_RELEASE_MAJOR_VERSION_C    != ETH_AR_RELEASE_MAJOR_VERSION) || \
     (ETH_AR_RELEASE_MINOR_VERSION_C    != ETH_AR_RELEASE_MINOR_VERSION) || \
     (ETH_AR_RELEASE_REVISION_VERSION_C != ETH_AR_RELEASE_REVISION_VERSION) \
    )
    #error "AutoSar Version Numbers of Eth_Fec.c and Eth.h are different"
#endif
/* Check if current file and ETH header file are of the same Software version */
#if ((ETH_SW_MAJOR_VERSION_C != ETH_SW_MAJOR_VERSION) || \
     (ETH_SW_MINOR_VERSION_C != ETH_SW_MINOR_VERSION) || \
     (ETH_SW_PATCH_VERSION_C != ETH_SW_PATCH_VERSION)    \
    )
    #error "Software Version Numbers of Eth_Fec.c and Eth.h are different"
#endif
/* Check if current file and Eth_Fec_Reg_Sys header file are of the same vendor */
#if (ETH_VENDOR_ID_C != ETH_VENDOR_ID_REG_SYS_H)
    #error "Eth_Fec.c and Eth_Fec_Reg_Sys.h have different vendor ids"
#endif
/* Check if current file and Eth_Fec_Reg_Sys header file are of the same module */
#if (ETH_MODULE_ID_C != ETH_MODULE_ID_REG_SYS_H)
    #error "Eth_Fec.c and Eth_Fec_Reg_Sys.h have different vendor ids"
#endif
/* Check if current file and Eth_Fec_Reg_Sys header file are of the same Autosar version */
#if ((ETH_AR_RELEASE_MAJOR_VERSION_C    != ETH_AR_RELEASE_MAJOR_VERSION_REG_SYS_H) || \
     (ETH_AR_RELEASE_MINOR_VERSION_C    != ETH_AR_RELEASE_MINOR_VERSION_REG_SYS_H) || \
     (ETH_AR_RELEASE_REVISION_VERSION_C != ETH_AR_RELEASE_REVISION_VERSION_REG_SYS_H))
    #error "AutoSar Version Numbers of Eth_Fec.c and Eth_Fec_Reg_Sys.h are different"
#endif
/* Check if current file and Eth_Fec_Reg_Sys header file are of the same Software version */
#if ((ETH_SW_MAJOR_VERSION_C != ETH_SW_MAJOR_VERSION_REG_SYS_H) || \
     (ETH_SW_MINOR_VERSION_C != ETH_SW_MINOR_VERSION_REG_SYS_H) || \
     (ETH_SW_PATCH_VERSION_C != ETH_SW_PATCH_VERSION_REG_SYS_H))
    #error "Software Version Numbers of Eth_Fec.c and Eth_Fec_Reg_Sys.h are different"
#endif
/* Check if current file and Eth_Fec_LLD header file are of the same Autosar version */
#if ((ETH_AR_RELEASE_MAJOR_VERSION_C    != ETH_AR_RELEASE_MAJOR_VERSION_FEC) || \
     (ETH_AR_RELEASE_MINOR_VERSION_C    != ETH_AR_RELEASE_MINOR_VERSION_FEC) || \
     (ETH_AR_RELEASE_REVISION_VERSION_C != ETH_AR_RELEASE_REVISION_VERSION_FEC) \
    )
    #error "AutoSar Version Numbers of Eth_Fec.c and Eth_Fec.h are different"
#endif
/* Check if current file and Eth_Fec_LLD header file are of the same Software version */
#if( (ETH_SW_MAJOR_VERSION_C != ETH_SW_MAJOR_VERSION_FEC) || \
     (ETH_SW_MINOR_VERSION_C != ETH_SW_MINOR_VERSION_FEC) || \
     (ETH_SW_PATCH_VERSION_C != ETH_SW_PATCH_VERSION_FEC)    \
   )
    #error "Software Version Numbers of Eth_Fec.c and Eth_Fec.h are different"
#endif

#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    /* Check if current file and StdRegMacros header file are of the same version */
    #if ((ETH_AR_RELEASE_MAJOR_VERSION_C != STDREGMACROS_AR_RELEASE_MAJOR_VERSION) ||   \
         (ETH_AR_RELEASE_MINOR_VERSION_C != STDREGMACROS_AR_RELEASE_MINOR_VERSION)      \
        )
        #error "AutoSar Version Numbers of Eth_Fec.c and StdRegMacros.h are different"
    #endif
    #if ((ETH_AR_RELEASE_MAJOR_VERSION_C != ETHIF_AR_RELEASE_MAJOR_VERSION) || \
         (ETH_AR_RELEASE_MINOR_VERSION_C != ETHIF_AR_RELEASE_MINOR_VERSION))
        #error "AutoSar Version Numbers of Eth_Fec.c and EthIf_Cbk.h are different"
    #endif
    #if STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API
    /* Check if current file and EthSWT header file are of the same AutoSar version */
    #if ((ETH_AR_RELEASE_MAJOR_VERSION_C != ETHSWT_AR_RELEASE_MAJOR_VERSION) || \
         (ETH_AR_RELEASE_MINOR_VERSION_C != ETHSWT_AR_RELEASE_MINOR_VERSION))
        #error "AutoSar Version Numbers of Eth_Fec.c and EthSwt.h are different"
    #endif
    #endif
#endif /* DISABLE_MCAL_INTERMODULE_ASR_CHECK */
/*==================================================================================================
*                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_START_SEC_VAR_NO_INIT_UNSPECIFIED
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
/**
 * @brief       Item definition of multicast MAC address pool.
 * @details     This structure define an entry of MAC address pool which
 *              allows reception of multiple MAC address defined in
 *              Eth_Fec_rMulticastPool array. Active parameter denote
 *              entries of MACAddress which will passed to receive
 *              callback function.
 */
 
typedef struct
{
    VAR(boolean, ETH_VAR) bActive;
    VAR(uint8, ETH_VAR) au8PhysAddr[6];
} Eth_Fec_McastPoolItem;
#endif
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
/*==============================================================================
*                                       LOCAL MACROS
==============================================================================*/
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
/**
* @brief   Generation polynomial value
* @details Value of generation polynomial register for CRC32 calculation.
*          Correspond to active elements of generation polynomial function
*          x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8
*          + x^7 + x^5 + x^4 + x^2 + x^1 + 1 written from right to left
*          without base element x^32.
*/
#define ETH_FEC_LLD_CRC32_POLYVAL 0xEDB88320U
/**
* @brief   Initial value of CRC32 calculation register
*/
#define ETH_FEC_LLD_CRC32_INITVAL 0xFFFFFFFFU
#endif
/*==============================================================================
*                                      LOCAL CONSTANTS
==================================================================================================*/
#define ETH_START_SEC_VAR_INIT_UNSPECIFIED
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"

/**
* @brief          Used for internal storage of configuration pointer
* @details        This variable is used to store the pointer to the instance
*                 of the Eth_ConfigType containing the configuration parameter,
*                 which is passed to the Eth_Init function, for the subsequent
*                 accesses.
*
* @note           This variable exists only if the Pre-Compile variant is not
*                 selected.
*
*/
    
P2CONST(Eth_ConfigType, ETH_VAR, ETH_APPL_CONST) Eth_InternalCfgPtr = NULL_PTR;

#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
/**
 * @brief        Pool multicast MAC address
 * @details      This is an array of structure of allowed MAC address
 *               for multicast frame reception.
 */
static VAR(Eth_Fec_McastPoolItem, ETH_VAR) Eth_Fec_rMulticastPool[ETH_MAXCTRLS_SUPPORTED][ETH_MULTICAST_POOL_SIZE] = \
    {{ {(boolean)FALSE, {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U}} }};

#endif /* ETH_UPDATE_PHYS_ADDR_FILTER */

#define ETH_STOP_SEC_VAR_INIT_UNSPECIFIED
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_START_SEC_VAR_INIT_16
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
#if (STD_OFF == ETH_TXFIFO_SINGLE_MODE)
/*Index buffer start for each queue*/
/**
* @brief        Index of buffer where start of a queue
* @details      This index base on number of buffer which confiured in configuration.              
*/
static VAR(uint16, ETH_VAR) Eth_Fec_u16BufStartIdx[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG] = {{0U}};
#endif
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER

/**
* @brief          Number of active items inside multicast filter pool
* @details        This variable is incremented with each added item to pool
*                 and decremented with remove. Value is set to zero at pool
*                 clean function.
*/
static VAR(uint16, ETH_VAR) Eth_Fec_u16McastItemsCnt[ETH_MAXCTRLS_SUPPORTED] = {0U};
#endif  /* ETH_UPDATE_PHYS_ADDR_FILTER */
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_STOP_SEC_VAR_INIT_16
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_START_SEC_VAR_NO_INIT_32
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
/**
* @brief    Address of Rx buffers ring start
* @details  Used for optimization of buffer address computation.
*           It is initialized during TX buffers initialization.
*/
static VAR(uint32, ETH_VAR) Eth_Fec_u32RxBufStartAddr[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_RXFIFO_CONFIG];
/**
* @brief    Address of Tx buffers ring start
* @details  Used for optimization of buffer address computation.
*           It is initialized during TX buffers initialization.
*/
static VAR(uint32, ETH_VAR) Eth_Fec_u32TxBufStartAddr[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG];
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_STOP_SEC_VAR_NO_INIT_32
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"

/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_START_SEC_VAR_NO_INIT_8
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
static VAR(uint8, ETH_VAR) Eth_u8LockedTxBufCount[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG];
/**
* @brief        Array of references to BD for each buffer.
* @details      Use buffer index for indexing this array.
*               It contains index of buffer descriptor this buffer belongs to.
*               The value is valid only if at least this flags are set on the
*               buffer: ETH_Fec_QOS_TXB_LOCK_U8 | ETH_Fec_QOS_TXB_LINK_U8 | ETH_Fec_QOS_TXB_FIRST_U8.
*               Otherwise the buffer is not linked with any BD or is not first
*               buffer of frame. 
*/
/**
* @brief          Active transmit buffer descriptor index
* @details        This variable contains index of the buffer descriptor which
*                 will be used for transmission after the TDAR register is
*                 written.
* @implements     Eth_u8ActiveTxBD_Object */
static VAR(volatile uint8, ETH_VAR) Eth_u8ActiveTxBD[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG];
/**
* @brief          Active receive buffer descriptor index
* @details        This variable contains number of the buffer descriptor which
*                 will be used  for the first reception from the time of the
*                 last call of the receive function.
* 
* @implements     Eth_u8ActiveRxBuf_Object */
static VAR(volatile uint8, ETH_VAR) Eth_u8ActiveRxBuf[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_RXFIFO_CONFIG];
/**
* @brief        Index of buffer where to continue search for free buffers
* @details      This variable is used to reduce buffer memory fragmentation.
*               Algorithm tries to allocate new buffers right after previously
*               allocated buffers.
*/
static VAR(uint8, ETH_VAR) Eth_Fec_u8SearchTxBufFrom[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG];
/**
* @brief          Counter of the locked TX buffers
* @details        This variable is incremented with each buffer to be confirmed
*                 transmission and decremented by confirmation of such buffer
*                 thus it holds number of the buffers to be confirmed. It is
*                 used for optimization of the buffers search algorithm.
*/

static VAR(uint8, ETH_VAR) Eth_au8TxBdOfBuf[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG][ETH_TX_BUFF_MAX];

/**
* @brief        An array containing buffer flags.
* @details      Use buffer index for indexing this array.
*               It contains 4 flags for each buffer:
*               TXB_LOCK 8, TXB_CONF 4, TXB_LINK 2, TXB_FIRST 1 
*/
static VAR(volatile uint8, ETH_VAR) Eth_au8TxBufFlags[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG][ETH_TX_BUFF_MAX];

/**
* @brief        An array containing Tx BD flags.
* @details      Use BD index for indexing this array.
*               It contains 1 flags for each BD:
*               TXB_LINK: 0x10U 
*/
static VAR(volatile uint8, ETH_VAR) Eth_au8TxBDFlags[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG][ETH_TX_BUFF_MAX];
#if STD_ON == ETH_USE_MULTIBUFFER_TX_FRAMES
/**
* @brief        Number of buffers allocated together for one frame
* @details      Use buffer index for indexing this array.
*
*/

static VAR(uint8, ETH_VAR) Eth_Fec_au8TxBufGroup[ETH_MAXCTRLS_SUPPORTED][ETH_MAX_TXFIFO_CONFIG][ETH_TX_BUFF_MAX];

#endif /* STD_ON == ETH_USE_MULTIBUFFER_TX_FRAMES */
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_STOP_SEC_VAR_NO_INIT_8
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"

/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_START_SEC_VAR_INIT_BOOLEAN
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"

#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
/**
* @brief        Variable indicating multicast pool overflow
* @details      Any time whenever count of active items in
*               Eth_Fec_rMulticastPool could be greater than
*               ETH_MULTICAST_POOL_SIZE this variable is set to TRUE
*               and keeps TRUE until Eth_ControllerInit is called.
*/
static VAR(boolean, ETH_VAR) Eth_Fec_bMcastPoolOvf[ETH_MAXCTRLS_SUPPORTED] = {(boolean)FALSE};

/**
* @brief        Multicast filter OPEN for all frames
* @details      Multicast filtering is disabled and ALL frames are received.
*               Means that all bytes of GAUR/GALR registers
*               are set to 0xff and multicast filtering accept all frames
*               at reception if the value is TRUE.
*/
static VAR(boolean, ETH_VAR) Eth_Fec_bMcastFullOpen[ETH_MAXCTRLS_SUPPORTED] = {(boolean)FALSE};
  
#endif /* ETH_UPDATE_PHYS_ADDR_FILTER */

/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_STOP_SEC_VAR_INIT_BOOLEAN
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_START_SEC_CONST_32
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"
static CONST(uint32, ETH_CONST) Eth_u32BaseAddr[ETH_FEC_CONTROLLERS_NO] = {
        /* @violates @ref Eth_Fec_c_REF_18 */
        FEC_0_BASEADDR,

#ifdef  FEC1_BASEADDR
        FEC_1_BASEADDR
#endif /* FEC1_BASEADDR */
};
/* @violates @ref Eth_Fec_c_REF_8 */
#define ETH_STOP_SEC_CONST_32
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"

#define ETH_START_SEC_CODE
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"

/* General memory access functions */
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_Write16TxBufMem   ( \
                                        CONST(uint32, AUTOMATIC)u32BaseAddr, \
                                        CONST(uint32, AUTOMATIC)u32Offset, \
                                        CONST(uint16, AUTOMATIC) u16Data \
                                                            );
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_McastGAClean(CONST(uint8, AUTOMATIC) u8CtrlIdx);
#endif
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_WriteRxBDBits ( \
                                        CONST(uint32, AUTOMATIC)u32BaseAddr, \
                                        CONST(uint8, AUTOMATIC) u8Bufnum, \
                                        CONST(uint32, AUTOMATIC) u32Data \
                                                        );
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_WriteRxBDBufPtr   ( \
                                        CONST(uint32, AUTOMATIC)u32BaseAddr, \
                                        CONST(uint8, AUTOMATIC) u8Bufnum, \
                                        CONST(uint32, AUTOMATIC) u32Data \
                                                            );
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_WriteTxBDBufPtr   ( \
                                        CONST(uint32, AUTOMATIC)u32BaseAddr, \
                                        CONST(uint8, AUTOMATIC) u8BdIdx, \
                                        CONST(uint32, AUTOMATIC) u32DataAddr \
                                                            );
LOCAL_INLINE FUNC(uint32, ETH_CODE) Eth_Fec_ReadRxBDBits(CONST(uint32, AUTOMATIC)u32BaseAddr, CONST(uint8, AUTOMATIC) u8Bufnum);
LOCAL_INLINE FUNC(uint32, ETH_CODE) Eth_Fec_ComputeTxBufAddr    ( \
                                         CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                         CONST(uint8, AUTOMATIC) u8FifoIdx, \
                                         CONST(uint8, AUTOMATIC) u8BufIdx \
                                                                );
LOCAL_INLINE FUNC(uint32, ETH_CODE) Eth_Fec_ComputeRxBufAddr    ( \
                                         CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                         CONST(uint8, AUTOMATIC) u8FifoIdx, \
                                         CONST(uint8, AUTOMATIC) u8BufIdx \
                                                                );
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_WriteTxBDBits ( \
                                        CONST(uint32, AUTOMATIC) u32BaseAddr, \
                                        CONST(uint8, AUTOMATIC) u8BdIdx, \
                                        CONST(uint32, AUTOMATIC) u32DataAddr \
                                                        );
LOCAL_INLINE FUNC(uint32, ETH_CODE) Eth_Fec_ReadTxBDBits    ( \
                                        CONST(uint32, AUTOMATIC) u32BaseAddr, \
                                        CONST(uint8, AUTOMATIC) u8BdIdx \
                                                            );
                                                            /* CRC functions */
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
static FUNC(uint32, ETH_CODE) Eth_Fec_GetCRC32Hash  ( \
                       CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pData, \
                       VAR(uint32, AUTOMATIC) u32Length \
                                                    );
static FUNC(boolean, ETH_CODE) Eth_Fec_ComparePhysAddr  ( \
                                    CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhyAddrA, \
                                    CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhyAddrB \
                                                        );
static FUNC(boolean, ETH_CODE) Eth_Fec_IsAddrInMcastPool    ( \
                                    CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                    CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr, \
                                    CONSTP2VAR(uint16, AUTOMATIC, ETH_APPL_DATA) pPoolItemIdx \
                                                            );
static FUNC(boolean, ETH_CODE) Eth_Fec_McastPoolAddItem ( \
                                    CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                    CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr
                                                        );
static FUNC(boolean, ETH_CODE) Eth_Fec_McastPoolRmvItem ( \
                                    CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                    CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr \
                                                        );
static FUNC(void, ETH_CODE) Eth_Fec_McastPoolClean(CONST(uint8, AUTOMATIC) u8CtrlIdx);
static FUNC(void, ETH_CODE) Eth_Fec_McastGAAdd ( \
                                    CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                    CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr \
                                                );
static FUNC(void, ETH_CODE) Eth_Fec_McastGARecalculate(CONST(uint8, AUTOMATIC) u8CtrlIdx);
static FUNC(boolean, ETH_CODE) Eth_Fec_IsPhysAddrAllowed    ( \
                    CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                    CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr \
                                                                );
#endif /* ETH_UPDATE_PHYS_ADDR_FILTER */
static FUNC(void, ETH_CODE) Eth_Fec_ClearMIBCounters(CONST(uint8, AUTOMATIC) u8CtrlIdx);
static FUNC(Eth_Fec_enRxBufferType, ETH_CODE) Eth_Fec_GetRxBufferType ( \
                        CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                        CONST(uint8, AUTOMATIC) u8Buf, \
                        CONST(uint8, AUTOMATIC) u8BufCtrMax, \
                        CONSTP2VAR(uint8, AUTOMATIC, ETH_APPL_DATA) pMultiEnd \
                                                                );
static FUNC(void, ETH_CODE) Eth_Fec_GetRxBufferData    ( \
                            CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                            CONST(uint8, AUTOMATIC) u8FifoIdx, \
                            CONST(uint8, AUTOMATIC) u8Buf, \
                            CONST(uint8, AUTOMATIC) u8MultiEnd, \
                            CONSTP2VAR(uint16, AUTOMATIC, ETH_APPL_DATA) pLength, \
                            P2P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA) pDataPtr, \
                            CONSTP2VAR(uint32, AUTOMATIC, ETH_APPL_DATA) pStatusPtr \
                                                        );
static FUNC(void, ETH_CODE) Eth_Fec_ClearRxBuffer   ( \
                        CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                        CONST(uint8, AUTOMATIC) u8BufIdx \
                                                    );
#if(STD_ON == ETH_DEM_EVENT_DETECT)
static FUNC(void, ETH_CODE) Eth_Fec_CheckDemStatus ( \
                            VAR(uint32, AUTOMATIC) u32Addr, \
                            VAR(uint32, AUTOMATIC) u32DemConfig, \
                            VAR(uint16, AUTOMATIC)DemId \
                                                    );
#endif
static FUNC(void, ETH_CODE) Eth_Fec_GiveBackTxBuffer(CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                                    CONST(uint8, AUTOMATIC) u8FifoIdx, \
                                                    VAR(uint8, AUTOMATIC) u8BufIdx \
                                                    );
static FUNC(void, ETH_CODE)  Eth_Fec_ConfigureRxBuffers(CONST(uint8, AUTOMATIC) u8CtrlIdx);
static FUNC(void, ETH_CODE)  Eth_Fec_ConfigureTxBuffers(CONST(uint8, AUTOMATIC) u8CtrlIdx);
#if STD_OFF == ETH_BRIDGE_SUPPORT
static FUNC(uint32, ETH_CODE) Eth_Fec_Htons( CONST(uint32, AUTOMATIC) u32HostShort);
#endif
/*==============================================================================
*                                       LOCAL FUNCTIONS
==============================================================================*/
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
/**
* @brief         Clean GALR/GAUR registers.
* @details       This function disable reception of all multicast address groups
*                by seting of 0x00U to GAUR and GALR registers.
* @param[in]     u8CtrlIdx Index of controller in which GA will be cleaned
*/
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_McastGAClean(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    /* Clear group address upper register */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_GAUR_ADDR16, 0U);
    /* Clear group address lower register */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_GALR_ADDR16, 0U);
}
#endif
/* Access to the buffer descriptor status bits and the data pointer: */
/*============================================================================*/
/**
* @brief          Writes the Receive buffer descriptor status bits.
* @details        32 bit long value containing status bits in upper 16 bits and
*                 buffer length in lower 16 bits is written into the given
*                 buffer descriptor.
* @param[in]      u32BaseAddr Starting address of the Receive buffer descriptors ring
* @param[in]      u8Bufnum Index of the buffer descriptor to be written
* @param[in]      u32Data Status bits and buffer length to be written into
*                 the descriptor
* @note           This function is an inline function.
*/
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_WriteRxBDBits ( \
                                CONST(uint32, AUTOMATIC) u32BaseAddr, \
                                CONST(uint8, AUTOMATIC) u8Bufnum, \
                                CONST(uint32, AUTOMATIC) u32Data  \
                                                        )
{
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */    
    *((P2VAR(volatile uint32, AUTOMATIC, ETH_APPL_DATA))(u32BaseAddr + ((uint32)u8Bufnum * (uint32)8U))) = u32Data;
}
/*============================================================================*/
/**
* @brief          Writes a data buffer address into the Receive buffer
*                 descriptor pointer.
* @param[in]      u32BaseAddr Starting address of the Receive buffer descriptors ring
* @param[in]      u8Bufnum Index of the buffer descriptor to be written
* @param[in]      u32Data Address to be written into the buffer pointer.
* @note           This function is an inline function.
*/
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_WriteRxBDBufPtr   ( \
                                    CONST(uint32, AUTOMATIC)u32BaseAddr, \
                                    CONST(uint8, AUTOMATIC) u8Bufnum, \
                                    CONST(uint32, AUTOMATIC) u32Data \
                                                            )
{
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    *((P2VAR(volatile uint32, AUTOMATIC, ETH_APPL_DATA))(u32BaseAddr + (uint32)4U + ((uint32)u8Bufnum * (uint32)8U))) = u32Data;
}
/*============================================================================*/
/**
* @brief          Writes a data buffer address into the Transmit buffer
*                 descriptor pointer.
* @param[in]      u32BaseAddr Starting address of the Transmit buffer
*                 descriptors ring.
* @param[in]      u8BdIdx Index of the buffer descriptor to be written.
* @param[in]      u32DataAddr Address to be written into the buffer pointer.
* @note           This function is an inline function.
*/
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_WriteTxBDBufPtr   ( \
                                    CONST(uint32, AUTOMATIC)u32BaseAddr, \
                                    CONST(uint8, AUTOMATIC) u8BdIdx, \
                                    CONST(uint32, AUTOMATIC) u32DataAddr \
                                                            )
{
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    *((P2VAR(volatile uint32, AUTOMATIC, ETH_APPL_DATA))(u32BaseAddr + (uint32)4U + ((uint32)u8BdIdx * (uint32)8U))) = u32DataAddr;
}
/*============================================================================*/
/**
* @brief          Reads the status bits from the Receive buffer descriptor
* @param[in]      u32BaseAddr Starting address of the Receive buffer descriptors ring
* @param[in]      u8Bufnum Index of the buffer descriptor to be read
* @return         Read status bits (upper 16 bits) and buffer length
*                 (lower 16 bits)
* @note           This function is an inline function.
*/
LOCAL_INLINE FUNC(uint32, ETH_CODE) Eth_Fec_ReadRxBDBits    ( \
                                    CONST(uint32, AUTOMATIC)u32BaseAddr, \
                                    CONST(uint8, AUTOMATIC) u8Bufnum \
                                                            )
{
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    return *((P2VAR(volatile uint32, AUTOMATIC, ETH_APPL_DATA))(u32BaseAddr + ((uint32)u8Bufnum * (uint32)8U)));
}

/* Access to the buffer data functions: */
/*============================================================================*/
/**
* @brief          Writes the 16 bit long data into the memory
* @details        This function abstracts the write access into the transmit
*                 buffer memory. The transmit buffer is identified by its
*                 beginning i.e. base address and the offset specifies where to
*                 write the data.
* @param[in]      u32BaseAddr Base address where to write
* @param[in]      u32Offset Offset to be added to base address before the write
* @param[in]      u16Data The 16 bit long data to be written into the buffer.
* @note           This function is an inline function. It is used to ensure
*                 aligned accesses into the buffer on all target platforms.
*/
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_Write16TxBufMem   ( \
                                CONST(uint32, AUTOMATIC)u32BaseAddr, \
                                CONST(uint32, AUTOMATIC)u32Offset, \
                                CONST(uint16, AUTOMATIC) u16Data \
                                                            )
{
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    *((P2VAR(volatile uint16, AUTOMATIC, ETH_APPL_DATA))(u32BaseAddr + (u32Offset))) = u16Data;
}

/*============================================================================*/
/**
* @brief        Compute address of TX buffer with given index
* @details      Type of the value of this macro is uint32
* @param[in]    u8CtrlIdx Index of controller we are working with
* @param[in]    u8BufIdx Index of buffer we need address of.
* @return       Address of beginning of given TX buffer.
*/
LOCAL_INLINE FUNC(uint32, ETH_CODE) Eth_Fec_ComputeTxBufAddr    ( \
                                         CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                         CONST(uint8, AUTOMATIC) u8FifoIdx, \
                                         CONST(uint8, AUTOMATIC) u8BufIdx \
                                                                )
{
    VAR(uint16, AUTOMATIC) u16BufLength;
    
    u16BufLength = (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pEgressCfg[u8FifoIdx].EthCtrlConfigEgressFifoBufLenByte);
    /*Calculate start address of data buffer when length of buffer in configuration isn't multiple of 64*/
    if (0U != (uint16)(u16BufLength % 16U))
    {
        u16BufLength += (uint16)((uint16)16U - (u16BufLength % 16U));
    }
    
    return (Eth_Fec_u32TxBufStartAddr[u8CtrlIdx][u8FifoIdx] + ((uint32)u16BufLength * (uint32)u8BufIdx));
}

/*============================================================================*/
/**
* @brief        Compute address of RX buffer with given index
* @details      Type of the value of this macro is uint32
* @param[in]    u8CtrlIdx Index of controller we are working with
* @param[in]    u8BufIdx Index of buffer we need address of.
* @return       Address of beginning of given RX buffer.
*/
LOCAL_INLINE FUNC(uint32, ETH_CODE) Eth_Fec_ComputeRxBufAddr    ( \
                                         CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                         CONST(uint8, AUTOMATIC) u8FifoIdx, \
                                         CONST(uint8, AUTOMATIC) u8BufIdx \
                                                                )
{
    VAR(uint16, AUTOMATIC) u16BufLength;
    
    u16BufLength = (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8FifoIdx].EthCtrlConfigIngressFifoBufLenByte);
    /*Calculate start address of data buffer when length of buffer in configuration isn't multiple of 16*/
    if (0U != (uint16)(u16BufLength % 16U))
    {
        u16BufLength += (uint16)((uint16)16U - (u16BufLength % 16U));
    }

    return (uint32)(Eth_Fec_u32RxBufStartAddr[u8CtrlIdx][u8FifoIdx] + ((uint32)((uint32)u16BufLength + 16U) * (uint32)u8BufIdx));
}

/*============================================================================*/
/**
* @brief          Writes the Transmit buffer descriptor status bits.
* @details        32 bit long value containing status bits in upper 16 bits and
*                 buffer length in lower 16 bits is written into the given
*                 buffer descriptor.
* @param[in]      u32BaseAddr Starting address of the Transmit buffer
*                 descriptors ring.
* @param[in]      u8BdIdx Index of the buffer descriptor to be written
* @param[in]      u32DataAddr Status bits and buffer length to be written into
*                 the descriptor
*/
LOCAL_INLINE FUNC(void, ETH_CODE) Eth_Fec_WriteTxBDBits  ( \
                                    CONST(uint32, AUTOMATIC) u32BaseAddr, \
                                    CONST(uint8, AUTOMATIC) u8BdIdx, \
                                    CONST(uint32, AUTOMATIC) u32DataAddr \
                                            )
{
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */  
    *((P2VAR(volatile uint32, AUTOMATIC, ETH_APPL_DATA))(u32BaseAddr + ((uint32)u8BdIdx * (uint32)8U))) = u32DataAddr;
}

/*============================================================================*/
/**
* @brief          Reads the status bits from the Transmit buffer descriptor
* @param[in]      u32BaseAddr Starting address of the Transmit buffer
*                 descriptors ring.
* @param[in]      u8BdIdx Index of the buffer descriptor to be read.
* @return         Read status bits (upper 16 bits) and buffer length
*                 (lower 16 bits)
* @note           This function is an inline function.
*/
LOCAL_INLINE FUNC(uint32, ETH_CODE) Eth_Fec_ReadTxBDBits ( \
                                    CONST(uint32, AUTOMATIC) u32BaseAddr, \
                                    CONST(uint8, AUTOMATIC) u8BdIdx \
                                            )
{
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    return *((P2VAR(volatile uint32, AUTOMATIC, ETH_APPL_DATA))(u32BaseAddr + ((uint32)u8BdIdx * (uint32)8U)));
}

#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
/**
 * @brief       Calculation of CRC32 hash
 * @details     This function calculates a CRC32 checksum of data of specified
 *              length.
 * @param[in]   pData Pointer to data array of bytes which CRC checksum has
 *              to be calculated.
 * @param[in]   u32Length Specifies the number of bytes of data array.
 * @return      CRC32 checksum.
 */
static FUNC(uint32, ETH_CODE) Eth_Fec_GetCRC32Hash (CONSTP2CONST(uint8, AUTOMATIC, ETH_VAR) pData, VAR(uint32, AUTOMATIC) u32Length)
{
    VAR(uint32, AUTOMATIC) u32CRC32Hash;    /* CRC hash output register */
    VAR(uint32, AUTOMATIC) u32CRC32ByteIdx; /* Index of data byte */
    VAR(uint8, AUTOMATIC) u8CRC32BitIdx;    /* Index of bit inside
                                               CRC32 calculated byte */

    u32CRC32Hash = ETH_FEC_LLD_CRC32_INITVAL;
    /* Loop over all bytes */
    for (u32CRC32ByteIdx = 0U; u32CRC32ByteIdx < u32Length; u32CRC32ByteIdx++)
    {
        u32CRC32Hash ^= (uint32)pData[u32CRC32ByteIdx];
        /* Loop over bits */
        for (u8CRC32BitIdx = 0U; 8U > u8CRC32BitIdx; u8CRC32BitIdx++)
        {
            u32CRC32Hash = (u32CRC32Hash >> 1) ^ ((~(u32CRC32Hash & 0x1U) + 0x1U) & ETH_FEC_LLD_CRC32_POLYVAL);
        }
    }
    
    return u32CRC32Hash;
}

/**
 * @brief       Compare two input physical addresses
 * @details     This function compares physical address pPhyAddrA
 *              against pPhyAddrB. In case that addresses match the TRUE
 *              is returned and FALSE otherwise.
 * @param[in]   pPhyAddrA Pointer to the first physical address array.
 * @param[in]   pPhyAddrB Pointer to the second physical address array.
 * @caution     Length of physical address is restricted to 6B!
 * @return      TRUE - addresses matches
 *              FALSE - otherwise
 */
static FUNC(boolean, ETH_CODE) Eth_Fec_ComparePhysAddr  ( \
                       CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhyAddrA, \
                       CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhyAddrB \
                                                        )
{
    /* Return variable */
    VAR(boolean, ETH_VAR) bReturn = (boolean)TRUE;
    VAR(uint8, AUTOMATIC) u8Count;
    
    for (u8Count=0U; u8Count<6U; u8Count++)
    {
        /** @violates @ref Eth_Fec_c_REF_5 */
        if (pPhyAddrA[u8Count] != pPhyAddrB[u8Count])
        { 
            /* Addresses are the same */
            bReturn = (boolean)FALSE;
            break;
        }
    }
    return bReturn;
}

/**
 * @brief       Add item into multicast pool
 * @details     This function checks if the added address is not already in the
 *              pool and if not add it.
 * @note        This function does not take care about overflow flag.
 * @param[in]   u8CtrlIdx Index of controller which will be added item
 * @param[in]   pPhysAddrPtr Pointer to Physical address which shall be
 *              added
 * @return      TRUE - item/addresses was added successfully or item is already
 *                     in the table
 *              FALSE - table is full
 */
static FUNC(boolean, ETH_CODE) Eth_Fec_McastPoolAddItem(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr)
{
    /* Temporary return variable / Matching entry found */
    VAR(boolean, AUTOMATIC) bReturnVariable = (boolean)FALSE;
    /* Index of pool entry */
    VAR(uint16, AUTOMATIC) u16PoolIdx = 0U;
    VAR(uint8, AUTOMATIC) u8Count = 0U;

    /* @violates @ref Eth_Fec_c_REF_9 */
    if ((boolean)TRUE == Eth_Fec_IsAddrInMcastPool(u8CtrlIdx, pPhysAddrPtr, &u16PoolIdx))
    { /* Item already in the table */
        bReturnVariable = (boolean)TRUE;
    }
    else if (ETH_MULTICAST_POOL_SIZE == Eth_Fec_u16McastItemsCnt[u8CtrlIdx])
    { /* Table is full */
        bReturnVariable = (boolean)FALSE;
    }
    else
    { /* Item is not in the table - Look for empty position*/
        while (ETH_MULTICAST_POOL_SIZE > u16PoolIdx)
        { /* Loop over table items */
            if ((boolean)FALSE == Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].bActive)
            { /* First empty item in table */
                /* Mark found item as used - active */
                Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].bActive = (boolean)TRUE;
                /* Write address to the pools */
                for (u8Count=0U; u8Count<6U; u8Count++)
                {
                    /** @violates @ref Eth_Fec_c_REF_5 */
                    Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].au8PhysAddr[u8Count]=pPhysAddrPtr[u8Count];
                }
                /* Increment the count of used items */
                Eth_Fec_u16McastItemsCnt[u8CtrlIdx]++;
                /* Set return variable */
                bReturnVariable = (boolean)TRUE;
                break;
            } /* Active item check */
            u16PoolIdx++;
        } /* Items loop */
    } /* Table check */
    
    return bReturnVariable;
}

/**
* @brief         Remove the physical address from the pool.
* @details       This function goes over multicast pool and is checking
*                if the specified physical address is located and activated
*                in the multicast pool.
* @param[in]     u8CtrlIdx Index of controller in which item will be removed
* @param[in]     pPhysAddrPtr Pointer to physical address which shall be
*                removed
* @note          This function does not take care about overflow flag.
* @return        TRUE - address was removed from the pool
*                FALSE - address was not found in the pool
*/
static FUNC(boolean, ETH_CODE) Eth_Fec_McastPoolRmvItem(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr)
{
    /* Index of pool entry */
    VAR(uint16, AUTOMATIC) u16PoolIdx = 0U;
    /* Return variable */
    VAR(boolean, AUTOMATIC) bReturnVariable;

    /* Look for item in the table */
    /* @violates @ref Eth_Fec_c_REF_9 */
    if ((boolean)TRUE ==  Eth_Fec_IsAddrInMcastPool(u8CtrlIdx, pPhysAddrPtr, &u16PoolIdx))
    { /* Item was found in the table at position u16PoolIdx */
        /* Deactivate it */
        Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].bActive = (boolean)FALSE;
        /* Decrement count of used pool items */
        Eth_Fec_u16McastItemsCnt[u8CtrlIdx]--;
        /* Set return variable */
        bReturnVariable = (boolean)TRUE;
    }
    else
    { /* Item is not in the table */
        bReturnVariable = (boolean)FALSE;
    }
    return bReturnVariable;
}

/**
* @brief         Check whenever the specified physical address is in
*                multicast pool.
* @details       This function goes over multicast pool and is checking
*                if the specified physical address is located and activated
*                in the multicast pool.
* @param[in]     u8CtrlIdx Index of controller in which the address will be checked
* @param[in]     pPhysAddrPtr This parameter is a pointer at tested
*                physical address.
* @param[out]    pPoolItemIdx Index of found Eth_Fec_rMulticastPool
*                item. This value is valid only if TRUE is returned.
* @return        TRUE - address is in the pool and active
*                FALSE - address is not in the pool
*/
static FUNC(boolean, ETH_CODE) Eth_Fec_IsAddrInMcastPool    ( \
                CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr, \
                CONSTP2VAR(uint16, AUTOMATIC, ETH_APPL_DATA) pPoolItemIdx \
                                                            )
{
    /* Temporary return variable / Matching entry found */
    VAR(boolean, AUTOMATIC) bAddressFound = (VAR(boolean, AUTOMATIC))FALSE;
    /* Index of pool entry */
    VAR(uint16, AUTOMATIC) u16PoolIdx = 0U;
    /* Used for counting of found active items in loop */
    VAR(uint16, AUTOMATIC) u16TmpActiveFound = 0U;

    /* Loop over multicast pool */
    while ((u16TmpActiveFound !=  Eth_Fec_u16McastItemsCnt[u8CtrlIdx]) && (ETH_MULTICAST_POOL_SIZE > u16PoolIdx))
    {
        /* Filter only active entries */
        if ((boolean)TRUE == Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].bActive)
        { /* Item is active */
            if ((boolean)TRUE == Eth_Fec_ComparePhysAddr(pPhysAddrPtr, Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].au8PhysAddr))
            { /* Item matches with requested */
                bAddressFound = (boolean)TRUE;
                *pPoolItemIdx = u16PoolIdx;
                break;
            }
            u16TmpActiveFound++;
        }
        u16PoolIdx++;
    }
    
    return bAddressFound;
}
/**
* @brief         Wipe all items of the pool.
* @details       This function goes over all items in the pool and sets
*                the active flag to FALSE
* @param[in]     u8CtrlIdx Index of controller which will be cleaned
* @note          This function does not take care about pool overflow
*/
static FUNC(void, ETH_CODE) Eth_Fec_McastPoolClean(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    /* Index of pool entry */
    VAR(uint16, AUTOMATIC) u16PoolIdx = 0U;

    while (ETH_MULTICAST_POOL_SIZE > u16PoolIdx)
    {
        Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].bActive = (VAR(boolean, AUTOMATIC))FALSE;
        u16PoolIdx++;
    }
    Eth_Fec_u16McastItemsCnt[u8CtrlIdx] = 0U;
}

/**
* @brief         Enables Group Address reception for requested Physical Address
* @details       This function decides which register of GAUR/GALR is affected
*                and sets related bit for requested Physical Address reception
*                enablement.
* @param[in]     u8CtrlIdx Index of controller which will be updated GAA
* @param[in]     pPhysAddrPtr Pointer to Physical Address which group
*                shall be enabled.
*/
static FUNC(void, ETH_CODE) Eth_Fec_McastGAAdd(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr)
{
    /* Storage of CRC32 hash of Physical Address */
    VAR(uint32,AUTOMATIC) u32TmpCRC32Hash;
    /* Manipulation variable */
    VAR(uint32,AUTOMATIC) u32ManipulationVar;

    /* Once pool overflow was detected the recalculation of
    * the GAUR/GALR registers can not be used anymore.
    * Only new group reception bit can be enabled. */
    /* Calculate CRC32 hash */
    u32TmpCRC32Hash = Eth_Fec_GetCRC32Hash(pPhysAddrPtr, 6U);
    /* Estimate address group number
    * NOTE: Destination hash group is in GAUR/GALR register
    *       Group number is in six most significant bits
    *       in CRC32MacHash without MSB which decide about
    *       GAUR/GALR
    */
    if (1U == (u32TmpCRC32Hash >> 31U))
    { /* Address is in group located in GAUR register */
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        /* @violates @ref Eth_Fec_c_REF_6 */
        u32ManipulationVar = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GAUR_ADDR16);
        u32ManipulationVar |= ((1UL << ((u32TmpCRC32Hash >> 26UL) & 0x1FUL)));
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        /* @violates @ref Eth_Fec_c_REF_6 */ 
        REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GAUR_ADDR16, u32ManipulationVar);
    }
    else
    { /* Address is in group located in GALR register */
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        /* @violates @ref Eth_Fec_c_REF_6 */
        u32ManipulationVar = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GALR_ADDR16);
        u32ManipulationVar |= ((1UL << ((u32TmpCRC32Hash >> 26UL) & 0x1FUL)));
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        /* @violates @ref Eth_Fec_c_REF_6 */ 
        REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GALR_ADDR16, u32ManipulationVar);
    }
}

/**
* @brief         Recalculates and updates the values of GALR/GAUR registers.
* @details       This function goes over active multicast pool items
*                and calculates the values of GAUR/GALR registers.
* @param[in]     u8CtrlIdx Index of controller in which GA will be recalculated
*/
static FUNC(void, ETH_CODE) Eth_Fec_McastGARecalculate(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    /* Used for counting of found active items in loop */
    VAR(uint16, AUTOMATIC) u16TmpActiveFound = 0U;
    /* Temporary storage of CRC32 hash  */
    VAR(uint32, AUTOMATIC) u32TmpCRC32Hash;
    /* Used for calculation of value for FEC_GALR_ADDR16 register */
    VAR(uint32, AUTOMATIC) u32TmpGALR = 0U;
    /* Used for calculation of value for FEC_GAUR_ADDR16 register */
    VAR(uint32, AUTOMATIC) u32TmpGAUR = 0U;
    /* Current item index */
    VAR(uint16, AUTOMATIC) u16PoolIdx = 0U;

    while ((u16TmpActiveFound != Eth_Fec_u16McastItemsCnt[u8CtrlIdx]) && (ETH_MULTICAST_POOL_SIZE > u16PoolIdx))
    { /* Go over pool till ends or all active items were processed  */
        if ((VAR(boolean, AUTOMATIC))TRUE == Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].bActive)
        { /* Filter only active items */
            /* Calculate CRC32 hash */
            u32TmpCRC32Hash = Eth_Fec_GetCRC32Hash(Eth_Fec_rMulticastPool[u8CtrlIdx][u16PoolIdx].au8PhysAddr, 6U);
            /* Estimate address group number
             * NOTE: Destination hash group is in GAUR/GALR register
             *       Group number is in six most significant bits
             *       in CRC32MacHash without MSB which decide about
             *       GAUR/GALR
             */
            if (1U == (u32TmpCRC32Hash >> 31U))
            { /* Address is in group located in GAUR register */
                u32TmpGAUR |= ((1UL << ((u32TmpCRC32Hash >> 26UL) & 0x1FUL)));
            }
            else
            { /* Address is in group located in GALR register */
                u32TmpGALR |= ((1UL << ((u32TmpCRC32Hash >> 26UL) & 0x1FUL)));
            }
            u16TmpActiveFound++;
        }
        u16PoolIdx++;
    }
    /* Write GAUR register */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GAUR_ADDR16, u32TmpGAUR);
    /* Write GALR register */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GALR_ADDR16, u32TmpGALR);
}

/*================================================================================================*/
/**
* @brief         Check whenever the specified physical address
*                is allowed for reception.
* @details       This function checks the filter statuses and look into
*                multicast pool whether reception is allowed for specified
*                physical address.
* @param[in]     u8CtrlIdx Index of controller to be checked
* @param[in]     copu32PhysAddrPtr Pointer to physical address in network byte
*                order.
* @return        bReceptionAllowed Boolean value which defines that the frame
*                is contained in the pool (TRUE) or not (FALSE).
*/
static FUNC(boolean, ETH_CODE) Eth_Fec_IsPhysAddrAllowed(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONSTP2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr)
{
    /* Return variable */
    VAR(boolean, AUTOMATIC) bReceptionAllowed;
    /* Multicast Pool table item index */
    VAR(uint16, AUTOMATIC) u16McastPoolIdx;

    if ((boolean)TRUE == Eth_Fec_bMcastPoolOvf[u8CtrlIdx])
    { /* Multicast filter overflow detected */
        bReceptionAllowed = (boolean)TRUE;
    }
    else if ((boolean)TRUE == Eth_Fec_bMcastFullOpen[u8CtrlIdx])
    { /* Filter is fully open */
        bReceptionAllowed = (boolean)TRUE;
    }
    else
    { 
        /* @violates @ref Eth_Fec_c_REF_9 */       
        bReceptionAllowed = Eth_Fec_IsAddrInMcastPool(u8CtrlIdx, pPhysAddrPtr, &u16McastPoolIdx);
    }
    
    return bReceptionAllowed;
}
#endif /* ETH_UPDATE_PHYS_ADDR_FILTER */

#if(STD_ON == ETH_DEM_EVENT_DETECT)
static FUNC(void, ETH_CODE) Eth_Fec_CheckDemStatus (VAR(uint32, AUTOMATIC) u32Addr, VAR(uint32, AUTOMATIC) u32DemConfig, VAR(uint16, AUTOMATIC)DemId)
{
    VAR(uint32, AUTOMATIC) u32TempRegValue;
    VAR(Std_ReturnType, AUTOMATIC) eReturnStatus = (Std_ReturnType)E_NOT_OK;
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    u32TempRegValue = REG_READ32(u32Addr);
    if (u32TempRegValue>0U)
    {
        
        if ((uint32)STD_ON == u32DemConfig)
        {
            
            eReturnStatus = Dem_SetEventStatus( DemId, DEM_EVENT_STATUS_PREFAILED );
        }
    }
    else
    {
        
        if ((uint32)STD_ON == u32DemConfig)
        {
            
            eReturnStatus = Dem_SetEventStatus( DemId, DEM_EVENT_STATUS_PREPASSED );
        }
    }
    (void)eReturnStatus;
}
#endif

/*============================================================================*/
/**
* @brief         Clears the receive buffer
* @details       Function sets the Empty bit in the given buffer descriptor, the
*                rest of the bits is left untouched because they are anyway
*                written by the hardware or unused. The advantage is that the
*                WRAP bit remains untouched.
* @param[in] u8Buf Index of the buffer to be cleared
* @param[in] u32BDAddress Address of the RX buffer descriptors ring start
*/

static FUNC(void, ETH_CODE) Eth_Fec_ClearRxBuffer  (CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(uint8, AUTOMATIC) u8BufIdx)
{
    VAR(uint32, AUTOMATIC) u32ManipulationVar;
    VAR(uint32, AUTOMATIC) u32BdAddress;   /* Stores buffer descriptor address */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    u32BdAddress = (uint32)ETH_CFG_RXBDSTARTADDRESS(u8CtrlIdx);
    
    /* Empty the buffer */
    u32ManipulationVar = Eth_Fec_ReadRxBDBits(u32BdAddress, u8BufIdx); /* Read bits */
    u32ManipulationVar = u32ManipulationVar | FEC_RXBD_E_U32;  /* Mark the buffer as empty */
    Eth_Fec_WriteRxBDBits(u32BdAddress, u8BufIdx, u32ManipulationVar); /* Write val.back */
    /* Write the RDAR register to notify the controller about a new buffer, 
       written value is ignored, the write access is what matters */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_RDAR_ADDR16, FEC_RDAR_R_DES_ACTIVE_U32); 
}
#if STD_ON == ETH_GETCOUNTVALAPI 
/*================================================================================================*/
/**
* @brief         Reads a list with drop counter values of the corresponding controller.
* @param[in]     u8CtrlIdx Index of controller within the context of the Ethernet Driver.
* @param[out]    CounterPtr Counter values according to IETF RFC 1757, RFC 1643 and RFC 2233.
* @details       Reads a list with drop counter values of the corresponding controller.
*                The meaning of these values is described at Eth_CounterType.
* @return        The search status
* @retval        E_OK Success
* @retval        E_NOT_OK Counter values read failure.
*/
FUNC(void, ETH_CODE) Eth_Fec_GetCounterValues  ( \
                               VAR(uint8, AUTOMATIC) u8CtrlIdx, \
                               P2VAR(Eth_CounterType, AUTOMATIC, ETH_APPL_DATA) CounterPtr \
                                           )
{
    VAR(uint32, AUTOMATIC) u32RegTemp;
    
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    REG_WRITE32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_MIBC_ADDR16), 0U);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    u32RegTemp = REG_READ32((uint32)Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_T_DROP_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->DropPktBufOverrun = (uint32)(u32RegTemp + REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_DROP_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    u32RegTemp = REG_READ32((uint32)Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_T_CRC_ALIGN_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->DropPktCrc = (uint32)(u32RegTemp + REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_CRC_ALIGN_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    u32RegTemp = REG_READ32((uint32)Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_T_UNDERSIZE_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->UndersizePkt = (uint32)(u32RegTemp + REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_UNDERSIZE_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    u32RegTemp = REG_READ32((uint32)Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_T_OVERSIZE_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->OversizePkt = (uint32)(u32RegTemp + REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_OVERSIZE_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    u32RegTemp = REG_READ32((uint32)Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_T_CRC_ALIGN_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->AlgnmtErr = (uint32)(u32RegTemp + REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_CRC_ALIGN_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->SqeTestErr = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_SQE_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->SnglCollPkt = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_1COL_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->MultCollPkt = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_MCOL_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->DfrdPkt = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_DEF_ADDR16);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    CounterPtr->LatCollPkt = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_LCOL_ADDR16);
}
#endif
#if STD_ON == ETH_GET_RXSTATS_API
/*================================================================================================*/
/**
* @brief         Return the list of Receive Statistics.
* @param[in]     u8CtrlIdx Index of controller within the context of the Ethernet Driver.
* @param[out]    RxStats List of values according to IETF RFC 2819.
* @details       RxStats List of values according to IETF RFC 2819, where the maximal possible value shall
*                denote an invalid value.
*                e.g. if this counter is not available.
* @return        The search status
* @retval        E_OK Success
* @retval        E_NOTOK drop counter not be obtained.
* @implements    Eth_Fec_GetRxStats_Activity
*/
FUNC(void, ETH_CODE) Eth_Fec_GetRxStats ( \
                               VAR(uint8, AUTOMATIC) u8CtrlIdx, \
                               P2VAR(Eth_RxStatsType, AUTOMATIC, ETH_APPL_DATA) RxStats \
                                           )
{
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   REG_WRITE32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_MIBC_ADDR16), 0U);
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsDropEvents = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_DROP_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsOctets = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_OCTETS_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsPkts = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_PACKETS_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsBroadcastPkts = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_BC_PKT_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsMulticastPkts = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_MC_PKT_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsCrcAlignErrors = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_CRC_ALIGN_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsUndersizePkts = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_UNDERSIZE_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsOversizePkts = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_OVERSIZE_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsFragments = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_FRAG_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsJabbers = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_JAB_ADDR16));
   /*Hardware doesn't support register to read this value*/
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsCollisions = (uint32)0xFFFFU;
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsPkts64Octets = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_P64_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsPkts65to127Octets = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_P65TO127_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsPkts128to255Octets = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_P128TO255_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsPkts256to511Octets = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_P256TO511_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsPkts512to1023Octets = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_P512TO1023_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   RxStats->RxStatsPkts1024to1518Octets = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_P1024TO2047_ADDR16));
}
#endif
#if STD_ON == ETH_GET_TXSTATS_API
/*================================================================================================*/
/**
* @brief         Return the list of Transmission Statistics.
* @param[in]     u8CtrlIdx Index of controller within the context of the Ethernet Driver.
* @param[out]     TxStats List of the controller within the context of the Ethernet Driver.
* @details       Return the list of Transmission Statistics out of IETF RFC1213
*                defined with Eth_TxStatsType, where the maximal possible value shall
*                denote an invalid value.
*                e.g. this counter is not available..
* @return        The search status
* @retval        E_OK Success
* @retval        E_NOTOK Tx-statistics could not be obtained.
* @implements    Eth_Fec_GetTxStats_Activity
*/
FUNC(void, ETH_CODE) Eth_Fec_GetTxStats ( \
                               VAR(uint8, AUTOMATIC) u8CtrlIdx, \
                               P2VAR(Eth_TxStatsType, AUTOMATIC, ETH_APPL_DATA) TxStats \
                                           )
{
   VAR(uint32, AUTOMATIC) u32Nunitemp;
   
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
   /* @violates @ref Eth_Fec_c_REF_5 */
   /* @violates @ref Eth_Fec_c_REF_6 */
   REG_WRITE32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_MIBC_ADDR16), 0U);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
   TxStats->TxNumberOfOctets = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_OCTETS_OK_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
   u32Nunitemp = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_T_BC_PKT_ADDR16));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
   TxStats->TxNUcastPkts = (uint32)(u32Nunitemp + REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + FEC_RMON_T_MC_PKT_ADDR16)));
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
   u32Nunitemp = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_T_PACKETS_ADDR16));
   TxStats->TxUniCastPkts = (uint32)(u32Nunitemp - TxStats->TxNUcastPkts);
}
#endif
#if STD_ON == ETH_GET_GETTXCOUNT_API
/*================================================================================================*/
/**
* @brief         Return the list of Transmission Error Counters Statistics.
* @param[in]     u8CtrlIdx Index of controller within the context of the Ethernet Driver.
* @param[out]    TxErrorCounterValues List of values to read statistic error counter values
*                    for transmission.
* @details       Return the list of Transmission Error Counters out of IETF RFC1213 and RFC1643
*                defined with Eth_TxErrorCounterValuesType, where the maximal possible value shall
*                denote an invalid value.
*                e.g. this counter is not available..
* @return        The search status
* @retval        E_OK Success
* @retval        E_NOTOK Tx-statistics could not be obtained.
*/
FUNC(void, ETH_CODE) Eth_Fec_GetTxErrorCounterValues ( \
                               VAR(uint8, AUTOMATIC) u8CtrlIdx, \
                               P2VAR(Eth_TxErrorCounterValuesType, AUTOMATIC, ETH_APPL_DATA) TxErrorCounterValues \
                                           )
{
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    REG_WRITE32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_MIBC_ADDR16), 0U);
    /*Hardware doesn't support register to read this value*/
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    TxErrorCounterValues->TxDroppedNoErrorPkts = (uint32)0xFFFFU;
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    TxErrorCounterValues->TxDroppedErrorPkts = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_T_DROP_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    TxErrorCounterValues->TxDeferredTrans = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_DEF_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    TxErrorCounterValues->TxSingleCollision = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_1COL_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    TxErrorCounterValues->TxMultipleCollision = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_MCOL_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    TxErrorCounterValues->TxLateCollision = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_LCOL_ADDR16));
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    TxErrorCounterValues->TxExcessiveCollison = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_EXCOL_ADDR16));
}
#endif
/*============================================================================*/
/**
* @brief         Determines the type of the given buffer
* @param[in]     u8CtrlIdx Index of examined controller
* @param[in]     u8Buf Index of the examined buffer
* @param[in]     u8BufCtrMax Number of the Rx buffers
* @param[out]    pMultiEnd Last found buffer of the multi-buffer frame
* @details       Function does the following
*                -# Checks the given buffer to be empty and returns RX_BUF_EMPTY
*                   if it is empty.
*                -# Otherwise it checks the buffer to be the last in the frame
*                   and returns RX_BUF_SINGLE if it is the last one.
*                -# Otherwise it goes through all  remaining buffers and
*                   searches for the full and last buffer or an empty buffer.
*                   Index of the found buffer is loaded into pMultiEnd argument.
*                -# RX_BUF_MULTI_UNFINISHED is returned if the found buffer
*                   was empty.
*                -# RX_BUF_MULTI_FINISHED is returned if the found buffer was
*                   full and last.
*                -# RX_BUF_OVERFLOW when buffer is not found.
* @return        Type of the examined buffer
* @retval        RX_BUF_EMPTY - buffer is empty,
* @retval        RX_BUF_SINGLE - buffer contains received frame
* @retval        RX_BUF_MULTI_UNFINISHED - buffer contains part of the
*                frame which has not been received yet
* @retval        RX_BUF_MULTI_FINISHED - buffer contains part of the frame which
*                has been received
* @retval        RX_BUF_OVERFLOW - all buffers are full and frame being received
*                           cannot be stored
*/

static FUNC(Eth_Fec_enRxBufferType, ETH_CODE) Eth_Fec_GetRxBufferType    ( \
                                    CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                    CONST(uint8, AUTOMATIC) u8Buf, \
                                    CONST(uint8, AUTOMATIC) u8BufCtrMax, \
                                    CONSTP2VAR(uint8, AUTOMATIC, ETH_APPL_DATA) pMultiEnd \
                                                                   )
{
  
    VAR(uint32, AUTOMATIC) u32ManipulationVar;
    VAR(uint8, AUTOMATIC ) u8BufCtr;
    VAR(Eth_Fec_enRxBufferType, AUTOMATIC) eReturnStatus = RX_BUF_OVERFLOW;
    VAR(boolean, AUTOMATIC) bBreakLoop; /* Signal that the loop should end */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    VAR(uint32, AUTOMATIC) u32BDAddress = (uint32)ETH_CFG_RXBDSTARTADDRESS(u8CtrlIdx);
    
    u32ManipulationVar = Eth_Fec_ReadRxBDBits(u32BDAddress, u8Buf);
    if (FEC_RXBD_E_U32 == (u32ManipulationVar & FEC_RXBD_E_U32))
    {
        /* Buffer is empty */
         eReturnStatus = RX_BUF_EMPTY;
    }
    else
    { /* Buffer is full */
        if (FEC_RXBD_L_U32 == (u32ManipulationVar & FEC_RXBD_L_U32))
        { /* Buffer contains whole frame */
            eReturnStatus = RX_BUF_SINGLE;
          /* Indicate that only single buffer is used */
          *pMultiEnd = u8Buf;
        }
        else
        {   /* Buffer contains only part of the frame */
            /* Search for the last buffer in that frame */      
            u8BufCtr = u8Buf;
            bBreakLoop = ((VAR(boolean, AUTOMATIC))FALSE);/*Loop shall continue*/
            do
            {
                /* Continue with the next buffer */
                if (u8BufCtrMax == u8BufCtr) /* Check if the counter wraps */
                { /* Yes, it wraps  */
                    u8BufCtr = 0U;
                }
                else
                { /* No, it does not wrap */ 
                    u8BufCtr++;
                }
                /* Check the buffer properties to determine whether 
                   it is the last buffer in the multi-buffer frame*/
                if (u8BufCtr == u8Buf) /* Check  the overflow */
                {   /* Search in the ring returned to the starting position 
                       without finding the buffer. This means the ring is full 
                       of full buffers and the last buffer which shall end
                       the multi-buffer frame cannot be written because there 
                       is no space to write it. 
                    */          
                    eReturnStatus = RX_BUF_OVERFLOW; /* Signal an error */
                    /* Searching again should be avoided */
                    bBreakLoop = ((VAR(boolean, AUTOMATIC))TRUE); 
                } 
                else
                { /* No overflow detected */
                    u32ManipulationVar = Eth_Fec_ReadRxBDBits(u32BDAddress, u8BufCtr);
                    /* Check empty state */
                    if (FEC_RXBD_E_U32 == (u32ManipulationVar & FEC_RXBD_E_U32))
                    { /* Multi-buffer frame has not been finished yet -
                         last buffer has not been written,
                         only empty space for it has been found */
                         *pMultiEnd = u8BufCtr;
                         eReturnStatus = RX_BUF_MULTI_UNFINISHED;
                         /* Buffer cannot be found, stop search */
                         bBreakLoop = ((VAR(boolean, AUTOMATIC))TRUE);             
                    }
                    /* Buffer is full, check whether it is also the last one */
                    else if (FEC_RXBD_L_U32 == (u32ManipulationVar & FEC_RXBD_L_U32)) 
                    {   /* This is the last buffer of the multi-buffer frame */
                         *pMultiEnd = u8BufCtr;
                         eReturnStatus = RX_BUF_MULTI_FINISHED;
                         /* Buffer has been found, stop search */
                         bBreakLoop = ((VAR(boolean, AUTOMATIC))TRUE);                          
                    }
                    else
                    {   /* This is the next but not the last buffer 
                           of the multi-buffer frame -
                                       Continue search with the next buffer */ 
                        bBreakLoop = ((VAR(boolean, AUTOMATIC))FALSE); 
                         /* This else is requested by MISRA otherwise 
                            it could be removed */
                    }
                }  
            }while (((boolean)FALSE) == bBreakLoop); 
        } 
    }
    
    return eReturnStatus;
}


/*============================================================================*/
/**
* @brief         Configures all receive buffers
* @details       Function initializes all RX buffer descriptors - sets the Empty
*                bit and clears the rest. It computes all buffer addresses
*                and writes them into buffer descriptor pointers. The buffer
*                descriptors ring start is written to the appropriate register.
* @param[in]     u8CtrlIdx Index of controller in which Rx buffer will be configured
* @par
*                Buffers immediately follow the buffer descriptors area when the
*                number of buffers is even, 8 bytes are skipped otherwise. All
*                buffers are of the same size, no space is between them.
*
* @warning       Buffer descriptors ring start address must be 16-bytes aligned.
*                All buffers must have length equal to multiple of 16 bytes.
*/

static FUNC(void, ETH_CODE)  Eth_Fec_ConfigureRxBuffers(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(uint32, AUTOMATIC) u32BdAddress;   /* Stores buffer descriptor address */
    VAR(uint32, AUTOMATIC) u32BufAddress;  /* Used to compute buffer address */
    VAR(uint32, AUTOMATIC) u32BDInit;   /* Initialization value for the BD bits */
    VAR(uint8, AUTOMATIC) u8BufCtr;    /* Counter used to loop over the buffers */
  
   /* Access to local variable is faster than  via pointer in case of post-build 
      or link-time configuration. Configured value should be somewhere stored in 
      case of pre-compile configuration. */
    VAR(uint8, AUTOMATIC) u8BufNum;       /* Holds configured number of buffers */
    VAR(uint16, AUTOMATIC) u16BufLength;   /* Holds configured maximal length of 
                                              one Rx buffer */
    VAR(uint8, AUTOMATIC) u8Idx = 0U;
    
    /* Get the length of one Rx buffer */
    u16BufLength = (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8Idx].EthCtrlConfigIngressFifoBufLenByte);
    /* Get the number of configured buffers */
    u8BufNum = (uint8)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8Idx].EthCtrlConfigIngressFifoBufTotal);
    /* Get start address of Rx buffer descriptor rings */
    /* Compiler_Warning: (diab) this should not be a warning because they are same type. 
    No potential problem here. */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    u32BdAddress = (uint32)ETH_CFG_RXBDSTARTADDRESS(u8CtrlIdx);
    /* Store the value into register - select ony necessary bits */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32( Eth_u32BaseAddr[u8CtrlIdx] + FEC_ERDSR_ADDR16, (u32BdAddress & FEC_ERDSR_R_DES_START_U32));   
    /* Assemble the configuration value */
    u32BDInit = FEC_RXBD_E_U32;
    /* Compute address of the first receive buffer data area - it has to be 16 
       bytes aligned which is done by following:
       - Buffer descriptors start address is generated as 16-bytes aligned 
       - All buffer descriptors are 8 bytes long and create continuous block
       - Buffer lengths are limited to be multiple of 16 bytes
       - Buffer area follows immediately after the buffer descriptors area if 
         the number of buffers is even
       - An empty space of 8 bytes is inserted between buffer descriptors and 
         buffers area if the number of buffers is odd    
    */
    /* Leave space for buffer descriptors */
    u32BufAddress = u32BdAddress + (u8BufNum * (uint32)ETH_FEC_BD_SIZE); 
    /* Check whether the number of buffers is odd */
    /* @violates @ref Eth_Fec_c_REF_8 MISRA rule 13.7 */
    if (0U != (u8BufNum & 0x01U))
    { /* Yes */
        u32BufAddress = u32BufAddress + ETH_FEC_BD_SIZE;  /* Skip 8 bytes */
    }
#if STD_ON == ETH_USE_RX_FRAMES_WRAP
    /* Create a space for leading buffers */
    /* 
       Payload(1500) + MAC(2*6) + VLAN(4) + TypeLength(2) + CRC(4) = 2047
       and therefore 1536 is needed
    */
    u32BufAddress += (uint32)((((2047U / 2U) + ((uint32)u16BufLength - 1U)) / u16BufLength )  * u16BufLength);
#endif /* ETH_USE_RX_FRAMES_WRAP */
    /* Write the buffer pointers to buffer descriptors and initialize
       status bits of all buffers */
    Eth_Fec_u32RxBufStartAddr[u8CtrlIdx][u8Idx] = u32BufAddress;
    /*Calculate start address of data buffer when length of buffer in configuration isn't multiple of 16*/
    if (0U != (uint16)(u16BufLength % 16U))
    {
        u16BufLength += (uint16)((uint16)16U - (u16BufLength % 16U));
    }
    for (u8BufCtr = 0U; u8BufCtr < u8BufNum; u8BufCtr++)
    {
        /* Write buffer descriptor control bits and length - buffer only needs 
           to be marked as empty, all other fields will be updated 
           during reception */
        Eth_Fec_WriteRxBDBits(u32BdAddress, u8BufCtr, u32BDInit); 
        /* Write buffer address into descriptor */
        Eth_Fec_WriteRxBDBufPtr(u32BdAddress, u8BufCtr, u32BufAddress);     
        /* Compute address of the next buffer */
        u32BufAddress = u32BufAddress + u16BufLength + 16U;
    } 
    /* Close the descriptor ring */
    u32BDInit = u32BDInit | FEC_RXBD_W_U32; /* This is the last descriptor */
    Eth_Fec_WriteRxBDBits(u32BdAddress, (uint8)(u8BufNum - 1U), u32BDInit);  /* Mark the last one */
}

/*============================================================================*/
/**
* @brief         Configures all transmit buffers
* @details       Function clears all buffer descriptor bits -> marks all buffer
*                descriptors as Free and not ready for the transmission.
*                The buffer descriptors ring start address is written it the
*                appropriate register.
* @par
*                All buffers of same size, immediately follow buffer descriptors
*                as a continuous block without empty spaces between buffers.
* @warning       Buffer descriptors ring start address must be 16-bytes aligned.
*                Buffer sizes are limited to be multiple of 16 bytes.
*/

static FUNC(void, ETH_CODE) Eth_Fec_ConfigureTxBuffers(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(uint32, AUTOMATIC) u32BdAddress; /* Stores buffer descriptor address */
    VAR(uint8, AUTOMATIC) u8Idx;      /* Index to go through buffer array */
    /* Number of TX buffers from configuration */
    VAR(uint8, AUTOMATIC) u8BufNum;  
    VAR(uint16, AUTOMATIC) u16BufLength;  
    /*Index of queue*/    
    VAR(uint8, AUTOMATIC) u8QueueIdx = 0U;
    VAR(uint32, AUTOMATIC) u32BufAddress;

    /* Get start address of TX buffer descriptors ring */
    /* Compiler_Warning: (diab) this should not be a warning because they are same type. 
    No potential problem here. */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    u32BdAddress = ETH_CFG_TXBDSTARTADDRESS(u8CtrlIdx);
    u8BufNum = (uint8)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pEgressCfg[u8QueueIdx].EthCtrlConfigEgressFifoBufTotal);
    u16BufLength = (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pEgressCfg[u8QueueIdx].EthCtrlConfigEgressFifoBufLenByte);
    /*Calculate start address of data buffer when length of buffer in configuration isn't multiple of 16*/
    if (0U != (uint16)(u16BufLength % 16U))
    {
        u16BufLength += (uint16)((uint16)16U - (u16BufLength % 16U));
    }
    if ((uint8)0U == (u8BufNum & 0x01U))
    {   /* Even number of descriptors - first data pointer is already aligned to 64 bytes */
        u32BufAddress = (uint32)(u32BdAddress + ((uint32)ETH_FEC_BD_SIZE * (uint32)u8BufNum));
    }
    else
    {   /* Odd number of descriptors - leave 32 bytes to get the first data pointer aligned to 64 bytes */
        u32BufAddress = (uint32)(u32BdAddress + ((uint32)ETH_FEC_BD_SIZE * (uint32)u8BufNum) + (uint32)ETH_FEC_BD_SIZE);
    }
    /* Store the TX buffer start address for future use */
    Eth_Fec_u32TxBufStartAddr[u8CtrlIdx][u8QueueIdx] = u32BufAddress;
    for (u8Idx=0U; u8Idx < u8BufNum; u8Idx++)
    {
        /* Unlock all TX buffers */
        Eth_au8TxBufFlags[u8CtrlIdx][u8QueueIdx][u8Idx] = 0U;
        /* Clear all buffer descriptor status bits, zero length */
        Eth_Fec_WriteTxBDBits(u32BdAddress, u8Idx, 0U); 
        Eth_Fec_WriteTxBDBufPtr(u32BdAddress, u8Idx, u32BufAddress);
        u32BufAddress += u16BufLength;
    }
    /* Set wrap bit on last buffer descriptor */
    /* Just in case, unnecessary because it is always set in Eth_Fec_Transmit */
    Eth_Fec_WriteTxBDBits(u32BdAddress, u8BufNum-1U, FEC_TXBD_W_U32); 
    /* Compute start address of TX buffers */
    if (0U == (u8BufNum & 0x01U))
    {   /* Even number of descriptors - first data pointer is already aligned to 64 bytes */
        Eth_Fec_u32TxBufStartAddr[u8CtrlIdx][u8QueueIdx] = (uint32)(u32BdAddress + ((uint32)ETH_FEC_BD_SIZE * (uint32)u8BufNum));
    }
    else
    {   /* Odd number of descriptors - leave 32 bytes to get the first data pointer aligned to 64 bytes */
        Eth_Fec_u32TxBufStartAddr[u8CtrlIdx][u8QueueIdx] = (uint32)(u32BdAddress + (uint32)((uint32)ETH_FEC_BD_SIZE * (uint32)u8BufNum) + (uint32)ETH_FEC_BD_SIZE);
    }
    /* Start free buffer search from beginning */
    Eth_Fec_u8SearchTxBufFrom[u8CtrlIdx][u8QueueIdx] = 0U;
    /* Store the value into register - select only necessary bits */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */   
    REG_WRITE32( Eth_u32BaseAddr[u8CtrlIdx] + FEC_ETDSR_ADDR16, (u32BdAddress & FEC_ETDSR_X_DES_START_U32));
}
#if STD_OFF == ETH_BRIDGE_SUPPORT
/*================================================================================================*/
/**
* @brief          Convert multi-byte short integer from host byte order
*                 to network byte order
* @param[in]      u32HostShort host short integer to be converted
* @return         Converted short integer in network order
*/
static FUNC(uint32, ETH_CODE) Eth_Fec_Htons( CONST(uint32, AUTOMATIC) u32HostShort)
{
    VAR(uint16, AUTOMATIC) u16First2Byte;
    VAR(uint16, AUTOMATIC) u16Last2Byte;
    VAR(uint32, AUTOMATIC) u32RetVal;
    
    u16First2Byte = (uint16)(u32HostShort >> 16U) & 0xFFFFU;
    u16Last2Byte = (uint16)(u32HostShort & 0xFFFFU);
    u32RetVal = ((uint32)((uint32)u16Last2Byte << 16U) & 0xFFFF0000U) | (uint32)u16First2Byte;

    return u32RetVal;
}
#endif
/*============================================================================*/
/**
* @brief         Clears all MIB Counters
* @details       Function disables the counters block, writes value 0 to all
*                counters and reenables the counters block.
* @param[in]     u8CtrlIdx Index of controller to be cleared the counters
*/

static FUNC(void, ETH_CODE) Eth_Fec_ClearMIBCounters(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(uint16, AUTOMATIC) u16TempCtr; /* Counter used to access MIB counters */ 
    
    /* Disable MIB */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_MIBC_ADDR16, FEC_MIBC_MIB_DISABLE_U32);
    /* Clear the MIB RAM */
    for (u16TempCtr = FEC_RMON_T_DROP_ADDR16; u16TempCtr <= FEC_IEEE_R_OCTETS_OK_ADDR16; u16TempCtr += 4U)
    {
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        /* @violates @ref Eth_Fec_c_REF_6 */    
        REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)u16TempCtr, 0U);
    }
    /* Enable MIB */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_MIBC_ADDR16, 0U);
}
/*============================================================================*/
/**
* @brief         Returns pointer to received frame, frame length and status
*                bits of the receive buffer
* @param[in]     u8CtrlIdx Index of controller to be read
* @param[in]     u8Buf First buffer of the frame
* @param[in]     u8MultiEnd Last buffer of the frame
* @param[out]    pLength  Frame length
* @param[out]    pDataPtr Pointer to the frame data
* @param[out]    pStatusPtr Buffer status bits
* @details       Function loads the pStatusPtr argument with the buffer status
*                bits, the length argument is loaded by the frame length
*                and the pDataPtr is loaded with the beginning address of the
*                received frame data.
* @note          The returned buffer contains Ethernet frame header and its
*                payload. The CRC is not included but it occupies next 4 bytes
*                in the memory after the buffer end.
* @implements    Eth_Fec_GetRxBufferData_Activity
*/

static FUNC(void, ETH_CODE) Eth_Fec_GetRxBufferData    ( \
                            CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                            CONST(uint8, AUTOMATIC) u8FifoIdx, \
                            CONST(uint8, AUTOMATIC) u8Buf, \
                            CONST(uint8, AUTOMATIC) u8MultiEnd, \
                            CONSTP2VAR(uint16, AUTOMATIC, ETH_APPL_DATA) pLength, \
                            P2P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA) pDataPtr, \
                            CONSTP2VAR(uint32, AUTOMATIC, ETH_APPL_DATA) pStatusPtr \
                                                        )
{
#if STD_ON == ETH_USE_RX_FRAMES_WRAP
    /* The maximum index of RX buffer */
    VAR(uint8, AUTOMATIC) u8BufCtrMax;
    /* Loop control variable */
    VAR(uint32, AUTOMATIC) u32ii;
    /* Temporary source and destination addresses */
    VAR(uint32, AUTOMATIC) u32srcAddr;
    VAR(uint32, AUTOMATIC) u32destAddr;
    VAR(uint8, AUTOMATIC) u8BufNum;
    VAR(uint16, AUTOMATIC) u16BufLength;
#endif /* ETH_USE_RX_FRAMES_WRAP */
    VAR(uint16, AUTOMATIC) u16FrameLength;
    /* Manipulation variable */
    VAR(uint32, AUTOMATIC) u32ManipulationVar;

#if STD_ON == ETH_USE_RX_FRAMES_WRAP
    u8BufNum = (uint8)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8FifoIdx].EthCtrlConfigIngressFifoBufTotal);
    u8BufCtrMax = (uint8)(u8BufNum - 1U);
#endif
    /* Get reception status of the frame */
    /* Compiler_Warning: (diab) this should not be a warning because they are same type. 
    No potential problem here. */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    u32ManipulationVar = Eth_Fec_ReadRxBDBits((uint32)ETH_CFG_RXBDSTARTADDRESS(u8CtrlIdx), u8MultiEnd);
    /* Return the status bits */
    *pStatusPtr = u32ManipulationVar & (uint32)0xFFFF0000U;
    /* Select the length field */
    u32ManipulationVar = u32ManipulationVar & FEC_RXBD_LENGTH_U32; 
    /* Return the length */
    u16FrameLength = (uint16)(u32ManipulationVar & FEC_RXBD_LENGTH_U32); 
    /* Get data pointer and data length */
#if STD_ON == ETH_USE_MULTIBUFFER_RX_FRAMES
    if (u16FrameLength > (uint16)2047U)
    {   /* The length must be incorrect, it is greater than maximal allowed length */
        /* Return maximal length instead */
        *pLength = (uint16)2047U;
    }
#else
    if (u16FrameLength > (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8FifoIdx].EthCtrlConfigIngressFifoBufLenByte))
    {   /* The length must be incorrect, it is greater than maximal allowed length */
        /* Return maximal length instead */
        *pLength = (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8FifoIdx].EthCtrlConfigIngressFifoBufLenByte);
    }
#endif
    else if (u16FrameLength < 14U)
    {   /* The length must be incorrect, minimal acceptable length is 14 (ethernet header only) */
        /* Return minimal length instead (avoid length underloop due to header length subtract) */
        *pLength = (uint16)14U;
    }
    else
    {   /* The length seems correct, return it */
        /* In IPV_FEC, CRC is not truncated, so remove it */
        *pLength = u16FrameLength-4U;
    }
    
    if (u8Buf > u8MultiEnd)
    {
        /* Wrap occurred */
    #if STD_ON == ETH_USE_RX_FRAMES_WRAP
        u16BufLength = (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8FifoIdx].EthCtrlConfigIngressFifoBufLenByte);
        /* Check whether data should be copied to leading or trailing area -
           chose which copy will be shorter: either buffer ring start to "u8MultiEnd", 
           or "u8Buf" to buffer ring end. */
        if (0U != (uint16)(u16BufLength % 16U))
        {
            u16BufLength += (uint16)((uint16)16U - (u16BufLength % 16U));
        }
        if ((u8BufCtrMax-u8Buf) > u8MultiEnd)
        { /* Copy from the start of the buffer ring to the trailing area because it is shorter */
            /* Setup source address */
            u32srcAddr = Eth_Fec_ComputeRxBufAddr(u8CtrlIdx, u8FifoIdx, 0U);
            /* Setup destination address */
            u32destAddr = Eth_Fec_ComputeRxBufAddr(u8CtrlIdx, u8FifoIdx, u8BufCtrMax) + (uint32)((uint32)u16BufLength + 16U);
            /* Store the data pointer */
            u32ManipulationVar = Eth_Fec_ComputeRxBufAddr(u8CtrlIdx, u8FifoIdx, u8Buf);
            /* Return the pointer */
            /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
            /* @violates @ref Eth_Fec_c_REF_5 */
            *pDataPtr = (P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA))u32ManipulationVar;
            
            /* Get number of buffers up to wrap */
            u32ManipulationVar = (((uint32)u8BufCtrMax - u8Buf) + 1U);
            /* Setup count. The 'length' value must be extended by 4 bytes of CRC */
            u32ManipulationVar = ((uint32)(*pLength) + 4U) - (u32ManipulationVar * (uint32)((uint32)u16BufLength + 16U));
        }
        else
        { /* Copy from the end of the buffer ring to the leading area because it is shorter */
            /* Get source address */
            u32srcAddr = Eth_Fec_ComputeRxBufAddr(u8CtrlIdx, u8FifoIdx, 0U) \
                            + ((uint32)u8Buf * ((uint32)u16BufLength + (uint32)16U));
            /* Set destination address */
            u32destAddr =  ( Eth_Fec_ComputeRxBufAddr(u8CtrlIdx, u8FifoIdx, 0U) \
                            - ((u8BufNum - (uint32)u8Buf) * (uint32)((uint32)u16BufLength + 16U)) \
                           );
            /* Return the pointer */
            /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
            /* @violates @ref Eth_Fec_c_REF_5 */
            *pDataPtr = (P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA))u32destAddr;
            /* Setup count */
            u32ManipulationVar = ((uint32)u8BufNum - (uint32)u8Buf) * (uint32)((uint32)u16BufLength + 16U);
        }
        
        /* Perform the copy */
        for (u32ii=u32destAddr; u32ii<(u32destAddr+u32ManipulationVar); u32ii+=4U)
        {
            /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
            /* @violates @ref Eth_Fec_c_REF_5 */
            *(P2VAR(uint32, AUTOMATIC, ETH_APPL_DATA)) u32ii = (uint32)(*(P2VAR(uint32, AUTOMATIC, ETH_APPL_DATA)) u32srcAddr);
            /* Move the source address */
            u32srcAddr+=4U;
        }
    #else
        /* Do not receive the frame. Setup the error flags to ensure that frame
            will be rejected. */
        *pStatusPtr |= (uint32) 0xFFFF0000U;
    #endif /* ETH_USE_RX_FRAMES_WRAP */
    }
    else if (u8Buf == u8MultiEnd)
    {
        /* Receive the single-buffer frame */
        /* Store the data pointer */
        u32ManipulationVar = Eth_Fec_ComputeRxBufAddr(u8CtrlIdx, u8FifoIdx, u8Buf);
        /* Return the pointer */
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        *pDataPtr = (P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA))u32ManipulationVar;
    }
    else
    {
    #if STD_ON == ETH_USE_MULTIBUFFER_RX_FRAMES
        /* Store the data pointer */
        u32ManipulationVar = Eth_Fec_ComputeRxBufAddr(u8CtrlIdx, u8FifoIdx, u8Buf);
        /* Return the pointer */
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        *pDataPtr = (P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA)) u32ManipulationVar;
    #else
        /* Do not receive the frame. Setup the error flags to ensure that frame
            will be rejected. */
        *pStatusPtr |= (uint32)0xFFFF0000U;
    #endif /* ETH_USE_MULTIBUFFER_RX_FRAMES */
    }
}

/*============================================================================*/
/**
* @brief         Unlocks given TX buffer and also BD if it is linked to buffer
* @param[in]     u8CtrlIdx Index of controller which will be release the buffer
* @param[in]     u8BufIdx DA index of the buffer to be unlocked
* @details       Function clears the Lock and the Transmitted bits of the given
*                buffer. Buffer becomes empty and can be reused for another
*                transmission.
* @note          All status bits and the length field are cleared.
*/
static FUNC(void, ETH_CODE) Eth_Fec_GiveBackTxBuffer(CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                                    CONST(uint8, AUTOMATIC) u8FifoIdx, \
                                                    VAR(uint8, AUTOMATIC) u8BufIdx \
                                                    )
{
    VAR(uint32, AUTOMATIC) u32ManipulationVar;
    VAR(uint8, AUTOMATIC) u8BDIdx; /* Index of linked BD (if any) */
#if STD_ON == ETH_USE_MULTIBUFFER_TX_FRAMES
    VAR(uint8, AUTOMATIC) u8BufNum; /* Number of buffers in current frame */
#endif /* ETH_USE_MULTIBUFFER_TX_FRAMES */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    VAR(uint32, AUTOMATIC) u32BDAddress = ETH_CFG_TXBDSTARTADDRESS(u8CtrlIdx);

    /* Is there a BD linked to this buffer? */
    if ((FEC_TXB_FIRST_U8 | FEC_TXB_LINK_U8 | FEC_TXB_LOCK_U8) == Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8BufIdx])
    {   /* Yes, unlink the BD */
        /* Remove it on the BD side: */
        u8BDIdx = Eth_au8TxBdOfBuf[u8CtrlIdx][u8FifoIdx][u8BufIdx];
        /* Read the TXBD status */
        u32ManipulationVar = Eth_Fec_ReadTxBDBits(u32BDAddress, u8BDIdx);
        /* Clear BufLinked flag */
        u32ManipulationVar &= (VAR(uint32, AUTOMATIC))(~FEC_TXBD_TO1_U32);
        /* Write modified bits back */
        Eth_Fec_WriteTxBDBits(u32BDAddress, u8BDIdx, u32ManipulationVar);
        /* NOTE: on buffer side the link is removed below */
    }

#if STD_ON == ETH_USE_MULTIBUFFER_TX_FRAMES
    /* Unlock all buffers of frame */
    u8BufNum = Eth_Fec_au8TxBufGroup[u8CtrlIdx][u8FifoIdx][u8BufIdx];
    while (0U != u8BufNum)
    {
        Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8BufIdx] = 0U;
        u8BufNum--;
        u8BufIdx++; /* The memory must be continuous, wrap may not occur */
    }
#else /* ETH_USE_MULTIBUFFER_TX_FRAMES */
    /* Unlock the buffer, there is only one */
    Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8BufIdx] = 0U;
#endif /* ETH_USE_MULTIBUFFER_TX_FRAMES */
}

/*==============================================================================
*                                       GLOBAL FUNCTIONS
==============================================================================*/

/*============================================================================*/
/**
* @brief         Finds empty TX buffer(s) (if any) and locks them
* @param[in]     u8CtrlIdx Index of controller to be borrowed buffer
* @param[out]    pBufIdx Granted buffer index to be used for frame
*                transmission is stored here.
* @param[out]    pBufPtr Pointer to data area beginning is stored here.
* @param[in,out] pBufLength Wanted or Granted buffer length
* @details       Function goes through buffers, searching either UnlockedAT
*                or Free buffers. If UnlockedAT buffer is found, whole frame
*                is freed at first. Once continuous region of memory of
*                requested length is found, it is allocated, pointer to the
*                memory is returned, index of first allocated buffer is returned
*                and real allocated length is also returned. Otherwise FALSE is
*                returned.
* @return        The search result
* @retval        TRUE Available buffer of desired length was found and locked.
* @retval        FALSE There is not empty buffer available at the moment.
* @implements    Eth_Fec_BorrowTxBuffer_Activity
*/
FUNC(boolean, ETH_CODE) Eth_Fec_BorrowTxBuffer  ( \
                    CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                    CONST(uint8, AUTOMATIC) u8FifoIdx, \
                    CONSTP2VAR(Eth_BufIdxType, AUTOMATIC, ETH_APPL_DATA) pBufIdx, \
                    P2P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA) pBufPtr, \
                    CONSTP2VAR(uint16, AUTOMATIC, ETH_APPL_DATA) pBufLength\
                                                )
{
    VAR(uint8, AUTOMATIC) u8BufNumNeed; /* Needed number of buffers */
    VAR(uint8, AUTOMATIC) u8BufNumFound; /* Number of free buffers found */
#if STD_ON == ETH_USE_MULTIBUFFER_TX_FRAMES
    VAR(uint8, AUTOMATIC) u8IdxL; /* General purpose index to be used in loops */
#endif /* ETH_USE_MULTIBUFFER_TX_FRAMES */
    VAR(uint32, AUTOMATIC) u32BDStatus;
    VAR(uint8, AUTOMATIC) u8Idx;  /* General purpose index to be used in loops */
    VAR(uint16, AUTOMATIC) u16SearchCnt; /* Countdown to limit search */
    
    VAR(boolean, AUTOMATIC) bDataAreaFound = ((boolean)FALSE); 
    /* Used to track if some free buffer was found */
    /* Local copies of configuration (optimization): */
    VAR(uint8, AUTOMATIC) u8TotalBufNum;
    VAR(uint16, AUTOMATIC) u16BufSize;
    /* Compiler_Warning: (diab) this should not be a warning because they are same type. 
    No potential problem here. */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    VAR(uint32, AUTOMATIC) u32BDAddr = ETH_CFG_TXBDSTARTADDRESS(u8CtrlIdx);
#if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
    P2P2VAR(uint8, AUTOMATIC, ETH_APPL_DATA) pType = NULL_PTR;
#endif   
    
    u8TotalBufNum = (uint8)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pEgressCfg[u8FifoIdx].EthCtrlConfigEgressFifoBufTotal);
    u16BufSize = (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pEgressCfg[u8FifoIdx].EthCtrlConfigEgressFifoBufLenByte);
#if STD_ON == ETH_USE_MULTIBUFFER_TX_FRAMES
    /* Compute needed number of buffers. Add 14B for eth header, round up */
    u8BufNumNeed = (uint8)((*pBufLength + (u16BufSize + (14U - 1U))) / u16BufSize);
    /* s16SearchCnt must be incremented by the number of needed buffers because
       we must check the buffers at the end again if we skipped them due to
       the fact that we started search in the middle of the continuous block
       just before the wrap (example: we need 4 buffers, and we start search
       from the 3rd buffer before the row end therefore we would end by
       examining the 4th buffer from the end (if no adjust was done) without
       discovering needed 4 buffers block at the end of the row). */
    u16SearchCnt = ((uint16)u8TotalBufNum + (uint16)u8BufNumNeed) - 1U;
#else /* ETH_USE_MULTIBUFFER_TX_FRAMES */
    /* One buffer is always needed */
    u8BufNumNeed = (uint8)1U;
    u16SearchCnt = u8TotalBufNum;
#endif /* ETH_USE_MULTIBUFFER_TX_FRAMES */

    /* Start at Eth_Fec_u8SearchTxBufFrom (to minimize fragmentation) */
    u8Idx = Eth_Fec_u8SearchTxBufFrom[u8CtrlIdx][u8FifoIdx];
    u8BufNumFound = 0U;
    while (((VAR(boolean, AUTOMATIC))FALSE == bDataAreaFound) && (u16SearchCnt != 0U))
    {
        /* Check buffer status, whether the buffer may be unlocked now */
        if ((FEC_TXB_LOCK_U8 | FEC_TXB_LINK_U8 | FEC_TXB_FIRST_U8) == Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8Idx])
        {   /* According to buffer flags, it may be unlocked now */
            /* Now check BD status, whether Ready bit is cleared */
            u32BDStatus = FEC_TXBD_R_U32 & Eth_Fec_ReadTxBDBits(u32BDAddr, Eth_au8TxBdOfBuf[u8CtrlIdx][u8FifoIdx][u8Idx]);
            if( 0U == u32BDStatus )
            {   /* Yes, the frame is in UNLOCKEDAT state and both BD and
                   buffers shall be unlocked and unlinked now */
                Eth_Fec_GiveBackTxBuffer(u8CtrlIdx, u8FifoIdx, u8Idx);
            }
        }
        /* Check buffer status. Is the buffer free ? */
        if (0U == Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8Idx])
        {   /* Yes, it is free */
            u8BufNumFound++;
            if (u8BufNumFound == u8BufNumNeed)
            {   /* All needed buffers found */
                bDataAreaFound = (boolean)TRUE;
                u8Idx++;
                /* Next time continue search from here */
                if (u8Idx >= u8TotalBufNum)
                {
                    Eth_Fec_u8SearchTxBufFrom[u8CtrlIdx][u8FifoIdx] = 0U;
                }        
                else     
                {        
                    Eth_Fec_u8SearchTxBufFrom[u8CtrlIdx][u8FifoIdx] = u8Idx;
                }
                /* Compute index of the first buffer, u8Idx is behind allocated
                   buffers now. Continuous block => no wrap => no under-loop */
                /* @violates @ref Eth_Fec_c_REF_6 */
                *pBufIdx = (Eth_BufIdxType)(u8Idx - u8BufNumFound);
                /* Compute buffer pointer, skip 14 bytes for ethernet header */
                /* @violates @ref Eth_Fec_c_REF_4 */
                /* @violates @ref Eth_Fec_c_REF_5 */
                /* @violates @ref Eth_Fec_c_REF_6 */
                *pBufPtr = (Eth_DataType *)(14U + (Eth_Fec_ComputeTxBufAddr(u8CtrlIdx, u8FifoIdx, (uint8)(*pBufIdx))));
                /* Return real length of buffers minus eth header length */
                *pBufLength = (uint16)((u16BufSize * u8BufNumNeed) - 14U);
#if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
                /* @violates @ref Eth_Fec_c_REF_5 */
                /* @violates @ref Eth_Fec_c_REF_6 */
                /* @violates @ref Eth_Fec_c_REF_14 */
                *pType = (void *)(12U + (Eth_Fec_ComputeTxBufAddr(u8CtrlIdx, (uint8)(*pBufIdx), u8FifoIdx)));
                (void)EthSwt_EthTxPrepareFrame (u8CtrlIdx, (Eth_BufIdxType)(*pBufIdx), pType, pBufLength);
#endif
                /* Lock all allocated buffers, do in critical section to prevent interference */
                Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][*pBufIdx] = (uint8)(FEC_TXB_LOCK_U8 | FEC_TXB_FIRST_U8); /* The 1st */

#if STD_ON == ETH_USE_MULTIBUFFER_TX_FRAMES
                /* Write number of buffers belonging to this frame */
                Eth_Fec_au8TxBufGroup[u8CtrlIdx][u8FifoIdx][*pBufIdx] = u8BufNumNeed;

                for (u8IdxL = (uint8)((uint8)(*pBufIdx) + (uint8)1U); u8IdxL < (uint8)((uint8)(*pBufIdx) + u8BufNumNeed); u8IdxL++) /* Skip the first */
                {
                    Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8IdxL] = FEC_TXB_LOCK_U8;
                }
#endif /* ETH_USE_MULTIBUFFER_TX_FRAMES */
            }
        }
        else
        {   /* No, buffer is locked => continuity broken */
            u8BufNumFound = 0U;
        }
        u16SearchCnt--;
        u8Idx++;
        if (u8Idx >= u8TotalBufNum)
        {   /* Wrapped */
            u8Idx = 0U;
            u8BufNumFound = 0U; /* Wrap => continuity broken */
        }
    }
    
    return bDataAreaFound;
}

/*============================================================================*/
/* TX Buffers status bits summary ()

    BufferState   BD_Bits Link BufferFlags
    Free:                        0000
    LockedBT:                    1001
    LockedIT:         11---------1111
    UnlockedIT:       11---------1011
    LockedAT:         01---------1111
    UnlockedAT:       01---------1011
    LockedATUnlinked:            1101
    LockedNotFirstOfFrame:       1000
    FreeBufferDescr:  00
                      ||    |    ||||-- FEC_TXB_FIRST_U8: First buffer of frame
                      ||    |    |||--- FEC_TXB_LINK_U8: Linked to BD
                      ||    |    ||---- FEC_TXB_CONF_U8: TxConfirmation needed
                      ||    |    |----- FEC_TXB_LOCK_U8: Buffer locked
                      ||    |---------- Link between BD and buffer. If the link
                      ||                exists, FEC_TXB_LINK_U8 and FEC_TXBD_TO1_U32 
                      ||                bits are set and following is true:
                      ||                BDIdx = Eth_au8TxBdOfBuf[BufIdx]
                      ||--------------- FEC_TXBD_TO1_U32: Linked to buffer(s)
                      |---------------- FEC_TXBD_R_U32:   In transmission (ready bit)

    Transitions between states:
    In Eth_Fec_BorrowTxBuffer():
        Free -> LockedBT:             Standard operation.
        UnlockedAT -> LockedBT:       Buffer automatically released and reused.
    In Eth_Fec_Transmit();
        LockedBT -> LockedIT:         Standard operation, TxConfirm required.
        LockedBT -> UnlockedIT:       Standard operation.
        UnlockedAT -> Free:           The linked buffer descriptor was needed
                                      -> both BD and Buffers were
                                      automatically freed.
        LockedAT -> LockedATUnlinked: The linked buffer descriptor was needed
                                      -> it was unlinked from the buffers.
    In FEC (the hardware):
        LockedIT -> LockedAT:         Standard operation.
        UnlockedIT -> UnlockedAT:     Standard operation.
    In TxConfirmation:
        LockedAT -> Free:             Standard operation.
        LockedATUnlinked -> Free:     Standard operation.
*/
/*================================================================================================*/
/**
* @brief         Checks whether the transmit buffer state is LOCKEDBT
* @param[in]     u8BufIdx Checked buffer index (first buffer of frame)
* @param[in]     u32BDAddr Address of the TX descriptor ring start
* @details       Function checks whether the buffer is locked and first of frame
*                (whether it may be passed to Transmit function).
* @retval        TRUE Buffer is in LOCKEDBT state, valid frame "handle"
* @retval        FALSE Buffer is in different state
*/
FUNC(boolean, ETH_CODE) Eth_Fec_IsTxBufLockedBT(CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                                CONST(uint8, AUTOMATIC) u8FifoIdx, \
                                                CONST(Eth_BufIdxType, AUTOMATIC) u8BufIdx \
                                                )
{
    VAR(boolean, AUTOMATIC) bResult; /* Result holder */ 

    if ((FEC_TXB_LOCK_U8|FEC_TXB_FIRST_U8)== Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8BufIdx])
    {   /* OK, it is locked and first buffer of frame */
        bResult = (boolean)TRUE;
    }
    else 
    {
        bResult = (boolean)FALSE;
    }
    return bResult;
}
#if (STD_OFF == ETH_TXFIFO_SINGLE_MODE)
/*============================================================================*/
/**
* @brief         Find Fifo idx from index of buffer
* @param[in]     u8CtrlIdx Index of controller in which TxIRQ flag will be checked
* @param[in]     u8BufIfx buffer index
* @retval        Index of Fifo
*/
FUNC(uint8, ETH_CODE) Eth_Fec_FindFifoIdx(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(Eth_BufIdxType, AUTOMATIC) BufIdx)
{
    VAR(uint8, AUTOMATIC) u8FifoNum;
    VAR(uint8, AUTOMATIC) u8Idx;
    VAR(uint8, AUTOMATIC) u8RetVal = 0U;
    
    u8FifoNum = (uint8)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).EthTxFifoNum);
    for (u8Idx = u8FifoNum; u8Idx > 0U; u8Idx--)
    {
        if (BufIdx >= (Eth_BufIdxType)Eth_Fec_u16BufStartIdx[u8CtrlIdx][u8Idx - 1U])
        {
            u8RetVal = (uint8)(u8Idx - 1U);
            break;
        }
        else
        {
            u8RetVal = FEC_TXFIFO_INVALID;  /*Invalid index of fifo*/
        }
    }
    
    return u8RetVal;
}
#endif
/*============================================================================*/
/**
* @brief         Triggers the transmission of the given frame
* @param[in]     u8CtrlIdx Index of controller which will be triggered the transmission
* @param[in]     u8BufIdx Buffer index provided by Eth_Fec_BorrowTxBuffer.
* @param[in]     u16EtherType Type or length field value in the 802.3 frame header
* @param[in]     u16Length Payload length
* @param[in]     bConfirm Selects whether the frame transmission shall
*                be confirmed or not
* @param[in]     pDest Frame destination address
* @details       At first Ethernet header is assembled.
*                Then the buffers are linked with active buffer descriptor
*                (Eth_u8ActiveTxBD) and the buffer descriptor is written
*                including the Ready bit. The controller is notified about the
*                new buffer by a write into the TDAR register.
* @note          Note that as buffer was successfully borrowed, at least one BD
*                will also be available, because number of BDs >= number of
*                frames in buffers, so even if all buffers (but this one) are
*                linked to BDs, at least one BD is free and may be used for
*                current frame. 
*                Buffer descriptors are used as ring buffer, where
*                Eth_u8ActiveTxBD is index of first available BD. It is also
*                the only one BD that may be used, because it is the BD where
*                FEC controller will look for next frame.
* @implements    Eth_Fec_Transmit_Activity
*/

FUNC(void, ETH_CODE) Eth_Fec_Transmit  (
                        CONST(uint8, AUTOMATIC) u8CtrlIdx,
                        CONST(uint8, AUTOMATIC) u8FifoIdx,
                        CONST(Eth_BufIdxType, AUTOMATIC) u8BufIdx,
                        CONST(Eth_FrameType, AUTOMATIC) u16Type,
                        CONST(uint16, AUTOMATIC) u16Length,
                        CONST(boolean, AUTOMATIC) bConfirm,
                        P2CONST(uint8, AUTOMATIC, ETH_APPL_DATA) pDest
#if STD_ON == ETH_BRIDGE_SUPPORT
                      , P2CONST(uint8, AUTOMATIC, ETH_APPL_DATA) pSource
#endif /* ETH_BRIDGE_SUPPORT  */
                                        )
{
    VAR(uint32, AUTOMATIC) u32BufAddr; /* Address of (first) buffer */
    VAR(uint32, AUTOMATIC) u32ManipulationVar; /* Used for bit manipulations */
    /* Local copies of configuration (optimization): */
    VAR(uint8, AUTOMATIC) u8TotalBufNum;
    /* Compiler_Warning: (diab) this should not be a warning because they are same type. 
    No potential problem here. */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    VAR(uint32, AUTOMATIC) u32BDAddr = ETH_CFG_TXBDSTARTADDRESS(u8CtrlIdx);
#if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
    P2P2VAR(uint8, AUTOMATIC, ETH_APPL_DATA) pDataPtr = NULL_PTR;
    P2VAR(uint16, AUTOMATIC, ETH_APPL_DATA) pLengthPtr = NULL_PTR;
    VAR(uint16, AUTOMATIC) u16BufLength;
#endif
    
    u8TotalBufNum = (uint8)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pEgressCfg[u8FifoIdx].EthCtrlConfigEgressFifoBufTotal);
#if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
    u16BufLength = (uint16)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pEgressCfg[u8FifoIdx].EthCtrlConfigEgressFifoBufLenByte);
#endif
    /* Assemble frame header */
    /* Compute address of the buffer. */
    /* @violates @ref Eth_Fec_c_REF_15 */
    u32BufAddr = Eth_Fec_ComputeTxBufAddr(u8CtrlIdx, u8FifoIdx, u8BufIdx);
    /* Copy destination MAC address - use a temporary variable to access 
       a given destination address because the pDest pointer is only of 8bit 
       type therefore the data may not have 16-bit alignment. The 16-bit 
       alignment of the buffer data is ensured by the buffer alignment 
       restrictions */
    u32ManipulationVar = ((uint32)pDest[0U] << 8U) | (uint32)pDest[1U];
    Eth_Fec_Write16TxBufMem(u32BufAddr, 0U, (uint16) u32ManipulationVar); /* Put first 2 bytes */
    u32ManipulationVar = ((uint32)pDest[2U] << 8U) | (uint32)pDest[3U];
    Eth_Fec_Write16TxBufMem(u32BufAddr, 2U, (uint16) u32ManipulationVar); /* Put second 2 bytes */
    u32ManipulationVar = ((uint32)pDest[4U] << 8U) | (uint32)pDest[5U];
    Eth_Fec_Write16TxBufMem(u32BufAddr, 4U, (uint16)u32ManipulationVar); /* Put third 2 bytes */
    
#if STD_ON == ETH_BRIDGE_SUPPORT
    if (NULL_PTR == pSource)
    {
        /* Read source MAC address from registers and put it to header */
        /* Read first 4 bytes */
        /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /** @violates @ref Eth_Fec_c_REF_5 */
        /** @violates @ref Eth_Fec_c_REF_6 */
        u32ManipulationVar = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PALR_ADDR16);
        Eth_Fec_Write16TxBufMem(u32BufAddr, 8U, (uint16)(u32ManipulationVar & 0xFFFFU)); /* Put second 2 bytes */
        u32ManipulationVar = u32ManipulationVar >> 16U; /* Put bits to right position */
        Eth_Fec_Write16TxBufMem(u32BufAddr, 6U, (uint16)(u32ManipulationVar & 0xFFFFU)); /* Prepend first 2 bytes */
        /* Read last 2 bytes */
        /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /** @violates @ref Eth_Fec_c_REF_5 */
        /** @violates @ref Eth_Fec_c_REF_6 */
        u32ManipulationVar = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PAUR_ADDR16);
        u32ManipulationVar = u32ManipulationVar >> 16U; /* Put bits to right position */
        Eth_Fec_Write16TxBufMem(u32BufAddr, 10U, (uint16)(u32ManipulationVar & 0xFFFFU)); /* Append third 2 bytes */  
    }
    else
    {
        u32ManipulationVar = ((uint32)pSource[4U] << 8U) | (uint32)pSource[5U];
        Eth_Fec_Write16TxBufMem(u32BufAddr, 10U, (uint16) u32ManipulationVar); /* Put first 2 bytes */
        u32ManipulationVar = ((uint32)pSource[2U] << 8U) | (uint32)pSource[3U];
        Eth_Fec_Write16TxBufMem(u32BufAddr, 8U, (uint16) u32ManipulationVar); /* Put second 2 bytes */
        u32ManipulationVar = ((uint32)pSource[0U] << 8U) | (uint32)pSource[1U];
        Eth_Fec_Write16TxBufMem(u32BufAddr, 6U, (uint16)u32ManipulationVar); /* Put third 2 bytes */
    }
#else
    /* Read source MAC address from registers and put it to header */
    /* Read first 4 bytes */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */
    u32ManipulationVar = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PALR_ADDR16);
    Eth_Fec_Write16TxBufMem(u32BufAddr, 8U, (uint16)(u32ManipulationVar & 0xFFFFU)); /* Put second 2 bytes */
    u32ManipulationVar = u32ManipulationVar >> 16U; /* Put bits to right position */
    Eth_Fec_Write16TxBufMem(u32BufAddr, 6U, (uint16)(u32ManipulationVar & 0xFFFFU)); /* Prepend first 2 bytes */
    /* Read last 2 bytes */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */
    u32ManipulationVar = Eth_Fec_Htons(REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PAUR_ADDR16));
    Eth_Fec_Write16TxBufMem(u32BufAddr, 10U, (uint16)(u32ManipulationVar & 0xFFFFU)); /* Append third 2 bytes */  
#endif
    /* Type field should be placed into the type/length header field
       Transmitted length is set up by the buffer length when type 
       field has value grater than 1499
    */
    /* Append the type field */
    Eth_Fec_Write16TxBufMem(u32BufAddr, 12U, (uint16)u16Type);

    /* Note: The link flags are set later below */
    Eth_au8TxBdOfBuf[u8CtrlIdx][u8FifoIdx][u8BufIdx] = Eth_u8ActiveTxBD[u8CtrlIdx][u8FifoIdx];
    /* Write frame/buffer status bits */
    if ((boolean)TRUE == bConfirm)
    {   /* TxConfirmation is requested, also set TxConfirmation bit */
        Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8BufIdx] = (uint8)(FEC_TXB_LOCK_U8 | FEC_TXB_FIRST_U8 | FEC_TXB_LINK_U8 | FEC_TXB_CONF_U8);
        /* Update number of pending confirmations */
        /* Enter critical section for RMW access */
        SchM_Enter_Eth_ETH_EXCLUSIVE_AREA_00();
        Eth_u8LockedTxBufCount[u8CtrlIdx][u8FifoIdx]++;
        /* Exit Exclusive area */
        SchM_Exit_Eth_ETH_EXCLUSIVE_AREA_00();
    }
    else
    {
        Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8BufIdx] = (uint8)(FEC_TXB_LOCK_U8 | FEC_TXB_FIRST_U8 | FEC_TXB_LINK_U8);
    }
    
    /* Now write the buffer descriptor */
    /* Write pointer */
    Eth_Fec_WriteTxBDBufPtr(u32BDAddr, Eth_u8ActiveTxBD[u8CtrlIdx][u8FifoIdx], u32BufAddr);
    /* Write status bits and frame length. Note that FEC_TXBD_R_U32 bit must be written
       last. It will be written last, together with other bits and length.
       14 bytes of ethernet header is added to the length.  */
    u32ManipulationVar = FEC_TXBD_LENGTH_U32 & ((uint32)u16Length + 14U);
    /* Set: FEC_TXBD_R_U32: buffer is ready for transmission
            FEC_TXBD_TO1_U32: buffers are linked to this BD
            FEC_TXBD_L_U32: This BD is last in frame
            FEC_TXBD_TC_U32: Compute and append CRC to frame */
    u32ManipulationVar |= FEC_TXBD_R_U32 | FEC_TXBD_TO1_U32 | FEC_TXBD_L_U32 | FEC_TXBD_TC_U32;
    if ( Eth_u8ActiveTxBD[u8CtrlIdx][u8FifoIdx] == (u8TotalBufNum - 1U) )
    {   /* It is the last BD in ring, it must have wrap bit set */
        u32ManipulationVar |= FEC_TXBD_W_U32;
    }
    /* Write the assembled value to BD to allow the frame transmission */
    Eth_Fec_WriteTxBDBits(u32BDAddr, Eth_u8ActiveTxBD[u8CtrlIdx][u8FifoIdx], u32ManipulationVar);
    /* This BD is not active any more, increment to next (consider wrap) */
    Eth_u8ActiveTxBD[u8CtrlIdx][u8FifoIdx]++;
    if ( Eth_u8ActiveTxBD[u8CtrlIdx][u8FifoIdx] >= u8TotalBufNum )
    {
        Eth_u8ActiveTxBD[u8CtrlIdx][u8FifoIdx] = 0U;
    }
#if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    /* @violates @ref Eth_Fec_c_REF_14 */
    /* @violates @ref Eth_Fec_c_REF_9 */
    *pDataPtr = (void *)((uint32)12U + Eth_Fec_u32TxBufStartAddr[u8CtrlIdx][u8FifoIdx] + ((uint32)u16BufLength * (uint32)u8BufIdx));
    /* @violates @ref Eth_Fec_c_REF_9 */
    *pLengthPtr = u16Length;
    /* @violates @ref Eth_Fec_c_REF_9 */
    (void)EthSwt_EthTxProcessFrame (u8CtrlIdx, u8BufIdx, pDataPtr, pLengthPtr);
#endif
    /* Write the TDAR register to notify the controller about a new buffer,
       written value is ignored, the write access is what matters. */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_TDAR_ADDR16, FEC_TDAR_X_DES_ACTIVE_U32); 
}                                    



/*============================================================================*/
/**
* @brief         Resets the Ethernet controller
* @param[in]     u8CtrlIdx Index of controller which will be reset
* @details       Function masks all interrupts, issues a controller reset, 
*                waits for a while to allow controller finish its 
*                initialization. It clears all interrupt flags at the end.
* @implements    Eth_Fec_ResetController_Activity
*/

FUNC(void, ETH_CODE) Eth_Fec_ResetController(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(volatile uint8, AUTOMATIC) u8WaitCtr; /* Waiting loop counter */

    /* Disable all interrupts before the masks are cleared to 
       avoid spurious interrupt generation */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIMR_ADDR16, 0U);
    /* Issue a reset */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_ECR_ADDR16, FEC_ECR_RESET_U32);
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
    /* Clear multicast pool buffer */
    Eth_Fec_McastPoolClean(u8CtrlIdx);
    /* Clear MulticastPool flags */
    Eth_Fec_bMcastPoolOvf[u8CtrlIdx] = (boolean)FALSE;
    Eth_Fec_bMcastFullOpen[u8CtrlIdx] = (boolean)FALSE;
#endif /* ETH_UPDATE_PHYS_ADDR_FILTER */
    /* Wait until reset is finished - approximately 8 bus cycles */
    for (u8WaitCtr = 0U; u8WaitCtr <= ETH_RESET_WAIT_LOOP_COUNT; u8WaitCtr++)
    {
        ; /* This loop is intentionally empty. It  provides only necessary
             delay needed for controller internal re-initialization. */
    }  
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
    Eth_Fec_McastGAClean(u8CtrlIdx);
#endif /* ETH_UPDATE_PHYS_ADDR_FILTER */
    /* Clear all interrupt flags - all interrupts are masked, 
       no spurious interrupt can occur */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIR_ADDR16, FEC_EIR_ALL_W1C); 
}

/*============================================================================*/
/**
* @brief         Checks the access to the controller
* @details       Function is intended to be used only after the Ethernet
*                controller reset. It checks the reset value of one register
*                and checks whether it agrees with the datasheet value.
*                Controller is claimed as accessible if the value agrees.
* @param[in]     u8CtrlIdx Index of controller which will be checked the access
* @return        Controller accessibility
* @retval        TRUE Controller is accessible, value in register agrees.
* @retval        FALSE Controller access failed, different value read.
*/

FUNC(boolean, ETH_CODE) Eth_Fec_CheckAccessToCtrl(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(boolean, AUTOMATIC) bControllerAvailable; /* Used to hold return value*/
    
    /* Check if the RCR register contains the reset value */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */
    if (FEC_RCR_INIT_VAL_U32 == REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_RCR_ADDR16))
    {
        /* Yes, it contains  right number, controller is probably available */
        bControllerAvailable = ((boolean)TRUE);
    }
    else
    {
        /* No, the value is wrong, controller is definitely not available. */
        bControllerAvailable = ((boolean)FALSE);
    }
    return bControllerAvailable;
}

/*============================================================================*/
/**
* @brief         Configures the controller
* @details       Function
*                -# enables/disables Received frame interrupts
*                -# enables/disables Transmitted frame interrupts
*                -# clears MAC addresses hash tables
*                -# configures the controller MAC address
*                -# configures the MII
*                -# configures RCR and TCR registers
*                -# configures the maximal received frame length
* @param[in]     u8CtrlIdx Index of controller which will be configured
* @note          The controller is ready for use after the function finishes
*                however the buffers configuration must be still done.
*/
FUNC(void, ETH_CODE) Eth_Fec_ConfigureCtrl(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(uint32, AUTOMATIC) u32RegisterValue; /* Used to assemble register 
              value before writing to register or to read the register value */ 
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
    VAR(uint8, AUTOMATIC) u8CtrlLoop;
    VAR(uint8, AUTOMATIC) u8Count;
    VAR(uint16, AUTOMATIC) u16McastItemLoop;
#endif
    VAR(uint8, AUTOMATIC) u8Idx = 0U;   /*index of queue*/
    /* Initialize interrupts */
    u32RegisterValue = 0U; /* All interrupts are disabled */
     /* Check whether the TX interrupt is enabled for this controller 
        and multiple configuration */
    if (((boolean)TRUE) == ETH_CFG_ENABLERXINTERRUPT(u8CtrlIdx))
    {
         u32RegisterValue = u32RegisterValue | FEC_EIMR_RXF_U32; /* Enable RX irq */       
    }
    /* Check whether the RX interrupt is enabled for this controller
       and multiple configuration */
    if (((boolean)TRUE) == ETH_CFG_ENABLETXINTERRUPT(u8CtrlIdx))
    {
        u32RegisterValue = u32RegisterValue | FEC_EIMR_TXF_U32; /* Enable TX irq */
    }
    /* Write the assembled value */ 
   /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIMR_ADDR16, u32RegisterValue);
    /* Configure MAC address(es) */
    u32RegisterValue = 0U;
    /* Configure Multicast hash table - no multicast received */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GAUR_ADDR16, u32RegisterValue);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GALR_ADDR16, u32RegisterValue);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_IAUR_ADDR16, u32RegisterValue);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_IALR_ADDR16, u32RegisterValue);
    /* Configure device MAC address */
    u32RegisterValue = ETH_CFG_MACADDRESSLOW(u8CtrlIdx);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PALR_ADDR16, u32RegisterValue);
    u32RegisterValue = ETH_CFG_MACADDRESSHIGH(u8CtrlIdx);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PAUR_ADDR16, u32RegisterValue);
    /* Configure MII management data clock speed */
    u32RegisterValue = ETH_CFG_MSCR(u8CtrlIdx);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_MSCR_ADDR16, u32RegisterValue);    
    /* The rest of MII configuration is in RCR register */    
    /* Configure Rx */
    u32RegisterValue = ETH_CFG_RCR(u8CtrlIdx);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_RCR_ADDR16, u32RegisterValue);    
    /* Configure the Rx buffers length */ 
    u32RegisterValue = (uint32)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8Idx].EthCtrlConfigIngressFifoBufLenByte);
    if (u32RegisterValue < 2032U)
    {
        /*Because this register has 4 bit which couldn't write*/
        u32RegisterValue = (uint32)(u32RegisterValue + (uint32)16U) & FEC_EMRBR_R_BUF_SIZE_U32; /*Clear other bits */
    }
    else
    {
        u32RegisterValue = (uint32)2047U & FEC_EMRBR_R_BUF_SIZE_U32;
    }
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EMRBR_ADDR16, u32RegisterValue); 
    /* Configure Tx */
    u32RegisterValue = ETH_CFG_TCR(u8CtrlIdx);
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_TCR_ADDR16, u32RegisterValue);
    /****************************************************************/
    /* Write also registers initialized by hardware - avoid mismatch 
       between documentation and hardware implementation */ 
    /* Write TFWR with value 3 (FIFO watermark = 192 bytes) to minimize
       chance of FIFO underflow */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_TFWR_ADDR16, 3U);
    /* Write FRSR with value 0x0000_0500 to set both FIFOs to 256 bytes -
    FIFOs occupy memory space from BASE + 0x400 to BASE + 0x600 */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_FRSR_ADDR16, 0x00000500U);
    /* Write the OPD register with pause duration of 15 slot times
    (1 slot time = 512 bit times  = approx 49us for 10BASE )*/    
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_OPD_ADDR16, (0x00010000U|15U));
    Eth_Fec_ConfigureRxBuffers(u8CtrlIdx);
    Eth_Fec_ConfigureTxBuffers(u8CtrlIdx);
    Eth_Fec_ClearMIBCounters(u8CtrlIdx);
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
    /* Initialize for variable */
    for (u8CtrlLoop = 0U; u8CtrlLoop < (uint8)ETH_MAXCTRLS_SUPPORTED; u8CtrlLoop++)
    {
        for (u16McastItemLoop = 0U; u16McastItemLoop < (uint16)ETH_MULTICAST_POOL_SIZE; u16McastItemLoop++)
        {
            Eth_Fec_rMulticastPool[u8CtrlLoop][u16McastItemLoop].bActive=(VAR(boolean, AUTOMATIC))FALSE;
            for (u8Count=0U; u8Count<6U; u8Count++)
            {
                Eth_Fec_rMulticastPool[u8CtrlLoop][u16McastItemLoop].au8PhysAddr[u8Count]=0U;
            }
        }
    }
#endif
}

/*============================================================================*/
/**
* @brief         Starts the controller
* @param[in]     u8CtrlIdx Index of controller which will be enabled
* @details       Function enables the controller after that it activates receive
*                and transmit buffer descriptors rings.
*/

FUNC(void, ETH_CODE) Eth_Fec_EnableController(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(uint8, AUTOMATIC) u8FifoIdx = 0U; /*Only support a queue*/
    /* Init the active Rx buffer descriptor pointer -
       the BDs are reset during controller reset or disablement */
    Eth_u8ActiveRxBuf[u8CtrlIdx][u8FifoIdx] = 0U;
    Eth_u8ActiveTxBD[u8CtrlIdx][u8FifoIdx] = 0U;
    Eth_u8LockedTxBufCount[u8CtrlIdx][u8FifoIdx] = 0U;
    /* Enable the controller - needs to be done at first */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */     
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_ECR_ADDR16, FEC_ECR_ETHER_EN_U32);
    /* Tell the controller to check Rx buffer descriptors */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */     
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_RDAR_ADDR16, FEC_RDAR_R_DES_ACTIVE_U32); 
    /* Tell the controller to check Tx buffer descriptors  */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_TDAR_ADDR16, FEC_TDAR_X_DES_ACTIVE_U32); 
}
/*============================================================================*/
/**
* @brief         Immediately stops the controller
* @details       Function clears the ECR[ETHER_EN] bit which causes
*                - receiver to stop
*                - transmitter to append bad CRC and stop, descriptor of
*                  this frame is no updated
*                - DMA, FIFO control and buffer descriptors reset
* @param[in]     u8CtrlIdx Index of controller which will be disabled
* @par
*                Actions needed to recover:
*                - set ECR[ETHER_EN] (reenable the controller)
*                - write RDAR, TDAR (tell that some buffers are prepared)
*/
FUNC(void, ETH_CODE) Eth_Fec_DisableController(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    /* Clear the ECR[ETHER_EN] bit */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */   
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_ECR_ADDR16, 0U); 
    /* Clear all buffers */
    Eth_Fec_ConfigureTxBuffers(u8CtrlIdx);
    Eth_Fec_ConfigureRxBuffers(u8CtrlIdx);
}


/*============================================================================*/
/**
* @brief         Check whether the controller is running
* @details       Function checks the ECR[ETHER_EN] bit to determine whether
*                the controller has been stopped or whether it is running.
* @param[in]     u8CtrlIdx Index of controller which will be checked active status
* @return        The current controller mode.
* @retval        ETH_MODE_ACTIVE The controller is running.
* @retval        ETH_MODE_DOWN The controller is stopped.
*/

FUNC(Eth_ModeType, ETH_CODE) Eth_Fec_CheckCtrlIsActive(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(Eth_ModeType, AUTOMATIC) eReturnValue; /* Return value holder */
    VAR(uint32, AUTOMATIC) u32RegisterValue; /* Used to access register */

    /* Find whether the module is on by reading ECR[ETHER_EN]*/
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5  */
    /** @violates @ref Eth_Fec_c_REF_6 */  
    u32RegisterValue = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_ECR_ADDR16);
    if (FEC_ECR_ETHER_EN_U32 == (u32RegisterValue & FEC_ECR_ETHER_EN_U32))
    {    /* Module is on */
         eReturnValue = ETH_MODE_ACTIVE;
    }
    else
    {    /* Module is off */
         eReturnValue = ETH_MODE_DOWN;
    }
    return eReturnValue;
}


/*============================================================================*/
/**
* @brief         Clears the RXF (received frame) flag
* @param[in]     u8CtrlIdx Index of controller in which RxIRQ flag will be cleared
*/

FUNC(void, ETH_CODE) Eth_Fec_ClearRxIrqFlag(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(uint8, AUTOMATIC) u8FifoIdx)
{
    (void)u8FifoIdx;
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */    
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIR_ADDR16, FEC_EIR_RXF_W1C);
}

/*============================================================================*/
/**
* @brief         Clears the TXF (transmitted frame) flag
*/
FUNC(void, ETH_CODE) Eth_Fec_ClearTxIrqFlag(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(uint8, AUTOMATIC) u8FifoIdx)
{
    (void)u8FifoIdx;
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */   
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIR_ADDR16, FEC_EIR_TXF_W1C);
}

/*============================================================================*/
/**
* @brief         Checks whether the TXF flag is set
* @details       This function can be used to check whether the frame 
*                transmitted interrupt flag is set.
* @param[in]     u8CtrlIdx Index of controller in which TxIRQ flag will be checked
* @retval        TRUE if the TXF flag is set
* @retval        FALSE if the TXF flag is cleared
*/
FUNC(boolean, ETH_CODE) Eth_Fec_IsTxIrqFlagSet(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(uint8, AUTOMATIC) u8FifoIdx)
{
    VAR(uint32, AUTOMATIC) u32RegisterValue; /* Used to read register value */
    VAR(boolean, AUTOMATIC) bReturnValue; /* Stores the result */
    
    (void)u8FifoIdx;
    /* Test point for Fault Injection Test, for other, this line will be skipped. */
    MCAL_FAULT_INJECTION_POINT(ETH_FIP_1_ISTXIRQFLAGSET_RET);
    /* Read the register */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */    
    u32RegisterValue = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIR_ADDR16);
    /* Check whether the bit is set */
    if (FEC_EIR_TXF_U32 == (u32RegisterValue & FEC_EIR_TXF_U32))
    {
        bReturnValue = (boolean)TRUE;
    }
    else
    {
        bReturnValue = (boolean)FALSE;
    }
    
    return bReturnValue;
    
}
/*============================================================================*/
/**
* @brief         Checks whether the RXF flag is set
* @details       This function can be used to check whether the frame received
*                interrupt flag is set.
* @param[in]     u8CtrlIdx Index of controller in which RxIRQ flag will be checked
* @retval        TRUE if the RXF flag is set
* @retval        FALSE if the RXF flag is cleared
*/
FUNC(boolean, ETH_CODE) Eth_Fec_IsRxIrqFlagSet(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(uint8, AUTOMATIC) u8FifoIdx)
{
    VAR(uint32, AUTOMATIC) u32RegisterValue; /* Used to read register value */
    VAR(boolean, AUTOMATIC) bReturnValue; /* Stores the result */
    
    (void)u8FifoIdx;
    /* Test point for Fault Injection Test, for other, this line will be skipped. */
    MCAL_FAULT_INJECTION_POINT(ETH_FIP_2_ISRXIRQFLAGSET_RET);
    /* Read the register */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */   
    u32RegisterValue = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIR_ADDR16);
    /* Check whether the bit is set */
    if (FEC_EIR_RXF_U32 == (u32RegisterValue & FEC_EIR_RXF_U32))
    {
        bReturnValue = (boolean)TRUE;
    }
    else
    {
        bReturnValue = (boolean)FALSE;
    }
    
    return bReturnValue;
}
/*============================================================================*/
/**
* @brief         Checks whether the transmit interrupt is enabled.
@param[in]       u8CtrlIdx Index of controller in which TxIRQ mask will be checked
* @retval        TRUE the interrupt is enabled
* @retval        FALSE the interrupt is disabled
*/
FUNC(boolean, ETH_CODE) Eth_Fec_IsTxIrqEnabled(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(uint8, AUTOMATIC) u8FifoIdx)
{
    VAR(uint32, AUTOMATIC) u32RegisterValue; /* Used to read register value */
    VAR(boolean, AUTOMATIC) bReturnValue; /* Stores the result */
    
    (void)u8FifoIdx;
    /* Read the register */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */
    u32RegisterValue = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIMR_ADDR16);
    /* Check whether the bit is set */
    if (FEC_EIMR_TXF_U32 == (u32RegisterValue & FEC_EIMR_TXF_U32))
    {
        bReturnValue = (boolean)TRUE;
    }
    else
    {
        bReturnValue = (boolean)FALSE;
    }

    return bReturnValue;
}
/*============================================================================*/
/**
* @brief         Checks whether the receive interrupt is enabled.
@param[in]       u8CtrlIdx Index of controller in which TxIRQ mask will be checked
* @retval        TRUE the interrupt is enabled
* @retval        FALSE the interrupt is disabled
*/
FUNC(boolean, ETH_CODE) Eth_Fec_IsRxIrqEnabled(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(uint8, AUTOMATIC) u8FifoIdx)
{
    VAR(uint32, AUTOMATIC) u32RegisterValue; /* Used to read register value */
    VAR(boolean, AUTOMATIC) bReturnValue; /* Stores the result */
    
    (void)u8FifoIdx;
    /* Read the register */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */
    u32RegisterValue = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIMR_ADDR16);
    /* Check whether the bit is set */
    if (FEC_EIMR_RXF_U32 == (u32RegisterValue & FEC_EIMR_RXF_U32))
    {
        bReturnValue = (boolean)TRUE;
    }
    else
    {
        bReturnValue = (boolean)FALSE;
    }
    return bReturnValue;
}

/*================================================================================================*/
/**
* @brief         Reports received frames to the upper layer
* @param[in]     u8CtrlIdx Index of the controller to report receptions
* @param[in]     bIrq Selects between the poll driven and interrupt driven
*                mode (algorithm). The value TRUE means interrupt driven mode.
* @details       Function examines type of receive buffers. It begins
*                from the empty buffer found by previous call or from the
*                first one if no call has been done since the controller has
*                been enabled or from the latest known full buffer containing
*                the single-buffer-error-free frame.
* @par
*                Each buffer is checked to be error-free, buffer type is
*                examined and the buffer is reported via the
*                EthIf_RxIndication function call if the buffer type
*                is RX_BUF_SINGLE. All buffers of multi-buffer frame are
*                discarded when such frame is detected i.e. buffer type is
*                RX_BUF_MULTI_FINISHED.
* @par
*                Search ends when empty buffer is found i.e. buffer type
*                is RX_BUF_MULTI_UNFINISHED or RX_BUF_EMPTY or in the poll
*                driven mode when a second single-buffer frame is found
*                (this frame is not reported to the EthIf_RxIndication).
*                Function silently discards all buffers when the receive
*                buffers ring overflow is detected i.e. RX_BUF_OVERFLOW value
*                of buffer type is found.
* @note          The function reports all found frames in the interrupt driven
*                mode. In the poll driven mode it reports only the first found
*                frame signals whether there is at least another frame to be
*                received (in the next call).
* @return        In the poll driven mode signalizes whether a frame has been
*                reported to the EthIf module and whether another frame is
*                available. It shall be ignored in the interrupt driven mode.
* @retval        ETH_RECEIVED Only one frame received
* @retval        ETH_NOT_RECEIVED No frame received
* @retval        ETH_RECEIVED_MORE_DATA_AVAILABLE More frames received
*                frame was discarded.
*/
FUNC(Eth_RxStatusType, ETH_CODE) Eth_Fec_ReportReception ( \
                                                CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                                                CONST(uint8, AUTOMATIC) u8FifoIdx, \
                                                CONST(boolean, AUTOMATIC) bIrq \
                                                         )
{
    VAR(uint8, AUTOMATIC) u8BufCtr; /* Buffer referencing variable */
    VAR(Eth_Fec_enRxBufferType, AUTOMATIC) eBufferType; /* Used to obtain
                                             buffer type from lower layers */
    VAR(uint8, AUTOMATIC) u8MultiEnd = 0U; /* Used to obtain number of last buffer in
                                                     the multi-buffer frame */
    VAR(uint8, AUTOMATIC) u8BufCtrMax; /* Variable used to hold the buffers
        number - this should be faster than reading the configuration */
    VAR(uint32, AUTOMATIC) u32ProtectionCounter = 0U; /* Protection counter */
    /* --- Frame information storage temporary variables --- */
    VAR(uint32, AUTOMATIC) u32FrameStatus;
    VAR(uint16, AUTOMATIC) u16Length;
    VAR(uint8, AUTOMATIC) u8BufNum;
    VAR(volatile uint32, AUTOMATIC) wait = 0U;
    P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA) pu8DataPtr = NULL_PTR;
    VAR(Eth_FrameType, AUTOMATIC) u16EtherType;
    VAR(boolean, AUTOMATIC) bBroadcast;
    VAR(uint32, AUTOMATIC) u32BdAddress;
    VAR(uint8, AUTOMATIC) u8EthIfCtrlIdx;  /* Controller which received it */
    /* --- Internal state machine state variables --- */
    VAR(boolean, AUTOMATIC) bFinishLoop; /* Decisions whether continue
                                              with buffer search stored here */
    VAR(boolean, AUTOMATIC) bFirstFrameFound; /* TRUE if some frame already
                                                found and reported to EthIf */
    VAR(Eth_RxStatusType, AUTOMATIC) eRetVal; /* Single return implementation
                                            needs to store the return value */
    /* The eRetVal could be used as a steering variable instead of the
       FirstFramFound but the readability would be decreased and the compiler
       will optimize it anyway */
#if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
    VAR(boolean, AUTOMATIC) bIsMgtmFrameOnly;
    P2VAR(Eth_DataType, AUTOMATIC, ETH_APPL_DATA) pu8DataPtrMn = NULL_PTR;
#endif
    u8BufCtr = Eth_u8ActiveRxBuf[u8CtrlIdx][u8FifoIdx];
    /** @violates @ref Eth_Fec_c_REF_5 */
    u8EthIfCtrlIdx = ETH_CFG_CTRLIDXINETHIF(u8CtrlIdx); /* Get the value */
    /* No valid frames have been found yet */
    bFirstFrameFound = (boolean)FALSE;
    eRetVal = ETH_NOT_RECEIVED;
    /* Initialize the loop-control variable */
    bFinishLoop = (boolean)FALSE;
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    u32BdAddress = ETH_CFG_RXBDSTARTADDRESS(u8CtrlIdx);
    u8BufNum = (uint8)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pIngressCfg[u8FifoIdx].EthCtrlConfigIngressFifoBufTotal);
    /* Get number of buffers */
    /** @violates @ref Eth_Fec_c_REF_5 */
    u8BufCtrMax = (uint8)(u8BufNum - 1U);
    do
    {
        /* @violates @ref Eth_Fec_c_REF_9 */
        eBufferType = Eth_Fec_GetRxBufferType(u8CtrlIdx, u8BufCtr, u8BufCtrMax, &u8MultiEnd);
        if ((RX_BUF_SINGLE == eBufferType) || (RX_BUF_MULTI_FINISHED == eBufferType))
        {   /* Single buffer frames are the only to be reported */
            /* Get the buffer length and pointer to it */
            /* @violates @ref Eth_Fec_c_REF_9 */
            Eth_Fec_GetRxBufferData(u8CtrlIdx, u8FifoIdx, u8BufCtr, u8MultiEnd, &u16Length, &pu8DataPtr, &u32FrameStatus);
            /* Check whether the frame has been received without any error
             * and if is multicast check if is in the multicast pool */
             /* Regular broadcast and unicast address which is not multicast */
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
            if ((0U == (u32FrameStatus & (ETH_FEC_RXF_ERRORS_MASK|ETH_FEC_RXF_MULTICAST))) \
               /* Frame received in promiscuous mode */
               || (ETH_FEC_RXF_PROMISCUOUS == (u32FrameStatus & (ETH_FEC_RXF_ERRORS_MASK | ETH_FEC_RXF_PROMISCUOUS))) \
               /* Multicast address contained in pool */
               || ((((uint32)0U == (u32FrameStatus & ETH_FEC_RXF_ERRORS_MASK))) && ((boolean)TRUE == Eth_Fec_IsPhysAddrAllowed(u8CtrlIdx, pu8DataPtr))) \
               )
#else
            if ((0U == (u32FrameStatus & (ETH_FEC_RXF_ERRORS_MASK))))
#endif /* STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER */
            {   /* No error, frame can be passed to upper layers */
                /* Check whether there is already a frame to pass */
                if ((boolean)FALSE == bFirstFrameFound)
                {   /* No, this is the first found received valid frame */
                    /* Pass the received frame to the upper layer */
                    /* Parse the u16EtherType from the frame header */
                    /** @violates @ref Eth_Fec_c_REF_5 */
                    /** @violates @ref Eth_Fec_c_REF_5 */
                    u16EtherType = ((uint16)pu8DataPtr[12U] << 8U);
                    /** @violates @ref Eth_Fec_c_REF_5 */
                    /** @violates @ref Eth_Fec_c_REF_5 */
                    u16EtherType |= (uint16)pu8DataPtr[13U];
                    /* Check whether the frame is sent to a broadcast
                       address */
                    if (ETH_FEC_RXF_BROADCAST == (u32FrameStatus & ETH_FEC_RXF_BROADCAST))
                    {   /* bBroadcast */
                        bBroadcast = (boolean)TRUE;
                    }
                    else
                    {   /* Unicast or multicast */
                        bBroadcast = (boolean)FALSE;
                    }
                #if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
                    pu8DataPtrMn = pu8DataPtr - 2U;
                    /* @violates @ref Eth_Fec_c_REF_9 */
                    (void)EthSwt_EthRxProcessFrame (u8CtrlIdx, u8BufCtr, &pu8DataPtrMn, &u16Length, &bIsMgtmFrameOnly);
                    if (((boolean)FALSE) == bIsMgtmFrameOnly)
                    {
                #endif
                        /* Notify the EthIf - pass the Ethernet controller index,
                        u16EtherType, broadcast indication, frame source address,
                        pointer to the payload and the payload length */
                        /* @violates @ref Eth_Fec_c_REF_11 */
                        EthIf_RxIndication(u8EthIfCtrlIdx, u16EtherType, bBroadcast, (pu8DataPtr + 6U), (pu8DataPtr + 14U), (u16Length - 14U));
                #if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
                    }
                    else
                    {
                        (void)EthSwt_EthRxFinishedIndication (u8CtrlIdx, u8BufCtr);
                    }
                #endif
                    /* Forget that the frame was found if the interrupt
                       mode is used so all frames will be reported. In the
                       poll driven mode on the other hand remember that the
                       first frame has been already reported so only one frame
                       will be reported. */
                    eRetVal = ETH_RECEIVED;
                    if ((boolean)FALSE == bIrq)
                    {   /* Poll driven mode - remember */
                        bFirstFrameFound = (boolean)TRUE;
                    }
                }
                else
                {   /* Another valid received frame has already been found */
                    /* Remember that there is another frame to be read and
                       stop the search */
                    eRetVal = ETH_RECEIVED_MORE_DATA_AVAILABLE;
                    bFinishLoop = ((boolean)TRUE);
                    /* The processing shall start with this buffer when the
                       function is called next time */
                    Eth_u8ActiveRxBuf[u8CtrlIdx][u8FifoIdx] = u8BufCtr;
                }
            }
            /* Clear the buffers */
            if ((boolean)FALSE == bFinishLoop)
            {
                /* Clear the interrupt flags */
                Eth_Fec_ClearRxIrqFlag(u8CtrlIdx, u8FifoIdx);
                /* Clear all the first buffer */
                Eth_Fec_ClearRxBuffer(u8CtrlIdx, u8BufCtr);
                /* Clear all others belong to frame */
                while (u8BufCtr != u8MultiEnd)
                {
                    u8BufCtr++;
                    if (u8BufCtr > u8BufCtrMax)
                    {
                        u8BufCtr = 0U;
                    }
                    Eth_Fec_ClearRxBuffer(u8CtrlIdx, u8BufCtr);
                }
                /* Continue with the next buffer */
                u8BufCtr++;
                if (u8BufCtr > u8BufCtrMax)
                {
                    u8BufCtr = 0U;
                }
                Eth_u8ActiveRxBuf[u8CtrlIdx][u8FifoIdx] = u8BufCtr;
            }
        }
        else /* RX_BUF_MULTI_UNFINISHED || RX_BUF_EMPTY || RX_BUF_OVERFLOW */
        {
            /* Other states mean that loop has to end */
            bFinishLoop = ((boolean)TRUE);
        }
        /* Protection against newerendless loop */
        u32ProtectionCounter++;
        if ((2U * (uint32)(u8BufCtrMax)) <= u32ProtectionCounter)
        { /* Buffer ring was processed twice in a loop without exit */
          /* Note that this condition is unreachable at normal HW conditions */
            /* Terminate the loop */
            bFinishLoop = ((boolean)TRUE);
        }
    }
    while (((boolean)FALSE) == bFinishLoop);
    /* Handler of buffers overflow - discard all buffers */
    if (RX_BUF_OVERFLOW == eBufferType)
    {
        #if STD_ON == DEBUG_VARIABLES /* Only if debug variables are used */
            /* Increment the debug variable */
            Eth_RxBuffersOverflow[u8CtrlIdx] = Eth_RxBuffersOverflow[u8CtrlIdx] + 1U;
        #endif
        /*In case, overlap memory*/
        u8BufCtr = Eth_u8ActiveRxBuf[u8CtrlIdx][u8FifoIdx];
        while (FEC_RXBD_E_U32 != (uint32)(Eth_Fec_ReadRxBDBits(u32BdAddress, u8BufCtr) & FEC_RXBD_E_U32))
        {
            Eth_Fec_ClearRxBuffer(u8CtrlIdx, u8BufCtr);
            u8BufCtr++;
            if (u8BufCtr > u8BufCtrMax)
            {
                u8BufCtr = 0U;
            }
        }
        Eth_u8ActiveRxBuf[u8CtrlIdx][u8FifoIdx] = u8BufCtr;
    }
    /* Return information about availability of more buffers */
    return eRetVal;
}
/*============================================================================*/
/**
* @brief         Confirms transmission of all transmitted buffers
* @param[in]     u8CtrlIdx Index of the controller to report transmissions
* @details       Function examines all transmit buffers whether some of them
*                have been already sent and whether they should be confirmed.
*                EthIf_TxConfirmation is called for each such buffer.
* @return        Error report
* @retval        TRUE No error has occurred.
* @retval        FALSE Some error has occurred.
* @implements    Eth_Fec_ReportTransmission_Activity
*/
FUNC(void, ETH_CODE) Eth_Fec_ReportTransmission(CONST(uint8, AUTOMATIC) u8CtrlIdx, CONST(uint8, AUTOMATIC) u8FifoIdx)
{
    VAR(uint8, AUTOMATIC) u8BufIdx; /* Counter used for buffer referencing */
    VAR(uint8, AUTOMATIC) u8TotalBufNum; /* Variable used to hold the buffs number
     - this should be faster than reading the configuration */
    VAR(uint32, AUTOMATIC) u32BDAddr; /* BD addr. used by lower driver layers
     - to avoid its re-initializations during function calls in the loop
       it is placed here. Reading value from (ROM) memory through pointer is
       slower than local variable access (register or stack). */
    VAR(uint8, AUTOMATIC) u8BDIdx; /* Index of linked BD */
    VAR(uint32, AUTOMATIC) u32BDStatus; /* Status bits of linked BD */
    VAR(uint8, AUTOMATIC) u8TxBufFlag; /* Temporary Tx buffer flag */
#if (STD_OFF == ETH_SWT_MANAGEMENT_SUPPORT_API)
    VAR(Std_ReturnType, AUTOMATIC) Result = (Std_ReturnType)E_NOT_OK;
    VAR(uint8, AUTOMATIC) u8EthIfCtrlIdx; /* Copy of the configured parameter
    EthCtrlIdxInEthIf  - this should improve execution time (multiple
    access to memory is slower than access to register) */
    /** @violates @ref Eth_Fec_c_REF_5 */
    u8EthIfCtrlIdx = ETH_CFG_CTRLIDXINETHIF(u8CtrlIdx); /* Get the value needed
                                  for EthIf_TxConfirmation callback call */
#endif                                
    /** @violates @ref Eth_Fec_c_REF_5 */
    u8TotalBufNum = (uint8)((*(Eth_InternalCfgPtr->pController[u8CtrlIdx])).pEgressCfg[u8FifoIdx].EthCtrlConfigEgressFifoBufTotal); /* Get number of buffers */
    /* Compiler_Warning: (diab) this should not be a warning because they are same type. 
    No potential problem here. */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    u32BDAddr = ETH_CFG_TXBDSTARTADDRESS(u8CtrlIdx); /* Get TXBDs base
                  memory address value to pass it to lower drivers layers*/
    
    /* Search through all buffers */
    for (u8BufIdx = 0U; (Eth_u8LockedTxBufCount[u8CtrlIdx][u8FifoIdx] > 0U) && (u8BufIdx < u8TotalBufNum); u8BufIdx++)
    {
        /* At first check status bits of buffer */
        u8TxBufFlag = Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8BufIdx];
        if ((FEC_TXB_LOCK_U8 | FEC_TXB_CONF_U8 | FEC_TXB_FIRST_U8) ==  \
        ((FEC_TXB_LOCK_U8 | FEC_TXB_CONF_U8 | FEC_TXB_FIRST_U8) & u8TxBufFlag) \
            )
        {   /* The frame is in LOCKEDAT or LOCKEDIT state */
            /* If there is link to BD, try to remove it */
            if ( FEC_TXB_LINK_U8 == (FEC_TXB_LINK_U8 & u8TxBufFlag))
            {   
               u8BDIdx = Eth_au8TxBdOfBuf[u8CtrlIdx][u8FifoIdx][u8BufIdx];
                /* There is link, may be removed only if FEC_TXBD_R_U32=0 and FEC_TXBD_TO1_U32=1
                  (if FEC_TXBD_TO1_U32 would be 0 it might be frame being turned into
                  LockedIT state with BD not written yet) */
                u32BDStatus = Eth_Fec_ReadTxBDBits(u32BDAddr,u8BDIdx);
                if( FEC_TXBD_TO1_U32 == ((FEC_TXBD_R_U32 | FEC_TXBD_TO1_U32) & u32BDStatus) )
                { 
                #if (STD_OFF == ETH_SWT_MANAGEMENT_SUPPORT_API)
                    Result = (Std_ReturnType)E_OK;
                #endif
                    /* Ready bit is zero -> frame was sent -> remove the link */
                    u8TxBufFlag &= (uint8)(~FEC_TXB_LINK_U8);
                    /*Enter exclusive area before update software flag to prevent interfere */
                    Eth_au8TxBufFlags[u8CtrlIdx][u8FifoIdx][u8BufIdx] = u8TxBufFlag;
                    /* Clear BufLinked flag */
                    u32BDStatus &= (uint32)(~FEC_TXBD_TO1_U32);
                    /* Write modified bits back */
                    Eth_Fec_WriteTxBDBits(u32BDAddr, u8BDIdx, u32BDStatus);
                }
            #if (STD_OFF == ETH_SWT_MANAGEMENT_SUPPORT_API)
                /* The link was removed -> LOCKEDAT state, call confirmation */
                EthIf_TxConfirmation(u8EthIfCtrlIdx, u8BufIdx, Result);
            #endif
            }
            /* Call TxConfirmation and free buffers only if the link is gone */
            if (0U == (FEC_TXB_LINK_U8 & u8TxBufFlag))
            {
            #if (STD_ON == ETH_SWT_MANAGEMENT_SUPPORT_API)
                (void)EthSwt_EthTxFinishedIndication (u8CtrlIdx, u8BufIdx);
            #endif
                Eth_Fec_GiveBackTxBuffer(u8CtrlIdx, u8FifoIdx, u8BufIdx); /* At last free the buffers */
                /* Update number of pending confirmations, need critical section because this is RMW access */
                SchM_Enter_Eth_ETH_EXCLUSIVE_AREA_01();
                Eth_u8LockedTxBufCount[u8CtrlIdx][u8FifoIdx]--;
                SchM_Exit_Eth_ETH_EXCLUSIVE_AREA_01();
            }
        }
    }
}

/*============================================================================*/
/**
* @brief         Returns lower four bytes of the controllers MAC address
* @details       Function reads MAC address from the register and returns it.
*                0xAABBCCDD is returned if the controller MAC address
*                is AA:BB:CC:DD:EE:FF
* @param[in]     u8CtrlIdx Index of controller to get 4 low bytes of PhysAddress
* @return        First four bytes of the MAC address.
*/

FUNC(uint32, ETH_CODE) Eth_Fec_GetPhysAddressLow(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    /* Return lower 32 bits of MAC address */
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */   
    return REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PALR_ADDR16);
}

/*============================================================================*/
/**
* @brief         Returns upper four bytes of the controllers MAC address
* @details       Function reads MAC address from the register and returns it.
*                0xEEFF is returned if the controller MAC address is
*                AA:BB:CC:DD:EE:FF.
* @param[in]     u8CtrlIdx Index of controller to get 2 high bytes of PhysAddress
* @return        Last two bytes of the MAC address.
*/

FUNC(uint16, ETH_CODE) Eth_Fec_GetPhysAddressHigh(CONST(uint8, AUTOMATIC) u8CtrlIdx)
{
    VAR(uint32, AUTOMATIC) u32RegisterValue;
    
    /* Get upper 16 bits of MAC address and move them to appropriate position*/
    /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /** @violates @ref Eth_Fec_c_REF_5 */
    /** @violates @ref Eth_Fec_c_REF_6 */   
    u32RegisterValue = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PAUR_ADDR16);
    u32RegisterValue = u32RegisterValue >> 16U;
    /* Return the obtained value */
    return (uint16)u32RegisterValue;
}

/*============================================================================*/
/**
* @brief         Update physical address of the controller.
* @param[in]     pPhysAddrPtr Pointer to MAC address which should set to
*                controller. The address in network byte order stored into 6
*                bytes of memory.
* @caution       This function may be called only when the controller is down.
*                Call of function Eth_ControllerInit change MAC address
*                to the default value!
* @implements    Eth_Fec_SetPhysAddr_Activity
*/

FUNC(boolean, ETH_CODE) Eth_Fec_SetPhysAddr(CONST(uint8, AUTOMATIC) u8CtrlIdx, P2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr)
{
    VAR(boolean, AUTOMATIC) bReturnStatus = (boolean)FALSE;
    VAR(uint32, AUTOMATIC) u32RegisterValue;

    /* Change mac address only when the conroller is down */
    if(ETH_MODE_DOWN == Eth_Fec_CheckCtrlIsActive(u8CtrlIdx))
    {
        /* Prepare lower bytes of MAC */
        /** @violates @ref Eth_Fec_c_REF_5 */
        u32RegisterValue = (uint32)pPhysAddrPtr[0U];
        /** @violates @ref Eth_Fec_c_REF_5 */
        u32RegisterValue = ((u32RegisterValue << 8U) | (uint32)pPhysAddrPtr[1U]);
        /** @violates @ref Eth_Fec_c_REF_5 */
        u32RegisterValue = ((u32RegisterValue << 8U) | (uint32)pPhysAddrPtr[2U]);
        /** @violates @ref Eth_Fec_c_REF_5 */
        u32RegisterValue = ((u32RegisterValue << 8U) | (uint32)pPhysAddrPtr[3U]);
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        /* @violates @ref Eth_Fec_c_REF_6 */     
        REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_PALR_ADDR16, u32RegisterValue);
        /* Prepare higher bytes of MAC */
        u32RegisterValue = 0U;
        /** @violates @ref Eth_Fec_c_REF_5 */
        u32RegisterValue = (uint32)pPhysAddrPtr[4U];
        /** @violates @ref Eth_Fec_c_REF_5 */
        /* @violates @ref Eth_Fec_c_REF_6 */ 
        u32RegisterValue = ((uint32)(u32RegisterValue << 8U) | (uint32)pPhysAddrPtr[5U]);
        u32RegisterValue = ((uint32)(u32RegisterValue << 16U) | (uint32)0x8808U);
        /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /* @violates @ref Eth_Fec_c_REF_5 */
        /* @violates @ref Eth_Fec_c_REF_6 */  
        REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_PAUR_ADDR16, u32RegisterValue);
        /* Set return status */
        bReturnStatus = (boolean)TRUE;
    }
    
    return bReturnStatus;
}
#if STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER
/*================================================================================================*/
/**
* @brief        Handle multicast addresses add or remove operations
* @details      This function handle add and remove operations with multicast
*               receive pool.
*               Handled pool of MAC address specifies the addresses which
*               will be pass to higher layers at frame reception.
* @param[in]    u8CtrlIdx Index of controller to be update the filter
* @param[in]    pPhysAddrPtr Pointer to the MAC address in network
*               byte order which will be added or removed to or from a pool.
* @param[in]    eAction This parameter defines the operation with a pool.
*               Value ETH_ADD_TO_FILTER behaves function to add new address into
*               a pool and ETH_REMOVE_FROM_FILTER means operation of removal
*               from the pool.
* @implements   Eth_Fec_UpdtePhysAddrFiltr_Activity
*/

FUNC(void, ETH_CODE) Eth_Fec_UpdtePhysAddrFiltr ( \
                        CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                        P2CONST(uint8, AUTOMATIC, ETH_APPL_CONST) pPhysAddrPtr, \
                        VAR(Eth_FilterActionType, AUTOMATIC) eAction \
                                                )
{
    /* Indicator of full open filter action */
    VAR(boolean, AUTOMATIC) bFullFilterOpenRequest;
    /* Indicator of full close filter action */
    VAR(boolean, AUTOMATIC) bFullFilterCloseRequest;
    /* Pattern for full open filter request */
    VAR(uint8, AUTOMATIC) au8FullFilterOpenPattern[] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
    /* Pattern for full close filter request */
    VAR(uint8, AUTOMATIC) au8FullFilterClosePattern[] = {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};

    /* Fill full open filter indicator */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_9 */ 
    bFullFilterOpenRequest = Eth_Fec_ComparePhysAddr(pPhysAddrPtr, au8FullFilterOpenPattern);
    /* Fill full close filter indicator */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_9 */ 
    bFullFilterCloseRequest = Eth_Fec_ComparePhysAddr(pPhysAddrPtr, au8FullFilterClosePattern);
    switch(eAction)
    {
        case ETH_ADD_TO_FILTER:
            if ((boolean)TRUE == bFullFilterOpenRequest)
            { /* Full open filter action (ETH_ADD_TO_FILTER) */
                /* Multicast filter will be bypassed at reception */
                Eth_Fec_bMcastFullOpen[u8CtrlIdx] = (VAR(boolean, AUTOMATIC))TRUE;
                /* Open all groups in GALR register */
                /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
                /* @violates @ref Eth_Fec_c_REF_5 */
                /* @violates @ref Eth_Fec_c_REF_6 */
                REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GALR_ADDR16, 0xffffffffU);
                /* Open all groups in GAUR register */
                /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
                /* @violates @ref Eth_Fec_c_REF_5 */
                /* @violates @ref Eth_Fec_c_REF_6 */
                REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_GAUR_ADDR16, 0xffffffffU);
            }
            /** @requirements   SWS_Eth_00147 */
            else if ((boolean)TRUE == bFullFilterCloseRequest)
            { /* Full close filter action (ETH_ADD_TO_FILTER) */
                /* Full close request excludes previous full open request */
                Eth_Fec_bMcastFullOpen[u8CtrlIdx] = (VAR(boolean, AUTOMATIC))FALSE;
                /* Clean overflow flag */
                Eth_Fec_bMcastPoolOvf[u8CtrlIdx] = (VAR(boolean, AUTOMATIC))FALSE;
                /* Clean the table */
                Eth_Fec_McastPoolClean(u8CtrlIdx);
                /* Reset the filter */
                Eth_Fec_McastGAClean(u8CtrlIdx);
            }
            else
            { /* Regular adding of PhysAddr into the pool (ETH_ADD_TO_FILTER) */
                if ((boolean)FALSE == Eth_Fec_McastPoolAddItem(u8CtrlIdx, pPhysAddrPtr))
                { /* Table is full */
                    /* Once table is full Overflow tag is set  */
                    Eth_Fec_bMcastPoolOvf[u8CtrlIdx] = (boolean)TRUE;
                }
                /* Open Group Address for requested Physical Address */
                Eth_Fec_McastGAAdd(u8CtrlIdx, pPhysAddrPtr);
            }
            break;
        case ETH_REMOVE_FROM_FILTER:
            if ((boolean)TRUE == bFullFilterOpenRequest)
            { /* Full open filter action (ETH_REMOVE_FROM_FILTER)  */
                Eth_Fec_bMcastFullOpen[u8CtrlIdx] = (VAR(boolean, AUTOMATIC))FALSE;
            }
            /** @requirements   SWS_Eth_00147 */
            else if ((boolean)TRUE == bFullFilterCloseRequest)
            { /* Full close filter action (ETH_REMOVE_FROM_FILTER) */
                /* Full close request excludes previous full open request */
                Eth_Fec_bMcastFullOpen[u8CtrlIdx] = (boolean)FALSE;
                /* Clean overflow flag */
                Eth_Fec_bMcastPoolOvf[u8CtrlIdx] = (boolean)FALSE;
                /* Clean the table */
                Eth_Fec_McastPoolClean(u8CtrlIdx);
                /* NOTE: Filter Reset is done at recalculation */
            }
            else
            { /* Regular removal of Physical Address from Pool */
                (void)Eth_Fec_McastPoolRmvItem(u8CtrlIdx, pPhysAddrPtr);
            }
            if (((boolean)FALSE == Eth_Fec_bMcastPoolOvf[u8CtrlIdx]) && ((boolean)FALSE == Eth_Fec_bMcastFullOpen[u8CtrlIdx]))
            { /* No Pool overflow or full open request */
                /* Recalculate the pool addresses */
                Eth_Fec_McastGARecalculate(u8CtrlIdx);
            }
            break;
        default:
            ; /* Required by MISRA but no action needed */
            break;
    }
}
#endif /* STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER */

#if STD_ON == ETH_CTRLENABLE_MII
/*============================================================================*/
/**
* @brief         Transfers management data over the MII
* @param[in]     u8CtrlIdx Index of controller to be transferred
* @param[in]     u8Trcv Transceiver to communicate with
* @param[in]     u8Reg Register which shall be accessed
* @param[in,out] pData Written/read data
* @param[in]     u32Operation Selection between write and read access
* @details       Function assembles the management frame and issues the bus
*                transaction, then it waits until the transaction finishes
*                and read data is returned in case of read access.
*                Waiting loop can be  broken if it reaches configured
*                number of iterations.
* @return        Failure status
* @retval        TRUE Success, no error has occurred.
* @retval        FALSE Failure, no response from the hardware within a timeout.
* @note          Function is present only if the macro ETH_CTRLENABLE_MII value
*                is equal to STD_ON.
*/
FUNC(boolean, ETH_CODE) Eth_Fec_DoMiiMMF    ( \
                        CONST(uint8, AUTOMATIC) u8CtrlIdx, \
                            CONST(uint8, AUTOMATIC) u8Trcv, \
                            CONST(uint8, AUTOMATIC) u8Reg, \
                            CONSTP2VAR(uint16, AUTOMATIC, ETH_APPL_DATA) pData, \
                            CONST(uint32, AUTOMATIC) u32Operation \
                                            )
{
    VAR(uint32, AUTOMATIC) u32RegisterValue; /* Used to assemble 
                register value before writing and for registers reads */
    VAR(uint32, AUTOMATIC) u32ManipulationVar; /* Used for bit manipulations */
    VAR(volatile uint32, AUTOMATIC) u32ProtectionCounter; /* The loop is
            claimed infinite when this counter reaches configured value */
    VAR(boolean, AUTOMATIC) bReturnStatus;
    
    /* Initialize the loop status variables - The loop works correctly */
    bReturnStatus = ((VAR(boolean, AUTOMATIC))TRUE);
    /* Write the initial value */
    u32ProtectionCounter = 0U; 
    /* Clear the EIR[MII] flag by writing 1 to it */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */ 
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIR_ADDR16, FEC_EIR_MII_W1C);   
    /* Start assembling the frame with ST, TA field and select operation */
    u32RegisterValue = (uint32) (FEC_MMFR_ST_VAL_U32|u32Operation|FEC_MMFR_TA_VAL_U32);
    /* Add the PHY address */
    /* Move it to the right position */
    u32ManipulationVar = (uint32)u8Trcv << 23U; 
    /* Clear any inappropriate bits */
    u32ManipulationVar = u32ManipulationVar & FEC_MMFR_PA_U32; 
    u32RegisterValue = u32RegisterValue | u32ManipulationVar; /* Apply it */
    /* Add the register address */
    /* Move it to the right position */
    u32ManipulationVar = (VAR(uint32, AUTOMATIC))u8Reg << 18U;
    /* Clear any inappropriate bits */
    u32ManipulationVar = u32ManipulationVar & FEC_MMFR_RA_U32; 
    u32RegisterValue = u32RegisterValue | u32ManipulationVar; /* Apply it */
    /* Add data - ignored by read operation */
    u32RegisterValue = u32RegisterValue | (* pData);
    /* Write assembled value to the register - it 
       triggers the MII MMF transaction */
    /* @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
    /* @violates @ref Eth_Fec_c_REF_5 */
    /* @violates @ref Eth_Fec_c_REF_6 */    
    REG_WRITE32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_MMFR_ADDR16, u32RegisterValue);
    /* Wait until transaction is finished */
    do
    {      
        /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /** @violates @ref Eth_Fec_c_REF_5 */
        /** @violates @ref Eth_Fec_c_REF_6 */
        u32RegisterValue = REG_READ32(Eth_u32BaseAddr[u8CtrlIdx] + FEC_EIR_ADDR16);
        /* Infinite loop protection */
        /* Check whether the loop is infinite */
        if (u32ProtectionCounter >= ETH_INFINITE_LOOP_PROTECTION)
        {   /* Yes */
            /* Loop is infinite and has to be broken*/
            bReturnStatus = ((boolean)FALSE); 
            #if STD_ON == DEBUG_VARIABLES
                Eth_MiiFailed[u8CtrlIdx] = Eth_MiiFailed[u8CtrlIdx] + 1U;
            #endif
            break;                /* Break the loop */
        }
        u32ProtectionCounter = u32ProtectionCounter + 1U; /* Increment counter */
        
    }
    while (FEC_EIR_MII_W1C != (u32RegisterValue & (uint32)FEC_EIR_MII_W1C));
    /* Check whether the previous code has been succesful */
    if (((boolean)TRUE) == bReturnStatus)
    {   /* Everything OK, continue */
        /* Read the data value from register - should 
           be ignored by write operation */
        /** @violates @ref Eth_Fec_c_REF_4 The cast is used to access memory mapped registers. */
        /** @violates @ref Eth_Fec_c_REF_5 */
        /** @violates @ref Eth_Fec_c_REF_6 */
        u32RegisterValue = REG_READ32((uint32)(Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_MMFR_ADDR16));
        * pData = (uint16)(u32RegisterValue & FEC_MMFR_DATA_U32);
    }
    return bReturnStatus; 
} 
#endif /* ETH_CTRLENABLE_MII */
/*================================================================================================*/
/**
* @brief        Get errors and lost frames.
* @details      The function checks for controller errors and lost frames.
*               Used for polling state changes. Calls EthIf_CtrlModeIndication when
*               the controller mode changed.
* @implements   Eth_Fec_MainFunction_Activity
*/
FUNC(void, ETH_CODE) Eth_Fec_MainFunction(VAR(void, AUTOMATIC))
{
    static VAR(Eth_ModeType, AUTOMATIC) eOldMode[ETH_MAXCTRLS_SUPPORTED]={ETH_MODE_DOWN};
    VAR(Eth_ModeType, AUTOMATIC) eCurrentMode;
    VAR(uint8, AUTOMATIC) u8EthIfCtrlIdx;      
    VAR(uint8, AUTOMATIC) u8CtrlIdx;

    for (u8CtrlIdx=0U; u8CtrlIdx<ETH_MAXCTRLS_SUPPORTED; u8CtrlIdx++)
    {
        u8EthIfCtrlIdx = ETH_CFG_CTRLIDXINETHIF( u8CtrlIdx);
        eCurrentMode = Eth_Fec_CheckCtrlIsActive(u8CtrlIdx);
        if (eOldMode[u8CtrlIdx]!=eCurrentMode)
        {
            eOldMode[u8CtrlIdx]=eCurrentMode;
            EthIf_CtrlModeIndication(u8EthIfCtrlIdx, eCurrentMode);
        }
#if (STD_ON == ETH_DEM_EVENT_DETECT)
        if ((boolean)FALSE == (boolean)Eth_Fec_CheckAccessToCtrl(u8CtrlIdx))
        {
            if ((uint32)STD_ON == (uint32)ETH_CFG_DEM_E_ACCESS_ENABLED( u8CtrlIdx))
            {
                (void)Dem_SetEventStatus((Dem_EventIdType)ETH_CFG_DEM_E_ACCESS( u8CtrlIdx), DEM_EVENT_STATUS_PREFAILED);
            }
        }
        else
        {   
            if((uint32)STD_ON == (uint32)ETH_CFG_DEM_E_ACCESS_ENABLED( u8CtrlIdx))
            {
                (void)Dem_SetEventStatus((Dem_EventIdType)ETH_CFG_DEM_E_ACCESS( u8CtrlIdx), DEM_EVENT_STATUS_PREPASSED);
                Eth_Fec_CheckDemStatus ( \
                    Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_DROP_ADDR16, \
                    
                    (uint32)ETH_CFG_DEM_E_FRAMELOST_ENABLED( u8CtrlIdx), \
                    
                    (Dem_EventIdType)ETH_CFG_DEM_E_FRAMELOST( u8CtrlIdx) \
                                    );
                Eth_Fec_CheckDemStatus ( \
                    Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_R_CRC_ADDR16, \
                    
                    (uint32)ETH_CFG_DEM_E_CRC_ENABLED( u8CtrlIdx), \
                    
                    (Dem_EventIdType)ETH_CFG_DEM_E_CRC( u8CtrlIdx) \
                                    );
                Eth_Fec_CheckDemStatus ( \
                    Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_UNDERSIZE_ADDR16, \
                    
                    (uint32)ETH_CFG_DEM_E_UNDERSIZE_ENABLED( u8CtrlIdx), \
                    
                    (Dem_EventIdType)ETH_CFG_DEM_E_UNDERSIZE( u8CtrlIdx) \
                                    );
                Eth_Fec_CheckDemStatus ( \
                    Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_RMON_R_OVERSIZE_ADDR16, \
                    
                    (uint32)ETH_CFG_DEM_E_OVERSIZE_ENABLED( u8CtrlIdx), \
                    
                    (Dem_EventIdType)ETH_CFG_DEM_E_OVERSIZE( u8CtrlIdx) \
                                    );
                Eth_Fec_CheckDemStatus ( \
                    Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_R_ALIGN_ADDR16, \
                    
                    (uint32)ETH_CFG_DEM_E_ALIGN_ENABLED( u8CtrlIdx), \
                    
                    (Dem_EventIdType)ETH_CFG_DEM_E_ALIGN( u8CtrlIdx) \
                                    );
                Eth_Fec_CheckDemStatus ( \
                    Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_1COL_ADDR16, \
                    
                    (uint32)ETH_CFG_DEM_E_1COL_ENABLED( u8CtrlIdx), \
                    
                    (Dem_EventIdType)ETH_CFG_DEM_E_1COL( u8CtrlIdx) \
                                    );
                Eth_Fec_CheckDemStatus ( \
                    Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_MCOL_ADDR16, \
                    
                    (uint32)ETH_CFG_DEM_E_MCOL_ENABLED( u8CtrlIdx), \
                    
                    (Dem_EventIdType)ETH_CFG_DEM_E_MCOL( u8CtrlIdx) \
                                    );
                Eth_Fec_CheckDemStatus ( \
                    Eth_u32BaseAddr[u8CtrlIdx] + (uint32)FEC_IEEE_T_LCOL_ADDR16, \
                    
                    (uint32)ETH_CFG_DEM_E_LCOL_ENABLED( u8CtrlIdx), \
                    
                    (Dem_EventIdType)ETH_CFG_DEM_E_LCOL( u8CtrlIdx) \
                                    );
            }
        }
#endif
    }
}


#define ETH_STOP_SEC_CODE
/* @violates @ref Eth_Fec_c_REF_1 This violation is not fixed since the inclusion of Eth_MemMap.h is as per AUTOSAR requirement*/
/* @violates @ref Eth_Fec_c_REF_2 Eth_MemMap.h is included after each section define in order to set the current memory section as defined by AUTOSAR */
#include "Eth_MemMap.h"

#ifdef __cplusplus
}
#endif
/** @} */

