/**
 * \file IfxEth.h
 * \brief ETH  basic functionality
 * \ingroup IfxLld_Eth
 *
 * \version iLLD_1_0_1_11_0
 * \copyright Copyright (c) 2019 Infineon Technologies AG. All rights reserved.
 *
 *
 *                                 IMPORTANT NOTICE
 *
 *
 * Use of this file is subject to the terms of use agreed between (i) you or 
 * the company in which ordinary course of business you are acting and (ii) 
 * Infineon Technologies AG or its licensees. If and as long as no such 
 * terms of use are agreed, use of this file is subject to following:


 * Boost Software License - Version 1.0 - August 17th, 2003

 * Permission is hereby granted, free of charge, to any person or 
 * organization obtaining a copy of the software and accompanying 
 * documentation covered by this license (the "Software") to use, reproduce,
 * display, distribute, execute, and transmit the Software, and to prepare
 * derivative works of the Software, and to permit third-parties to whom the 
 * Software is furnished to do so, all subject to the following:

 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer, must
 * be included in all copies of the Software, in whole or in part, and all
 * derivative works of the Software, unless such copies or derivative works are
 * solely in the form of machine-executable object code generated by a source
 * language processor.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.

 *
 * \defgroup IfxLld_Eth_Std_DataStructures Data Structures
 * \ingroup IfxLld_Eth_Std
 * \defgroup IfxLld_Eth_Std_Unions Unions
 * \ingroup IfxLld_Eth_Std
 * \defgroup IfxLld_Eth_Std_Configuration Configuration Functions
 * \ingroup IfxLld_Eth_Std
 * \defgroup IfxLld_Eth_Std_Utility Utility Functions
 * \ingroup IfxLld_Eth_Std
 * \defgroup IfxLld_Eth_Std_Initialisation Initialisation Functions
 * \ingroup IfxLld_Eth_Std
 * \defgroup IfxLld_Eth_Std_Enum Enumerations
 * \ingroup IfxLld_Eth_Std
 */

#ifndef IFXET_H
#define IFXET_H 1

/******************************************************************************/
/*----------------------------------Includes----------------------------------*/
/******************************************************************************/

#include "_Impl/IfxEth_cfg.h"
#include "Cpu/Std/Ifx_Types.h"
#include "IfxEth_reg.h"
#include "IfxEth_bf.h"
#include "_PinMap/IfxEth_PinMap.h"
#include "Src/Std/IfxSrc.h"
#include "Scu/Std/IfxScuWdt.h"
#include "_Utilities/Ifx_Assert.h"
#include "Cpu/Std/IfxCpu.h"

/******************************************************************************/
/*-----------------------------------Macros-----------------------------------*/
/******************************************************************************/

/** \brief Size of one ethernet frame buffer
 */
#ifndef IFXETH_RTX_BUFFER_SIZE
#define IFXETH_RTX_BUFFER_SIZE 1536
#endif

/** \brief Rx buffers (ring mode)
 */
#ifndef IFXETH_MAX_RX_BUFFERS
#define IFXETH_MAX_RX_BUFFERS  8
#endif

/** \brief Tx buffers (ring mode)
 */
#ifndef IFXETH_MAX_TX_BUFFERS
#define IFXETH_MAX_TX_BUFFERS  16
#endif

/** \brief 4 DWORDS (16 bytes)
 */
#define IFXETH_DESCR_SIZE      4

/******************************************************************************/
/*--------------------------------Enumerations--------------------------------*/
/******************************************************************************/

/** \addtogroup IfxLld_Eth_Std_Enum
 * \{ */
typedef enum
{
    IfxEth_ChecksumMode_bypass            = 0,
    IfxEth_ChecksumMode_ipv4              = 1,
    IfxEth_ChecksumMode_tcpUdpIcmpSegment = 2,
    IfxEth_ChecksumMode_tcpUdpIcmpFull    = 3
} IfxEth_ChecksumMode;

typedef enum
{
    IfxEth_DescriptorMode_chain,  /**< \brief chain mode descriptors */
    IfxEth_DescriptorMode_ring    /**< \brief ring mode descriptors */
} IfxEth_DescriptorMode;

/** \brief External Phy Interface RMII Mode
 */
typedef enum
{
    IfxEth_PhyInterfaceMode_mii,  /**< \brief MII mode */
    IfxEth_PhyInterfaceMode_rmii  /**< \brief RMII mode */
} IfxEth_PhyInterfaceMode;

/** \brief indicates the Receive DMA FSM state
 */
typedef enum
{
    IfxEth_ReceiveProcessState_reset,           /**< \brief Stopped: Reset or Stop Receive Command issued */
    IfxEth_ReceiveProcessState_fetching,        /**< \brief Running: Fetching Receive Transfer Descriptor */
    IfxEth_ReceiveProcessState_none,            /**< \brief Reserved for future use */
    IfxEth_ReceiveProcessState_waiting,         /**< \brief Running: Waiting for receive packet */
    IfxEth_ReceiveProcessState_suspended,       /**< \brief Suspended: Receive Descriptor Unavailable */
    IfxEth_ReceiveProcessState_closing,         /**< \brief Running: Closing Receive Descriptor */
    IfxEth_ReceiveProcessState_timestampWrite,  /**< \brief TIME_STAMP write state */
    IfxEth_ReceiveProcessState_transfering      /**< \brief Running: Transferring the receive packet data from receive buffer to host memory */
} IfxEth_ReceiveProcessState;

/** \brief Buffer(s) used in ring mode
 */
typedef enum
{
    IfxEth_RingModeBufferUsed_buffer1,     /**< \brief Buffer 1 used */
    IfxEth_RingModeBufferUsed_buffer2,     /**< \brief Buffer 2 used */
    IfxEth_RingModeBufferUsed_bothBuffers  /**< \brief BOth Buffers used */
} IfxEth_RingModeBufferUsed;

/** \brief indicates the Transmit DMA FSM state
 */
typedef enum
{
    IfxEth_TransmitProcessState_reset,           /**< \brief Stopped; Reset or Stop Transmit Command issued */
    IfxEth_TransmitProcessState_fetching,        /**< \brief Running; Fetching Transmit Transfer Descriptor */
    IfxEth_TransmitProcessState_waiting,         /**< \brief Running; Waiting for status */
    IfxEth_TransmitProcessState_reading,         /**< \brief Running; Reading Data from host memory buffer and queuing it to transmit buffer (Tx FIFO) */
    IfxEth_TransmitProcessState_timestampWrite,  /**< \brief TIME_STAMP write state */
    IfxEth_TransmitProcessState_none,            /**< \brief Reserved for future use */
    IfxEth_TransmitProcessState_suspended,       /**< \brief Suspended; Transmit Descriptor Unavailable or Transmit Buffer Underflow */
    IfxEth_TransmitProcessState_closing          /**< \brief Running; Closing Transmit Descriptor */
} IfxEth_TransmitProcessState;

/** \} */

/******************************************************************************/
/*-----------------------------Data Structures--------------------------------*/
/******************************************************************************/

/** \addtogroup IfxLld_Eth_Std_DataStructures
 * \{ */
/** \brief Structure for Alternate/Enhanced RX descriptor DWORD 0 Bit field access
 */
typedef struct
{
    uint32 ext : 1;      /**< \brief Extended Status Available/Rx MAC Address */
    uint32 CE : 1;       /**< \brief CRC Error */
    uint32 DBE : 1;      /**< \brief Dribble Bit Error */
    uint32 RE : 1;       /**< \brief Receive Error */
    uint32 RWT : 1;      /**< \brief Receive Watchdog Timeout */
    uint32 FT : 1;       /**< \brief Frame Type */
    uint32 LC : 1;       /**< \brief Late Collision */
    uint32 IPC : 1;      /**< \brief IPC Checksum Error/Giant Frame */
    uint32 LS : 1;       /**< \brief Last Descriptor */
    uint32 FS : 1;       /**< \brief First Descriptor */
    uint32 VLAN : 1;     /**< \brief VLAN Tag */
    uint32 OE : 1;       /**< \brief Overflow Error */
    uint32 LE : 1;       /**< \brief Length Error */
    uint32 SAF : 1;      /**< \brief Source Address Filter Fail */
    uint32 DE : 1;       /**< \brief Descriptor Error */
    uint32 ES : 1;       /**< \brief Error Summary, ES = PCE | CE | RE | RWT | LC | IPC | OE | DE */
    uint32 FL : 14;      /**< \brief Frame Length */
    uint32 AFM : 1;      /**< \brief Destination Address Filter Fail */
    uint32 OWN : 1;      /**< \brief Own Bit, 1 = own by DMA */
} IfxEth_AltRxDescr0_Bits;

/** \brief Structure for Alternate/Enhanced RX descriptor DWORD 1 Bit field access
 */
typedef struct
{
    uint32 RBS1 : 13;     /**< \brief Receive Buffer 1 Size */
    uint32 resv1 : 1;     /**< \brief reserved */
    uint32 RCH : 1;       /**< \brief Second Address Chained */
    uint32 RER : 1;       /**< \brief Receive End of Ring */
    uint32 RBS2 : 13;     /**< \brief Receive Buffer 2 Size */
    uint32 resv : 2;      /**< \brief reserved) */
    uint32 DIC : 1;       /**< \brief Disable Interrupt on Completion */
} IfxEth_AltRxDescr1_Bits;

/** \brief Structure for Alternate/Enhanced TX descriptor DWORD 0 Bit field access
 */
typedef struct
{
    uint32 DB : 1;        /**< \brief Deferred bit */
    uint32 UF : 1;        /**< \brief Underflow error */
    uint32 ED : 1;        /**< \brief Excessive deferral */
    uint32 CC : 4;        /**< \brief Collision count */
    uint32 VLAN : 1;      /**< \brief VLAN TAG */
    uint32 EC : 1;        /**< \brief Excessive Collision */
    uint32 LC : 1;        /**< \brief Late Collision */
    uint32 NC : 1;        /**< \brief No Carrier */
    uint32 LOC : 1;       /**< \brief Loss of Carrier */
    uint32 PCE : 1;       /**< \brief Payload Checksum Error */
    uint32 FF : 1;        /**< \brief Frame Flushed */
    uint32 JT : 1;        /**< \brief Jabber Timeout */
    uint32 ES : 1;        /**< \brief Error Summary, ES = JT | FF | LOC | NC | LC | EC | ED | UF */
    uint32 IHE : 1;       /**< \brief IP Header Error */
    uint32 TTSS : 1;      /**< \brief Transmit Time Stamp Status */
    uint32 resv : 2;      /**< \brief (reserved) */
    uint32 TCH : 1;       /**< \brief Second Address Chained */
    uint32 TER : 1;       /**< \brief Transmit End of Ring */
    uint32 CIC : 2;       /**< \brief Checksum Insertion Control */
    uint32 resv1 : 1;     /**< \brief (Reserved) */
    uint32 TTSE : 1;      /**< \brief Transmit Time Stamp Enable */
    uint32 DP : 1;        /**< \brief Disable Padding */
    uint32 DC : 1;        /**< \brief Disable CRC */
    uint32 FS : 1;        /**< \brief First Segment */
    uint32 LS : 1;        /**< \brief Last Segment */
    uint32 IC : 1;        /**< \brief Interrupt on Completion */
    uint32 OWN : 1;       /**< \brief Own Bit, 1 = own by DMA */
} IfxEth_AltTxDescr0_Bits;

/** \brief Structure for Alternate/Enhanced TX descriptor DWORD 1 Bit field access
 */
typedef struct
{
    uint32 TBS1 : 13;     /**< \brief Transmit Buffer 1 Size */
    uint32 resv1 : 3;     /**< \brief (reserved) */
    uint32 TBS2 : 13;     /**< \brief Transmit Buffer 2 Size */
    uint32 resv2 : 3;     /**< \brief (reserved) */
} IfxEth_AltTxDescr1_Bits;

/** \} */

/** \addtogroup IfxLld_Eth_Std_Unions
 * \{ */
/** \brief Union for RX descriptor DWORD 0
 */
typedef union
{
    IfxEth_AltRxDescr0_Bits A;       /**< \brief Structure for RX descriptor DWORD 0 Bit field access */
    uint32                  U;       /**< \brief Unsigned long access */
} IfxEth_RxDescr0;

/** \brief Union for RX descriptor DWORD 1
 */
typedef union
{
    IfxEth_AltRxDescr1_Bits A;       /**< \brief Structure for RX descriptor DWORD 1 Bit field access */
    uint32                  U;       /**< \brief unsigned long access */
} IfxEth_RxDescr1;

/** \brief Union for RX descriptor DWORD 2
 */
typedef union
{
    uint32 U;       /**< \brief unsigned long access */
} IfxEth_RxDescr2;

/** \brief Union for RX descriptor DWORD 3
 */
typedef union
{
    uint32 U;       /**< \brief unsigned long access */
} IfxEth_RxDescr3;

/** \brief Union for TX descriptor DWORD 0
 */
typedef union
{
    IfxEth_AltTxDescr0_Bits A;       /**< \brief Structure for TX descriptor DWORD 0 Bit field access */
    uint32                  U;       /**< \brief Unsigned long access */
} IfxEth_TxDescr0;

/** \brief Union for TX descriptor DWORD 1
 */
typedef union
{
    IfxEth_AltTxDescr1_Bits A;       /**< \brief Structure for RX descriptor DWORD 1 Bit field access */
    uint32                  U;       /**< \brief unsigned long access */
} IfxEth_TxDescr1;

/** \brief Union for TX descriptor DWORD 2
 */
typedef union
{
    uint32 U;       /**< \brief unsigned long access */
} IfxEth_TxDescr2;

/** \brief Union for TX descriptor DWORD 3
 */
typedef union
{
    uint32 U;       /**< \brief unsigned long access */
} IfxEth_TxDescr3;

/** \} */

/** \addtogroup IfxLld_Eth_Std_DataStructures
 * \{ */
/** \brief Configuration structure for Ring Mode Receive Buffers
 */
typedef struct
{
    IfxEth_RingModeBufferUsed rxBufferUsed;                /**< \brief Receive Buffer(s) used in ringmode */
    uint32                    rxBuffer1StartAddress;       /**< \brief Start address of Rx Buffer 1 */
    uint32                    rxBuffer2StartAddress;       /**< \brief Start address of Rx Buffer 2 */
    uint16                    rxBuffer1Size;               /**< \brief Size of Rx Buffer 1 */
    uint16                    rxBuffer2Size;               /**< \brief Size of Rx Buffer 2 */
} IfxEth_RingModeRxBuffersConfig;

/** \brief Configuration structure for Ring Mode Transmit buffers
 */
typedef struct
{
    IfxEth_RingModeBufferUsed txBufferUsed;                /**< \brief Transmit Buffer(s) used in ringmode */
    uint32                    txBuffer1StartAddress;       /**< \brief Start address of Tx Buffer 1 */
    uint32                    txBuffer2StartAddress;       /**< \brief Start address of Tx Buffer 2 */
    uint16                    txBuffer1Size;               /**< \brief Size of Tx Buffer 1 */
    uint16                    txBuffer2Size;               /**< \brief Size of Tx Buffer 2 */
} IfxEth_RingModeTxBuffersConfig;

/** \brief Normal RX descriptor
 */
typedef struct
{
    IfxEth_RxDescr0 RDES0;       /**< \brief RX descriptor DWORD 0 */
    IfxEth_RxDescr1 RDES1;       /**< \brief RX descriptor DWORD 1 */
    IfxEth_RxDescr2 RDES2;       /**< \brief RX descriptor DWORD 2 */
    IfxEth_RxDescr3 RDES3;       /**< \brief RX descriptor DWORD 3 */
} IfxEth_RxDescr;

/** \brief Normal TX descriptor
 */
typedef struct
{
    IfxEth_TxDescr0 TDES0;       /**< \brief TX descriptor DWORD 0 */
    IfxEth_TxDescr1 TDES1;       /**< \brief TX descriptor DWORD 1 */
    IfxEth_TxDescr2 TDES2;       /**< \brief TX descriptor DWORD 2 */
    IfxEth_TxDescr3 TDES3;       /**< \brief TX descriptor DWORD 3 */
} IfxEth_TxDescr;

/** \} */

/** \addtogroup IfxLld_Eth_Std_DataStructures
 * \{ */
/** \brief Port pins for MII mode configuration
 */
typedef struct
{
    IfxEth_Crs_In     *crs;         /**< \brief pointer to CRS input pin config */
    IfxEth_Col_In     *col;         /**< \brief pointer to COL input pin config */
    IfxEth_Txclk_In   *txClk;       /**< \brief Pointer to TXCLK input pin config */
    IfxEth_Rxclk_In   *rxClk;       /**< \brief Pointer to RXCLK input pin config */
    IfxEth_Rxdv_In    *rxDv;        /**< \brief Pointer to RXDV input pin config */
    IfxEth_Rxer_In    *rxEr;        /**< \brief Pointer to RXER input pin config */
    IfxEth_Rxd_In     *rxd0;        /**< \brief Pointer to RXD0 input pin config */
    IfxEth_Rxd_In     *rxd1;        /**< \brief Pointer to RXD1 input pin config */
    IfxEth_Rxd_In     *rxd2;        /**< \brief Pointer to RXD2 input pin config */
    IfxEth_Rxd_In     *rxd3;        /**< \brief Pointer to RXD3 input pin config */
    IfxEth_Txen_Out   *txEn;        /**< \brief Pointer to TXEN output pin config */
    IfxEth_Txer_Out   *txEr;        /**< \brief Pointer to TXER output pin config */
    IfxEth_Txd_Out    *txd0;        /**< \brief Pointer to TXD0 output pin config */
    IfxEth_Txd_Out    *txd1;        /**< \brief Pointer to TXD1 output pin config */
    IfxEth_Txd_Out    *txd2;        /**< \brief Pointer to TXD2 output pin config */
    IfxEth_Txd_Out    *txd3;        /**< \brief Pointer to TXD3 output pin config */
    IfxEth_Mdc_Out    *mdc;         /**< \brief Pointer to MDC pin config */
    IfxEth_Mdio_InOut *mdio;        /**< \brief Pointer to MDIO pin config */
} IfxEth_MiiPins;

/** \brief Configuration structure for Ring Mode descriptors
 */
typedef struct
{
    IfxEth_RingModeTxBuffersConfig txConfig;       /**< \brief Transmit buffers ring mode config */
    IfxEth_RingModeRxBuffersConfig rxConfig;       /**< \brief Receive buffers ring mode config */
} IfxEth_RingModeBuffersConfig;

/** \brief Port pins for RMII mode configuration
 */
typedef struct
{
    IfxEth_Crsdv_In   *crsDiv;       /**< \brief pointer to CRSDIV input pin config */
    IfxEth_Refclk_In  *refClk;       /**< \brief Pointer to REFCLK input pin config */
    IfxEth_Rxd_In     *rxd0;         /**< \brief Pointer to RXD0 input pin config */
    IfxEth_Rxd_In     *rxd1;         /**< \brief Pointer to RXD1 input pin config */
    IfxEth_Mdc_Out    *mdc;          /**< \brief Pointer to MDC output pin config */
    IfxEth_Mdio_InOut *mdio;         /**< \brief Pointer to MDIO pin config */
    IfxEth_Txd_Out    *txd0;         /**< \brief Pointer to TXD0 output pin config */
    IfxEth_Txd_Out    *txd1;         /**< \brief Pointer to TXD1 output pin config */
    IfxEth_Txen_Out   *txEn;         /**< \brief Pointer to TXEN output pin config */
} IfxEth_RmiiPins;

/** \} */

/** \addtogroup IfxLld_Eth_Std_Unions
 * \{ */
typedef union
{
    IfxEth_RxDescr items[IFXETH_MAX_RX_BUFFERS];
    uint32         U[IFXETH_MAX_RX_BUFFERS][IFXETH_DESCR_SIZE];
} IfxEth_RxDescrList;

typedef union
{
    IfxEth_TxDescr items[IFXETH_MAX_TX_BUFFERS];
    uint32         U[IFXETH_MAX_TX_BUFFERS][IFXETH_DESCR_SIZE];
} IfxEth_TxDescrList;

/** \} */

/** \addtogroup IfxLld_Eth_Std_DataStructures
 * \{ */
/** \brief ETH configuration structure
 */
typedef struct
{
    uint8 macAddress[6];                                      /**< \brief MAC address for the ethernet, should be unique in the network */
    uint32 (*phyInit)(void);                                  /**< \brief Pointer to the transceiver init function */
    boolean (*phyLink)(void);                                 /**< \brief Pointer to the transceiver link function */
    IfxEth_PhyInterfaceMode      phyInterfaceMode;            /**< \brief Phy Interface mode */
    IFX_CONST IfxEth_RmiiPins   *rmiiPins;                    /**< \brief Pointer to port pins configuration of RMII mode */
    IFX_CONST IfxEth_MiiPins    *miiPins;                     /**< \brief Pointer to port pins configuration of MII mode */
    Ifx_Priority                 isrPriority;                 /**< \brief Interrupt service priority */
    IfxSrc_Tos                   isrProvider;                 /**< \brief Interrupt service provider */
    Ifx_ETH                     *ethSfr;                      /**< \brief Pointer to register base */
    IfxEth_RxDescrList          *rxDescr;                     /**< \brief pointer to RX descriptor RAM */
    IfxEth_TxDescrList          *txDescr;                     /**< \brief pointer to TX descriptor RAM */
    IfxEth_DescriptorMode        descriptorMode;              /**< \brief Descriptor mode (chain or ring) */
    IfxEth_RingModeBuffersConfig ringModeBuffersConfig;       /**< \brief Ring mode buffers condiguration */
} IfxEth_Config;

/** \} */

/** \addtogroup IfxLld_Eth_Std_DataStructures
 * \{ */
/** \brief ETH driver structure
 */
typedef struct
{
    Ifx_ETH_STATUS            status;               /**< \brief Intermediate variable to use register content in control structure */
    uint32                    rxCount;              /**< \brief Number of frames received */
    uint32                    txCount;              /**< \brief Number of frames transmitted */
    uint32                    error;                /**< \brief Indicate an error has occurred during execution */
    sint32                    isrRxCount;           /**< \brief Count of RX ISR */
    sint32                    isrTxCount;           /**< \brief Count of TX ISR */
    sint32                    txDiff;               /**< \brief Difference between isrTxCount and txCount */
    sint32                    rxDiff;               /**< \brief Difference between isrRxCount and rxCount */
    sint32                    isrCount;             /**< \brief count of all ISR */
    IfxEth_Config             config;               /**< \brief Copy of the configuration passed through IfxEth_init() */
    IfxEth_RxDescrList       *rxDescr;              /**< \brief pointer to RX descriptor RAM */
    IfxEth_TxDescrList       *txDescr;              /**< \brief pointer to TX descriptor RAM */
    IfxEth_RxDescr           *pRxDescr;
    IfxEth_TxDescr           *pTxDescr;
    Ifx_ETH                  *ethSfr;               /**< \brief Pointer to register base */
    IfxEth_DescriptorMode     descriptorMode;       /**< \brief Descriptor mode (chain or ring) */
    IfxEth_RingModeBufferUsed txBufferUsed;         /**< \brief Transmit Buffer(s) used in ringmode */
    IfxEth_RingModeBufferUsed rxBufferUsed;         /**< \brief Receive Buffer(s) used in ringmode */
} IfxEth;

/** \brief Structure for RX descriptor DWORD 0 Bit field access
 */
typedef struct
{
    uint32 PCE : 1;      /**< \brief Rx MAC Address/Payload Checksum Error */
    uint32 CE : 1;       /**< \brief CRC Error */
    uint32 DBE : 1;      /**< \brief Dribble Bit Error */
    uint32 RE : 1;       /**< \brief Receive Error */
    uint32 RWT : 1;      /**< \brief Receive Watchdog Timeout */
    uint32 FT : 1;       /**< \brief Frame Type */
    uint32 LC : 1;       /**< \brief Late Collision */
    uint32 IPC : 1;      /**< \brief IPC Checksum Error/Giant Frame */
    uint32 LS : 1;       /**< \brief Last Descriptor */
    uint32 FS : 1;       /**< \brief First Descriptor */
    uint32 VLAN : 1;     /**< \brief VLAN Tag */
    uint32 OE : 1;       /**< \brief Overflow Error */
    uint32 LE : 1;       /**< \brief Length Error */
    uint32 SAF : 1;      /**< \brief Source Address Filter Fail */
    uint32 DE : 1;       /**< \brief Descriptor Error */
    uint32 ES : 1;       /**< \brief Error Summary, ES = PCE | CE | RE | RWT | LC | IPC | OE | DE */
    uint32 FL : 14;      /**< \brief Frame Length */
    uint32 AFM : 1;      /**< \brief Destination Address Filter Fail */
    uint32 OWN : 1;      /**< \brief Own Bit, 1 = own by DMA */
} IfxEth_RxDescr0_Bits;

/** \brief Structure for RX descriptor DWORD 1 Bit field access
 */
typedef struct
{
    uint32 RBS1 : 11;     /**< \brief Receive Buffer 1 Size */
    uint32 RBS2 : 11;     /**< \brief Receive Buffer 2 Size */
    uint32 resv : 2;      /**< \brief (reserved) */
    uint32 RCH : 1;       /**< \brief Second Address Chained */
    uint32 RER : 1;       /**< \brief Receive End of Ring */
    uint32 resv2 : 5;     /**< \brief (reserved) */
    uint32 DIC : 1;       /**< \brief Disable Interrupt on Completion */
} IfxEth_RxDescr1_Bits;

/** \brief Structure for TX descriptor DWORD 0 Bit field access
 */
typedef struct
{
    uint32 DB : 1;        /**< \brief Deferred Bit */
    uint32 UF : 1;        /**< \brief Underflow Error */
    uint32 ED : 1;        /**< \brief Excessive Deferral */
    uint32 CC : 4;        /**< \brief Collision Count */
    uint32 VLAN : 1;      /**< \brief VLAN Tag */
    uint32 EC : 1;        /**< \brief Excessive Collision */
    uint32 LC : 1;        /**< \brief Late Collision */
    uint32 NC : 1;        /**< \brief No Carrier */
    uint32 LOC : 1;       /**< \brief Loss of Carrier */
    uint32 PCE : 1;       /**< \brief Payload Checksum Error */
    uint32 FF : 1;        /**< \brief Frame Flushed */
    uint32 JT : 1;        /**< \brief Jabber Timeout */
    uint32 ES : 1;        /**< \brief Error Summary, ES = JT | FF | LOC | NC | LC | EC | ED | UF */
    uint32 IHE : 1;       /**< \brief IP Header Error */
    uint32 TTSS : 1;      /**< \brief Tx Time Stamp Status */
    uint32 resv : 13;     /**< \brief (reserved) */
    uint32 OWN : 1;       /**< \brief Own Bit, 1 = own by DMA */
} IfxEth_TxDescr0_Bits;

/** \brief Structure for TX descriptor DWORD 1 Bit field access
 */
typedef struct
{
    uint32 TBS1 : 11;     /**< \brief Transmit Buffer 1 Size */
    uint32 TBS2 : 11;     /**< \brief Transmit Buffer 2 Size */
    uint32 TTSE : 1;      /**< \brief Transmit Time Stamp Enable */
    uint32 DP : 1;        /**< \brief Disable Padding */
    uint32 TCH : 1;       /**< \brief Second Address Chained */
    uint32 TER : 1;       /**< \brief Transmit End of Ring */
    uint32 DC : 1;        /**< \brief Disable CRC */
    uint32 CIC : 2;       /**< \brief Checksum Insertion Control */
    uint32 FS : 1;        /**< \brief First Segment */
    uint32 LS : 1;        /**< \brief Last Segment */
    uint32 IC : 1;        /**< \brief Interrupt on Completion */
} IfxEth_TxDescr1_Bits;

/** \} */

/** \addtogroup IfxLld_Eth_Std_Configuration
 * \{ */

/******************************************************************************/
/*-------------------------Inline Function Prototypes-------------------------*/
/******************************************************************************/

/** \brief Set buffer of an RX descriptor
 * \param descr descr Pointer to an RX descriptor
 * \param buffer pointer to buffer
 * \return None
 */
IFX_INLINE void IfxEth_RxDescr_setBuffer(IfxEth_RxDescr *descr, void *buffer);

/** \brief Get pointer to next TX descriptor
 * \param descr descr Pointer to a TX descriptor
 * \return next Tx descriptor
 */
IFX_INLINE IfxEth_TxDescr *IfxEth_TxDescr_getNext(IfxEth_TxDescr *descr);

/** \brief Return TRUE if a TX descriptor is available for setup
 * \param descr pointer to descriptor
 */
IFX_INLINE boolean IfxEth_TxDescr_isAvailable(IfxEth_TxDescr *descr);

/** \brief Set buffer of a TX descriptor
 * \param descr Entdescr Pointer to a TX descriptorer_String_here
 * \param buffer pointer to Buffer
 * \return None
 */
IFX_INLINE void IfxEth_TxDescr_setBuffer(IfxEth_TxDescr *descr, void *buffer);

/** \brief Applies the Software Reset
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_applySoftwareReset(IfxEth *eth);

/** \brief Clear Early Receive Interrupt request
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_clearEriInterrupt(IfxEth *eth);

/** \brief Clear receive interrupt request
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_clearRxInterrupt(IfxEth *eth);

/** \brief Clear Transmit Buffer Unavailable request
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_clearTuInterrupt(IfxEth *eth);

/** \brief Clear transmit interrupt request
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_clearTxInterrupt(IfxEth *eth);

/** \brief Disables Timestamp Fine or Coarse Update
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_disableTimeStampCoarseUpdate(IfxEth *eth);

/** \brief Disables Processing of PTP frames sent over IPV4 UDP
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_disableTimeStampForIpv4Frames(IfxEth *eth);

/** \brief Enables theMMC counter
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_enableMmcCounter(IfxEth *eth);

/** \brief Enables the TimeStamp
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_enableTimeStamp(IfxEth *eth);

/** \brief Enables Timestamp Fine or Coarse Update
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_enableTimeStampCoarseUpdate(IfxEth *eth);

/** \brief Enables the TimeStamp for All frames
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_enableTimeStampForAllFrames(IfxEth *eth);

/** \brief Enables Processing of PTP over Ethernet Frames
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_enableTimeStampForEthFrames(IfxEth *eth);

/** \brief Enables Processing of PTP frames sent over IPV4 UDP
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_enableTimeStampForIpv4Frames(IfxEth *eth);

/** \brief Enables PTP packet Processing for Version 2 Format
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_enableTimeStampForVer2Format(IfxEth *eth);

/** \brief returns the status of the TimeStamp Initialisation
 * \param eth ETH driver structure
 * \return Status, TRUE: initialising, FLASE: initialised
 */
IFX_INLINE boolean IfxEth_getTimeStampInitialiseStatus(IfxEth *eth);

/** \brief returns the status of the System Time updation
 * \param eth ETH driver structure
 * \return Status, TRUE: initialising, FLASE: initialised
 */
IFX_INLINE boolean IfxEth_getTimeStampUpdateStatus(IfxEth *eth);

/** \brief Initialises  the TimeStamp
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_initialiseTimeStamp(IfxEth *eth);

/** \brief Returns the status of Software Reset
 * \param eth ETH driver structure
 * \return Status
 */
IFX_INLINE boolean IfxEth_isSoftwareResetDone(IfxEth *eth);

/** \brief Sets addition, the time value is added with the contents of the update register
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_setAddToTimeUpdate(IfxEth *eth);

/** \brief Enable/Disables Timestamp Digital or Binary Rollover Control
 * \param eth ETH driver structure
 * \param enabled Enable = 1 / Disable = 0
 * \return None
 */
IFX_INLINE void IfxEth_setBinaryRolloverControl(IfxEth *eth, boolean enabled);

/** \brief Sets the loopback mode
 * \param eth ETH driver structure
 * \param loopbackMode loopback mode enable/disbale
 * \return None
 */
IFX_INLINE void IfxEth_setLoopbackMode(IfxEth *eth, boolean loopbackMode);

/** \brief Sets the time in sub seconds representation, to be initialized or added to the system time
 * \param eth ETH driver structure
 * \param value Sub Second Increment Value
 * \return None
 */
IFX_INLINE void IfxEth_setNanoSecondsUpdateValue(IfxEth *eth, uint8 value);

/** \brief Sets the Phy Interface mode
 * \param eth ETH driver structure
 * \param mode Phy interface mode
 * \return None
 */
IFX_INLINE void IfxEth_setPhyInterfaceMode(IfxEth *eth, IfxEth_PhyInterfaceMode mode);

/** \brief Sets receive descriptor address
 * \param eth pointer to the ethernet module
 * \param address Address
 * \return None
 */
IFX_INLINE void IfxEth_setReceiveDescriptorAddress(Ifx_ETH *eth, void *address);

/** \brief Sets the time in seconds to be initialized or added to the system time
 * \param eth ETH driver structure
 * \param value Sub Second Increment Value
 * \return None
 */
IFX_INLINE void IfxEth_setSecondsUpdateValue(IfxEth *eth, uint8 value);

/** \brief Sets the Sub Second Increment Value
 * \param eth ETH driver structure
 * \param value Sub Second Increment Value
 * \return None
 */
IFX_INLINE void IfxEth_setSubSecondIncrementValue(IfxEth *eth, uint8 value);

/** \brief Sets subtraction, the time value is subtracted with the contents of the update register
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_setSubtractToTimeUpdate(IfxEth *eth);

/** \brief Sets transmit descriptor address
 * \param eth pointer to the ethernet module
 * \param address Address
 * \return None
 */
IFX_INLINE void IfxEth_setTransmitDescriptorAddress(Ifx_ETH *eth, void *address);

/** \brief Updates  the System time with specified values in SECONDS and NANOSECONDS registers
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_updateTimeStamp(IfxEth *eth);

/** \brief Waits for one TX buffer becomes available
 * \param eth ETH driver structure
 * retval non NULL_PTR TX buffer is available at the address pointed by the returned value
 * retval NULL_PTR TX buffer is busy.
 */
IFX_INLINE void *IfxEth_waitTransmitBuffer(IfxEth *eth);

/******************************************************************************/
/*-------------------------Global Function Prototypes-------------------------*/
/******************************************************************************/

/** \brief Free the receive buffer, enabling it for the further reception
 * \param eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_freeReceiveBuffer(IfxEth *eth);

/** \brief Request to send the transmit buffer
 *
 * The transmit buffer is the last one specified by IfxEth_getTransmitBuffer()
 * \param eth ETH driver structure
 * \param len Length of the data put in the transmit buffer (in bytes)
 * \return None
 */
IFX_EXTERN void IfxEth_sendTransmitBuffer(IfxEth *eth, uint16 len);

/** \brief Request to send the transmit buffer
 *
 * The transmit buffer is the last one specified by IfxEth_getTransmitBuffer()
 * \param eth ETH driver structure
 * \param buffer1Length Length of the data put in the transmit buffer 1 (in bytes)
 * \param buffer2Length Length of the data put in the transmit buffer 2 (in bytes)
 * \return None
 */
IFX_EXTERN void IfxEth_sendTransmitBuffersRingMode(IfxEth *eth, uint16 buffer1Length, uint16 buffer2Length);

/** \brief Sets the MAC address
 * \param eth ETH driver structure
 * \param macAddress MAC address
 * \return None
 */
IFX_EXTERN void IfxEth_setMacAddress(IfxEth *eth, const uint8 *macAddress);

/** \brief Start the receiver functions
 * \param eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_startReceiver(IfxEth *eth);

/** \brief Stops the receiver functions
 * \param eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_stopReceiver(IfxEth *eth);

/** \brief writes the header format into buffrer
 * \param eth ETH driver structure
 * \param txBuffer pointer to tx buffer
 * \param destinationAddress pointer to destination address
 * \param sourceAddress pointer to source address
 * \param packetSize size of the packet
 * \return None
 */
IFX_EXTERN void IfxEth_writeHeader(IfxEth *eth, uint8 *txBuffer, uint8 *destinationAddress, uint8 *sourceAddress, uint32 packetSize);

/** \} */

/** \addtogroup IfxLld_Eth_Std_Utility
 * \{ */

/******************************************************************************/
/*-------------------------Inline Function Prototypes-------------------------*/
/******************************************************************************/

/** \brief Get pointer to next RX descriptor
 * \param descr descr Pointer to an RX descriptor
 * \return next RX descriptor
 */
IFX_INLINE IfxEth_RxDescr *IfxEth_RxDescr_getNext(IfxEth_RxDescr *descr);

/** \brief release RX descriptor
 * \param descr pointer to Rx descriptor
 * \return None
 */
IFX_INLINE void IfxEth_RxDescr_release(IfxEth_RxDescr *descr);

/** \brief Release a TX descriptor for transmit queue
 * \param descr Enter_String_herdescr Pointer to a TX descriptore
 * \return None
 */
IFX_INLINE void IfxEth_TxDescr_release(IfxEth_TxDescr *descr);

/** \brief resets Ethernet Configuration register
 * \return None
 */
IFX_INLINE void IfxEth_clearMacConfiguration(void);

/** \brief Get pointer to actual RX descriptor
 * \param eth eth ETH driver structure
 */
IFX_INLINE IfxEth_RxDescr *IfxEth_getActualRxDescriptor(IfxEth *eth);

/**
 */
IFX_INLINE uint32 IfxEth_getActualRxIndex(IfxEth *eth);

/** \brief Get pointer to actual TX descriptor
 * \param eth eth ETH driver structure
 */
IFX_INLINE IfxEth_TxDescr *IfxEth_getActualTxDescriptor(IfxEth *eth);

/** \brief Get pointer to base RX descriptor
 * \param eth eth ETH driver structure
 */
IFX_INLINE IfxEth_RxDescr *IfxEth_getBaseRxDescriptor(IfxEth *eth);

/** \brief Get pointer to base TX descriptor
 * \param eth eth ETH driver structure
 */
IFX_INLINE IfxEth_TxDescr *IfxEth_getBaseTxDescriptor(IfxEth *eth);

/** \brief returns the status of th eloopback mode
 * \param eth ETH driver structure
 * \return Loop back mode status (TRUE / FALSE)
 */
IFX_INLINE boolean IfxEth_getLoopbackMode(IfxEth *eth);

/** \brief Returns pointer to the MAC address configured for this ETH
 * \param eth ETH driver structure
 */
IFX_INLINE void *IfxEth_getMacAddressPointer(IfxEth *eth);

/** \brief returns the Receive Process State
 * \param eth ETH driver structure
 * \return Receive Process State
 */
IFX_INLINE IfxEth_ReceiveProcessState IfxEth_getReceiveProcessState(IfxEth *eth);

/** \brief Returns length of the oldest available RX data
 * \param eth ETH driver structure
 * \return Data length
 */
IFX_INLINE uint16 IfxEth_getRxDataLength(IfxEth *eth);

/** \brief Returns the SRC pointer of Eth
 * \param eth ETH driver structure
 * \return pointer to ETH SRCR  register
 */
IFX_INLINE volatile Ifx_SRC_SRCR *IfxEth_getSrcPointer(IfxEth *eth);

/** \brief returns the Transmit Process State
 * \param eth ETH driver structure
 * \return Transmit Process State
 */
IFX_INLINE IfxEth_TransmitProcessState IfxEth_getTransmitProcessState(IfxEth *eth);

/** \brief Checks whether Early Receive interrupt is requested
 * \param eth ETH driver structure
 * \return TRUE/FALSE
 */
IFX_INLINE boolean IfxEth_isEriInterrupt(IfxEth *eth);

/** \brief Checks whether physical connection is active
 * \param eth ETH driver structure
 * \return retval zero Connection is inactive
 * retval non zero Connection is active
 */
IFX_INLINE boolean IfxEth_isLinkActive(IfxEth *eth);

/** \brief Checks whether NIS interrupt is requested
 * \param eth ETH driver structure
 * \return TRUE/FALSE
 */
IFX_INLINE boolean IfxEth_isNisInterrupt(IfxEth *eth);

/**
 * \param eth pointer to ETH driver structure
 */
IFX_INLINE boolean IfxEth_isRxChecksumError(IfxEth *eth);

/** \brief Checks whether one or more RX data is available
 * \param eth ETH driver structure
 * \return retval TRUE one or more RX data is available
 * retval FALSE no RX data is available
 */
IFX_INLINE boolean IfxEth_isRxDataAvailable(IfxEth *eth);

/** \brief Checks whether receive interrupt is requested
 * \param eth ETH driver structure
 * \return TRUE/FALSE
 */
IFX_INLINE boolean IfxEth_isRxInterrupt(IfxEth *eth);

/** \brief Checks whether Transmit Buffer Unavailable interrupt is requested
 * \param eth ETH driver structure
 * \return TRUE/FALSE
 */
IFX_INLINE boolean IfxEth_isTuInterrupt(IfxEth *eth);

/** \brief Checks whether transmit interrupt is requested
 * \param eth ETH driver structure
 * \return TRUE/FALSE
 */
IFX_INLINE boolean IfxEth_isTxInterrupt(IfxEth *eth);

/** \brief reads the status of all flags
 * \param eth ETH driver structure
 * \return None
 */
IFX_INLINE void IfxEth_readAllFlags(IfxEth *eth);

/******************************************************************************/
/*-------------------------Global Function Prototypes-------------------------*/
/******************************************************************************/

/** \brief Disable ETH Module
 * \return None
 */
IFX_EXTERN void IfxEth_disableModule(void);

/** \brief Enable ETH Module
 * \return None
 */
IFX_EXTERN void IfxEth_enableModule(void);

/** \brief Gets receive buffer\n
 * note: IfxEth_freeReceiveBuffer() shall be called after the data from the RX buffer has been processed
 * \param eth ETH driver structure
 * \return retval NULL_PTR no received frame
 * retval !NULL_PTR a frame has been received
 */
IFX_EXTERN void *IfxEth_getReceiveBuffer(IfxEth *eth);

/** \brief Get a free transmit buffer
 * \param eth ETH driver structure
 * \return retval NULL_PTR no free transmit buffer is available
 * retval !NULL_PTR a free transmit buffer is available
 */
IFX_EXTERN void *IfxEth_getTransmitBuffer(IfxEth *eth);

/** \brief Reads the MAC address from module register
 * \param eth ETH driver structure
 * \param macAddress MAC address
 * \return None
 */
IFX_EXTERN void IfxEth_readMacAddress(IfxEth *eth, uint8 *macAddress);

/** \brief resets Ethernet kernel
 * \return None
 */
IFX_EXTERN void IfxEth_resetModule(void);

/**
 * \param eth pointer to ETH driver structure
 * \param len length of buffer
 * \return None
 */
IFX_EXTERN void IfxEth_setAndSendTransmitBuffer(IfxEth *eth, void *buffer, uint16 len);

/** \brief Set up checksum Engine
 * \param eth eth ETH driver structure
 * \param mode specifies checksum mode
 * \return None
 */
IFX_EXTERN void IfxEth_setupChecksumEngine(IfxEth *eth, IfxEth_ChecksumMode mode);

/** \brief Shuffle to next RX descriptor
 * \param eth eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_shuffleRxDescriptor(IfxEth *eth);

/** \brief Shuffle to next TX descriptor
 * \param eth eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_shuffleTxDescriptor(IfxEth *eth);

/** \brief Start the transmitter functions
 * \param eth eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_startTransmitter(IfxEth *eth);

/** \brief Stop the transmitter functions
 * \param eth eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_stopTransmitter(IfxEth *eth);

/** \brief Wakeup the receiver functions
 * \param eth eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_wakeupReceiver(IfxEth *eth);

/** \brief Wakeup the transmitter functions
 * \param eth eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_wakeupTransmitter(IfxEth *eth);

/** \} */

/** \addtogroup IfxLld_Eth_Std_Initialisation
 * \{ */

/******************************************************************************/
/*-------------------------Inline Function Prototypes-------------------------*/
/******************************************************************************/

/** \brief Setup some properties of a TX descriptor
 * \param descr Enter_Sdescr Pointer to a TX descriptortring_here
 * \param length specifies length of transmit descriptor
 * \param firstSegment specifies first segment of frame
 * \param lastSegment specifies last segment of frame
 * \return None
 */
IFX_INLINE void IfxEth_TxDescr_setup(IfxEth_TxDescr *descr, uint16 length, boolean firstSegment, boolean lastSegment);

/** \brief Sets the receive buffer1 of the receive descriptor along with its size
 * \param eth ETH driver structure
 * \param descr Pointer to Rx descreptor
 * \param address Buffer 1 start address
 * \param size Buffer 1 size
 * \return None
 */
IFX_INLINE void IfxEth_setReceiveBuffer1RingMode(IfxEth *eth, IfxEth_RxDescr *descr, uint32 address, uint16 size);

/** \brief Sets the receive buffer2 of the receive descriptor along with its size
 * \param eth ETH driver structure
 * \param descr Pointer to Rx descreptor
 * \param address Buffer 1 start address
 * \param size Buffer 1 size
 * \return None
 */
IFX_INLINE void IfxEth_setReceiveBuffer2RingMode(IfxEth *eth, IfxEth_RxDescr *descr, uint32 address, uint16 size);

/** \brief Sets the transmit buffer1 of the receive descriptor along with its size
 * \param eth ETH driver structure
 * \param descr Pointer to Tx descreptor
 * \param address Buffer 1 start address
 * \param size Buffer 1 size
 * \return None
 */
IFX_INLINE void IfxEth_setTransmitBuffer1RingMode(IfxEth *eth, IfxEth_TxDescr *descr, uint32 address, uint16 size);

/** \brief Sets the transmit buffer2 of the receive descriptor along with its size
 * \param eth ETH driver structure
 * \param descr Pointer to Tx descreptor
 * \param address Buffer 1 start address
 * \param size Buffer 1 size
 * \return None
 */
IFX_INLINE void IfxEth_setTransmitBuffer2RingMode(IfxEth *eth, IfxEth_TxDescr *descr, uint32 address, uint16 size);

/******************************************************************************/
/*-------------------------Global Function Prototypes-------------------------*/
/******************************************************************************/

/** \brief Initialises the driver
 * \param eth ETH driver structure
 * \param config ETH configuration structure
 * \return None
 */
IFX_EXTERN void IfxEth_init(IfxEth *eth, const IfxEth_Config *config);

/** \brief Initialises the configuration Structure
 * \param config ETH configuration structure
 * \param ethSfr Pointer to register base
 * \return None
 */
IFX_EXTERN void IfxEth_initConfig(IfxEth_Config *config, Ifx_ETH *ethSfr);

/** \brief Initialises the receive descriptors
 * \param eth ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_initReceiveDescriptors(IfxEth *eth);

/** \brief Initialises the receive descriptors
 * \param eth ETH driver structure
 * \param config Ring mode Rx buffers configuration
 * \return None
 */
IFX_EXTERN void IfxEth_initReceiveDescriptorsRingMode(IfxEth *eth, const IfxEth_RingModeRxBuffersConfig *config);

/** \brief Initialises transmit descriptors
 * \param eth pointer to ETH driver structure
 * \return None
 */
IFX_EXTERN void IfxEth_initTransmitDescriptors(IfxEth *eth);

/** \brief Initialises transmit descriptors
 * \param eth pointer to ETH driver structure
 * \param config Ring mode Tx buffers configuration
 * \return None
 */
IFX_EXTERN void IfxEth_initTransmitDescriptorsRingMode(IfxEth *eth, const IfxEth_RingModeTxBuffersConfig *config);

/** \brief Set up MII mode input pins
 * \param eth eth pointer to ETH driver structure
 * \param miiPins pin of port to be set
 * \return None
 */
IFX_EXTERN void IfxEth_setupMiiInputPins(IfxEth *eth, const IfxEth_MiiPins *miiPins);

/** \brief setup MII mode output pins
 * \param eth eth pointer to ETH driver structure
 * \param miiPins pin of port to be set
 * \return None
 */
IFX_EXTERN void IfxEth_setupMiiOutputPins(IfxEth *eth, const IfxEth_MiiPins *miiPins);

/** \brief Set up input pins
 * \param eth eth pointer to ETH driver structure
 * \param rmiiPins pin of port to be set
 * \return None
 */
IFX_EXTERN void IfxEth_setupRmiiInputPins(IfxEth *eth, const IfxEth_RmiiPins *rmiiPins);

/** \brief set output pin of port
 * \param eth eth pointer to ETH driver structure
 * \param rmiiPins pin of port to be set
 * \return None
 */
IFX_EXTERN void IfxEth_setupRmiiOutputPins(IfxEth *eth, const IfxEth_RmiiPins *rmiiPins);

/** \} */

/******************************************************************************/
/*-------------------Global Exported Variables/Constants----------------------*/
/******************************************************************************/

/** \brief receive buffers
 */
IFX_EXTERN uint8              IfxEth_rxBuffer[IFXETH_MAX_RX_BUFFERS][IFXETH_RTX_BUFFER_SIZE];

IFX_EXTERN IfxEth_RxDescrList IfxEth_rxDescr;

/** \brief Transmit buffers
 */
IFX_EXTERN uint8              IfxEth_txBuffer[IFXETH_MAX_TX_BUFFERS][IFXETH_RTX_BUFFER_SIZE];

IFX_EXTERN IfxEth_TxDescrList IfxEth_txDescr;

/******************************************************************************/
/*---------------------Inline Function Implementations------------------------*/
/******************************************************************************/

IFX_INLINE IfxEth_RxDescr *IfxEth_RxDescr_getNext(IfxEth_RxDescr *descr)
{
    return (IfxEth_RxDescr *)(descr->RDES3.U);
}


IFX_INLINE void IfxEth_RxDescr_release(IfxEth_RxDescr *descr)
{
    descr->RDES0.A.OWN = 1U;
}


IFX_INLINE void IfxEth_RxDescr_setBuffer(IfxEth_RxDescr *descr, void *buffer)
{
    descr->RDES2.U = (uint32)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), buffer);
}


IFX_INLINE IfxEth_TxDescr *IfxEth_TxDescr_getNext(IfxEth_TxDescr *descr)
{
    return (IfxEth_TxDescr *)(descr->TDES3.U);
}


IFX_INLINE boolean IfxEth_TxDescr_isAvailable(IfxEth_TxDescr *descr)
{
    return (descr->TDES0.A.OWN == 0) ? TRUE : FALSE;
}


IFX_INLINE void IfxEth_TxDescr_release(IfxEth_TxDescr *descr)
{
    descr->TDES0.A.OWN = 1U;
}


IFX_INLINE void IfxEth_TxDescr_setBuffer(IfxEth_TxDescr *descr, void *buffer)
{
    descr->TDES2.U = (uint32)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), buffer);
}


IFX_INLINE void IfxEth_TxDescr_setup(IfxEth_TxDescr *descr, uint16 length, boolean firstSegment, boolean lastSegment)
{
    IfxEth_TxDescr0 tdes0;

    tdes0.U        = descr->TDES0.U;
    tdes0.A.FS     = firstSegment;
    tdes0.A.LS     = lastSegment;
    descr->TDES0.U = tdes0.U;
    descr->TDES1.U = length;
}


IFX_INLINE void IfxEth_applySoftwareReset(IfxEth *eth)
{
    (void)eth;
    ETH_BUS_MODE.B.SWR = 1; /* reset module */
}


IFX_INLINE void IfxEth_clearEriInterrupt(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.STATUS.U = (uint32)((1 << IFX_ETH_STATUS_NIS_OFF) | (1 << IFX_ETH_STATUS_ERI_OFF));
}


IFX_INLINE void IfxEth_clearMacConfiguration(void)
{
    MODULE_ETH.MAC_CONFIGURATION.U = 0;
}


IFX_INLINE void IfxEth_clearRxInterrupt(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.STATUS.U = (uint32)((1 << IFX_ETH_STATUS_NIS_OFF) | (1 << IFX_ETH_STATUS_RI_OFF));
}


IFX_INLINE void IfxEth_clearTuInterrupt(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.STATUS.U = (uint32)((1 << IFX_ETH_STATUS_NIS_OFF) | (1 << IFX_ETH_STATUS_TU_OFF));
}


IFX_INLINE void IfxEth_clearTxInterrupt(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.STATUS.U = (uint32)((1 << IFX_ETH_STATUS_NIS_OFF) | (1 << IFX_ETH_STATUS_TI_OFF));
}


IFX_INLINE void IfxEth_disableTimeStampCoarseUpdate(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSCFUPDT = 0;
}


IFX_INLINE void IfxEth_disableTimeStampForIpv4Frames(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSIPV4ENA = 0;
}


IFX_INLINE void IfxEth_enableMmcCounter(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.MMC_CONTROL.B.CNTFREEZ = 0;
}


IFX_INLINE void IfxEth_enableTimeStamp(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSENA = 1;
}


IFX_INLINE void IfxEth_enableTimeStampCoarseUpdate(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSCFUPDT = 1;
}


IFX_INLINE void IfxEth_enableTimeStampForAllFrames(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSENALL = 1;
}


IFX_INLINE void IfxEth_enableTimeStampForEthFrames(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSIPENA = 1;
}


IFX_INLINE void IfxEth_enableTimeStampForIpv4Frames(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSIPV4ENA = 1;
}


IFX_INLINE void IfxEth_enableTimeStampForVer2Format(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSVER2ENA = 1;
}


IFX_INLINE IfxEth_RxDescr *IfxEth_getActualRxDescriptor(IfxEth *eth)
{
    return eth->pRxDescr;
}


IFX_INLINE uint32 IfxEth_getActualRxIndex(IfxEth *eth)
{
    uint32 offset = (uint32)eth->pRxDescr - (uint32)IfxEth_getBaseRxDescriptor(eth);
    return offset / sizeof(IfxEth_RxDescr);
}


IFX_INLINE IfxEth_TxDescr *IfxEth_getActualTxDescriptor(IfxEth *eth)
{
    return eth->pTxDescr;
}


IFX_INLINE IfxEth_RxDescr *IfxEth_getBaseRxDescriptor(IfxEth *eth)
{
    return eth->rxDescr->items;
}


IFX_INLINE IfxEth_TxDescr *IfxEth_getBaseTxDescriptor(IfxEth *eth)
{
    return eth->txDescr->items;
}


IFX_INLINE boolean IfxEth_getLoopbackMode(IfxEth *eth)
{
    (void)eth;
    return (ETH_MAC_CONFIGURATION.B.LM != 0) ? TRUE : FALSE;
}


IFX_INLINE void *IfxEth_getMacAddressPointer(IfxEth *eth)
{
    return (void *)eth->config.macAddress;
}


IFX_INLINE IfxEth_ReceiveProcessState IfxEth_getReceiveProcessState(IfxEth *eth)
{
    (void)eth;
    return (IfxEth_ReceiveProcessState)MODULE_ETH.STATUS.B.RS;
}


IFX_INLINE uint16 IfxEth_getRxDataLength(IfxEth *eth)
{
    uint16 length = 0;

    if (IfxEth_isRxDataAvailable(eth) != FALSE)
    {
        length = (uint16)IfxEth_getActualRxDescriptor(eth)->RDES0.A.FL;
    }

    return length;
}


IFX_INLINE volatile Ifx_SRC_SRCR *IfxEth_getSrcPointer(IfxEth *eth)
{
    (void)eth;
    return &MODULE_SRC.ETH.ETH[0].SR;
}


IFX_INLINE boolean IfxEth_getTimeStampInitialiseStatus(IfxEth *eth)
{
    (void)eth;
    return MODULE_ETH.TIMESTAMP_CONTROL.B.TSINIT;
}


IFX_INLINE boolean IfxEth_getTimeStampUpdateStatus(IfxEth *eth)
{
    (void)eth;
    return MODULE_ETH.TIMESTAMP_CONTROL.B.TSUPDT;
}


IFX_INLINE IfxEth_TransmitProcessState IfxEth_getTransmitProcessState(IfxEth *eth)
{
    (void)eth;
    return (IfxEth_TransmitProcessState)MODULE_ETH.STATUS.B.TS;
}


IFX_INLINE void IfxEth_initialiseTimeStamp(IfxEth *eth)
{
    (void)eth;

    if (MODULE_ETH.TIMESTAMP_CONTROL.B.TSINIT == 0)
    {
        MODULE_ETH.TIMESTAMP_CONTROL.B.TSINIT = 1;
    }
}


IFX_INLINE boolean IfxEth_isEriInterrupt(IfxEth *eth)
{
    (void)eth;

    return MODULE_ETH.STATUS.B.ERI != 0;
}


IFX_INLINE boolean IfxEth_isLinkActive(IfxEth *eth)
{
    return eth->config.phyLink() != 0;
}


IFX_INLINE boolean IfxEth_isNisInterrupt(IfxEth *eth)
{
    (void)eth;

    return MODULE_ETH.STATUS.B.NIS != 0;
}


IFX_INLINE boolean IfxEth_isRxChecksumError(IfxEth *eth)
{
    IfxEth_RxDescr *descr = IfxEth_getActualRxDescriptor(eth);
    boolean         error = (descr->RDES0.A.IPC != 0);
    descr->RDES0.A.IPC = 0;

    return error;
}


IFX_INLINE boolean IfxEth_isRxDataAvailable(IfxEth *eth)
{
    //return (IfxEth_rxDescr[eth->rxIndex][0] & (1U << 31)) == 0);
    return IfxEth_getActualRxDescriptor(eth)->RDES0.A.OWN == 0;
}


IFX_INLINE boolean IfxEth_isRxInterrupt(IfxEth *eth)
{
    (void)eth;

    return MODULE_ETH.STATUS.B.RI != 0;
}


IFX_INLINE boolean IfxEth_isSoftwareResetDone(IfxEth *eth)
{
    (void)eth;
    return ETH_BUS_MODE.B.SWR == 0 ? 1 : 0;
}


IFX_INLINE boolean IfxEth_isTuInterrupt(IfxEth *eth)
{
    (void)eth;

    return MODULE_ETH.STATUS.B.TU != 0;
}


IFX_INLINE boolean IfxEth_isTxInterrupt(IfxEth *eth)
{
    (void)eth;

    return MODULE_ETH.STATUS.B.TI != 0;
}


IFX_INLINE void IfxEth_readAllFlags(IfxEth *eth)
{
    eth->status.U = ETH_STATUS.U;
}


IFX_INLINE void IfxEth_setAddToTimeUpdate(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.SYSTEM_TIME_NANOSECONDS_UPDATE.B.ADDSUB = 0;
}


IFX_INLINE void IfxEth_setBinaryRolloverControl(IfxEth *eth, boolean enabled)
{
    (void)eth;
    MODULE_ETH.TIMESTAMP_CONTROL.B.TSCTRLSSR = 1;
}


IFX_INLINE void IfxEth_setLoopbackMode(IfxEth *eth, boolean loopbackMode)
{
    (void)eth;
    ETH_MAC_CONFIGURATION.B.LM = loopbackMode ? 1 : 0;
}


IFX_INLINE void IfxEth_setNanoSecondsUpdateValue(IfxEth *eth, uint8 value)
{
    (void)eth;
    MODULE_ETH.SYSTEM_TIME_NANOSECONDS_UPDATE.B.TSSS = value;
}


IFX_INLINE void IfxEth_setPhyInterfaceMode(IfxEth *eth, IfxEth_PhyInterfaceMode mode)
{
    (void)eth;
    ETH_GPCTL.B.EPR = mode;
}


IFX_INLINE void IfxEth_setReceiveBuffer1RingMode(IfxEth *eth, IfxEth_RxDescr *descr, uint32 address, uint16 size)
{
    descr->RDES2.U      = (uint32)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), address);
    descr->RDES1.A.RBS1 = size;
}


IFX_INLINE void IfxEth_setReceiveBuffer2RingMode(IfxEth *eth, IfxEth_RxDescr *descr, uint32 address, uint16 size)
{
    descr->RDES3.U      = (uint32)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), address);
    descr->RDES1.A.RBS2 = size;
}


IFX_INLINE void IfxEth_setReceiveDescriptorAddress(Ifx_ETH *eth, void *address)
{
    eth->RECEIVE_DESCRIPTOR_LIST_ADDRESS.U = (uint32)address;
}


IFX_INLINE void IfxEth_setSecondsUpdateValue(IfxEth *eth, uint8 value)
{
    (void)eth;
    MODULE_ETH.SYSTEM_TIME_SECONDS_UPDATE.B.TSS = value;
}


IFX_INLINE void IfxEth_setSubSecondIncrementValue(IfxEth *eth, uint8 value)
{
    (void)eth;
    MODULE_ETH.SUB_SECOND_INCREMENT.B.SSINC = value;
}


IFX_INLINE void IfxEth_setSubtractToTimeUpdate(IfxEth *eth)
{
    (void)eth;
    MODULE_ETH.SYSTEM_TIME_NANOSECONDS_UPDATE.B.ADDSUB = 1;
}


IFX_INLINE void IfxEth_setTransmitBuffer1RingMode(IfxEth *eth, IfxEth_TxDescr *descr, uint32 address, uint16 size)
{
    descr->TDES2.U      = (uint32)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), address);
    descr->TDES1.A.TBS1 = size;
}


IFX_INLINE void IfxEth_setTransmitBuffer2RingMode(IfxEth *eth, IfxEth_TxDescr *descr, uint32 address, uint16 size)
{
    descr->TDES3.U      = (uint32)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), address);
    descr->TDES1.A.TBS2 = size;
}


IFX_INLINE void IfxEth_setTransmitDescriptorAddress(Ifx_ETH *eth, void *address)
{
    eth->TRANSMIT_DESCRIPTOR_LIST_ADDRESS.U = (uint32)address;
}


IFX_INLINE void IfxEth_updateTimeStamp(IfxEth *eth)
{
    (void)eth;

    if (MODULE_ETH.TIMESTAMP_CONTROL.B.TSUPDT == 0)
    {
        MODULE_ETH.TIMESTAMP_CONTROL.B.TSUPDT = 1;
    }
}


IFX_INLINE void *IfxEth_waitTransmitBuffer(IfxEth *eth)
{
    void *tx;

    do
    {
        tx = IfxEth_getTransmitBuffer(eth);
    } while (tx == NULL_PTR);

    return tx;
}


#endif /* IFXET_H */
