/* ======================================================================
 *   Copyright (C) 2022 Texas Instruments Incorporated
 *
 *   All rights reserved. Property of Texas Instruments Incorporated.
 *   Restricted rights to use, duplicate or disclose this code are
 *   granted through contract.
 *
 *   The program may not be used without the written permission
 *   of Texas Instruments Incorporated or against the terms and conditions
 *   stipulated in the agreement under which this program has been
 *   supplied.
 * ==================================================================== */

/**
 *  \file     EthApp.c
 *
 *  \brief    This file contains the Eth test example
 *
 */

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */

#include "stdlib.h"
#include "string.h"
#include "Std_Types.h"
#include "hw_types.h"
#include "Det.h"
#include "Dem.h"
#include "Eth.h"
#include "Eth_Irq.h"
#include "Eth_GeneralTypes.h"
#include "Eth_Cfg.h"
#include "EthIf_Cbk.h"
#include "EcuM_Cbk.h"
#include "Mcu.h"
#include "Mcu_Cfg.h"
#include "Port.h"
#include "Port_Cfg.h"
#include "EthTrcv.h"

/* Starterware Includes */
#include "soc.h"
#include "hw_ctrl_core.h"
#include "sys_vim.h"
#include "app_utils.h"
#include "trace.h"
#include "EthApp.h"
#include "app_utilsEth.h"

/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */
#define APP_NAME                        "ETH_APP"

/* ========================================================================== */
/*                         Structures and Enums                               */
/* ========================================================================== */



/* ========================================================================== */
/*                 Internal Function Declarations                             */
/* ========================================================================== */

typedef void (*EthExampleFxn_t)(void);
#if (ETH_GLOBALTIMESUPPORT_API == STD_ON) && (ETHAPP_TIMESTAMP_TEST == STD_ON)
static void EthApp_TimeStampTest(Eth_ConfigType *pEthConfigPtr);
#endif
#if (STD_ON == ETHAPP_FILTER_TEST) && (STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER_API)
static void EthApp_FilterTest(Eth_ConfigType *pEthConfigPtr);
#endif
static void EthApp_InterruptConfig(void);
static void EthApp_PlatformInit(void);
static void EthApp_RxTxTest(void);
static void EthApp_ReceivePacketTest(Eth_ConfigType *pEthConfigPtr);
static void EthApp_TransmitPacketTest(Eth_ConfigType *pEthConfigPtr);
void EthExample_TransmitStress(void);
void EthApp_printMACAddr(uint8 macAddr[]);
static Std_ReturnType EthApp_showStats(uint8 ctrlIdx);
static void EthExample_PerformanceTest(void);
uint32 Performance_Result[50];
uint32 				frc;
/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

App_State                 gAppObj;
volatile uint32           gTestPassed = E_OK;
volatile uint32           gStopTestFlag = FALSE;
volatile uint32           gEthcontrollerModeChangeFlag = FALSE;
uint8                     gTestMacAddr[ETH_MAC_ADDR_LEN];
uint8                     MainFunc_Execution;
float32                   ExecutimeTime;
static volatile uint32    msgCounter1     = 0U;
static sint32             i2 = 0U;
volatile uint32           gLoopCntr = 1U;
extern const Mcu_ConfigType McuModuleConfiguration;
extern AppUtilsPinMux_ConfigType Port_Config;
uint8 _gDstBuff[MAX_BUFFER_SIZE] __attribute__(( aligned(128), section(".data") ));

#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)
volatile uint32 tsyncGetTsStress = 0;
volatile uint32 tsyncXmitStress = 0;
uint32 gTimeStampEnabled[ETH_NUM_TX_BUFFERS]={FALSE};

char * timeStampQualString[3] = { "ETH_VALID", "ETH_INVALID", "ETH_UNCERTAIN" };

char *msgTypeString[15] =
{
    "CPTS_MESSAGE_SYNC",
    "CPTS_MESSAGE_DELAY_REQ",
    "CPTS_MESSAGE_PDELAY_REQ",
    "CPTS_MESSAGE_PDELAY_RESP",
    "4", "5", "6", "7",
    "CPTS_MESSAGE_FOLLOW_UP",
    "CPTS_MESSAGE_DELAY_RESP",
    "CPTS_MESSAGE_PDELAY_RESP_FOLLOW_UP",
    "CPTS_MESSAGE_ANNOUNCE",
    "CPTS_MESSAGE_SIGNALING",
    "CPTS_MESSAGE_MANAGEMENT",
    "CPTS_MESSAGE_INVALID",
};
#endif


#define FAIL_MESSAGE AppUtils_printf("\r\nFailed in %s \n", __func__)
#define htons(a) ( (((a)>>8)&0xffU) + (((a)<<8)&0xff00U) )
#define htonl(a) ((((a) & 0xff000000U) >> 24) | (((a) & 0x00ff0000U) >> 8) | \
                  (((a) & 0x0000ff00U) << 8)  | (((a) & 0x000000ffU) << 24) )

#define ntohl(a) (htonl(a))
#define ntohs(a) (htons(a))

char *ethRcvStatusString[3] =
{
    "ETH_RECEIVED",
    "ETH_NOT_RECEIVED",
    "ETH_RECEIVED_MORE_DATA_AVAILABLE",
};

Eth_MdioConfigType        gMdioCfg =
{
    .mdioBusFreq   = ETH_CPSW_DEFAULT_MDIOBUSFREQ,
    .mdioClockFreq = ETH_CPSW_DEFAULT_MDIOCLOCKFREQ
};

Eth_CpdmaConfigType       gCpdmaCfg =
{
    .pacingClkFreq = ETH_CPSW_DEFAULT_MAINCLKFREQ,
    .rxInterruptPacingEnabled = (uint32) TRUE,
    .rxInterruptsPerMsec      = 2U,
    .txInterruptPacingEnabled = (uint32) TRUE,
    .txInterruptsPerMsec      = 2U,
    .dmaModeFlags  = 0U,
    .rxThreshCount = 0x0F
};

Eth_CptsConfigType        gCptsCfg =
{
    /* 200U MHz */
    .cptsInputFreq    = 200000000UL,
   .vlanType          = ETH_CPTS_VLAN_TYPE_SINGLE_TAG,
    .msgTypeCfg       = ETH_CPTS_MESSAGE_ALL
};


uint8 gUniCstAddr[ETH_MAC_ADDR_LEN] =  {0x18, 0x03, 0x73, 0xb2, 0xcc, 0x01};
uint8 gBCstMacAddr[ETH_MAC_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8 gPtpMcastAddr[ETH_MAC_ADDR_LEN] = {0x01,0x1B,0x19,0x00,0x00,0x0};


const uint8 CtrlIdx = 0;

static VAR(uint8,AUTOMATIC) MacDest[6];
P2VAR(uint8,AUTOMATIC,ETH_APPL_DATA)PhysAddrPtr=MacDest;

static VAR(Eth_ModeType,AUTOMATIC) Ethmode=ETH_MODE_DOWN;
P2VAR(Eth_ModeType, AUTOMATIC,ETH_APPL_DATA) CtrlModePtr=&Ethmode;
	 
	EthExampleFxn_t           EthExampleFxnTbl[] =
{
    EthApp_RxTxTest,
};
/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

/** @fn void main(void)
 *   @brief Application main function
 *   @note This function is empty by default.
 *
 *   This function is called after startup.
 *   The user can use this function to implement the application.
 */
int main(void)
{
    uint32 i = 0;
    uint32 index;
    Std_ReturnType returnval;
    uint32 LucBufIdx[128];
	uint8    gTestMacAddr[ETH_MAC_ADDR_LEN];

    Std_ReturnType retVal = (Std_ReturnType) E_OK;
	Eth_ConfigType     *pEthConfigPtr;
	pEthConfigPtr = &EthConfigSet_EthCtrlConfig_0;

    gTestPassed = E_OK;
    AppUtils_logTestResult(APP_UTILS_TEST_STATUS_INIT);
    AppUtils_defaultInit();
    EthApp_InterruptConfig();
	EthApp_PlatformInit();
	I2C();

#if (ETHAPP_THROUGHPUT_TEST == STD_ON)
    EthExample_PerformanceTest();
#endif

    AppUtils_printf( APP_NAME ": Sample Application - STARTS !!! \n");
	
	
	for (i = 0U; i < APPUTILS_ARRAYSIZE(EthExampleFxnTbl); i++)
    {
        EthExampleFxnTbl[i]();
    }
	
    GT_1trace(McalAppTrace, GT_INFO,
              "\n\rETH Stack Usage: %d bytes", AppUtils_getStackUsage());
    /* if (AppUtils_checkStackAndSectionCorruption() != E_OK)
    {
        gTestPassed = E_NOT_OK;
        GT_0trace(McalAppTrace, GT_ERR, "\n\rETH Stack/section corruption!!!\n");
    } */
	AppUtils_printf( "\n\rETH_APP: Sample Application - DONE !!!\n");
    if (E_OK == gTestPassed)
    {
        GT_0trace(McalAppTrace, GT_INFO, "\n\rETH Test Passed!!!\r\n");
        AppUtils_logTestResult(APP_UTILS_TEST_STATUS_PASS);
    }
    else
    {
        GT_0trace(McalAppTrace, GT_ERR, "\n\rETH Test Failed!!!\r\n");
        AppUtils_logTestResult(APP_UTILS_TEST_STATUS_FAIL);
    }
	
	 return gTestPassed;
}	
	 

static void EthApp_RxTxTest()
{
    Eth_ConfigType     *pEthConfigPtr;
    Std_ReturnType      retVal    = (Std_ReturnType) E_NOT_OK;
    uint8               myMacAddr[ETH_MAC_ADDR_LEN];
    uint8 i=0;
    memset(&gAppObj, 0U, sizeof (App_State));
    gAppObj.checkPackets = 1U;
	
	AppUtils_ethPrintVersionInfo();

	pEthConfigPtr = &EthConfigSet_EthCtrlConfig_0;
	
#if (STD_OFF == ETH_PRE_COMPILE_VARIANT)
#if  (ETH_ENABLE_MII_API == STD_ON)
    /* Initialize configuration */
    memcpy(&pEthConfigPtr->mdioCfg,
           &gMdioCfg,
           sizeof (Eth_MdioConfigType));
#endif
#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)
    memcpy(&pEthConfigPtr->cptsCfg,
           &gCptsCfg,
           sizeof (Eth_CptsConfigType));
#endif
    memcpy(&pEthConfigPtr->cpdmaCfg,
           &gCpdmaCfg,
           sizeof (Eth_CpdmaConfigType));
#endif

	
    /* Do Eth driver initialization */
#if (STD_ON == ETH_PRE_COMPILE_VARIANT)
    Eth_Init((const Eth_ConfigType *) NULL_PTR);
#else
    Eth_Init(pEthConfigPtr);
#endif
	
	/* Initialiaze the ETH Transceiver */
   AppUtils_ethAm263xPHYDelayConfig(pEthConfigPtr, 0);
#if (STD_ON == ETHTRCV_PRE_COMPILE_VARIANT)
    AppUtils_ethTrcvInit((EthTrcv_ConfigType *) NULL_PTR);
#else
    AppUtils_ethTrcvInit(&EthTrcvConfigSet_EthTrcvConfig_0);
#endif
	
	/* Set the Controller:0 in Active mode */
    retVal = Eth_SetControllerMode(pEthConfigPtr->ctrlIdx,ETH_MODE_ACTIVE);
	if ((Std_ReturnType) E_OK != retVal)
    {
        AppUtils_printf(APP_NAME ": Failed in Eth_SetControllerMode \r\n");
        gTestPassed = E_NOT_OK;
    }
	
	/* Get Back the Controller mode  */
    retVal = Eth_GetControllerMode(pEthConfigPtr->ctrlIdx,CtrlModePtr);
    if ((Std_ReturnType) E_OK != retVal)
    {
        AppUtils_printf(APP_NAME ": Failed in Eth_GetControllerMode \r\n");
        gTestPassed = E_NOT_OK;
    }
	
    /* Generate Random MAC addresses to use */
    for (i = 0U; i < ETH_MAC_ADDR_LEN; i++)
    {
        gTestMacAddr[i] = (uint8) ((CtrlIdx * 0x10U) + i);
    }
    Eth_SetPhysAddr(pEthConfigPtr->ctrlIdx,gTestMacAddr);
							  
    /* Get back the Mac address of the controller*/
    Eth_GetPhysAddr(pEthConfigPtr->ctrlIdx,PhysAddrPtr);
	AppUtils_printf("\r\nMAC Port %d Address:\r\n", 01U);
    EthApp_printMACAddr(gTestMacAddr);
	
	/* Adding a Destination address to the filter */
    Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,gTestMacAddr,ETH_ADD_TO_FILTER);
    //Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,gBCstMacAddr,ETH_ADD_TO_FILTER);
	
#if (STD_ON == ETHAPP_STRESS_TEST)
    {
        uint32 tempVar = 1U;
        while(tempVar)
        {
	
	       EthApp_ReceivePacketTest(pEthConfigPtr);

           EthApp_TransmitPacketTest(pEthConfigPtr);
	    }
    }
#endif
 
 #if (STD_ON == ETHAPP_FILTER_TEST) && (STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER_API)
    AppUtils_printf("\n\r-----------------------------------------------");
    AppUtils_printf("\n\r*********** ETH FILTER TEST *******************");
    AppUtils_printf("\n\r-----------------------------------------------\n");
    EthApp_FilterTest(pEthConfigPtr);
#endif


#if (ETH_GLOBALTIMESUPPORT_API == STD_ON) && (ETHAPP_TIMESTAMP_TEST == STD_ON)
    Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,gPtpMcastAddr,ETH_ADD_TO_FILTER);
    EthApp_TimeStampTest(pEthConfigPtr);
#endif

    gAppObj.frameRcvdFlag = FALSE;

    EthApp_ReceivePacketTest(pEthConfigPtr);

    EthApp_TransmitPacketTest(pEthConfigPtr);
	
	retVal = EthApp_showStats(pEthConfigPtr->ctrlIdx);
        if (E_OK != retVal)
        {
            AppUtils_printf("main: failed to show statistics\n");
        }
	
}

/* =========================Function separator========================= */

static void EthApp_ReceivePacketTest(Eth_ConfigType *pEthConfigPtr)
{
    Std_ReturnType      retVal    = (Std_ReturnType) E_OK;
    uint32     loopCntr;
#if (STD_ON != ETH_ENABLE_RX_INTERRUPT)
    Eth_RxStatusType    rxStatus;
#endif

    AppUtils_printf("\r\n---------------------------------------------\r");
    AppUtils_printf("\r\n***********ETH RECEIVE  TEST*******************");
    AppUtils_printf("\r\n---------------------------------------------\r\n");

#if (ETH_ENABLE_RX_INTERRUPT != STD_ON)
    AppUtils_printf("\r\nUsing Eth Receive in polling mode.\r\n");
#endif


        AppUtils_printf("\r\nWaiting to receive %d packets from CANoe/PC packet player\r\n", ETHAPP_NUM_RECEIVE_PACKET);
        gAppObj.stats.recvPacketCnt = 0U;
        while (gAppObj.stats.recvPacketCnt < ETHAPP_NUM_RECEIVE_PACKET)
        {

            /* Wait for Rx packets */
            #if (ETH_ENABLE_RX_INTERRUPT != STD_ON)
            do
            {
                Eth_Receive(pEthConfigPtr->ctrlIdx, 0, &rxStatus);
                #if DEBUG
                AppUtils_printf("\r\n\tEth_Receive = [%s] \r\n", ethRcvStatusString[rxStatus]);
                #endif
            }
            while (ETH_RECEIVED_MORE_DATA_AVAILABLE == rxStatus);
            #endif
        }

    if ((Std_ReturnType) E_NOT_OK == retVal)
    {
        gTestPassed = E_NOT_OK;
    }
    else
    {
        /*
         * Wait for 1U second for clearing all pending receive
         * transfers if any.
         */
        AppUtils_delay(1000U);

        if (gAppObj.checkPackets)
        {
            AppUtils_printf("\r\nReceive packet statistics:");
            AppUtils_printf("\r\n EXPECTEDETHERTYPE_IPV4 (0x%x) = %d ",
                                    ETHAPP_ETHERTYPE_IPV4, 
									gAppObj.stats.expectedEtherType_ipv4);
            AppUtils_printf("\r\n EXPECTEDETHERTYPE_VLAN (0x%x) = %d",
                                    ETHAPP_ETHERTYPE_VLAN,
									gAppObj.stats.expectedEtherType_vlan);
            AppUtils_printf("\r\n UNEXPECTEDETHERTYPE = %d",
                                    gAppObj.stats.unexpectedEtherType++);
            AppUtils_printf("\r\n");

        }
    }

    if ((Std_ReturnType) E_OK != retVal)
    {
        gTestPassed = E_NOT_OK;
    }

}

/* =========================Function separator========================= */

static void EthApp_TransmitPacketTest(Eth_ConfigType *pEthConfigPtr)
{
    volatile uint32     loopCntr;

    AppUtils_printf("\r\n-----------------------------------------------");
    AppUtils_printf("\r\n***********ETH TRANSMIT TEST*******************");
    AppUtils_printf("\r\n-----------------------------------------------\r\n");


    gAppObj.stats.ethTransmitPckCnt = 0U;

    gAppObj.stats.txBuffUnderflow = gAppObj.stats.txConfirmPacketCnt = 0U;

        AppUtils_printf("\r\nTransmitting %d packets, ", ETHAPP_NUM_TRANSMIT_PACKET);
        AppUtils_printf("\r\nExpect CANoe / PC Wireshark to receive %d packets..",
                     		ETHAPP_NUM_TRANSMIT_PACKET);

        EthExample_TransmitStress();

        AppUtils_delay(1000U);
        AppUtils_printf("\r\nStats: Sent=%d,\r\n",
                        gAppObj.stats.ethTransmitPckCnt);
        /* for first iteration we disable txConfirmation, so we check only (ETH_APP_LOOP_COUNT - 1) for TxConfirmation count  */
        if ((gAppObj.stats.ethTransmitPckCnt != ETHAPP_NUM_TRANSMIT_PACKET) )
        {
            AppUtils_printf("\r\nTx error, sent only %d packets [of %d] \r\n", gAppObj.stats.ethTransmitPckCnt, ETHAPP_NUM_TRANSMIT_PACKET);
        }
        else
       {
        AppUtils_printf("\r\nTransmitted %d packets \r\n", gAppObj.stats.ethTransmitPckCnt);
       }
}
	 
/* =========================Function separator========================= */

void EthExample_TransmitStress()
{

    BufReq_ReturnType   bufStatus = BUFREQ_NOT_OK;
    uint8 *bufPtr;
    uint16  i;
    Eth_BufIdxType bufIdx;
    uint16 lenByte;
    volatile uint32 packetCnt;
    Std_ReturnType      retVal    = (Std_ReturnType) E_NOT_OK;
    boolean             txConfirmation;
    Eth_FrameType       frameType = 0x0800;  /* ICMP IP packet */
    Eth_ConfigType     *pEthConfigPtr;
    static uint32       maxTxPacketSizeTestDone = FALSE;
    static uint32       txConfirmationTestDone  = FALSE;

    lenByte = ETH_DATA_LEN;

    pEthConfigPtr = &EthConfigSet_EthCtrlConfig_0;


    packetCnt = 0;
    while (packetCnt < ETHAPP_NUM_TRANSMIT_PACKET)
    {
        txConfirmation = FALSE;

        if (!maxTxPacketSizeTestDone)
        {
            /* Do maximum ethernet Tx packet test only once */
            lenByte = 1600U;
        }

requestbuffer:
        gTestPassed = E_OK;
        bufStatus = Eth_ProvideTxBuffer(pEthConfigPtr->ctrlIdx,
		                                0,
                                        &bufIdx,
                                        &bufPtr,
                                        &lenByte);
        if (BUFREQ_OK != bufStatus)
        {
            if (BUFREQ_E_OVFL == bufStatus)
            {
                /* Length approved less than asked */
                gTestPassed = E_NOT_OK;
                gAppObj.stats.txBuffLenUnSufficient++;

                /* As per SWS_Eth_00079 if a buffer requested with Eth_ProvideTxBuffer
                 * is larger than the available buffer length, the buffer shall not be
                 * locked but return the available length and BUFREQ_E_OVFL. */
                AppUtils_printf("\r\nMax Tx Packet Size Test passed \r\n");

                /* we change packet length and request again */
                lenByte = ETH_DATA_LEN;
                /* Set max packet test done flag */
                maxTxPacketSizeTestDone = TRUE;

                goto requestbuffer;
            }
            else
            {
                gAppObj.stats.txBuffUnderflow++;
                /* No free buffer */
                gTestPassed = E_NOT_OK;
                #if(STD_OFF == ETHAPP_TRAFFIC_SHAPING_TEST)
                AppUtils_delay(100U);
                #endif
                /* Try again */
                goto requestbuffer;
            }
        }

        if (E_OK == gTestPassed)
        {
#if (1U == ENABLE_VLAN_TAG)
            uint32 pcp = 5U;
            uint32 vlanId = 1024U;
            uint32 tpId = 0x8100;
            uint32 etherType = 0x0800;

            frameType = tpId;
            /* Fill data into buffer provided by driver */
            *(uint32 *)(bufPtr) = htonl((pcp<<29)|(1<<28)|(vlanId<<16)|etherType);
#endif

            /* Fill data into buffer provided by driver */
            for (i = 0U; i <= lenByte; i++)
            {
                bufPtr[i] = i;
            }
            
            retVal         = Eth_Transmit(pEthConfigPtr->ctrlIdx,
                                          bufIdx,
                                          frameType,
                                          txConfirmation,
                                          lenByte,
                                          gBCstMacAddr);
            if ((Std_ReturnType) E_NOT_OK == retVal)
            {
                gTestPassed = E_NOT_OK;
                gAppObj.stats.ethTransmitErr++;
            }
            else
            {
                gAppObj.stats.ethTransmitPckCnt++;
            }
			
        }
        else
        {
            gAppObj.stats.provideTxBuffErr++;
        }
        packetCnt++;
    }

}

void I2C_Write(uint32 cmd, uint32 reg){
	uint32 count, temp = 0;
	count = 2;
	HW_WR_REG32(0x52502014, count); /* Count */
	HW_WR_REG32(0x52502024, 0x4620); /* Start Write */
	HW_WR_REG32(0x52502024, 0x6620); /* Start Write */
	AppUtils_delay(10);
	HW_WR_REG32(0x52502020, cmd); /* Data Command */
	while(temp == 0)
	{
		temp = HW_RD_REG32(0x52502008);
		temp = (temp >> 4) & 0x01;
	}
	HW_WR_REG32(0x52502020, reg); /* Data */
	HW_WR_REG32(0x52502024, 0x4E20); /* Stop I2C */
}

void I2C_Read(uint32 cmd, uint32 *reg){
	uint32 count;
	count = 1;
	HW_WR_REG32(0x52502014, count); /* Count */
	HW_WR_REG32(0x52502024, 0x4620); /* Start Write */
	HW_WR_REG32(0x52502024, 0x6620); /* Start Write */
	AppUtils_delay(10);
	HW_WR_REG32(0x52502020, cmd); /* Data Command */
	count = 1;
	HW_WR_REG32(0x52502014, count); /* Count */
	HW_WR_REG32(0x52502024, 0x4420); /* Start Read */
	HW_WR_REG32(0x52502024, 0x6420); /* Start Read */
	AppUtils_delay(10);
	*reg = HW_RD_REG32(0x52502018); /* Read */
	HW_WR_REG32(0x52502024, 0x4A20); /* Stop I2C */
}

void I2C(){
	uint32 count, reg;
	HW_WR_REG32(0x52502024, 0x0); /* Reset */
	HW_WR_REG32(0x52502000, 0x10); /* Own Address */
	HW_WR_REG32(0x5250200C, 0x09); /* Clock Low */
	HW_WR_REG32(0x52502010, 0x09); /* Clock High */
	HW_WR_REG32(0x52502030, 0x07); /* PreScalar */
	HW_WR_REG32(0x5250201C, 0x20); /* Slave Address */
	
	I2C_Read(0x06, &reg);
	reg &= (~0x7C);
	I2C_Write(0x06, reg);
	
	I2C_Read(0x07, &reg);
	reg &= (~0x11);
	I2C_Write(0x07, reg);
	
	I2C_Read(0x00, &reg);
	reg |= 0x70;
	reg &= (~0x0C);
	I2C_Write(0x02, reg);
	
	I2C_Read(0x01, &reg);
	reg |= 0x11;
	I2C_Write(0x03, reg);
}

/* =========================Function separator========================= */
void EthIf_CtrlModeIndication(uint8        ControllerId,
                              Eth_ModeType ControllerMode)
{
    AppUtils_printf("\r\nETH_APP: EthIf_CtrlModeIndication: Eth Controller mode change - %20s ",
       (ControllerMode == ETH_MODE_ACTIVE) ? "ETH_MODE_ACTIVE" : "ETH_MODE_DOWN");

    gEthcontrollerModeChangeFlag = TRUE;
    MainFunc_Execution = 3U;
}

/* =========================Function separator========================= */
void EthIf_TrcvModeIndication(uint8        CtrlIdx,
                              EthTrcv_ModeType TrcvMode)
{
    if( ETHTRCV_MODE_ACTIVE == TrcvMode)
    {
        AppUtils_printf("\rETH_APP:EthTRCV Controller Up\n");
    }
    else
    {
        AppUtils_printf("\rETH_APP:EthTRCV Controller Down\n");
    }
    MainFunc_Execution = 2U;
}

/* =========================Function separator========================= */
Std_ReturnType Det_ReportError(uint16 ModuleId, uint8 InstanceId, uint8 ApiId,
                               uint8 ErrorId)
{
    gTestPassed = E_NOT_OK;
    GT_assert(McalAppTrace, FALSE);
    return (Std_ReturnType) E_OK;
}

/* =========================Function separator========================= */

void SchM_Enter_Port_PORT_EXCLUSIVE_AREA_0(void)
{
    AppUtils_SchM_Enter_EXCLUSIVE_AREA_0();
}

/* =========================Function separator========================= */

void SchM_Exit_Port_PORT_EXCLUSIVE_AREA_0(void)
{
    AppUtils_SchM_Exit_EXCLUSIVE_AREA_0();
}

/* =========================Function separator========================= */

void SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_0()
{
    AppUtils_SchM_Enter_EXCLUSIVE_AREA_0();
}

/* =========================Function separator========================= */

void SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_0()
{
    AppUtils_SchM_Exit_EXCLUSIVE_AREA_0();
}

/* =========================Function separator========================= */
static void EthApp_PlatformInit()
{
    uint16 mss_uart_tx_pin, mss_uart_rx_pin;
#if (STD_OFF == MCU_NO_PLL)
    uint32 sys_clk_freq_vclk_const;

    /* MCU PLL Config */
    gAdcAppMcuConfig.Mcu_PllConfig = McuModuleConfiguration_0.Mcu_PllConfig;
    gAdcAppMcuConfig.Mcu_PllSourceId = McuModuleConfiguration_0.Mcu_PllSourceId;
#endif

	Mcu_Init(&McuModuleConfiguration);
	Port_Init(PortConfigSet_0_pt);

	 mss_uart_tx_pin = 13;
    mss_uart_rx_pin = 14;
	
	// Set up the pinmux for UART tx
    Port_SetPinMode(mss_uart_tx_pin, PORT_PIN_MODE_LIN0);
    /* Set up the pinmux for UART rx */
    Port_SetPinMode(mss_uart_rx_pin, PORT_PIN_MODE_LIN0);
	Port_SetPinDirection(mss_uart_rx_pin, PORT_PIN_IN);

	#if (STD_OFF == MCU_NO_PLL)
    if(McuModuleConfiguration_0.Mcu_PllSourceId == MCU_CLKSRC_DPLL)
    {
        sys_clk_freq_vclk_const = (McuModuleConfiguration_0.
		Mcu_PllConfig[MCU_CLKSRC_DPLL].Mcu_PllClk1.MCU_PLL_HSDIV2 / (2e6)) * 30;
    }
    else
    {
        sys_clk_freq_vclk_const = (McuModuleConfiguration_0.
		Mcu_PllConfig[MCU_CLKSRC_APLL].Mcu_PllClk1.MCU_PLL_HSDIV0 / (2e6)) * 30;
    }
    Enable_Uart();
    #else
    Enable_Uart();
    #endif
 }

/* =========================Function separator========================= */
void EthApp_printMACAddr(uint8 macAddr[])
{
    AppUtils_printf("\r%02x:%02x:%02x:%02x:%02x:%02x\r\n",
        macAddr[0U], macAddr[1U], macAddr[2U],
        macAddr[3U], macAddr[4U], macAddr[5U]);
}

/* =========================Function separator========================= */
static void EthApp_InterruptConfig(void)
{
    vimInit();
    Vim_IntCfg Eth_IntCfg;
    Eth_IntCfg.map = VIM_INTTYPE_IRQ;
    Eth_IntCfg.type = VIM_INTTRIGTYPE_PULSE;

#if (STD_ON == ETH_ENABLE_RX_INTERRUPT)
    Eth_IntCfg.intNum = CPSW_TH_INT;    
    Eth_IntCfg.handler = Eth_RxIrqHdlr_0;
    Eth_IntCfg.priority = VIM_PRIORITY_2;
    vimRegisterInterrupt(&Eth_IntCfg);
#endif

#if (STD_ON == ETH_ENABLE_TX_INTERRUPT)
    Eth_IntCfg.intNum = CPSW_FH_INT;
    Eth_IntCfg.handler = Eth_TxIrqHdlr_0;
    Eth_IntCfg.priority = VIM_PRIORITY_3;
    vimRegisterInterrupt(&Eth_IntCfg);
#endif

#if (STD_ON == ETH_ENABLE_RX_INTERRUPT)
    Eth_IntCfg.intNum = CPSW_TH_TRSH_INT;    
    Eth_IntCfg.handler = Eth_RxThreshIrqHdlr_0;
    Eth_IntCfg.priority = VIM_PRIORITY_4;
    vimRegisterInterrupt(&Eth_IntCfg);
#endif

#if (ETH_USR_MDIO_INTERRUPT == STD_ON) ||(ETH_STATS_INTERRUPT == STD_ON)
    Eth_IntCfg.intNum = CPSW_MISC_INT;    
    Eth_IntCfg.handler = Eth_MiscIrqHdlr_0;
    Eth_IntCfg.priority = VIM_PRIORITY_5;
    vimRegisterInterrupt(&Eth_IntCfg);
#endif
}

#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)

void EthExample_SendTimeStampPacket(uint8* pPacketPtr, uint16 lenByte)
{
    BufReq_ReturnType   bufStatus = BUFREQ_NOT_OK;
    uint8 *bufPtr;
    Eth_BufIdxType bufIdx;
    Std_ReturnType           retVal    = (Std_ReturnType) E_NOT_OK;
    boolean                  txConfirmation;
    Eth_FrameType            frameType = ETHAPP_ETHERTYPE_PTP1588;
    Eth_ConfigType          *pEthConfigPtr;

    pEthConfigPtr = &EthConfigSet_EthCtrlConfig_0;

requestbuffer:
    gTestPassed = E_OK;
    bufStatus = Eth_ProvideTxBuffer(pEthConfigPtr->ctrlIdx,
	                            0,
                                &bufIdx,
                                &bufPtr,
                                &lenByte);
    if (BUFREQ_OK != bufStatus)
    {
        if (BUFREQ_E_OVFL == bufStatus)
        {
            /* Length approved less than asked */
            gTestPassed = E_NOT_OK;
            gAppObj.stats.txBuffLenUnSufficient++;
        }
        else
        {
            gAppObj.stats.txBuffUnderflow++;
            /* No free buffer */
            gTestPassed = E_NOT_OK;
            AppUtils_delay(100U);
            /* Try again */
            goto requestbuffer;
        }
    }

    if (E_OK == gTestPassed)
    {
        memcpy(bufPtr, pPacketPtr, lenByte);

        /* set no. of transmitted packets to zero */
        gAppObj.stats.txConfirmPacketCnt = 0U;
        txConfirmation = FALSE;
        gTimeStampEnabled[bufIdx] = TRUE;

        Eth_EnableEgressTimeStamp(pEthConfigPtr->ctrlIdx, bufIdx);

        retVal         = Eth_Transmit(pEthConfigPtr->ctrlIdx,
                                      bufIdx,
                                      frameType,
                                      txConfirmation,
                                      lenByte,
                                      gBCstMacAddr);
    }

    if ((Std_ReturnType) E_NOT_OK == retVal)
    {
        gTestPassed = E_NOT_OK;
        gAppObj.stats.ethTransmitErr++;
    }
    else
    {
        gAppObj.stats.ethTransmitPckCnt++;
    }

    return;
}
#endif

#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)
void EthApp_printSysTime(Eth_TimeStampType *ts)
{
    AppUtils_printf("[%2u.%4u.%10u]",
            ts->secondsHi, ts->seconds, ts->nanoseconds);
}
#endif

#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)
/** \brief Macros for time conversions */
#define NSEC_PER_SEC                                (1000000000U)
#define TIME_SYNC_SECONDSHIGH_MASK                  (0x0000FFFF00000000ULL)
#define TIME_SYNC_SECONDS_MASK                      (0xFFFFFFFFU)
void EthApp_getdiffTimePeriod(Eth_TimeStampType prev, Eth_TimeStampType curr)
{
    typedef unsigned long long uint64;

    uint64 prevSec48bit, currSec48bit;
    uint64 temp64bit, deltaSec48bit;
    Eth_TimeStampType diff;

    temp64bit = curr.secondsHi;
    currSec48bit =  (uint64)(temp64bit << 32U) + (uint64)curr.seconds;

    temp64bit = prev.secondsHi;
    prevSec48bit =  (uint64)(temp64bit << 32U) + (uint64)prev.seconds;

    if (curr.nanoseconds < prev.nanoseconds)
    {
        curr.nanoseconds += NSEC_PER_SEC;
        currSec48bit--;
    }

    deltaSec48bit = currSec48bit - prevSec48bit;
    diff.nanoseconds = curr.nanoseconds - prev.nanoseconds;

    diff.secondsHi = (uint16)( (deltaSec48bit & TIME_SYNC_SECONDSHIGH_MASK) >> 32U );
    diff.seconds   = (uint32)( deltaSec48bit & TIME_SYNC_SECONDS_MASK);

    AppUtils_printf("\r\tTimeSync_Diff: ");
    EthApp_printSysTime(&diff);
}
#endif

#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)
void EthApp_TimeStampGetTime(Eth_ConfigType *pEthConfigPtr)
{
    Std_ReturnType retVal;
    Eth_TimeStampType timeStamp = {0,0,0};
    Eth_TimeStampType prevTimestamp = {0,0,0};
    Eth_TimeStampQualType timeQual;
    uint32 i;
    uint32 startTime = 0U, elapsedTime = 0U;

    /* ###----####---###---###*/
    AppUtils_printf("\r\n\tGet global time after delay upto 1000ms (loop=10)\n" );
    memset(&timeStamp, 0U, sizeof (Eth_TimeStampType));
    for (i=0;i<10;i++)
    {
        startTime = AppUtils_getCurTimeInMsec();
        AppUtils_delay(rand()%1000);
        retVal = Eth_GetCurrentTime(pEthConfigPtr->ctrlIdx, &timeQual, &timeStamp);
        if (E_NOT_OK != retVal)
        {
            AppUtils_printf("\r\n\tCurr_Time: ");
            EthApp_printSysTime(&timeStamp);
            EthApp_getdiffTimePeriod (prevTimestamp,timeStamp);
            memcpy(&prevTimestamp, &timeStamp, sizeof (Eth_TimeStampType));
        }
        else
        {
            FAIL_MESSAGE;
        }
        elapsedTime = AppUtils_getElapsedTimeInMsec(startTime);
        AppUtils_printf("(32K Cntr Diff %3d)", elapsedTime);
    }

    AppUtils_printf("\r\n");

    memset(&prevTimestamp, 0U, sizeof (Eth_TimeStampType));
    while(tsyncGetTsStress)
    {
        uint32 delay = rand();
        retVal = Eth_GetCurrentTime(pEthConfigPtr->ctrlIdx, &timeQual, &timeStamp);
        if (E_NOT_OK != retVal)
        {
            AppUtils_printf("\r\n\tCurr_Time: ");
            EthApp_printSysTime(&timeStamp);
            AppUtils_printf("\r\n\t Delay = %d", delay);
            AppUtils_delay(delay);
            AppUtils_printf("(Time diff %f)", (timeStamp.seconds - (float)delay/(float)1000));
            memcpy(&prevTimestamp, &timeStamp, sizeof (Eth_TimeStampType));
        }
        else
        {
            FAIL_MESSAGE;
        }
    }
}
#endif


#if (ETH_GLOBALTIMESUPPORT_API == STD_ON) && (ETHAPP_TIMESTAMP_TEST == STD_ON)
void EthApp_TimeStampTest(Eth_ConfigType *pEthConfigPtr)
{
    uint32 egressPckCnt = 0;

    AppUtils_printf("\r\n-----------------------------------------------");
    AppUtils_printf("\r\n***********Time Stamping Test*******************");
    AppUtils_printf("\r\n-----------------------------------------------\n");

    EthApp_TimeStampGetTime(pEthConfigPtr);

    AppUtils_printf("\r\n\n Time Sync Packet Egress Test " );
    AppUtils_printf("\r\n--------------------------------" );

    while ( (egressPckCnt < ETHAPP_NUM_TIME_SYNC_PACKET) || tsyncXmitStress )
    {
        EthExample_SendTimeStampPacket(&timeSyncPacket[0],lengthOfTimeSyncPacket);
        EthExample_SendTimeStampPacket(&pDelayRequestPacket[0],lengthOfPdelayRequestPacket);
		egressPckCnt++;
    }

    AppUtils_printf("\r\n\n Time Sync Packet Ingress Test " );
    AppUtils_printf("\r\n---------------------------------" );
    AppUtils_printf("\r\n Send timestamp (0x88F7) packets (%d) from PC \n", ETHAPP_NUM_TIME_SYNC_PACKET );

    /* Ingress time stamp is taken in EthIf_RxIndication function */
    while (gAppObj.stats.expectedEtherType_ptp < ETHAPP_NUM_TIME_SYNC_PACKET);

    AppUtils_printf("\r\n ----------------------------\n" );
    AppUtils_printf("\r\n Time Stamping Test Completed \n" );
    AppUtils_printf("\r\n ----------------------------\n" );
}

#endif

#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)
void EthApp_TimeStampGetIngressTime(uint8 ctrlIdx, Eth_DataType *DataPtr)
{
    Eth_TimeStampQualType   timeQual = ETH_INVALID;
    Eth_TimeStampType       timeStamp;
    uint8 *msgtype;
    uint16 *seqid;
    uint16 messageType;

    msgtype = (uint8 *)DataPtr;
    seqid = (uint16 *)( (uint8 *)DataPtr + 30U /* TIME_SYNC_OFFSET_PTP_SEQUENCE_ID */);
    messageType = (uint16) (*msgtype & 0xf);

    Eth_GetIngressTimeStamp(ctrlIdx,
                            DataPtr,
                            &timeQual,
                            &timeStamp );

    AppUtils_printf("\r\n\tPacket Igress MessagType-%35s, SeqID-%5d ",
                           (messageType > 15) ? "Invalid msg type" : msgTypeString[messageType],
                            ntohs(*seqid));
    EthApp_printSysTime(&timeStamp);
    AppUtils_printf("\r [%11s]", timeStampQualString[timeQual]);

}
#endif


static Std_ReturnType EthApp_showStats(uint8 ctrlIdx)
{
    Std_ReturnType retVal;
#if (STD_ON == ETH_GET_DROPCOUNT_API)
    Eth_CounterType ethCounter;
    retVal = Eth_GetCounterValues(ctrlIdx, &ethCounter);
    if (E_OK == retVal)
    {
        AppUtils_printf("\r----------------------------\n");
        AppUtils_printf("\rController %d Counters\n", ctrlIdx);
        AppUtils_printf("\r----------------------------\n");
        AppUtils_printf("\rBuffer overruns   : %d\n", ethCounter.DropPktBufOverrun);
        AppUtils_printf("\rCRC errors        : %d\n", ethCounter.DropPktCrc);
        AppUtils_printf("\rUndersize packets : %d\n", ethCounter.UndersizePkt);
        AppUtils_printf("\rOversized packets : %d\n", ethCounter.OversizePkt);
        AppUtils_printf("\rAlignment errors  : %d\n", ethCounter.AlgnmtErr);;
        AppUtils_printf("\rErroneous inbound : %d\n", ethCounter.ErrInbdPkt);
        AppUtils_printf("\rErroneous outbound: %d\n", ethCounter.ErrOtbdPkt);
        AppUtils_printf("\rSingle collision  : %d\n", ethCounter.SnglCollPkt);
        AppUtils_printf("\rMultiple collision: %d\n", ethCounter.MultCollPkt);
        AppUtils_printf("\rDeferred transm   : %d\n", ethCounter.DfrdPkt);
        AppUtils_printf("\rLate collisions   : %d\n", ethCounter.LatCollPkt);
        AppUtils_printf("\rExcessive colls   : %d\n", ethCounter.HwDepCtr0);
        AppUtils_printf("\rCarrier loss      : %d\n", ethCounter.HwDepCtr1);
    }
    else
    {
        AppUtils_printf("\rshowCountValues: failed to get counters: %d\n", retVal);
    }
#else
    AppUtils_printf("\rshowCountValues: Eth_GetCounterValues() API not enabled\n");
    retVal = E_NOT_OK;
#endif

#if (STD_ON == ETH_GETETHERSTATS_API)
    Eth_RxStatsType rxStats;
    retVal = Eth_GetRxStats(ctrlIdx, &rxStats);
    if (E_OK == retVal)
    {
        AppUtils_printf("\r----------------------------\n");
        AppUtils_printf("\rController %d Rx Statistics\n", ctrlIdx);
        AppUtils_printf("\r----------------------------\n");
        AppUtils_printf("\rRx Drop Events       : %d\n", rxStats.RxStatsDropEvents);
        AppUtils_printf("\rRx Octets            : %d\n", rxStats.RxStatsOctets);
        AppUtils_printf("\rRx Packets           : %d\n", rxStats.RxStatsPkts);
        AppUtils_printf("\rRx Bcast Packets     : %d\n", rxStats.RxStatsBroadcastPkts);
        AppUtils_printf("\rRx Mcast Packets     : %d\n", rxStats.RxStatsMulticastPkts);
        AppUtils_printf("\rRx CRC/Align Errors  : %d\n", rxStats.RxStatsCrcAlignErrors);
        AppUtils_printf("\rRx Undersized Packets: %d\n", rxStats.RxStatsUndersizePkts);
        AppUtils_printf("\rRx Oversized Packets : %d\n", rxStats.RxStatsOversizePkts);
        AppUtils_printf("\rRx Fragments         : %d\n", rxStats.RxStatsFragments);
        AppUtils_printf("\rRx Jabbers           : %d\n", rxStats.RxStatsJabbers);
        AppUtils_printf("\rRx Unicast Packets            : %d\n", rxStats.RxUnicastFrames);
    }
    else
    {
        AppUtils_printf("\rgetRxStats: failed to get counters: %d\n", retVal);
    }
#else
    AppUtils_printf("getRxStats: Eth_GetRxStats() API not enabled\n");
    retVal = E_NOT_OK;
#endif

#if (STD_ON == ETH_GETTX_STATS_API)
    Eth_TxStatsType txStats;
    retVal = Eth_GetTxStats(ctrlIdx, &txStats);
    if (E_OK == retVal)
    {
        AppUtils_printf("\r----------------------------\n");
        AppUtils_printf("\rController %d Tx Statistics \n", ctrlIdx);
        AppUtils_printf("\r----------------------------\n");
        AppUtils_printf("\rTx Num octets          : %d\n", txStats.TxNumberOfOctets);
        AppUtils_printf("\rTx No Unicast Packets  : %d\n", txStats.TxNUcastPkts);
        AppUtils_printf("\rTx Unicast Packets     : %d\n", txStats.TxUniCastPkts);
    }
    else
    {
        AppUtils_printf("\rgetTxStats: failed to get TX stats: %d\n", retVal);
    }
#else
    AppUtils_printf("g\retTxStats: Eth_GetTxStats() API not enabled\n");
    retVal = E_NOT_OK;
#endif

#if (STD_ON == ETH_GETTXERROR_COUNTERVALUES_API)
    Eth_TxErrorCounterValuesType txErrorCounterValues;
    retVal = Eth_GetTxErrorCounterValues(ctrlIdx, &txErrorCounterValues);
    if (E_OK == retVal)
    {
        AppUtils_printf("\r--------------------------------\n");
        AppUtils_printf("\rController %d Tx Error Counters \n", ctrlIdx);
        AppUtils_printf("\r--------------------------------\n");
        AppUtils_printf("\rTx Deferred transm      : %d\n", txErrorCounterValues.TxDeferredTrans);
        AppUtils_printf("\rTx Single collisions    : %d\n", txErrorCounterValues.TxSingleCollision);
        AppUtils_printf("\rTx Multiple collisions  : %d\n", txErrorCounterValues.TxMultipleCollision);
        AppUtils_printf("\rTx Late collisions      : %d\n", txErrorCounterValues.TxLateCollision);
        AppUtils_printf("\rTx Excessive collisions : %d\n", txErrorCounterValues.TxExcessiveCollison);
    }
    else
    {
        AppUtils_printf("\rshowTxErrStatsCount: failed to get counters: %d\n", retVal);
    }
#else
    AppUtils_printf("\rshowTxErrStatsCount: Eth_GetTxErrorCounterValues() API not enabled\n");
    retVal = E_NOT_OK;
#endif


    return retVal;
}

/* =========================Function separator========================= */
void EthIf_RxIndication(uint8         ctrlIdx,
                        Eth_FrameType FrameType,
                        boolean       IsBroadcast,
                        uint8        *PhysAddrPtr,
                        Eth_DataType *DataPtr,
                        uint16        lenByte)
{

    /* This flag would be used by app to ack ping request  */
    gAppObj.frameRcvdFlag = TRUE;
    gAppObj.currFrameDataPtr = DataPtr;
    gAppObj.currFrameSize = lenByte;

    (void) memcpy(gAppObj.currFramePhysAddr, PhysAddrPtr, (size_t) ETH_MAC_ADDR_LEN);

    i2++;
    /* Increase Rx frame count */
    gAppObj.stats.recvPacketCnt++;

    if (gAppObj.checkPackets)
    {
        /* Save the callback configuration info to the channel structure*/
        if (FrameType == ETHAPP_ETHERTYPE_IPV4)
        {
            gAppObj.stats.expectedEtherType_ipv4++;
        }
        else if (FrameType == ETHAPP_ETHERTYPE_VLAN)
        {
#if (ETH_GLOBALTIMESUPPORT_API == STD_ON) && (ETHAPP_TIMESTAMP_TEST == STD_ON)
            uint16* ethTypePtr = (uint16*)DataPtr + 1;
            if ( ntohs(*ethTypePtr) == ETHAPP_ETHERTYPE_PTP1588)
            {
                /* Single tagged PTP */
                gAppObj.stats.expectedEtherType_ptp++;
                EthApp_TimeStampGetIngressTime(ctrlIdx, (Eth_DataType *)((uint8*)DataPtr + 4U) );
            }
            else if ( ntohs(*ethTypePtr) == ETHAPP_ETHERTYPE_VLAN)
            {
                /* Doubly tagged PTP */
                ethTypePtr = (uint16*)DataPtr + 3;
                if ( ntohs(*ethTypePtr) == ETHAPP_ETHERTYPE_PTP1588)
                {
                    /* Single tagged PTP */
                    gAppObj.stats.expectedEtherType_ptp++;
                    EthApp_TimeStampGetIngressTime(ctrlIdx,
                                                  (Eth_DataType *)((uint8*)DataPtr + 8U));
                }
                else
                {
                    gAppObj.stats.expectedEtherType_stackedvlan++;
                }
            }
            else
#endif
            {
                gAppObj.stats.expectedEtherType_vlan++;
            }
        }
#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)
        else if (FrameType == ETHAPP_ETHERTYPE_PTP1588)
        {
            gAppObj.stats.expectedEtherType_ptp++;
            EthApp_TimeStampGetIngressTime(ctrlIdx, DataPtr);
        }
#endif
        else
        {
            gAppObj.stats.errorCnt++;
            gAppObj.stats.unexpectedEtherType++;
        }
    }

#if (1U == ENABLE_PACKET_CPU_COPY)
    memcpy((void *)&_gDstBuff, DataPtr, lenByte);
#endif

    MainFunc_Execution = 5U;
}

void EthIf_TxConfirmation(uint8          ctrlIdx,
                          Eth_BufIdxType bufIdx)
{
    /* Increase Rx frame count */
    gAppObj.stats.txConfirmPacketCnt++;

#if  (ETH_GLOBALTIMESUPPORT_API == STD_ON)
    if (gTimeStampEnabled[bufIdx] == TRUE)
    {
        Eth_TimeStampQualType   timeQual = ETH_INVALID;
        Eth_TimeStampType       timeStamp;

        Eth_GetEgressTimeStamp(ctrlIdx, bufIdx, &timeQual, &timeStamp);

        AppUtils_printf("\r\n\tPacket Egress TS:");
        EthApp_printSysTime(&timeStamp);
        AppUtils_printf("[%11s]", timeStampQualString[timeQual]);

        gTimeStampEnabled[bufIdx] = FALSE;
    }
#endif

    i2++;
    MainFunc_Execution = 4U;
}

#if	(ETHAPP_THROUGHPUT_TEST == STD_ON)
static void Start_Timer(void)
{

	HW_WR_REG32(0x52180000, 0x00000000);//GCTRL
	HW_WR_REG32(0x52180008, 0x00000000);//Capture Control
	HW_WR_REG32(0x5218000C, 0x00000000);//COMP CTRL
	HW_WR_REG32(0x52180010, 0x00000000);//FRC0
	HW_WR_REG32(0x52180014, 0x00000000);//UP Counter
	HW_WR_REG32(0x52180018, 0x00000001);//Compare Up Counter
	HW_WR_REG32(0x52180084, 0x00070F0F);//Clear Interrupt
	HW_WR_REG32(0x52180000, 0x00000001);//GCTRL Start Timer

}

static void Stop_Timer(uint8 Api_Id)
{
	HW_WR_REG32(0x52180000, 0x00000000);//GCTRL Stop Timer
    frc = HW_RD_REG32(0x52180010);
	Performance_Result[Api_Id] = frc;
}

static void EthExample_PerformanceTest()
{
Std_VersionInfoType versioninfo;
	
Eth_ConfigType     *pEthConfigPtr;
pEthConfigPtr = &EthConfigSet_EthCtrlConfig_0;

EthTrcv_ConfigType *ethTrcvConfigPtr;
ethTrcvConfigPtr = &EthTrcvConfigSet_EthTrcvConfig_0;

EthTrcv_ModeType       trcvMode;
EthTrcv_LinkStateType  linkState;
EthTrcv_BaudRateType   baudRate;
EthTrcv_DuplexModeType duplexMode;
EthTrcv_CableDiagResultType ResultPtr;
uint32 OrgUniqueIdPtr;
uint8 ModelNrPtr;
uint8 RevisionNrPtr;
Eth_FrameType       frameType = 0x0800; 
boolean             txConfirmation= TRUE;

Eth_BufIdxType bufIdx;
uint8 *bufPtr;
uint16 lenByte;
Eth_RxStatusType    rxStatus;
uint16 RegValPtr = 0U;
Eth_DataType *DataPtr;

Eth_CounterType ethCounter;
Eth_RxStatsType rxStats;
Eth_TxStatsType txStats;
Eth_TxErrorCounterValuesType txErrorCounterValues;
Eth_TimeStampQualType timeQual;
Eth_TimeStampType timeStamp = {0,0,0};

#if (ETH_VERSION_INFO_API == STD_ON)	
Start_Timer();	
Eth_GetVersionInfo(&versioninfo);
Stop_Timer(0U);
#endif

Start_Timer();	
Eth_Init(pEthConfigPtr);
Stop_Timer(1U);

Start_Timer();
EthTrcv_Init(ethTrcvConfigPtr);
Stop_Timer(2U);

#if (STD_ON == ETHTRCV_VERSION_INFO_API)
Start_Timer();
EthTrcv_GetVersionInfo(&versioninfo);
Stop_Timer(3U);
#endif 
#if (STD_ON == ETHTRCV_SETTRANSCEIVERMODE_API)
Start_Timer();
EthTrcv_SetTransceiverMode(ethTrcvConfigPtr->trcvIdx,
                                        ETHTRCV_MODE_ACTIVE);
Stop_Timer(4U);
#endif 
#if (STD_ON == ETHTRCV_GETTRANSCEIVERMODE_API)
Start_Timer();
EthTrcv_GetTransceiverMode(ethTrcvConfigPtr->trcvIdx, &trcvMode);
Stop_Timer(5U);
#endif 
#if (STD_ON == ETHTRCV_STARTAUTONEGOTIATION_API)
Start_Timer();
EthTrcv_StartAutoNegotiation (ethTrcvConfigPtr->trcvIdx);
Stop_Timer(6U);
#endif 

#if (STD_ON == ETHTRCV_GETLINKSTATE_API)
Start_Timer();
EthTrcv_GetLinkState(ethTrcvConfigPtr->trcvIdx, &linkState);
Stop_Timer(7U);
#endif 
#if (STD_ON == ETHTRCV_GETBAUDRATE_API)
Start_Timer();
EthTrcv_GetBaudRate(ethTrcvConfigPtr->trcvIdx, &baudRate);
Stop_Timer(8U);
#endif 
#if (STD_ON == ETHTRCV_GETDUPLEXMODE_API)
Start_Timer();
EthTrcv_GetDuplexMode(ethTrcvConfigPtr->trcvIdx, &duplexMode);
Stop_Timer(9U);
#endif 

Start_Timer();
EthTrcv_SetPhyLoopbackMode(ethTrcvConfigPtr->trcvIdx, ETHTRCV_PHYLOOPBACK_NONE);
Stop_Timer(10U);

#if (STD_ON == ETHTRCV_SETPHYTXMODE_API)
Start_Timer();
EthTrcv_SetPhyTxMode(ethTrcvConfigPtr->trcvIdx, ETHTRCV_PHYTXMODE_NORMAL);
Stop_Timer(11U);
#endif 

#if (STD_ON == ETHTRCV_GETCABLEDIAGNOSTICSRESULT_API)
Start_Timer();
EthTrcv_GetCableDiagnosticsResult(ethTrcvConfigPtr->trcvIdx, &ResultPtr);
Stop_Timer(12U);
#endif 
#if (STD_ON == ETHTRCV_GETPHYIDENTIFIER_API)
Start_Timer();
EthTrcv_GetPhyIdentifier(ethTrcvConfigPtr->trcvIdx, &OrgUniqueIdPtr, 
                                       &ModelNrPtr, &RevisionNrPtr );
Stop_Timer(13U);
#endif 

Start_Timer();
EthTrcv_MainFunction();
Stop_Timer(14U);

Start_Timer();
EthTrcv_SetPhyTestMode(ethTrcvConfigPtr->trcvIdx, ETHTRCV_PHYTESTMODE_NONE);
Stop_Timer(15U);

Start_Timer();
Eth_SetControllerMode(pEthConfigPtr->ctrlIdx,ETH_MODE_ACTIVE);
Stop_Timer(16U);

Start_Timer();
Eth_GetControllerMode(pEthConfigPtr->ctrlIdx,CtrlModePtr);
Stop_Timer(17U);

Start_Timer();
Eth_SetPhysAddr(pEthConfigPtr->ctrlIdx,gTestMacAddr);
Stop_Timer(18U);

Start_Timer();
Eth_GetPhysAddr(pEthConfigPtr->ctrlIdx,PhysAddrPtr);
Stop_Timer(19U);

Start_Timer();
Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,gBCstMacAddr,ETH_ADD_TO_FILTER);
Stop_Timer(20U);

Start_Timer();
Eth_ProvideTxBuffer(pEthConfigPtr->ctrlIdx, 0, &bufIdx, &bufPtr, &lenByte);
Stop_Timer(21U);

Start_Timer();
Eth_Transmit(pEthConfigPtr->ctrlIdx,bufIdx,frameType,txConfirmation,lenByte,
                                                              gBCstMacAddr);
Stop_Timer(22U);

Start_Timer();
Eth_TxConfirmation(pEthConfigPtr->ctrlIdx);
Stop_Timer(23U);

Start_Timer();
Eth_Receive(pEthConfigPtr->ctrlIdx, 0, &rxStatus);
Stop_Timer(24U);

#if (ETH_ENABLE_MII_API == STD_ON)
Start_Timer();
Eth_WriteMii(pEthConfigPtr->ctrlIdx, 0, 0, 0x10);
Stop_Timer(25U);

Start_Timer();
Eth_ReadMii(pEthConfigPtr->ctrlIdx, 0, 0, &RegValPtr);
Stop_Timer(26U);
#endif

#if(ETH_GET_DROPCOUNT_API==STD_ON)
Start_Timer();
Eth_GetCounterValues(pEthConfigPtr->ctrlIdx, &ethCounter);
Stop_Timer(27U);
#endif
#if (ETH_GETETHERSTATS_API == STD_ON)
Start_Timer();
Eth_GetRxStats(pEthConfigPtr->ctrlIdx, &rxStats);
Stop_Timer(28U);
#endif
#if(ETH_GETTX_STATS_API==STD_ON)
Start_Timer();
Eth_GetTxStats(pEthConfigPtr->ctrlIdx, &txStats);
Stop_Timer(29U);
#endif
#if(ETH_GETTXERROR_COUNTERVALUES_API==STD_ON)
Start_Timer();
Eth_GetTxErrorCounterValues(pEthConfigPtr->ctrlIdx, &txErrorCounterValues);
Stop_Timer(30U);
#endif
#if(ETH_GLOBALTIMESUPPORT_API==STD_ON)
Start_Timer();
Eth_GetCurrentTime(pEthConfigPtr->ctrlIdx, &timeQual, &timeStamp);
Stop_Timer(31U);

Start_Timer();
Eth_EnableEgressTimeStamp(pEthConfigPtr->ctrlIdx, bufIdx);
Stop_Timer(32U);

Start_Timer();
Eth_GetEgressTimeStamp(pEthConfigPtr->ctrlIdx, bufIdx, &timeQual, &timeStamp);
Stop_Timer(33U);

Start_Timer();
Eth_GetIngressTimeStamp(pEthConfigPtr->ctrlIdx, DataPtr,&timeQual, &timeStamp );
Stop_Timer(34U);
#endif

Start_Timer();
Eth_MainFunction();
Stop_Timer(35U);

}
#endif


#if (STD_ON == ETHAPP_FILTER_TEST) && (STD_ON == ETH_UPDATE_PHYS_ADDR_FILTER_API)

static void EthApp_FilterTest(Eth_ConfigType *pEthConfigPtr)
{
    Std_ReturnType      retVal    = (Std_ReturnType) E_NOT_OK;
    uint32 i;

    for (i = 0U; i < ETH_MAC_ADDR_LEN; i++)
    {
        gTestMacAddr[i] = (i + 10);
    }

    AppUtils_printf("\n\rAdding MAC Address to filter:");
    EthApp_printMACAddr(gTestMacAddr);

    retVal = Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,
                                       gTestMacAddr,
                                       ETH_ADD_TO_FILTER);

    AppUtils_printf("\n\rWaiting to receive %d packets from PC packet player..\n", ETHAPP_NUM_RECEIVE_PACKET_FILTER);
    AppUtils_printf("\n\rSend packets with destination MAC address:");
    EthApp_printMACAddr(gTestMacAddr);

    while(gAppObj.stats.recvPacketCnt < ETHAPP_NUM_RECEIVE_PACKET_FILTER);
    gAppObj.stats.recvPacketCnt = 0;
    AppUtils_printf("\n\rRemoving MAC Address from filter:");
    EthApp_printMACAddr(gTestMacAddr);
    retVal += Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,
                                       gTestMacAddr,
                                       ETH_REMOVE_FROM_FILTER);


    AppUtils_printf("\n\rMulticast address filter test \n");
    /* Change mac address to multicast address */
    gTestMacAddr[0] = 0x01;gTestMacAddr[1] = 0x00;gTestMacAddr[2] = 0x5E;
    AppUtils_printf("\n\r Adding multicast MAC Address to filter:");
    EthApp_printMACAddr(gTestMacAddr);
    retVal += Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,
                                       gTestMacAddr,
                                       ETH_ADD_TO_FILTER);

    AppUtils_printf("\n\rWaiting to receive %d packets from PC packet player..\n", ETHAPP_NUM_RECEIVE_PACKET_FILTER);
    AppUtils_printf("\n\r Send packets with destination MAC address:");
    EthApp_printMACAddr(gTestMacAddr);

    while(gAppObj.stats.recvPacketCnt < ETHAPP_NUM_RECEIVE_PACKET_FILTER);
    gAppObj.stats.recvPacketCnt = 0u;

    AppUtils_printf("\n\r Removing MAC Address from filter:");
    EthApp_printMACAddr(gTestMacAddr);

    retVal += Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,
                                       gTestMacAddr,
                                       ETH_REMOVE_FROM_FILTER);

    AppUtils_printf("\n\rOpening up filter completely (ALE bypass)\n");
    retVal += Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,
                                       gBCstMacAddr,
                                       ETH_ADD_TO_FILTER);

    AppUtils_printf("\n\rWaiting to receive %d packets from PC packet player..\n", ETHAPP_NUM_RECEIVE_PACKET_FILTER);
    AppUtils_printf("\n\rSend packets with any MAC address\n");

    while(gAppObj.stats.recvPacketCnt < ETHAPP_NUM_RECEIVE_PACKET_FILTER);
    gAppObj.stats.recvPacketCnt = 0u;

    AppUtils_printf("\n\rALE Bypass Transmit Test\n");
    AppUtils_printf("\n\rTransmitting %d packets ", ETHAPP_NUM_TRANSMIT_PACKET );
    AppUtils_printf("\n\rExpect PC Wireshark to receive %d packets..",
                                ETHAPP_NUM_TRANSMIT_PACKET);
    EthExample_TransmitStress();

    AppUtils_printf("\n\rDisabling filter bypass & adding host address back to filter \n");
    /* Send 00:00:00:00:00:00 as MAC address to reuse earlier Controller MAC address */
    for (i = 0U; i < ETH_MAC_ADDR_LEN; i++)
    {
        gTestMacAddr[i] = 0U;
    }
    retVal += Eth_UpdatePhysAddrFilter(pEthConfigPtr->ctrlIdx,
                                       gTestMacAddr,
                                       ETH_ADD_TO_FILTER);

    AppUtils_printf("\n\rWaiting to receive %d packets from PC packet player..\n", ETHAPP_NUM_RECEIVE_PACKET_FILTER);
    AppUtils_printf("\n\rSend packets with Controller MAC address\n");
    while(gAppObj.stats.recvPacketCnt < ETHAPP_NUM_RECEIVE_PACKET_FILTER);
    gAppObj.stats.recvPacketCnt = 0u;

    if ((Std_ReturnType) E_OK != retVal)
    {
        FAIL_MESSAGE;
        gTestPassed = E_NOT_OK;
    }
}
#endif
