
/* XDC Includes. */

#include "stdio.h"
#include "string.h"
#include "math.h"

#include <xdc/runtime/System.h>
#include <xdc/runtime/Timestamp.h> //new for calculations
#include <xdc/runtime/Types.h> //new for calculations
#include <ti/sysbios/BIOS.h>

/* CSL SRIO Functional Layer */
#include <ti/csl/csl_srio.h>
#include <ti/csl/csl_srioAux.h>
#include <ti/csl/csl_srioAuxPhyLayer.h>

/* SRIO Driver Includes. */
#include <ti/drv/srio/srio_types.h>
#include <ti/drv/srio/include/listlib.h>
#include <ti/drv/srio/srio_drv.h>

/* Application Include Files */
#include "srio_device.h"

/* CSL BootCfg Module */
#include <ti/csl/csl_bootcfg.h>
#include <ti/csl/csl_bootcfgAux.h>

/* CSL PSC Module */
#include <ti/csl/csl_pscAux.h>

/* CSL Chip Functional Layer */
#include <ti/csl/csl_chip.h>

/* QMSS Include */
#include <ti/drv/qmss/qmss_drv.h>

/* Producer-Consumer Include Files. */
#include "srio_config.h"

#define NUM_SHARED_STATS_BUFFERS	2

/* Status Output defines */
#define STAT_LINE_LEN 256
#define NUM_PKT_SIZES 12
#define LANE_SPEEDS   1
#define LANE_CONFIGS  1

#define CYCLES_TO_SECS(CYCLES, CPUFREQ) \
    ((float)((((Double)CYCLES * 1))/(Double)CPUFREQ))

/* Convert cycles to milliseconds */
#define CYCLES_TO_MS(CYCLES, CPUFREQ) \
    ((UInt32)((((Double)CYCLES * 1000))/(Double)CPUFREQ))

/* Convert cycles to microseconds */
#define CYCLES_TO_US(CYCLES, CPUFREQ) \
    ((UInt32)((((Double)CYCLES * 1000000))/(Double)CPUFREQ))

/* Convert cycles to nanoseconds */
#define CYCLES_TO_NS(CYCLES, CPUFREQ) \
    ((UInt32)((((Double)CYCLES * 1000000000))/(Double)CPUFREQ))

#pragma DATA_SECTION (srioStatsOutputBuffer, ".srioSharedMem");
static char	srioStatsOutputBuffer[NUM_SHARED_STATS_BUFFERS][STAT_LINE_LEN * NUM_PKT_SIZES * LANE_SPEEDS * LANE_CONFIGS];


extern struct_srio_control testControl;
extern uint32_t srio_device_ID1;
extern uint32_t srio_device_ID2;

extern Srio_SockHandle     mgmtSocket;
extern Srio_DrvHandle      hAppManagedSrioDrv;

srioRefClockMhz_e srio_refClockMhz = srio_ref_clock_312p50Mhz;
int gSrioPort;

uint32_t l2_global_address (uint32_t addr)
{
	uint32_t coreNum;

	/* Get the core number. */
	coreNum = CSL_chipReadReg (CSL_CHIP_DNUM);

	/* Compute the global address. */
	return (addr + (0x10000000 + (coreNum*0x1000000)));
}

uint32_t l2_global_address_for_core (uint32_t addr, uint32_t coreNum)
{
	/* Compute the global address. */
	return (addr + (0x10000000 + (coreNum*0x1000000)));
}

uint32_t getIterationCountUsingSeconds (uint64_t tsLoopStart, uint64_t tsLoopEnd, uint32_t timeInSeconds)
{
	uint32_t		newIterationCount;
	uint64_t		elapsedIterationCycles;
	float			cpuTimerFreqRatio, elapsedIterationSeconds;
    Types_FreqHz	timerFreq, cpuFreq;

    Timestamp_getFreq (&timerFreq);
    BIOS_getCpuFreq (&cpuFreq);
    cpuTimerFreqRatio = (float)(cpuFreq.lo / timerFreq.lo);

    elapsedIterationCycles = tsLoopEnd - tsLoopStart;
    elapsedIterationCycles *= cpuTimerFreqRatio;
    elapsedIterationSeconds = CYCLES_TO_SECS(elapsedIterationCycles, cpuFreq.lo);

    /* Determine elapsed seconds based on a reduced precision of 2 decimal places to the right */
    newIterationCount = elapsedIterationSeconds * 100000;
    elapsedIterationSeconds = ceil((float)newIterationCount / (float)1000) / (float)100;

	newIterationCount = (uint32_t)ceil((float)timeInSeconds / (float)elapsedIterationSeconds);
	if (newIterationCount <= 0)
		newIterationCount = 1;

    //System_printf(" Calculated iteration count: %lu\n", newIterationCount);

	return newIterationCount;
}

int32_t setEnableSrioPllRxTx (CSL_SrioHandle hSrio, srioRefClockMhz_e refClockMhz, srioLaneRateGbps_e linkRateGbps, int isLoopbackMode)
{
	uint32_t pllValue = getPllValue (refClockMhz, linkRateGbps);
	uint32_t rxConfig = 0;
	uint32_t txConfig = 0;
	Uint8	bootCompleteFlag;

	/* Return immediately if pllValue has not been identified and is still zero */
	if (pllValue == 0)
		return -1;

	/* Get Pll setting for single speed of 3.125Gbps or setting for all other speeds of 5.0Gbps, 2.5Gbps, and 1.25Gpbs */
    CSL_BootCfgSetSRIOSERDESConfigPLL (pllValue);

    /* Loop around until the SERDES PLL is locked. */
    while (1)
    {
        uint32_t    status;

        /* Get the SRIO SERDES Status */
        CSL_BootCfgGetSRIOSERDESStatus (&status);
        if (status & 0x1)
            break;
    }

	/* Get boot complete flag setting */
	CSL_SRIO_GetBootComplete (hSrio, &bootCompleteFlag);

    if (bootCompleteFlag == 1)
    	/* Set boot complete to be 0; to enable writing to the SRIO registers. */
		CSL_SRIO_SetBootComplete (hSrio, 0);

    /* Set rx/tx config values based on the lane rate specified */
	switch (linkRateGbps)
	{
		case srio_lane_rate_5p000Gbps:	/* Pll setting determines 5.0 Gpbs or 3.125 Gbps */
		case srio_lane_rate_3p125Gbps:	/* Same Tx and Rx settings for 5.0 Gbps or 3.125 Gbps */
			rxConfig = 0x00440495;
						// (0)     Enable Receiver
						// (1-3)   Bus Width 010b (20 bit)
						// (4-5)   Half rate. Two data samples per PLL output clock cycle
						// (6)     Normal polarity
						// (7-9)   Termination programmed to be 001
						// (10-11) Comma Alignment enabled
						// (12-14) Loss of signal detection disabled
						// (15-17) First order. Phase offset tracking up to +-488 ppm
						// (18-20) Fully adaptive equalization
						// (22)    Offset compensation enabled
						// (23-24) Loopback disabled
						// (25-27) Test pattern mode disabled
						// (28-31) Reserved

			txConfig = 0x00180795;
			//txConfig = 0x00181F15;
						// (0)     Enable Transmitter
						// (1-3)   Bus Width 010b (20 bit)
						// (4-5)   Half rate. Two data samples per PLL output clock cycle
						// (6)     Normal polarity
						// (7-10)  Swing max.
						// (11-13) Precursor Tap weight 0%
						// (14-18) Adjacent post cursor Tap weight 0%
						// (19)    Transmitter pre and post cursor FIR filter update
						// (20)    Synchronization master
						// (21-22) Loopback disabled
						// (23-25) Test pattern mode disabled
						// (26-31) Reserved
			break;
		case srio_lane_rate_2p500Gbps:	/* Tx and Rx settings for 2.50 Gbps */
			rxConfig = 0x004404A5;
						// (4-5)   Quarter rate. One data sample per PLL output clock cycle

			txConfig = 0x001807A5;
						// (4-5)   Quarter rate. One data sample per PLL output clock cycle
			break;
		case srio_lane_rate_1p250Gbps:	/* Tx and Rx settings for 1.25 Gbps */
			rxConfig = 0x004404B5;
						// (4-5)   Eighth rate. One data sample every two PLL output clock cycles

			txConfig = 0x001807B5;
						// (4-5)   Eighth rate. One data sample every two PLL output clock cycles

			break;
		default:	/* Invalid SRIO lane rate specified */
			return -1;
	}

	/* Return with error if rx/tx configuration values have not been determined and are still zero */
	if ((rxConfig == 0) || (txConfig == 0))
		return -1;

	/* If loop-back mode then set the appropriate bits */
	if (isLoopbackMode)
	{
		/* set RX and TX loop-back bits */
		rxConfig |= 0x01800000;
		txConfig |= 0x00600000;
	}

	/* Configure the SRIO SERDES Receive Configuration. */
	CSL_BootCfgSetSRIOSERDESRxConfig (0, rxConfig);
	CSL_BootCfgSetSRIOSERDESRxConfig (1, rxConfig);
	CSL_BootCfgSetSRIOSERDESRxConfig (2, rxConfig);
	CSL_BootCfgSetSRIOSERDESRxConfig (3, rxConfig);

	/* Configure the SRIO SERDES Transmit Configuration. */
	CSL_BootCfgSetSRIOSERDESTxConfig (0, txConfig);
	CSL_BootCfgSetSRIOSERDESTxConfig (1, txConfig);
	CSL_BootCfgSetSRIOSERDESTxConfig (2, txConfig);
	CSL_BootCfgSetSRIOSERDESTxConfig (3, txConfig);

    if (bootCompleteFlag == 1)
		/* Set boot complete back to 1; configuration is complete. */
		CSL_SRIO_SetBootComplete (hSrio, 0);

	return 0;
}

int32_t SrioDevice_init (void)
{
    CSL_SrioHandle      hSrio;
	int32_t             i;
    SRIO_PE_FEATURES    peFeatures;
    SRIO_OP_CAR         opCar;
    Qmss_QueueHnd       queueHnd;
    uint8_t             isAllocated;
    uint32_t            gargbageQueue[] = { GARBAGE_LEN_QUEUE,  GARBAGE_TOUT_QUEUE,
                                            GARBAGE_RETRY_QUEUE,GARBAGE_TRANS_ERR_QUEUE,
                                            GARBAGE_PROG_QUEUE, GARBAGE_SSIZE_QUEUE };
    uint32_t			srioIDMask = (testControl.srio_isDeviceID16Bit ? 0xFFFF : 0xFF);
    uint32_t			srio_primary_ID = srio_device_ID1;
    uint32_t			srio_secondary_ID = srio_device_ID2;

    /* Set primary port ID based on whether going board to board and the
     * initialization core number */
    if (testControl.srio_isBoardToBoard && (testControl.srio_initCorenum != SLAVE_CORE) )
    {
    	srio_primary_ID = srio_device_ID2;
    	srio_secondary_ID = srio_device_ID1;
    }


#ifndef SIMULATOR_SUPPORT
    /* Disable SRIO reset isolation */
    if (CSL_PSC_isModuleResetIsolationEnabled(CSL_PSC_LPSC_SRIO))
    	CSL_PSC_disableModuleResetIsolation(CSL_PSC_LPSC_SRIO);

    /* Reset SRIO module and wait for the reset to complete */
    CSL_PSC_setModuleLocalReset (CSL_PSC_LPSC_SRIO,PSC_MDLRST_ASSERTED);
    CSL_PSC_setModuleNextState (CSL_PSC_LPSC_SRIO,PSC_MODSTATE_ENABLE);
    System_printf ("Debug: Waiting for module reset...\n");
    while (!CSL_PSC_isModuleResetDone(CSL_PSC_LPSC_SRIO));
    System_printf ("Debug: Waiting for module local reset...\n");
    while (!CSL_PSC_isModuleLocalResetDone (CSL_PSC_LPSC_SRIO));
#endif

    /* Get the CSL SRIO Handle. */
    hSrio = CSL_SRIO_Open (0);
    if (hSrio == NULL)
        return -1;

    /* Enable reception of packets */
	hSrio->RIO_PCR = (hSrio->RIO_PCR & 0x7) | CSL_SRIO_RIO_PCR_RESTORE_MASK;

    /* Disable the SRIO Global block */
	CSL_SRIO_GlobalDisable (hSrio);

	/* Disable each of the individual SRIO blocks. */
	for(i = 0; i <= 9; i++)
		CSL_SRIO_DisableBlock (hSrio, i);

	/* Set boot complete to be 0; we are not done with the initialization. */
	CSL_SRIO_SetBootComplete (hSrio, 0);

    /* Set the sRIO shadow registers for 9/3/2/2 */
    CSL_SRIO_SetLSUShadowRegs (hSrio,0x19,0x19);

	/* Now enable the SRIO block and all the individual blocks also. */
	CSL_SRIO_GlobalEnable (hSrio);
	for (i = 0; i <= 9; i++)
		CSL_SRIO_EnableBlock (hSrio,i);

	if (testControl.srio_isLoopbackMode)
	{
		/* Configure SRIO to operate in Loopback mode. */
		CSL_SRIO_SetLoopbackMode (hSrio,0);
		CSL_SRIO_SetLoopbackMode (hSrio,1);
		CSL_SRIO_SetLoopbackMode (hSrio,2);
		CSL_SRIO_SetLoopbackMode (hSrio,3);
	}
	else
	{
		/* Configure SRIO to operate in Normal mode. */
		CSL_SRIO_SetNormalMode (hSrio,0);
		CSL_SRIO_SetNormalMode (hSrio,1);
		CSL_SRIO_SetNormalMode (hSrio,2);
		CSL_SRIO_SetNormalMode (hSrio,3);
	}

	/* Enable Automatic Priority Promotion of response packets. */
	CSL_SRIO_EnableAutomaticPriorityPromotion (hSrio);

	/* Set the SRIO Prescalar select to operate in the range of 44.7 to 89.5 */
	CSL_SRIO_SetPrescalarSelect (hSrio, 0);

    /* Unlock the Boot Configuration Kicker */
    CSL_BootCfgUnlockKicker ();

	if (setEnableSrioPllRxTx(hSrio, srio_refClockMhz, testControl.srio_laneSpeedGbps, 0) < 0)
		return -1;

    /* Loop around until the SERDES PLL is locked. */
    while (1)
    {
        uint32_t    status;

        /* Get the SRIO SERDES Status */
        CSL_BootCfgGetSRIOSERDESStatus (&status);
        if (status & 0x1)
            break;
    }

    /* Clear the LSU pending interrupts. */
    CSL_SRIO_ClearLSUPendingInterrupt (hSrio, 0xFFFFFFFF, 0xFFFFFFFF);

    /* Set the Device Information */
    CSL_SRIO_SetDeviceInfo (hSrio, srio_primary_ID, DEVICE_VENDOR_ID, DEVICE_REVISION);

    /* Set the Assembly Information */
    CSL_SRIO_SetAssemblyInfo (hSrio, DEVICE_ASSEMBLY_ID, DEVICE_ASSEMBLY_VENDOR_ID,
                             DEVICE_ASSEMBLY_REVISION, DEVICE_ASSEMBLY_INFO);

	/* Configure the processing element features*/
	peFeatures.isBridge                          = 0;
	peFeatures.isEndpoint                        = 0;
	peFeatures.isProcessor                       = 1;
	peFeatures.isSwitch                          = 0;
	peFeatures.isMultiport                       = 0;
	peFeatures.isFlowArbiterationSupported       = 0;
	peFeatures.isMulticastSupported              = 0;
	peFeatures.isExtendedRouteConfigSupported    = 0;
	peFeatures.isStandardRouteConfigSupported    = 1;
	peFeatures.isFlowControlSupported            = 1;
	peFeatures.isCRFSupported                    = 0;
	peFeatures.isCTLSSupported                   = 1;
	peFeatures.isExtendedFeaturePtrValid         = 1;
	peFeatures.numAddressBitSupported            = 1;
	CSL_SRIO_SetProcessingElementFeatures (hSrio, &peFeatures);

	/* Configure the source operation CAR */
	memset ((void *) &opCar, 0, sizeof (opCar));
	opCar.portWriteOperationSupport = 1;
	opCar.atomicClearSupport        = 1;
	opCar.atomicSetSupport          = 1;
	opCar.atomicDecSupport          = 1;
	opCar.atomicIncSupport          = 1;
	opCar.atomicTestSwapSupport     = 1;
	opCar.doorbellSupport           = 1;
	opCar.dataMessageSupport        = 1;
	opCar.writeResponseSupport      = 1;
	opCar.streamWriteSupport        = 1;
	opCar.writeSupport              = 1;
	opCar.readSupport               = 1;
	opCar.dataStreamingSupport      = 1;
	CSL_SRIO_SetSourceOperationCAR (hSrio, &opCar);

	/* Configure the destination operation CAR */
	memset ((void *) &opCar, 0, sizeof (opCar));
	opCar.portWriteOperationSupport  = 1;
	opCar.doorbellSupport            = 1;
	opCar.dataMessageSupport         = 1;
	opCar.writeResponseSupport       = 1;
	opCar.streamWriteSupport         = 1;
	opCar.writeSupport               = 1;
	opCar.readSupport                = 1;
	CSL_SRIO_SetDestOperationCAR (hSrio, &opCar);

	/* Set the 16 bit and 8 bit identifier for the SRIO Device. */
	CSL_SRIO_SetDeviceIDCSR (hSrio, SLAVE_8BIT_DEVICE_ID, SLAVE_16BIT_DEVICE_ID);

    /* Enable TLM Base Routing Information for Maintainance Requests & ensure that
     * the BRR's can be used by all the ports. */
    CSL_SRIO_SetTLMPortBaseRoutingInfo (hSrio, 0, 1, 1, 1, 0);
    /* Only add additional route if doing core to core on the same board */
    if (!testControl.srio_isBoardToBoard)
	CSL_SRIO_SetTLMPortBaseRoutingInfo (hSrio, 0, 2, 1, 1, 0);

    /* Configure the Base Routing Register to ensure that all packets matching the
     * Device Identifier & the Secondary Device Id are admitted. */
    CSL_SRIO_SetTLMPortBaseRoutingPatternMatch (hSrio, 0, 1, srio_primary_ID, srioIDMask);
    /* Only add additional route if doing core to core on the same board */
    if (!testControl.srio_isBoardToBoard)
	   CSL_SRIO_SetTLMPortBaseRoutingPatternMatch (hSrio, 0, 2, srio_secondary_ID, srioIDMask);

    /* We need to open the Garbage collection queues in the QMSS. This is done to ensure that
     * these queues are not opened by another system entity. */
    for (i = 0; i < 6; i++)
    {
        /* Open the Garabage queues */
        queueHnd = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, gargbageQueue[i], &isAllocated);
        if (queueHnd < 0)
            return -1;

        /* Make sure the queue has not been opened already; we dont the queues to be shared by some other
         * entity in the system. */
        if (isAllocated > 1)
            return -1;
    }

    /* Set the Transmit Garbage Collection Information. */
    CSL_SRIO_SetTxGarbageCollectionInfo (hSrio, GARBAGE_LEN_QUEUE, GARBAGE_TOUT_QUEUE,
                                         GARBAGE_RETRY_QUEUE, GARBAGE_TRANS_ERR_QUEUE,
                                         GARBAGE_PROG_QUEUE, GARBAGE_SSIZE_QUEUE);

    /* Set the Host Device Identifier. */
    CSL_SRIO_SetHostDeviceID (hSrio, srio_primary_ID);

    /* Configure the component tag CSR */
    CSL_SRIO_SetCompTagCSR (hSrio, 0x00000000);

	/* Configure the PLM for all the ports. */
	for (i = 0; i < 4; i++)
	{
		/* Set the PLM Port Silence Timer. */
		CSL_SRIO_SetPLMPortSilenceTimer (hSrio, i, 0x2);

		/* TODO: We need to ensure that the Port 0 is configured to support both
		 * the 2x and 4x modes. The Port Width field is read only. So here we simply
		 * ensure that the Input and Output ports are enabled. */
		CSL_SRIO_EnableInputPort (hSrio, i);
		CSL_SRIO_EnableOutputPort (hSrio, i);

		/* Set the PLM Port Discovery Timer. */
		CSL_SRIO_SetPLMPortDiscoveryTimer (hSrio, i, 0x2);

		/* Reset the Port Write Reception capture. */
		CSL_SRIO_SetPortWriteReceptionCapture (hSrio, i, 0x0);
	}

	/* Set the Port link timeout CSR */
	// CSL_SRIO_SetPortLinkTimeoutCSR (hSrio, 0x000FFF);
	CSL_SRIO_SetPortLinkTimeoutCSR (hSrio, 0xFF0FFF);
	CSL_SRIO_SetPortResponseTimeoutCSR (hSrio, 0xFF0FFF);

	/* Set the Port General CSR: Only executing as Master Enable */
	CSL_SRIO_SetPortGeneralCSR (hSrio, 0, 1, 0);

	/* Clear the sticky register bits. */
	CSL_SRIO_SetLLMResetControl (hSrio, 1);

	/* Set the device id to be 0 for the Maintenance Port-Write operation
	 * to report errors to a system host. */
	CSL_SRIO_SetPortWriteDeviceId (hSrio, 0x0, 0x0, 0x0);

    /* Set the Data Streaming MTU */
    CSL_SRIO_SetDataStreamingMTU (hSrio, 64);

	/* Configure the path mode for the ports. */
	if (setSrioLanes(hSrio, testControl.srio_lanesMode) < 0)
		return -1;

	/* Set the LLM Port IP Prescalar. */
	//CSL_SRIO_SetLLMPortIPPrescalar (hSrio, 0x21);
	CSL_SRIO_SetLLMPortIPPrescalar (hSrio, 0x1F);

	/* Configure the ingress watermarks */
	for (i = 0; i < 4; i++)
	{
		CSL_SRIO_SetPBMPortIngressPriorityWatermark (hSrio, i, 0, 0x24, 0x24);
		CSL_SRIO_SetPBMPortIngressPriorityWatermark (hSrio, i, 1, 0x1B, 0x1B);
		CSL_SRIO_SetPBMPortIngressPriorityWatermark (hSrio, i, 2, 0x12, 0x12);
		CSL_SRIO_SetPBMPortIngressPriorityWatermark (hSrio, i, 3, 0x9, 0x9);
	}

    /* Disable interrupt pacing for all interrupt destinations. */
    for (i = 0; i < 24; i++)
        CSL_SRIO_DisableInterruptPacing (hSrio, i);

	/* Set all the queues 0 to operate at the same priority level and to send packets onto Port 0 */
    for (i =0 ; i < 16; i++)
    	CSL_SRIO_SetTxQueueSchedInfo (hSrio, i, 0, 0);


   	CSL_SRIO_SetDoorbellRoute (hSrio, 1);

    for (i = 0; i < 16; i++)
    {
        CSL_SRIO_RouteDoorbellInterrupts (hSrio, 0, i, 0);
        CSL_SRIO_RouteDoorbellInterrupts (hSrio, 1, i, 1);
        CSL_SRIO_RouteDoorbellInterrupts (hSrio, 2, i, 2);
        CSL_SRIO_RouteDoorbellInterrupts (hSrio, 3, i, 3);
    }

	/* Enable the peripheral. */
	CSL_SRIO_EnablePeripheral (hSrio);

    /* Configuration has been completed. */
    CSL_SRIO_SetBootComplete (hSrio, 1);

#ifndef SIMULATOR_SUPPORT
    /* Check Ports and make sure they are operational. */
	if (waitAllSrioPortsOperational(hSrio, testControl.srio_lanesMode) < 0)
		return -1;
#endif

    if (displaySrioLanesStatus(hSrio) < 0)
    	return -1;

    /* Initialization has been completed. */
    return 0;
}

void myDIOIsr(UArg argument)
{
    uint8_t     intDstDoorbell[4];

    /* The Interrupt Destination Decode registers which need to be looked into.
     * Please refer to the SRIO Device Initialization code. */
    intDstDoorbell[0] = 0x0;
    intDstDoorbell[1] = 0x1;
    intDstDoorbell[2] = 0x2;
    intDstDoorbell[3] = 0x3;

    /* Pass the control to the driver DIO ISR handler. */
    Srio_dioCompletionIsr ((Srio_DrvHandle)argument, intDstDoorbell);
    return;
}

Srio_SockHandle createMgmtSocket(void)
{
    Srio_SockHandle         mgmtSocket;
    Srio_SockBindAddrInfo   bindInfo;
    uint32_t                doorbellInfo;
    uint32_t				        coreNum;
    bool					          useBlockingSocket;

    /* Set non-blocking or blocking socket designator based on polled mode */
    useBlockingSocket = TRUE;

    /* Get the core number. */
    coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);

    /* Create the Management Socket. */
    mgmtSocket = Srio_sockOpen (hAppManagedSrioDrv, Srio_SocketType_DIO, useBlockingSocket);
    if (mgmtSocket == NULL)
    {
        System_printf ("Error: Unable to open the DIO Management socket\n");
        return NULL;
    }

    /* DIO Binding Information: Use 16/8 bit identifiers and we are bound to the first source id.
     * and we are using 16/8 bit device identifiers. */
    bindInfo.dio.doorbellValid  = 0;
    bindInfo.dio.intrRequest    = 0;
    bindInfo.dio.supInt         = 0;
    bindInfo.dio.xambs          = 0;
    bindInfo.dio.priority       = 0;
    bindInfo.dio.outPortID      = SRIO_PORT_NUM0 + gSrioPort;
    bindInfo.dio.idSize         = ((testControl.srio_isDeviceID16Bit) ? 1 : 0);
    bindInfo.dio.srcIDMap       = 0;
    bindInfo.dio.hopCount       = 0;
    bindInfo.dio.doorbellReg    = 0;
    bindInfo.dio.doorbellBit    = 0;

    /* Bind the DIO socket. */
    if (Srio_sockBind (mgmtSocket, &bindInfo) < 0)
    {
        System_printf ("Error: Binding the DIO Management Socket failed.\n");
        return NULL;
    }

    if (coreNum == SLAVE_CORE)
    {
		/* Register the CONSUMER Doorbell Information */
		doorbellInfo = SRIO_SET_DBELL_INFO(CONSUMER_DOORBELL_REG, CONSUMER_DOORBELL_BIT);
    }
    else
    {
		/* Register the PRODUCER Doorbell Information */
		doorbellInfo = SRIO_SET_DBELL_INFO(PRODUCER_DOORBELL_REG, PRODUCER_DOORBELL_BIT);
    }
    if (Srio_setSockOpt (mgmtSocket, Srio_Opt_REGISTER_DOORBELL, (void *)&doorbellInfo, sizeof(uint32_t)) < 0)
    {
        System_printf ("Error: Unable to register the %s Doorbell\n",coreNum);
        return NULL;
    }

    /* Return the management socket. */
    return mgmtSocket;
}

int32_t displaySrioLanesStatus (CSL_SrioHandle hSrio)
{
	SRIO_LANE_STATUS	ptrLaneStatus;
	Int8				i;
	uint32_t			laneCode=0;
	int32_t				returnStatus=0;
	char				laneSetupText[MAX_MSG_LEN];

   	for (i = 3; i >= 0; i--)
   	{
   		CSL_SRIO_GetLaneStatus (hSrio,i,&ptrLaneStatus);
   		laneCode = laneCode | (ptrLaneStatus.laneNum << (i * 4));
   	}

	switch (laneCode)
	{
		case 0x0000:	/* four 1x ports */
			sprintf (laneSetupText,"four 1x ports");
			break;
		case 0x0010:	/* one 2x port and two 1x ports */
			sprintf (laneSetupText,"one 2x port and two 1x ports");
			break;
		case 0x1000:	/* two 1x ports and one 2x port */
			sprintf (laneSetupText,"two 1x ports and one 2x port");
			break;
		case 0x1010:	/* two 2x ports */
			sprintf (laneSetupText,"two 2x ports");
			break;
		case 0x3210:	/* one 4x port */
			sprintf (laneSetupText,"one 4x port");
			break;
		default: /* four 1x ports */
			sprintf (laneSetupText,"INVALID LANE COMBINATION FOUND");
			returnStatus = -1;
			break;
	}
	System_printf ("Debug:   Lanes status shows lanes formed as %s%s", laneSetupText, "\n");

	return returnStatus;
}

int32_t setSrioLanes (CSL_SrioHandle hSrio, srioLanesMode_e laneMode)
{
	Uint8	port, pathMode;
	Uint8	bootCompleteFlag;
	Uint32	serdesTXConfig;
	Uint32	msyncSet = 0x00100000;
	CSL_SRIO_GetBootComplete (hSrio, &bootCompleteFlag);

    if (bootCompleteFlag == 1)
    	/* Set boot complete to be 0; to enable writing to the SRIO registers. */
		CSL_SRIO_SetBootComplete (hSrio, 0);

    /* Set the path mode number to the lane configuration specified */
	switch (laneMode)
	{
		case srio_lanes_form_four_1x_ports:					/* four 1x ports (forms ports: 0,1,2 and 3) */
			pathMode = 0;
			break;
		case srio_lanes_form_one_2x_port_and_two_1x_ports:	/* one 2x port and two 1x ports (forms ports: 0, 2 and 3) */
			pathMode = 1;
			break;
		case srio_lanes_form_two_1x_ports_and_one_2x_port:	/* two 1x ports and one 2x port (forms ports: 0, 1 and 2) */
			pathMode = 2;
			break;
		case srio_lanes_form_two_2x_ports:					/* two 2x ports (forms ports: 0 and 2) */
			pathMode = 3;
			break;
		case srio_lanes_form_one_4x_port:					/* one 4x port (forms port: 0) */
			pathMode = 4;
			break;
		default:	/* Invalid lane configuration mode specified */
		    return -1;
	}

    /* Configure the path mode for all ports. */
    for (port = 0; port < 4; port++)
    {
        /* Configure the path mode for the port. */
        CSL_SRIO_SetPLMPortPathControlMode (hSrio, port, pathMode);

        /* Get the current SERDES TX config */
        CSL_BootCfgGetSRIOSERDESTxConfig (port,&serdesTXConfig);

        /* Determine the MSYNC bit's setting according to laneMode being used */
    	switch (laneMode)
    	{
    		case srio_lanes_form_four_1x_ports:						/* four 1x ports (forms ports: 0,1,2 and 3) */
    			msyncSet = 0x00100000;
    			break;
    		case srio_lanes_form_one_2x_port_and_two_1x_ports:		/* one 2x port and two 1x ports (forms ports: 0, 2 and 3) */
    			msyncSet = (port != 1 ? 0x00100000 : 0xFFEFFFFF);
    			break;
    		case srio_lanes_form_two_1x_ports_and_one_2x_port:		/* two 1x ports and one 2x port (forms ports: 0, 1 and 2) */
    			msyncSet = (port != 3 ? 0x00100000 : 0xFFEFFFFF);
    			break;
    		case srio_lanes_form_two_2x_ports:						/* two 2x ports (forms ports: 0 and 2) */
    			msyncSet = (((port != 1) && (port != 3)) ? 0x00100000 : 0xFFEFFFFF);
    			break;
    		case srio_lanes_form_one_4x_port:						/* one 4x port (forms port: 0) */
    			msyncSet = (port == 0 ? 0x00100000 : 0xFFEFFFFF);
    			break;
    		default:	/* Invalid lane configuration mode specified */
    		    return -1;
    	}

    	/* Set msync for each port according to the lane mode (port width) specified */
    	if (msyncSet == 0x00100000)
        	serdesTXConfig |= msyncSet;				/* Set MSYNC bit */
        else
        	serdesTXConfig &= msyncSet;				/* Clear MSYNC bit */

    	/* Write SERDES TX MSYNC bit */
		CSL_BootCfgSetSRIOSERDESTxConfig (port, serdesTXConfig);
    }

    if (bootCompleteFlag == 1)
		/* Set boot complete back to 1; configuration is complete. */
		CSL_SRIO_SetBootComplete (hSrio, 1);

    return 0;
}

int32_t getPllValue (srioRefClockMhz_e refClockMhz, srioLaneRateGbps_e linkRateGbps)
{
	int32_t pllValue = 0;

	/* Get PLL value based on reference clock and lane rate */
	switch (refClockMhz)
	{
		case srio_ref_clock_125p00Mhz:
			switch (linkRateGbps)
			{
				case srio_lane_rate_3p125Gbps:
					pllValue = 0x265; //10 0110 010 1 (12.5x and set enable bit)
					break;
				default:
					pllValue = 0x2A1; //10 1010 000 1 (20x and set enable bit)
					break;
			}
			break;
		case srio_ref_clock_156p25Mhz:
			switch (linkRateGbps)
			{
				case srio_lane_rate_3p125Gbps:
					pllValue = 0x251; //10 0101 000 1 (10x and set enable bit)
					break;
				default:
					pllValue = 0x281; //10 1000 000 1 (16x and set enable bit)
					break;
			}
			break;
		case srio_ref_clock_250p00Mhz:
			switch(linkRateGbps)
			{
				case srio_lane_rate_3p125Gbps:
					pllValue = 0x233; //10 0011 001 1 (6.25x and set enable bit)
					break;
				default:
					pllValue = 0x251; //10 0101 000 1 (10x and set enable bit)
					break;
			}
			break;
		case srio_ref_clock_312p50Mhz:
			switch (linkRateGbps)
			{
				case srio_lane_rate_3p125Gbps:
					pllValue = 0x229; //10 0010 100 1 (5x and set enable bit)
					break;
				default:
					pllValue = 0x241; //10 0100 000 1 (8x and set enable bit)
					break;
			}
			break;
	}

	return pllValue;
}

int32_t waitAllSrioPortsOperational (CSL_SrioHandle hSrio, srioLanesMode_e laneMode)
{
	Uint8		port;
	Uint8		portsMask=0xF;		// 0b1111
	char		statusText[4]="";
    uint64_t	tscTemp;

    /* Set port mask to use based on the lane mode specified */
	switch (laneMode)
	{
		case srio_lanes_form_four_1x_ports:					/* check ports 0 to 3 */
			portsMask = 0xF;	// 0b1111
			break;
		case srio_lanes_form_one_2x_port_and_two_1x_ports:	/* check ports 0, 2, and 3 */
			portsMask = 0xD;	// 0b1101
			break;
		case srio_lanes_form_two_1x_ports_and_one_2x_port:	/* check ports 0, 1, and 2 */
			portsMask = 0x7;	// 0b0111
			break;
		case srio_lanes_form_two_2x_ports:					/* check ports 0 and 2 */
			portsMask = 0x5;	// 0b0101
			break;
		case srio_lanes_form_one_4x_port:					/* check port 0 */
			portsMask = 0x1;	// 0b0001
			break;
		default: /* check ports 0 to 3 */
			portsMask = 0xF;	// 0b1111
			break;
	}

    /* Wait for all SRIO ports for specified lane mode to be operational */
	System_printf ("Debug: Waiting for SRIO ports to be operational...  \n");
	tscTemp = CSL_tscRead () + 5000000000;
#if 1
	while(1){
		for (port = 0; port < 4; port++)
		{
			if ((portsMask >> port) & 0x1 == 1)
			{
				sprintf (statusText, "NOT ");
				/* Check for good port status on each valid port, timeout if not received after 5 seconds */
				while (CSL_tscRead() < tscTemp)
//				while (1)
				{
					if (CSL_SRIO_IsPortOk (hSrio, port) == TRUE)
					{
						sprintf (statusText,"");
						gSrioPort = port;
						return 0;
					}
				}
				System_printf ("Debug: SRIO port %d is %soperational.\n", port, statusText);

				tscTemp = CSL_tscRead() + 10000000;
			}
		}
	}
#else

	while(1)
	{
		for (port = 0; port < 4; port++)
		{
			if ((portsMask >> port) & 0x1 == 1)
			{
				sprintf (statusText, "NOT ");
				/* Check for good port status on each valid port, timeout if not received after 5 seconds */
				if (CSL_SRIO_IsPortOk (hSrio, port) == TRUE)
				{
					sprintf (statusText,"");
					System_printf ("Debug: SRIO port %d is %soperational.\n", port, statusText);
					return 0;
				}
			}
		}
	}
#endif
    return 0;
}

void clearSrioStatsOutputBuffer (void)
{
	uint32_t		coreNumber;

	/* Get the core number. */
    coreNumber = CSL_chipReadReg (CSL_CHIP_DNUM);

	strcpy (srioStatsOutputBuffer[coreNumber], "");
}


