/* ======================================================================
 *   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     Eth.c
 *
 *  \brief    This file contains ETH MCAL driver
 *
 */

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


#include "Eth.h"
#include "Eth_Cfg.h"
#include "EthIf_Cbk.h"
#if (STD_ON == ETH_DEV_ERROR_DETECT)
#include "Det.h"
#endif
#include "Dem.h"
#include "Os.h"
#include "SchM_Eth.h"


#include "string.h"
#include "Std_Types.h"
#include "soc.h"

/* There are static inline functions in hw_types.h file. Map them as well */
#define ETH_START_SEC_CODE
/* MISRAC_2012_R.20.1
  * "Reason - This is the format to use for specifying memory sections " */
#include "Eth_MemMap.h"
#include "hw_types.h"
#define ETH_STOP_SEC_CODE
/* MISRAC_2012_R.20.1
  * "Reason - This is the format to use for specifying memory sections " */
#include "Eth_MemMap.h"

#include "cpsw_ale.h"
#include "Eth_Priv.h"
#include "cpsw.h"
#include "cpsw_mdio.h"
#include "cpsw_priv.h"
#include "cpsw_stats.h"
/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/* AUTOSAR version information check has to match definition in header file */
#if ((ETH_AR_RELEASE_MAJOR_VERSION != (4U)) || \
    (ETH_AR_RELEASE_MINOR_VERSION != (3U)) ||  \
    (ETH_AR_RELEASE_REVISION_VERSION != (1U)))
    #error "Eth: AUTOSAR Version Numbers of Eth are different!!"
#endif

/* AUTOSAR version information check has to match definition in header file */
#if ((ETH_SW_MAJOR_VERSION != (0U)) || \
    (ETH_SW_MINOR_VERSION != (9U)) ||  \
    (ETH_SW_PATCH_VERSION != (0U)))
    #error "Eth: Software Version Numbers are inconsistent!!"
#endif

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

/* None */

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

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

#define ETH_START_SEC_VAR_INIT_UNSPECIFIED
/* MISRAC_2012_R.20.1
  * "Reason - This is the format to use for specifying memory sections " */
#include "Eth_MemMap.h"
/** \brief ETH driver status */
/* Requirements : SWS_Eth_00159 */
    volatile VAR(Eth_StateType, ETH_VAR_ZERO_INIT)
        gEthDrvStatus = ETH_STATE_UNINIT;
#define ETH_STOP_SEC_VAR_INIT_UNSPECIFIED
/* MISRAC_2012_R.20.1
  * "Reason - This is the format to use for specifying memory sections " */
#include "Eth_MemMap.h"

#if (STD_ON == ETH_DEV_ERROR_DETECT)
    uint32 ctrlIdx1 = ETH_CONTROLLER_ID_0_PORT_1;
#endif  /* STD_ON == ETH_DEV_ERROR_DETECT */

#define ETH_START_SEC_CODE
/* MISRAC_2012_R.20.1
  * "Reason - This is the format to use for specifying memory sections " */
#include "Eth_MemMap.h"

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

#if (ETH_VERSION_INFO_API == STD_ON)
/******************************************************************************
 * Eth_GetVersionInfo
 ******************************************************************************/
/** \brief      This function will return the version for this module.
 *
 *  \param[in]  None
 *
 *  \param[out] Std_VersionInfoType VersionInfo - the structure that will
 *              contain version info after fxn call.
 *
 *  \context    App
 ******************************************************************************/
FUNC(void, ETH_CODE) Eth_GetVersionInfo
            (P2VAR(Std_VersionInfoType, AUTOMATIC, ETH_APPL_DATA) VersionInfo)
{
#if (ETH_DEV_ERROR_DETECT == STD_ON)
    if (NULL_PTR == VersionInfo)
    {
        (void) Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                               ETH_SID_GET_VERSION_INFO,
                               ETH_E_PARAM_POINTER);
    }
    else
#endif
    {
        VersionInfo->vendorID         =  ETH_VENDOR_ID;
        VersionInfo->moduleID         =  ETH_MODULE_ID;
        VersionInfo->sw_major_version =  ETH_SW_MAJOR_VERSION;
        VersionInfo->sw_minor_version =  ETH_SW_MINOR_VERSION;
        VersionInfo->sw_patch_version =  ETH_SW_PATCH_VERSION;
    }
}
#endif


FUNC(void, ETH_CODE) Eth_Init(
                   P2CONST(Eth_ConfigType, AUTOMATIC,ETH_APPL_DATA) CfgPtr)
{

    const Eth_ConfigType *ConfigPtr =CfgPtr;
    VAR(Std_ReturnType, AUTOMATIC) RetValue=E_OK;
    

if(gEthDrvStatus == ETH_STATE_UNINIT){
  #ifdef ETH_VARIANT_PRE_COMPILE
    if (NULL_PTR == ConfigPtr)
    {
        ConfigPtr = (const Eth_ConfigType *) &EthConfigSet_EthCtrlConfig_0;
    }
  #endif/* (STD_ON == ETH_PRE_COMPILE_VARIANT) */
  
  #ifdef ETH_VARIANT_LINK_TIME
    if (NULL_PTR == ConfigPtr)
    {
        ConfigPtr = (const Eth_ConfigType *) &EthConfigSet_EthCtrlConfig_0;
    }
  #endif/* (STD_ON == ETH_VARIANT_LINK_TIME) */

#if (STD_ON == ETH_DEV_ERROR_DETECT)
#ifdef ETH_VARIANT_POST_BUILD
    if (NULL_PTR == ConfigPtr)
    {
        (void) Det_ReportError(
            ETH_MODULE_ID,
            ETH_INSTANCE_ID,
            ETH_SID_INIT,
            ETH_E_PARAM_POINTER);
        RetValue = E_NOT_OK;
    }
	else
#endif
    {
        if (ETH_CONTROLLER_ID_0_PORT_0 != ConfigPtr->ctrlIdx)
        {
        (void) Det_ReportError(
            ETH_MODULE_ID,
            ETH_INSTANCE_ID,
            ETH_SID_INIT,
            ETH_E_INV_PARAM);
        RetValue = E_NOT_OK;
        }
	}
#endif  /* STD_ON == ETH_DEV_ERROR_DETECT */
    if ((uint32) TRUE == CPSWCheckHostErr(gEthDrvObj.baseAddr))
    {
            RetValue = E_NOT_OK;
    }
    else if(RetValue == E_OK)
    {
			Eth_HwInit(ConfigPtr);
            /* Change driver state to initialized */
            gEthDrvStatus = ETH_STATE_INIT;
    }
    else{
        /* Eth Driver not initialized*/
        }
    }
    else
     {
        /*Driver already Initialized*/
     }

}


FUNC(Std_ReturnType,ETH_CODE) Eth_SetControllerMode (
                                        VAR(uint8, AUTOMATIC) CtrlIdx,
                                        VAR(Eth_ModeType, AUTOMATIC) CtrlMode)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal = E_OK;

#if (ETH_DEV_ERROR_DETECT == STD_ON)
  if(gEthDrvStatus == ETH_STATE_UNINIT){
        (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                              ETH_SID_SET_CONTROLLER_MODE,ETH_E_UNINIT);
        RetVal = E_NOT_OK;
  }

  else if (CtrlIdx != ETH_CONTROLLER_ID_0_PORT_0)
      {
    (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
	                      ETH_SID_SET_CONTROLLER_MODE,ETH_E_INV_CTRL_IDX);
    RetVal = E_NOT_OK;
  }
  else
#endif
  {
    if ((uint32) TRUE == CPSWCheckHostErr(gEthDrvObj.baseAddr))
    {
            RetVal = E_NOT_OK;
    }
	else{
         RetVal = Eth_HwSetControllerMode(CtrlIdx,CtrlMode);
	}
  }
    /* Return Status */
  return(RetVal);
}

FUNC(Std_ReturnType, ETH_CODE) Eth_GetControllerMode(
                     VAR(uint8, AUTOMATIC) CtrlIdx,
                     P2VAR(Eth_ModeType, AUTOMATIC,ETH_APPL_DATA) CtrlModePtr)
{
    VAR(Std_ReturnType, AUTOMATIC) RetVal=E_OK;
	
  #if (ETH_DEV_ERROR_DETECT == STD_ON)
        if(gEthDrvStatus == ETH_STATE_UNINIT){
      (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                            ETH_SID_GET_CONTROLLER_MODE,ETH_E_UNINIT);
      RetVal = E_NOT_OK;
  }
   else if (ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx)
   {
      (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                            ETH_SID_GET_CONTROLLER_MODE,ETH_E_INV_CTRL_IDX);
      RetVal = E_NOT_OK;
  }
  else if(CtrlModePtr == NULL_PTR){
        (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                              ETH_SID_GET_CONTROLLER_MODE,ETH_E_PARAM_POINTER);
        RetVal = E_NOT_OK;
   }
   else
  #endif
   {
            *CtrlModePtr = gEthDrvObj.ctrlMode;
   }
     /* Return Status */
  return(RetVal);
}


FUNC(void, ETH_CODE) Eth_GetPhysAddr(
                     VAR(uint8, AUTOMATIC) CtrlIdx,
                     P2VAR(uint8, AUTOMATIC,ETH_APPL_DATA) PhysAddrPtr)
{
    Eth_PortConfigType *pPortCfg = NULL_PTR;
	
 #if (ETH_DEV_ERROR_DETECT == STD_ON)
    /* Return if a development error occured */
    if(gEthDrvStatus == ETH_STATE_UNINIT)
	{
      (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                            ETH_SID_GET_PHYS_ADDR,ETH_E_UNINIT);
    }
    else if (ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx)
    {
     (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                           ETH_SID_GET_PHYS_ADDR,ETH_E_INV_CTRL_IDX);
    }
    else if(PhysAddrPtr == NULL_PTR)
	{
     (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID, 
	                       ETH_SID_GET_PHYS_ADDR,ETH_E_PARAM_POINTER);
    }
     else
  #endif
    {
            /* Each port is considered as one controller */
            pPortCfg = &(gEthDrvObj.portObj.portCfg);

            /* Copy MAC address into PhysAddrPtr variable */
            (void) memcpy(PhysAddrPtr,
                          (void *) &pPortCfg->macCfg.macAddr[0U],
                          ETH_MAC_ADDR_LEN);

    }
}


FUNC(void, ETH_CODE) Eth_SetPhysAddr(VAR(uint8, AUTOMATIC) CtrlIdx,
                            P2CONST(uint8, AUTOMATIC,ETH_APPL_DATA) PhysAddrPtr)
{

    #if (ETH_DEV_ERROR_DETECT == STD_ON)
        /* Return if a development error occured */
    if(gEthDrvStatus == ETH_STATE_UNINIT)
	{
       (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                             ETH_SID_SET_PHYS_ADDR,ETH_E_UNINIT);
    }
    else if (ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx)
    {
       (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                             ETH_SID_SET_PHYS_ADDR,ETH_E_INV_CTRL_IDX);
    }
    else if(PhysAddrPtr == NULL_PTR)
	{
        (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                               ETH_SID_SET_PHYS_ADDR,ETH_E_PARAM_POINTER);
    }
    else
    #endif /* (ETH_DEV_ERROR_DETECT == STD_ON) */
    {
         Eth_HwSetPhysAddr(CtrlIdx,PhysAddrPtr);
    }
}


FUNC(Std_ReturnType, ETH_CODE)
Eth_UpdatePhysAddrFilter(uint8 CtrlIdx,
                         P2VAR(uint8, AUTOMATIC, ETH_APPL_DATA) PhysAddrPtr,
                         Eth_FilterActionType Action)
{
   VAR(Std_ReturnType, AUTOMATIC) RetValue = E_OK;
   
#if (ETH_DEV_ERROR_DETECT == STD_ON)
       /* Return if a development error occured */
   if(gEthDrvStatus == ETH_STATE_UNINIT)
   {
      (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                            ETH_SID_UPDATE_PHYS_ADDR_FILTER,ETH_E_UNINIT);
       RetValue = E_NOT_OK;
   }
   else if (ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx)
   {
      (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                            ETH_SID_UPDATE_PHYS_ADDR_FILTER,ETH_E_INV_CTRL_IDX);
      RetValue = E_NOT_OK;
    }

   else if(PhysAddrPtr == NULL_PTR){
        (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                              ETH_SID_UPDATE_PHYS_ADDR_FILTER,
							  ETH_E_PARAM_POINTER);
        RetValue = E_NOT_OK;
        }
   else
    #endif /* (ETH_DEV_ERROR_DETECT == STD_ON) */
    {
        RetValue = Eth_HwUpdatePhysAddrFilter(CtrlIdx,PhysAddrPtr,Action);
    }
   /* Return Status */
  return(RetValue);

}

FUNC(BufReq_ReturnType, ETH_CODE) Eth_ProvideTxBuffer(
                        VAR(uint8, AUTOMATIC)CtrlIdx,
                        VAR(uint8, AUTOMATIC)Priority,
                        P2VAR(Eth_BufIdxType,AUTOMATIC,ETH_APPL_DATA)BufIdxPtr,
                        P2VAR(uint8,AUTOMATIC,ETH_APPL_DATA)*BufPtr,
                        P2VAR(uint16,AUTOMATIC,ETH_APPL_DATA)LenBytePtr)
{
     VAR(BufReq_ReturnType, AUTOMATIC) RetValue = BUFREQ_E_NOT_OK;
	 
    #if (ETH_DEV_ERROR_DETECT == STD_ON)
         /*  ETH_NOT_INITIALIZED */
        if(gEthDrvStatus == ETH_STATE_UNINIT){
            (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                  ETH_SID_PROVIDE_TX_BUFFER,ETH_E_UNINIT);
        }
        else if (ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
            (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                                  ETH_SID_PROVIDE_TX_BUFFER,ETH_E_INV_CTRL_IDX);
        }
        else if (BufIdxPtr == NULL_PTR){
            (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                 ETH_SID_PROVIDE_TX_BUFFER,ETH_E_PARAM_POINTER);
            /* ETH_INV_POINTER */
        }
        else if (BufPtr == NULL_PTR){
            (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                 ETH_SID_PROVIDE_TX_BUFFER,ETH_E_PARAM_POINTER);
            /* ETH_INV_POINTER */
        }
        else if (LenBytePtr == NULL_PTR){
            (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                 ETH_SID_PROVIDE_TX_BUFFER,ETH_E_PARAM_POINTER);
            /* ETH_INV_POINTER */
        }
        /* Return if a development error occurred */
       else
  #endif /* (ETH_DEV_ERROR_DETECT == STD_ON) */
        {
           RetValue = Eth_HwProvideTxBuffer(
                   CtrlIdx,0U,BufIdxPtr,
                    BufPtr,LenBytePtr);
        }
         /* Return Status */
        return(RetValue);
}

FUNC(Std_ReturnType, ETH_CODE) Eth_Transmit(
                            VAR(uint8, AUTOMATIC) CtrlIdx,
                            VAR(Eth_BufIdxType,AUTOMATIC)BufIdx,
                            VAR(Eth_FrameType,AUTOMATIC) FrameType,
                            VAR(boolean,AUTOMATIC) TxConfirmation,
                            VAR(uint16,AUTOMATIC) LenByte,
                            P2CONST(uint8, AUTOMATIC,ETH_APPL_DATA) PhysAddrPtr)
{
    VAR(Std_ReturnType, AUTOMATIC) RetBufState = E_NOT_OK;
	
    #if (ETH_DEV_ERROR_DETECT == STD_ON)
    /*  ETH_NOT_INITIALIZED */
        if(gEthDrvStatus == ETH_STATE_UNINIT){
               (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                ETH_SID_TRANSMIT,ETH_E_UNINIT);
        }
        else if (ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
               (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                ETH_SID_TRANSMIT,ETH_E_INV_CTRL_IDX);
        }
        else if (BufIdx >= ETH_NUM_TX_BUFFERS) {
               (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
               ETH_SID_TRANSMIT,ETH_E_INV_PARAM);
            }

        else  if(gEthDrvObj.ctrlMode != ETH_MODE_ACTIVE)  {
               (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
               ETH_SID_TRANSMIT,ETH_E_INV_MODE);
        }
        else if (PhysAddrPtr == NULL_PTR){
               (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
               ETH_SID_TRANSMIT,ETH_E_PARAM_POINTER);
        }
        else
   #endif
        {
            RetBufState = Eth_HwTransmit(CtrlIdx,BufIdx,FrameType,
                    TxConfirmation,LenByte,PhysAddrPtr);
        }
     /* Return Status */
  return(RetBufState);
}

FUNC(void, ETH_CODE) Eth_Receive(
                VAR(uint8, AUTOMATIC)CtrlIdx,
                VAR(uint8, AUTOMATIC)FifoIdx,
                P2VAR(Eth_RxStatusType,AUTOMATIC,ETH_APPL_DATA)RxStatusPtr)
{
 #if (ETH_DEV_ERROR_DETECT == STD_ON)
    /*  ETH_NOT_INITIALIZED */
    if(gEthDrvStatus == ETH_STATE_UNINIT){
            (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
             ETH_SID_RECEIVE,ETH_E_UNINIT);
    }
    else if(CtrlIdx !=ETH_CONTROLLER_ID_0_PORT_0){
              (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
              ETH_SID_RECEIVE,ETH_E_INV_CTRL_IDX);
    }
    else if(gEthDrvObj.ctrlMode != ETH_MODE_ACTIVE)  {
              (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
              ETH_SID_RECEIVE,ETH_E_INV_MODE);
    }
    else
#endif
    {
         Eth_HwReceive(CtrlIdx,0U,RxStatusPtr);

    }
}

#if (ETH_ENABLE_MII_API == STD_ON)

FUNC(Std_ReturnType, ETH_CODE) Eth_WriteMii
    (uint8 CtrlIdx, uint8 TrcvIdx, uint8 RegIdx, uint16 RegVal)
{
    Std_ReturnType retVal = E_OK;

#if (STD_ON == ETH_DEV_ERROR_DETECT)
    if(gEthDrvStatus == ETH_STATE_UNINIT)
   {
       (void) Det_ReportError( ETH_MODULE_ID, ETH_INSTANCE_ID,
                               ETH_SID_WRITE_MII,ETH_E_UNINIT);
       retVal = E_NOT_OK;
   }
   else if (ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx)
   {
       (void) Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                              ETH_SID_WRITE_MII, ETH_E_INV_CTRL_IDX);
       retVal = E_NOT_OK;
   }
   else
#endif  /* STD_ON == ETH_DEV_ERROR_DETECT */
    {
            /*
             * Requirements SWS_Eth_00241
             * The function shall call EthTrcv_WriteMiiIndication when the MII
             * access finished.
             */
            CPSWMdioPhyRegWrite(gEthDrvObj.baseAddr, TrcvIdx, RegIdx, RegVal);
            retVal = E_OK;
    }

    return (retVal);
}
#endif /* #if (ETH_ENABLE_MII_API == STD_ON) */


#if (ETH_ENABLE_MII_API == STD_ON)
 FUNC(Std_ReturnType, ETH_CODE) Eth_ReadMii
    (uint8 CtrlIdx,
    uint8 TrcvIdx,
    uint8 RegIdx,
    P2VAR(uint16, AUTOMATIC, ETH_APPL_DATA) RegValPtr)
{
     Std_ReturnType retVal = E_OK;

#if (STD_ON == ETH_DEV_ERROR_DETECT)
     if(gEthDrvStatus == ETH_STATE_UNINIT)
    {
        (void) Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                               ETH_SID_READ_MII, ETH_E_UNINIT);
        retVal = E_NOT_OK;
    }
    else if (ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx)
    {
        (void) Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                               ETH_SID_READ_MII, ETH_E_INV_CTRL_IDX);
        retVal = E_NOT_OK;
    }
    else if (NULL_PTR == RegValPtr)
    {
        (void) Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                               ETH_SID_READ_MII, ETH_E_PARAM_POINTER);
        retVal = E_NOT_OK;
    }
    else
#endif  /* STD_ON == ETH_DEV_ERROR_DETECT */
    {
            /*
             * Requirements: SWS_Eth_00242
             * The function shall call EthTrcv_ReadMiiIndication when the MII
             * access finished.
             */
            CPSWMdioPhyRegRead(gEthDrvObj.baseAddr, TrcvIdx, RegIdx, RegValPtr);
            retVal = E_OK;
    }
    return (retVal);
}
#endif /* #if (ETH_ENABLE_MII_API == STD_ON) */


#if(ETH_GET_DROPCOUNT_API==STD_ON)
 FUNC(Std_ReturnType,ETH_CODE) Eth_GetCounterValues(
                 VAR(uint8, AUTOMATIC)CtrlIdx,
                 P2VAR(Eth_CounterType,AUTOMATIC,ETH_APPL_DATA)CounterPtr)
 {
     VAR(Std_ReturnType, AUTOMATIC) RetValue = E_NOT_OK;
     #if (ETH_DEV_ERROR_DETECT == STD_ON)
       /*  ETH_NOT_INITIALIZED */
               if(gEthDrvStatus == ETH_STATE_UNINIT) {
              (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                    ETH_SID_GET_COUNTER_VALUES,ETH_E_UNINIT);
                  }
               else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
              (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                                ETH_SID_GET_COUNTER_VALUES,ETH_E_INV_CTRL_IDX);
               }
               else if (CounterPtr == NULL_PTR){
             (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                              ETH_SID_GET_COUNTER_VALUES,ETH_E_PARAM_POINTER);
               }
               else
     #endif
               {
                 Eth_HwGetCounterValues(CtrlIdx,CounterPtr);
                 RetValue = E_OK;
               }
          /* Return Status */
       return(RetValue);
     }
#endif /* #if (ETH_GET_DROPCOUNT_API == STD_ON) */


#if (ETH_GETETHERSTATS_API == STD_ON)
FUNC(Std_ReturnType, ETH_CODE_FAST) Eth_GetRxStats(
                          VAR(uint8, AUTOMATIC)CtrlIdx,
                          P2VAR(Eth_RxStatsType,AUTOMATIC,ETH_APPL_DATA)RxStats)
{
    VAR(Std_ReturnType, AUTOMATIC) RetValue=E_NOT_OK;
#if (ETH_DEV_ERROR_DETECT == STD_ON)
    /*  ETH_NOT_INITIALIZED */
    if(gEthDrvStatus == ETH_STATE_UNINIT) {
           (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                 ETH_SID_GET_RX_STATS,ETH_E_UNINIT);
    }
    else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
           (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                                 ETH_SID_GET_RX_STATS,ETH_E_INV_CTRL_IDX);
    }
    else if (RxStats == NULL_PTR){
          (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                ETH_SID_GET_RX_STATS,ETH_E_PARAM_POINTER);
    }
    else
#endif
    {
      Eth_HwGetRxStats(CtrlIdx,RxStats);
      RetValue=E_OK;
    }
     /* Return Status */
  return(RetValue);
}
#endif

#if(ETH_GETTX_STATS_API==STD_ON)
FUNC(Std_ReturnType, ETH_CODE_FAST) Eth_GetTxStats(
                          VAR(uint8, AUTOMATIC)CtrlIdx,
                          P2VAR(Eth_TxStatsType,AUTOMATIC,ETH_APPL_DATA)TxStats)
{
    VAR(Std_ReturnType, AUTOMATIC) RetValue=E_NOT_OK;
#if (ETH_DEV_ERROR_DETECT == STD_ON)
    /*  ETH_NOT_INITIALIZED */
    if(gEthDrvStatus == ETH_STATE_UNINIT) {

           (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                 ETH_SID_GET_TX_STATS,ETH_E_UNINIT);
    }
    else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx ){
           (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                                 ETH_SID_GET_TX_STATS,ETH_E_INV_CTRL_IDX);
    }
    else if (TxStats == NULL_PTR){
          (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                ETH_SID_GET_TX_STATS,ETH_E_PARAM_POINTER);
    }
    else
#endif
    {
      Eth_HwGetTxStats(CtrlIdx,TxStats);
      RetValue=E_OK;
    }
     /* Return Status */
  return(RetValue);
}
#endif

#if(ETH_GETTXERROR_COUNTERVALUES_API==STD_ON)
FUNC(Std_ReturnType, ETH_CODE_FAST) Eth_GetTxErrorCounterValues(
     VAR(uint8, AUTOMATIC)CtrlIdx,
         P2VAR(Eth_TxErrorCounterValuesType,AUTOMATIC,ETH_APPL_DATA)
                                                    TxErrorCounterValues)
{
    VAR(Std_ReturnType, AUTOMATIC) RetValue=E_NOT_OK;
#if (ETH_DEV_ERROR_DETECT == STD_ON)
    /*  ETH_NOT_INITIALIZED */
    if(gEthDrvStatus == ETH_STATE_UNINIT) {
           (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                                ETH_SID_GET_TXERROR_COUNTERVALUES,ETH_E_UNINIT);
    }
    else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx ){
           (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                          ETH_SID_GET_TXERROR_COUNTERVALUES,ETH_E_INV_CTRL_IDX);
    }
    else if (TxErrorCounterValues == NULL_PTR){
          (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                  ETH_SID_GET_TXERROR_COUNTERVALUES,ETH_E_PARAM_POINTER);
    }
    else
#endif
    {
      Eth_HwGetTxErrorCounterValues(CtrlIdx,TxErrorCounterValues);
      RetValue=E_OK;
    }
     /* Return Status */
  return(RetValue);
}
#endif

#if(ETH_GLOBALTIMESUPPORT_API==STD_ON)
FUNC(Std_ReturnType, ETH_CODE) Eth_GetCurrentTime(
            VAR(uint8, AUTOMATIC)CtrlIdx,
            P2VAR(Eth_TimeStampQualType,AUTOMATIC,ETH_APPL_DATA)timeQualPtr,
            P2VAR(Eth_TimeStampType,AUTOMATIC,ETH_APPL_DATA)timeStampPtr)
{
   VAR(Std_ReturnType, AUTOMATIC) retVal = E_NOT_OK;
#if (ETH_DEV_ERROR_DETECT == STD_ON)

 /*  ETH_NOT_INITIALIZED */
    if(gEthDrvStatus == ETH_STATE_UNINIT) {
          (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                  ETH_SID_GET_CURRENT_TIME,ETH_E_UNINIT);
     }

    else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
          (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                  ETH_SID_GET_CURRENT_TIME,ETH_E_INV_CTRL_IDX);
     }
    else if(timeQualPtr == NULL_PTR){
            (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                    ETH_SID_GET_CURRENT_TIME,ETH_E_PARAM_POINTER);
     }
    else if(timeStampPtr == NULL_PTR){
                (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                        ETH_SID_GET_CURRENT_TIME,ETH_E_PARAM_POINTER);
     }
    else
#endif
     {
        uint64 nsec = 0U;
        Eth_CptsStateObj *pCptsStateObj = &(gEthDrvObj.cptsObj);

        memset(timeStampPtr, 0, sizeof (Eth_TimeStampType));
        retVal = Eth_cptsCounterRead( pCptsStateObj, &nsec );

        if ((Std_ReturnType)E_NOT_OK != retVal)
        {
            Eth_cptsGetSysTime(pCptsStateObj, &nsec, timeStampPtr);
            /* Quality information not supported, the value always Valid. */
            *timeQualPtr = ETH_VALID;
        }
     }
	return retVal;
}

FUNC(void, ETH_CODE) Eth_EnableEgressTimeStamp(
                    VAR(uint8, AUTOMATIC)CtrlIdx,
                    VAR(Eth_BufIdxType, AUTOMATIC)BufIdx)
{
  #if (ETH_DEV_ERROR_DETECT == STD_ON)
    /*  ETH_NOT_INITIALIZED */
    if(gEthDrvStatus == ETH_STATE_UNINIT) {
              (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                      ETH_SID_ENABLE_EGRESS_TIMESTAMP,ETH_E_UNINIT);
    }
    else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
              (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                      ETH_SID_ENABLE_EGRESS_TIMESTAMP,ETH_E_INV_CTRL_IDX);
         }

    else
  #endif /* (ETH_DEV_ERROR_DETECT == STD_ON) */
    {
		/*
         * time stamping is always enabled
         */
        Eth_BufObjType *pTempBufObj = 
		                 &(gEthDrvObj.portObj.txBufObjArray[BufIdx]);
        pTempBufObj->enableEgressTimeStamp =  (boolean) TRUE;

    }
}


FUNC(void, ETH_CODE) Eth_GetEgressTimeStamp(
            VAR(uint8, AUTOMATIC)CtrlIdx,
            VAR(Eth_BufIdxType, AUTOMATIC)BufIdx,
            P2VAR(Eth_TimeStampQualType, AUTOMATIC,ETH_APPL_DATA)timeQualPtr,
            P2VAR(Eth_TimeStampType,AUTOMATIC,ETH_APPL_DATA)timeStampPtr)
{
    VAR(Std_ReturnType, AUTOMATIC) RetValue = E_NOT_OK;
    #if (ETH_DEV_ERROR_DETECT == STD_ON)
    /*  ETH_NOT_INITIALIZED */
    if(gEthDrvStatus == ETH_STATE_UNINIT) {
          (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                  ETH_SID_GET_EGRESS_TIMESTAMP,ETH_E_UNINIT);
     }

    else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
          (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                  ETH_SID_GET_EGRESS_TIMESTAMP,ETH_E_INV_CTRL_IDX);
     }
    else if(timeQualPtr == NULL_PTR){
            (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                    ETH_SID_GET_EGRESS_TIMESTAMP,ETH_E_PARAM_POINTER);
     }
    else if(timeStampPtr == NULL_PTR){
                (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                        ETH_SID_GET_EGRESS_TIMESTAMP,ETH_E_PARAM_POINTER);
     }
    else
  #endif
    {
     Eth_HwGetEgressTimeStamp(CtrlIdx,BufIdx,timeQualPtr,timeStampPtr);
    }
}

FUNC(void, ETH_CODE) Eth_GetIngressTimeStamp(
            VAR(uint8, AUTOMATIC)CtrlIdx,
            P2CONST(Eth_DataType,AUTOMATIC,ETH_APPL_DATA)DataPtr,
            P2VAR(Eth_TimeStampQualType,AUTOMATIC,ETH_APPL_DATA)timeQualPtr,
            P2VAR(Eth_TimeStampType ,AUTOMATIC,ETH_APPL_DATA)timeStampPtr)
{
    VAR(Std_ReturnType, AUTOMATIC) RetValue = E_NOT_OK;
#if (ETH_DEV_ERROR_DETECT == STD_ON)
    /*  ETH_NOT_INITIALIZED */
    if(gEthDrvStatus == ETH_STATE_UNINIT) {
          (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                  ETH_SID_GET_INGRESS_TIMESTAMP,ETH_E_UNINIT);
     }
    else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
          (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
                  ETH_SID_GET_INGRESS_TIMESTAMP,ETH_E_INV_CTRL_IDX);
     }
    else if(DataPtr == NULL_PTR){
          (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                  ETH_SID_GET_INGRESS_TIMESTAMP,ETH_E_PARAM_POINTER);
     }
    else if(timeQualPtr == NULL_PTR){
            (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                  ETH_SID_GET_INGRESS_TIMESTAMP,ETH_E_PARAM_POINTER);
     }
    else if(timeStampPtr == NULL_PTR){
                (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                  ETH_SID_GET_INGRESS_TIMESTAMP,ETH_E_PARAM_POINTER);
     }
    else
 #endif
    {
      Eth_HwGetIngressTimeStamp(CtrlIdx,DataPtr,timeQualPtr,timeStampPtr);
    }
}
#endif

FUNC(void, ETH_CODE)Eth_TxConfirmation(VAR(uint8, AUTOMATIC)CtrlIdx)
{
    #if (ETH_DEV_ERROR_DETECT == STD_ON)
        /*  ETH_NOT_INITIALIZED */
        if(gEthDrvStatus == ETH_STATE_UNINIT) {
               (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
                ETH_SID_TX_CONFIRMATION,ETH_E_UNINIT);
              }
       else if(ETH_CONTROLLER_ID_0_PORT_0 != CtrlIdx){
              (void)Det_ReportError(ETH_MODULE_ID,ETH_INSTANCE_ID,
               ETH_SID_TX_CONFIRMATION,ETH_E_INV_CTRL_IDX);
             }
       else  if(gEthDrvObj.ctrlMode != ETH_MODE_ACTIVE)  {
              (void)Det_ReportError(ETH_MODULE_ID, ETH_INSTANCE_ID,
              ETH_SID_TX_CONFIRMATION,ETH_E_INV_MODE);
              }
       else
    #endif
        {
        SchM_Enter_Eth_ETH_EXCLUSIVE_AREA_0();

        /* check all filled transmit buffers for successful transmission */
        EthTxBuffDescProcess(gEthDrvObj.ctrlIdx, 
		                     ETH_CPDMA_DEFAULT_TX_CHANNEL_NUM);

        SchM_Exit_Eth_ETH_EXCLUSIVE_AREA_0();
        }
}



FUNC(void, ETH_CODE_FAST)Eth_MainFunction(void)
{
    Eth_ModeType   ctrlMode;
    Std_ReturnType retVal = E_NOT_OK;

#if (STD_ON == ETH_DEV_ERROR_DETECT)
    if (ETH_STATE_UNINIT == gEthDrvStatus)
    {
        (void) Det_ReportError( ETH_MODULE_ID, ETH_INSTANCE_ID,
                                ETH_SID_MAIN_FUNCTION, ETH_E_UNINIT);
    }
    else
#endif
    {
        retVal = Eth_GetControllerMode(gEthDrvObj.ctrlIdx, &ctrlMode);

        if ( (retVal != (Std_ReturnType) E_NOT_OK) &&
             (ETH_MODE_DOWN != ctrlMode) )
        {
            if ((uint32) TRUE == CPSWCheckHostErr(gEthDrvObj.baseAddr))
            {
                 retVal = E_NOT_OK;
            }
            else
            {
                Eth_HwcheckCtrlrErrors();
                CPSWAleAgeOut(gEthDrvObj.baseAddr);
            }
        }

        if (((uint32) TRUE) == gEthControllerModeChangeFlag)
        {

            if (((Std_ReturnType) E_OK) == retVal)
            {
                if (ETH_MODE_DOWN == ctrlMode)
                {
                    EthIf_CtrlModeIndication(gEthDrvObj.ctrlIdx,
                                             ETH_MODE_DOWN);
                }
                else
                {
                    EthIf_CtrlModeIndication(gEthDrvObj.ctrlIdx,
                                             ETH_MODE_ACTIVE);
                }
                gEthControllerModeChangeFlag = (uint32) FALSE;
            }
        }
    }
}

#define ETH_STOP_SEC_CODE
#include "Eth_MemMap.h"
