/***************************************************************************\
 *       Copyright (C) 2013-2014 Texas Instruments Incorporated.            *
 *                           All Rights Reserved                            *
 *                                                                          *
 * GENERAL DISCLAIMER                                                       *
 * ------------------                                                       *
 * All software and related documentation is provided "AS IS" and without   *
 * warranty or support of any kind and Texas Instruments expressly disclaims*
 * all other warranties, express or implied, including, but not limited to, *
 * the implied warranties of merchantability and fitness for a particular   *
 * purpose.  Under no circumstances shall Texas Instruments be liable for   *
 * any incidental, special or consequential damages that result from the    *
 * use or inability to use the software or related documentation, even if   *
 * Texas Instruments has been advised of the liability.                     *
   **************************************************************************
This file Print GE status and error information
****************************************************************************
 * Created by :                                                             *
 *            Brighton Feng                                                 *
 *            Texas Instruments                                             * 
 *            June 11, 2013                                                 *
 Oct 20, 2014, Brighton Feng updated for K2E, K2L
\***************************************************************************/
#include <stdio.h>
#include <string.h>
#include <tistdtypes.h>
#include <csl_cpsgmii.h>
#include "K2_GE_Init_drv.h"
#include "K2_common.h"
#include "GE_PktDMA_Init.h"
#include "GE_debug.h"

char * GE_speed_str[]=
{
    "10Mbps",
    "100Mbps",
    "1000Mbps"
};

char * GE_duplex_str[]=
{
    "Half Duplex",
    "Full Duplex"
};

void SGMII_getLinkPartnerAdvAbility (
    Uint32                      portNum,
	CSL_SGMII_ADVABILITY*       pSgmiiAdvAbility
)
{
    pSgmiiAdvAbility->linkSpeed     =   (CSL_SGMII_LINKSPEED) CSL_FEXTR (gpSGMII_regs[portNum]->MR_LP_ADV_ABILITY_REG, 11, 10);
    pSgmiiAdvAbility->duplexMode    =   (CSL_SGMII_DUPLEXMODE) CSL_FEXTR (gpSGMII_regs[portNum]->MR_LP_ADV_ABILITY_REG, 12, 12);
    pSgmiiAdvAbility->bLinkUp       =   CSL_FEXTR (gpSGMII_regs[portNum]->MR_LP_ADV_ABILITY_REG, 15, 15);

    return;        
}

void print_GE_link_ability(Uint32 uiPort)
{
	CSL_SGMII_ADVABILITY sgmiiAdvAbility;

	SGMII_getLinkPartnerAdvAbility(uiPort, &sgmiiAdvAbility);
	printf("SGMII%d Link Partner Advertised Ability %s %s\n", uiPort, 
		GE_speed_str[sgmiiAdvAbility.linkSpeed],
		GE_duplex_str[sgmiiAdvAbility.duplexMode]);
}

//save the previous statistics
Ethernet_Statistics pre_statistics[GE_NUM_ETHERNET_PORT+1];

//print GE statistics
void print_GE_statistics()
{
	int i;
	char moduleName[16];

	//save the previous statistics
	memcpy((void *)pre_statistics, (void *)statistics, sizeof(pre_statistics));
	
	//update statistics data
	K2_GE_Accumulate_Statistics();

#if defined(DEVICE_K2H) || defined(DEVICE_K2K)
	for(i=0; i< GE_NUM_ETHERNET_PORT; i++)
	{
		sprintf(moduleName, "STATS%c", 'A'+i);
#else 	//K2E or K2L
	for(i=0; i< GE_NUM_ETHERNET_PORT+1; i++)
	{
		sprintf(moduleName, "CPSW_port%d", i);
#endif
	    if(statistics[i].RxGoodFrames     != pre_statistics[i].RxGoodFrames     ) printf("%s.RxGoodFrames     =%llu\n", moduleName, statistics[i].RxGoodFrames     );
	    if(statistics[i].RxBCastFrames    != pre_statistics[i].RxBCastFrames    ) printf("%s.RxBCastFrames    =%llu\n", moduleName, statistics[i].RxBCastFrames    );
	    if(statistics[i].RxMCastFrames    != pre_statistics[i].RxMCastFrames    ) printf("%s.RxMCastFrames    =%llu\n", moduleName, statistics[i].RxMCastFrames    );
	    if(statistics[i].RxPauseFrames    != pre_statistics[i].RxPauseFrames    ) printf("%s.RxPauseFrames    =%llu\n", moduleName, statistics[i].RxPauseFrames    );
	    if(statistics[i].RxCRCErrors      != pre_statistics[i].RxCRCErrors      ) printf("!%s.RxCRCErrors     =%llu\n", moduleName, statistics[i].RxCRCErrors      );
	    if(statistics[i].RxAlignCodeErrors!= pre_statistics[i].RxAlignCodeErrors) printf("!%s.RxAlignCodeError=%llu\n", moduleName, statistics[i].RxAlignCodeErrors);
	    if(statistics[i].RxOversized      != pre_statistics[i].RxOversized      ) printf("!%s.RxOversized     =%llu\n", moduleName, statistics[i].RxOversized      );
	    if(statistics[i].RxJabber         != pre_statistics[i].RxJabber         ) printf("!%s.RxJabber        =%llu\n", moduleName, statistics[i].RxJabber         );
	    if(statistics[i].RxUndersized     != pre_statistics[i].RxUndersized     ) printf("!%s.RxUndersized    =%llu\n", moduleName, statistics[i].RxUndersized     );
	    if(statistics[i].RxFragments      != pre_statistics[i].RxFragments      ) printf("%s.RxFragments      =%llu\n", moduleName, statistics[i].RxFragments      );
	    if(statistics[i].RxOctets         != pre_statistics[i].RxOctets         ) printf("%s.RxOctets         =%llu\n", moduleName, statistics[i].RxOctets         );
	    if(statistics[i].TxGoodFrames     != pre_statistics[i].TxGoodFrames     ) printf("%s.TxGoodFrames     =%llu\n", moduleName, statistics[i].TxGoodFrames     );
	    if(statistics[i].TxBCastFrames    != pre_statistics[i].TxBCastFrames    ) printf("%s.TxBCastFrames    =%llu\n", moduleName, statistics[i].TxBCastFrames    );
	    if(statistics[i].TxMCastFrames    != pre_statistics[i].TxMCastFrames    ) printf("%s.TxMCastFrames    =%llu\n", moduleName, statistics[i].TxMCastFrames    );
	    if(statistics[i].TxPauseFrames    != pre_statistics[i].TxPauseFrames    ) printf("%s.TxPauseFrames    =%llu\n", moduleName, statistics[i].TxPauseFrames    );
	    if(statistics[i].TxDeferred       != pre_statistics[i].TxDeferred       ) printf("!%s.TxDeferred      =%llu\n", moduleName, statistics[i].TxDeferred       );
	    if(statistics[i].TxCollision      != pre_statistics[i].TxCollision      ) printf("!%s.TxCollision     =%llu\n", moduleName, statistics[i].TxCollision      );
	    if(statistics[i].TxSingleColl     != pre_statistics[i].TxSingleColl     ) printf("!%s.TxSingleColl    =%llu\n", moduleName, statistics[i].TxSingleColl     );
	    if(statistics[i].TxMultiColl      != pre_statistics[i].TxMultiColl      ) printf("!%s.TxMultiColl     =%llu\n", moduleName, statistics[i].TxMultiColl      );
	    if(statistics[i].TxExcessiveColl  != pre_statistics[i].TxExcessiveColl  ) printf("!%s.TxExcessiveColl =%llu\n", moduleName, statistics[i].TxExcessiveColl  );
	    if(statistics[i].TxLateColl       != pre_statistics[i].TxLateColl       ) printf("!%s.TxLateColl      =%llu\n", moduleName, statistics[i].TxLateColl       );
	    if(statistics[i].TxCarrierSLoss   != pre_statistics[i].TxCarrierSLoss   ) printf("!%s.TxCarrierSLoss  =%llu\n", moduleName, statistics[i].TxCarrierSLoss   );
	    if(statistics[i].TxOctets         != pre_statistics[i].TxOctets         ) printf("%s.TxOctets         =%llu\n", moduleName, statistics[i].TxOctets         );
	    if(statistics[i].Frame64          != pre_statistics[i].Frame64          ) printf("%s.Frame64          =%llu\n", moduleName, statistics[i].Frame64          );
	    if(statistics[i].Frame65t127      != pre_statistics[i].Frame65t127      ) printf("%s.Frame65t127      =%llu\n", moduleName, statistics[i].Frame65t127      );
	    if(statistics[i].Frame128t255     != pre_statistics[i].Frame128t255     ) printf("%s.Frame128t255     =%llu\n", moduleName, statistics[i].Frame128t255     );
	    if(statistics[i].Frame256t511     != pre_statistics[i].Frame256t511     ) printf("%s.Frame256t511     =%llu\n", moduleName, statistics[i].Frame256t511     );
	    if(statistics[i].Frame512t1023    != pre_statistics[i].Frame512t1023    ) printf("%s.Frame512t1023    =%llu\n", moduleName, statistics[i].Frame512t1023    );
	    if(statistics[i].Frame1024tUp     != pre_statistics[i].Frame1024tUp     ) printf("%s.Frame1024tUp     =%llu\n", moduleName, statistics[i].Frame1024tUp     );
	    if(statistics[i].NetOctets        != pre_statistics[i].NetOctets        ) printf("%s.NetOctets        =%llu\n", moduleName, statistics[i].NetOctets        );
	}	
}

//print GE ethernet port error/status
void print_GE_ethernet_ports_status()
{
	int i;
	Uint32 SGMII_STATUS;
	Uint32 GMII_EN, MAC_STATUS;

	for(i=0; i< GE_NUM_ETHERNET_PORT; i++)
	{
#if defined(DEVICE_K2H) || defined(DEVICE_K2K)
		GMII_EN= gpMAC_regs[i]->MACCONTROL_REG
			&CSL_CPGMAC_SL_MACCONTROL_REG_GMII_EN_MASK;
		MAC_STATUS= gpMAC_regs[i]->MACSTATUS_REG;
#else 	//K2E or K2L
		GMII_EN= gpCPSW_regs->ENETPORT[i].PN_MAC_CONTROL_REG
			&CSL_XGE_CPSW_PN_MAC_CONTROL_REG_GMII_EN_SHIFT;
		MAC_STATUS= gpCPSW_regs->ENETPORT[i].PN_MAC_STATUS_REG;
#endif

		if(GMII_EN)
		{//only print status for enabled port
			//read status from the registers
			SGMII_STATUS      = gpSGMII_regs[i]->STATUS_REG;

			if(0==(SGMII_STATUS&CSL_CPSGMII_STATUS_REG_LOCK_MASK))
			{
				printf("SGMII%d SerDes PLL is NOT locked!\n", i);
			}
			if(0==(SGMII_STATUS&CSL_CPSGMII_STATUS_REG_LINK_MASK))
			{
				printf("SGMII%d Link is NOT up!\n", i);
			}

			if(SGMII_STATUS&CSL_CPSGMII_STATUS_REG_MR_AN_COMPLETE_MASK)
			{//only print autonegotiation status when it is complete
				if(SGMII_STATUS&CSL_CPSGMII_STATUS_REG_AN_ERROR_MASK)
				{
					printf("SGMII%d Auto-negotiation error, occurs when halfduplex gigabit is commanded!\n", i);
				}
				//print_GE_link_ability(i);
			}

			if(0==(MAC_STATUS&CSL_CPGMAC_SL_MACSTATUS_REG_IDLE_MASK))
			{
				printf("EMAC port %d is NOT in the idle state.\n", i);
			}
			if(0==(MAC_STATUS&CSL_CPGMAC_SL_MACSTATUS_REG_EXT_GIG_MASK))
			{
				printf("EMAC port %d GIG input signal from SGMII is low.\n", i);
			}
			if(0==(MAC_STATUS&CSL_CPGMAC_SL_MACSTATUS_REG_EXT_FULLDUPLEX_MASK))
			{
				printf("EMAC port %d FULLDUPLEX input signal from SGMII is low.\n", i);
			}
			if(MAC_STATUS&CSL_CPGMAC_SL_MACSTATUS_REG_RX_FLOW_ACT_MASK)
			{
				printf("EMAC port %d RX flow control is enabled and active.\n", i);
			}
			if(MAC_STATUS&CSL_CPGMAC_SL_MACSTATUS_REG_TX_FLOW_ACT_MASK)
			{
				printf("EMAC port %d TX flow control is enabled and active.\n", i);
			}
		}
	}
}

//print GE MDIO status
Uint32 pre_PHY_ALIVE=0, pre_PHY_LINK=0;
void print_GE_MDIO_status()
{
	Uint32 PHY_ALIVE, PHY_LINK;

	if(gpMDIO_regs->CONTROL_REG&CSL_MDIO_CONTROL_REG_ENABLE_MASK)
	{//only print status when MDIO is enabled
		PHY_ALIVE= gpMDIO_regs->ALIVE_REG;
		PHY_LINK= gpMDIO_regs->LINK_REG;
	
		if(pre_PHY_ALIVE!=PHY_ALIVE)
		{
			printf("MDIO ALIVE flag: 0x%08x\n", PHY_ALIVE);
			pre_PHY_ALIVE = PHY_ALIVE;
		}

		if(pre_PHY_LINK!=PHY_LINK)
		{
			printf("MDIO LINK  flag: 0x%08x\n", PHY_LINK);
			pre_PHY_LINK = PHY_LINK;
		}
	}
}

//print GE status and errors
void print_GE_status_error()
{
	GE_Check_Free_Queues();
	GE_Check_TxRx_Queues(TRUE);

	print_GE_statistics();
	print_GE_ethernet_ports_status();
	print_GE_MDIO_status();
}



