

/* Standard library, XDC and sysbios Include Files. */
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/Memory.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/family/c64p/EventCombiner.h>
#include <ti/sysbios/family/c66/tci66xx/CpIntc.h>
#include <ti/sysbios/BIOS.h>

/* IPC includes */
#include <ti/ipc/Ipc.h>
#include <ti/ipc/MultiProc.h>

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

/* CSL Cache Functional Layer */
#include <ti/csl/csl_cacheAux.h>

/* CSL PSC Include Files */
#include <ti/csl/csl_psc.h>
#include <ti/csl/csl_pscAux.h>

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

/* SRIO Driver Include File. */
#include "srio_osal.h"
#include <ti/drv/srio/srio_drv.h>

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

/* CPPI/QMSS Include Files. */
#include <ti/drv/cppi/cppi_drv.h>
#include <ti/drv/qmss/qmss_drv.h>
#include <ti/drv/qmss/qmss_firmware.h>

/* CSL TSC Module */
#include <ti/csl/csl_tsc.h>

#include "gpio.h"
#define CORE0 1

struct_srio_control testControl = {
		SRIO_LANE_SPEED,					// srioLaneRateGbps_e	srio_laneSpeedGbps;
		SRIO_PORT_WIDTH,					// srioLanesMode_e		srio_lanesMode;
		TESTS_TO_RUN,						// srioTestsToRun_e		srio_testsToRun;
		NUM_SECS_TO_RUN_EACH_PACKET_SIZE,	// uint32_t				srio_testTimeInSeconds;
		CORE_TO_INITIALIZE_SRIO,			// int32_t				srio_initCorenum;
		IS_BOARD_TO_BOARD,					// bool					srio_isBoardToBoard;
		IS_OVER_EXTERNAL_SRIO_SWITCH,		// bool					srio_isExternalSrioSwitch;
		USE_LOOPBACK_MODE,					// bool					srio_isLoopbackMode;
		USE_SRIO_16_BIT_ID,					// bool					srio_isDeviceID16Bit;
		RUN_LATENCY_MEASUREMENT,			// bool					srio_isLatencyTest;
		DISPLAY_RUN_PROGRESS_MESSAGES,		// bool					srio_isRunProgress;
		(MESSAGE_INITIAL_DATA_SIZE - SOFTWARE_HEADER_BYTES),	// int32_t				srio_payloadSize;
		(MESSAGE_MAX_DATA_SIZE - SOFTWARE_HEADER_BYTES),		// int32_t				srio_payloadEndSize;
		SLAVE_INITIAL_DATA_SIZE,				// int32_t				srio_dioPayloadSize;
		SLAVE_MAX_DATA_SIZE,					// int32_t				srio_dioPayloadEndSize;
};

uint32_t srio_device_ID1;			/* Consumer. Value is set in main */
uint32_t srio_device_ID2;			/* Producer. Value is set in main */

uint64_t srio_numPackets = (uint64_t)MIN_NUM_PACKETS_TO_SEND;		/* Initial value only. Determined by the test seconds specified */
uint64_t srio_numDioPackets = (uint64_t)MIN_NUM_PACKETS_TO_SEND;	/* Initial value only. Determined by the test seconds specified */
uint64_t srio_latencyNumPackets = (uint64_t)100;					/* Static value */
uint32_t srio_iterationCount = 2;//10;	/* Initial value only. Determined by the test seconds specified */

/* Memory allocated for the descriptors. This is 16 bit aligned. */
#pragma DATA_ALIGN (master_region, 16)
uint8_t             master_region[NUM_HOST_DESC * SIZE_HOST_DESC];

#pragma DATA_ALIGN (gHiPriAccumList, 16)
uint32_t            gHiPriAccumList[64];

#pragma DATA_SECTION(SrioBootCmd, ".boot_cmd");
#pragma DATA_ALIGN(SrioBootCmd, 8);

volatile unsigned int SrioBootCmd;

#pragma DATA_ALIGN   (isSRIOInitialized, 128)
#pragma DATA_SECTION (isSRIOInitialized, ".srioSharedMem");
volatile Uint32     isSRIOInitialized[(SRIO_MAX_CACHE_ALIGN / sizeof(Uint32))] = { 0 };

/* QMSS device specific configuration */
extern Qmss_GlobalConfigParams  qmssGblCfgParams;
extern int gGpioLedFlag;
/* CPPI device specific configuration */
extern Cppi_GlobalConfigParams  cppiGblCfgParams;
Srio_DrvHandle      hAppManagedSrioDrv;
Srio_SockHandle     mgmtSocket;
Qmss_QueueHnd       memoryHeapQueue;


Void myStartupFxn (Void);
static void myAppRawRxFree (Srio_DrvBuffer hDrvBuffer);
static int32_t system_init (void);
static int32_t setupSRIOAppConfig (Qmss_MemRegion memRegion);
static int32_t initMemPool (Qmss_MemRegion memRegion);


Void myStartupFxn (Void)
{
	MultiProc_setLocalId (CSL_chipReadReg (CSL_CHIP_DNUM));
}



/**
 *  @b Description
 *  @n
 *      This function enables the power/clock domains for SRIO.
 *      The SRIO power domain is turned OFF by default.
 *
 *  @retval
 *      Success     -   0
 *  @retval
 *      Error       -   <0
 */
static int32_t enable_srio (void)
{
    /* Set SRIO Power domain to ON */
    CSL_PSC_enablePowerDomain (CSL_PSC_PD_SRIO);

    /* Enable the clocks too for SRIO */
    CSL_PSC_setModuleNextState (CSL_PSC_LPSC_SRIO, PSC_MODSTATE_ENABLE);

    /* Start the state transition */
    CSL_PSC_startStateTransition (CSL_PSC_PD_SRIO);

    /* Wait until the state transition process is completed. */
    while (!CSL_PSC_isStateTransitionDone (CSL_PSC_PD_SRIO));

    /* Return SRIO PSC status */
    if ((CSL_PSC_getPowerDomainState(CSL_PSC_PD_SRIO) == PSC_PDSTATE_ON) &&
        (CSL_PSC_getModuleState (CSL_PSC_LPSC_SRIO) == PSC_MODSTATE_ENABLE))
    {
        /* SRIO ON. Ready for use */
        return 0;
    }
    else
    {
        /* SRIO Power on failed. Return error */
        return -1;
    }
}

static int32_t initMemPool (Qmss_MemRegion memRegion)
{
    Cppi_DescCfg        descCfg;
    uint32_t            numAllocated;
    uint32_t            index;
    uint8_t*            ptrDataBuffer;
    Error_Block	        errorBlock;
    Qmss_QueueHnd       tempQueue;
    uint8_t             isAllocated;
    Cppi_HostDesc*      ptrHostDesc;
	uint32_t coreNum;

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


    /* Create a general purpose heap queue. */
    memoryHeapQueue = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated);
    if (memoryHeapQueue < 0)
        return -1;

    /* Populate the CPPI descriptor configuration */
    descCfg.memRegion                 = memRegion;
	descCfg.descNum                   = ((coreNum == 0) ? NUM_TX_DESC_ON_RX_SIDE : NUM_TX_DESC);
    descCfg.destQueueNum              = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.queueType                 = Qmss_QueueType_GENERAL_PURPOSE_QUEUE;
    descCfg.initDesc                  = Cppi_InitDesc_INIT_DESCRIPTOR;
    descCfg.descType                  = Cppi_DescType_HOST;
    descCfg.returnQueue.qMgr          = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.returnQueue.qNum          = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.epibPresent               = Cppi_EPIB_NO_EPIB_PRESENT;
    descCfg.returnPushPolicy          = Qmss_Location_TAIL;
    descCfg.cfg.host.returnPolicy     = Cppi_ReturnPolicy_RETURN_ENTIRE_PACKET;
    descCfg.cfg.host.psLocation       = Cppi_PSLoc_PS_IN_DESC;

    /* Initialize the descriptors and place all of them into the Memory Heap Queue. */
    tempQueue  = Cppi_initDescriptor (&descCfg, &numAllocated);
    if (tempQueue < 0)
        return -1;

    /* Did we get all the descriptors we requested for? */
    if (numAllocated != descCfg.descNum)
        return -1;

    /* Now attach buffers to these descriptors. */
    for (index = 0; index < numAllocated; index++)
    {
        /* Allocate a data buffer from the System Heap. */
        ptrDataBuffer = Memory_alloc (NULL, MESSAGE_MAX_DATA_SIZE, 0, &errorBlock);
        if (ptrDataBuffer == NULL)
            return -1;

        /* Convert the address to a global address. */
        ptrDataBuffer = (uint8_t*)l2_global_address((uint32_t)ptrDataBuffer);

        /* Pop off the descriptor from the temporary queue. */
        ptrHostDesc = Qmss_queuePop (tempQueue);

        /* Set the data and payload length. */
	    Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc*)ptrHostDesc, ptrDataBuffer, MESSAGE_MAX_DATA_SIZE);
        Cppi_setOriginalBufInfo (Cppi_DescType_HOST, (Cppi_Desc*)ptrHostDesc, ptrDataBuffer, MESSAGE_MAX_DATA_SIZE);

        /* Initialize the return queue to be the same as the memory heap queue. */
        Cppi_setReturnQueue (Cppi_DescType_HOST, (Cppi_Desc*)ptrHostDesc, Qmss_getQueueNumber(memoryHeapQueue));

        /* Push the descriptor back into the Heap queue. */
        Qmss_queuePushDesc (memoryHeapQueue, (uint32_t *)ptrHostDesc);
    }

    /* Close the temporary queue. */
    Qmss_queueClose (tempQueue);

    if (testControl.srio_isRunProgress)
    {
    	/* Debug Message: */
    	System_printf ("Debug: Memory Heap Queue 0x%x\n", memoryHeapQueue);
    }
    return 0;
}
static int32_t system_init (void)
{
    int32_t             result;
    Qmss_InitCfg        qmssInitConfig;

    /* Initialize the QMSS Configuration block. */
    memset (&qmssInitConfig, 0, sizeof (Qmss_InitCfg));

    /* Set up the linking RAM. Use the internal Linking RAM.
     * LLD will configure the internal linking RAM address and maximum internal linking RAM size if
     * a value of zero is specified. Linking RAM1 is not used */
    qmssInitConfig.linkingRAM0Base = 0;
    qmssInitConfig.linkingRAM0Size = 0;
    qmssInitConfig.linkingRAM1Base = 0;
    qmssInitConfig.maxDescNum      = NUM_HOST_DESC*2;


    /* PDSP Configuration: Little Endian */
    qmssInitConfig.pdspFirmware[0].pdspId   = Qmss_PdspId_PDSP1;
    qmssInitConfig.pdspFirmware[0].firmware = &acc48_le;
    qmssInitConfig.pdspFirmware[0].size     = sizeof (acc48_le);

    /* Initialize Queue Manager Sub System */
    result = Qmss_init (&qmssInitConfig, &qmssGblCfgParams);
    if (result != QMSS_SOK)
    {
        System_printf ("Error initializing Queue Manager SubSystem error code : %d\n", result);
        return -1;
    }

    /* Start the QMSS. */
    if (Qmss_start() != QMSS_SOK)
    {
        System_printf ("Error: Unable to start the QMSS\n");
        return -1;
    }

    /* Initialize CPPI CPDMA */
    result = Cppi_init (&cppiGblCfgParams);
    if (result != CPPI_SOK)
    {
        System_printf ("Error initializing Queue Manager SubSystem error code : %d\n", result);
        return -1;
    }

    if (testControl.srio_isRunProgress)
    {
    	/* CPPI and Queue Manager are initialized. */
    	System_printf ("Debug: Queue Manager and CPPI are initialized.\n");
    }
    return 0;
}



static void myAppRawRxFree (Srio_DrvBuffer hDrvBuffer)
{
    Qmss_QueueHnd       returnQueueHnd;
    Cppi_HostDesc*      ptrHostDesc;

    /* Get the pointer to the descriptor. */
    ptrHostDesc = (Cppi_HostDesc*)hDrvBuffer;

    /* Cycle through all the linked descriptors and clean them up. */
    while (ptrHostDesc != NULL)
    {
        /* Get the return queue. */
        returnQueueHnd = Qmss_getQueueHandle (Cppi_getReturnQueue(Cppi_DescType_HOST, (Cppi_Desc*)ptrHostDesc));

        /* Push the descriptor into the return queue. */
        Qmss_queuePushDesc (returnQueueHnd, (Ptr)ptrHostDesc);

        /* Get the next linked descriptor. */
        ptrHostDesc = (Cppi_HostDesc*)Cppi_getNextBD(Cppi_DescType_HOST,(Cppi_Desc*)ptrHostDesc);
    }
}


static int32_t setupSRIOAppConfig (Qmss_MemRegion memRegion)
{
    Qmss_QueueHnd   myRxFreeQueueHnd;
    Qmss_QueueHnd   myRxCompletionQueueHnd;
    Qmss_QueueHnd   tmpQueueHnd;
    uint32_t        numAllocated;
    uint8_t         isAllocated;
    Cppi_DescCfg    descCfg;
    uint16_t        index;
    Cppi_HostDesc*  ptrHostDesc;
    uint8_t*        ptrRxData;
    Srio_DrvConfig  appCfg;
    Error_Block	    errorBlock;
    Qmss_Queue      queueInfo;
    int32_t         coreToQueueSelector[4];
	uint32_t coreNum;

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

    /* Initialize the SRIO Driver Configuration. */
    memset ((Void *)&appCfg, 0, sizeof(Srio_DrvConfig));

    /* Create the application receive free queue. */
    myRxFreeQueueHnd = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, QMSS_PARAM_NOT_SPECIFIED,
                                       &isAllocated);
    if (myRxFreeQueueHnd < 0)
	{
	    System_printf ("Error: Unable to create receive queues.\n");
	    return -1;
    }

    /* This is the table which maps the core to a specific receive queue for interrupt support. */

	/* High priority accumulation and interrupt support queues */
	coreToQueueSelector[0] = HIGH_PRIORITY_ACC_INT_QUEUE_BASE;
	coreToQueueSelector[1] = HIGH_PRIORITY_ACC_INT_QUEUE_BASE + 1;
	coreToQueueSelector[2] = HIGH_PRIORITY_ACC_INT_QUEUE_BASE + 2;
	coreToQueueSelector[3] = HIGH_PRIORITY_ACC_INT_QUEUE_BASE + 3;

	/* Create the application receive completion queue. */
	myRxCompletionQueueHnd = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE,
											 coreToQueueSelector[CSL_chipReadReg(CSL_CHIP_DNUM)],
											 &isAllocated);
	if (myRxCompletionQueueHnd < 0)
	{
		System_printf ("Error: Unable to create the receive completion queue.\n");
		return -1;
	}


    /* Application created queue which stores all the receive buffers. */
    descCfg.memRegion                 = memRegion;
	descCfg.descNum                   = ((coreNum == 0) ? NUM_RX_DESC : NUM_RX_DESC_ON_TX_SIDE);
	descCfg.destQueueNum              = QMSS_PARAM_NOT_SPECIFIED;
	descCfg.queueType                 = Qmss_QueueType_GENERAL_PURPOSE_QUEUE;
	descCfg.initDesc                  = Cppi_InitDesc_INIT_DESCRIPTOR;
	descCfg.descType                  = Cppi_DescType_HOST;
	descCfg.returnQueue               = Qmss_getQueueNumber (myRxFreeQueueHnd);
	descCfg.epibPresent               = Cppi_EPIB_NO_EPIB_PRESENT;
    descCfg.returnPushPolicy          = Qmss_Location_HEAD;
	descCfg.cfg.host.returnPolicy     = Cppi_ReturnPolicy_RETURN_ENTIRE_PACKET;
	descCfg.cfg.host.psLocation       = Cppi_PSLoc_PS_IN_DESC;

    /* Initialize the descriptors. */
	tmpQueueHnd = Cppi_initDescriptor (&descCfg, &numAllocated);
	if (tmpQueueHnd < 0)
	    return -1;

    /* Initialize the application receive buffers. */
    for (index = 0; index < descCfg.descNum; index++)
    {
	    /* Pop off a descriptor */
	    ptrHostDesc = (Cppi_HostDesc *)Qmss_queuePop(tmpQueueHnd);
	    if (ptrHostDesc == NULL)
	        return -1;

	    /* Allocate the receive buffer where the data will be received into by the SRIO CPDMA. */
	    /* Make sure to adjust the RX buffer size to work around the SRIO CPDMA issue.         */
	    ptrRxData = (uint8_t*)Memory_alloc (NULL, (MESSAGE_MAX_DATA_SIZE+RX_BUFFER_BYTES_ADJUSTMENT), 0, &errorBlock);
	    if (ptrRxData == NULL)
	        return -1;

        /* Convert the address to a global address. */
        ptrRxData = (uint8_t*)l2_global_address((uint32_t)ptrRxData);

        /* Set the DATA and ORIGNAL DATA in the buffer descriptor. */
        Cppi_setData (Cppi_DescType_HOST, (Cppi_Desc*)ptrHostDesc, (uint8_t*)ptrRxData, (MESSAGE_MAX_DATA_SIZE+RX_BUFFER_BYTES_ADJUSTMENT));
        Cppi_setOriginalBufInfo (Cppi_DescType_HOST, (Cppi_Desc*)ptrHostDesc, (uint8_t*)ptrRxData, (MESSAGE_MAX_DATA_SIZE+RX_BUFFER_BYTES_ADJUSTMENT));

        /* Add the packet descriptor to the Application Receive Free Queue. */
	    Qmss_queuePushDesc (myRxFreeQueueHnd, (uint32_t*)ptrHostDesc);
    }

    /* Close the temporary queue. */
    Qmss_queueClose (tmpQueueHnd);

    /* Setup the SRIO Driver Configuration: This is application managed configuration */
    appCfg.bAppManagedConfig = TRUE;

    /* Get the queue information about the receive completion queue. */
    queueInfo = Qmss_getQueueNumber (myRxCompletionQueueHnd);

    /* The application managed configuration is capable of reception. */
    appCfg.u.appManagedCfg.bIsRxFlowCfgValid = 1;

    /* Configure the Receive Flow */
	appCfg.u.appManagedCfg.rxFlowCfg.flowIdNum          = -1;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_dest_qnum       = queueInfo.qNum;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_dest_qmgr       = queueInfo.qMgr;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_sop_offset      = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_ps_location     = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_desc_type       = 0x1; /* Host Descriptor. */
	appCfg.u.appManagedCfg.rxFlowCfg.rx_error_handling  = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_psinfo_present  = 0x1; /* PS Information */
	appCfg.u.appManagedCfg.rxFlowCfg.rx_einfo_present   = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_dest_tag_lo     = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_dest_tag_hi     = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_src_tag_lo      = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_src_tag_hi      = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_dest_tag_lo_sel = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_dest_tag_hi_sel = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_src_tag_lo_sel  = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_src_tag_hi_sel  = 0x0;

    /* Disable Receive size thresholds. */
    appCfg.u.appManagedCfg.rxFlowCfg.rx_size_thresh0_en = 0x0;
    appCfg.u.appManagedCfg.rxFlowCfg.rx_size_thresh1_en = 0x0;
    appCfg.u.appManagedCfg.rxFlowCfg.rx_size_thresh2_en = 0x0;

	/* Use the Application Receive Free Queue for picking all descriptors. */
	queueInfo = Qmss_getQueueNumber (myRxFreeQueueHnd);
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq1_qnum       = queueInfo.qNum;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq1_qmgr       = queueInfo.qMgr;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq2_qnum       = 0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq2_qmgr       = 0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq3_qnum       = 0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq3_qmgr       = 0;

    /* Use the Receive Queue for picking the SOP packet also. */
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq0_sz0_qnum   = queueInfo.qNum;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq0_sz0_qmgr   = queueInfo.qMgr;

    /* There are no size thresholds configured. */
    appCfg.u.appManagedCfg.rxFlowCfg.rx_size_thresh0    = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_size_thresh1    = 0x0;
    appCfg.u.appManagedCfg.rxFlowCfg.rx_size_thresh2    = 0x0;

    /* The other threshold queues do not need to be configured */
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq0_sz1_qnum   = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq0_sz1_qmgr   = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq0_sz2_qnum   = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq0_sz2_qmgr   = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq0_sz3_qnum   = 0x0;
	appCfg.u.appManagedCfg.rxFlowCfg.rx_fdq0_sz3_qmgr   = 0x0;

		/* Program the accumulator. */
	appCfg.u.appManagedCfg.bIsAccumlatorCfgValid = 1;


    /* Accumulator Configuration. */
	appCfg.u.appManagedCfg.accCfg.channel             = CSL_chipReadReg (CSL_CHIP_DNUM);
	appCfg.u.appManagedCfg.accCfg.command             = Qmss_AccCmd_ENABLE_CHANNEL;
	appCfg.u.appManagedCfg.accCfg.queueEnMask         = 0;
	appCfg.u.appManagedCfg.accCfg.queMgrIndex         = coreToQueueSelector[CSL_chipReadReg(CSL_CHIP_DNUM)];
	appCfg.u.appManagedCfg.accCfg.maxPageEntries      = sizeof(gHiPriAccumList)/8;
	appCfg.u.appManagedCfg.accCfg.timerLoadCount      = 0;
	appCfg.u.appManagedCfg.accCfg.interruptPacingMode = Qmss_AccPacingMode_LAST_INTERRUPT;
	appCfg.u.appManagedCfg.accCfg.listEntrySize       = Qmss_AccEntrySize_REG_D;
	appCfg.u.appManagedCfg.accCfg.listCountMode       = Qmss_AccCountMode_ENTRY_COUNT;
	appCfg.u.appManagedCfg.accCfg.multiQueueMode      = Qmss_AccQueueMode_SINGLE_QUEUE;

    /* Initialize the accumulator list memory */
    memset ((void *)&gHiPriAccumList[0], 0, sizeof(gHiPriAccumList));
    appCfg.u.appManagedCfg.accCfg.listAddress = l2_global_address((uint32_t)&gHiPriAccumList[0]);

    /* Populate the rest of the configuration. */
    appCfg.u.appManagedCfg.rawRxFreeDrvBuffer = myAppRawRxFree;
    appCfg.u.appManagedCfg.txQueueNum = QMSS_PARAM_NOT_SPECIFIED;

    /* Set the PKTDMA TX channel priority to low */
    appCfg.u.appManagedCfg.srioPktDmaTxPrio = Srio_PktDma_Prio_Low;

    /* Start the application Managed SRIO Driver. */
    hAppManagedSrioDrv = Srio_start (&appCfg);
    if (hAppManagedSrioDrv == NULL)
    {
        System_printf ("Error: Application Managed SRIO Driver failed to start\n");
        return -1;
    }

    if (testControl.srio_isRunProgress)
    {
    	/* Debug Message: */
        System_printf ("Debug: AppConfig RxFreeQueue: 0x%x RxCompletionQueue: 0x%x\n",
                        myRxFreeQueueHnd, myRxCompletionQueueHnd);
        System_printf ("Debug: Accumulator List: 0x%x\n", appCfg.u.appManagedCfg.accCfg.listAddress);
    }

    /* Configuration was successful. */
    return 0;
}

char* testsToRunDecodeText (uint32_t testToRunCode)
{
	static char		testToRunCodeString[25];
	switch (testToRunCode)
	{
		case srio_nwrite_tests:
			sprintf (testToRunCodeString,"NWRITE tests");
			break;
		case srio_nread_tests:
			sprintf (testToRunCodeString,"NREAD tests");
			break;
		case srio_nwrite_nread_tests:
			sprintf (testToRunCodeString,"NWRITE and NREAD tests");
			break;
		case srio_type11_tests:
			sprintf (testToRunCodeString,"Type-11 tests");
			break;
		case srio_all_available_tests:
			sprintf (testToRunCodeString,"All tests");
			break;
		default:
			sprintf (testToRunCodeString,"Unknown: %d",testToRunCode);
			break;
	}
	return (testToRunCodeString);
}
static int32_t setOneStartParameter (int paramIndex, int32_t paramValue)
{
	int32_t	returnStatus = 0;

	switch (paramIndex)
	{
		case 0:	/* Parameter is always zero and therefore is not of use */
			break;
		case 1: /* Set port lane configuration */
			switch (paramValue)
			{
				case 1:
					testControl.srio_lanesMode = srio_lanes_form_four_1x_ports;
					System_printf ("Four 1X ports");
					break;
				case 2:
					testControl.srio_lanesMode = srio_lanes_form_two_2x_ports;
					System_printf ("Two 2X ports");
					break;
				case 4:
					testControl.srio_lanesMode = srio_lanes_form_one_4x_port;
					System_printf ("One 4X port");
					break;
				default:
					System_printf ("\n**Port configuration value");
					returnStatus = -1;
					break;
			}
			break;
		case 2:	/* Set lane rate */
			switch (paramValue)
			{
				case 1:
					testControl.srio_laneSpeedGbps = srio_lane_rate_1p250Gbps;
					System_printf ("1.25Gbaud lane rate");
					break;
				case 2:
					testControl.srio_laneSpeedGbps = srio_lane_rate_2p500Gbps;
					System_printf ("2.5Gbaud lane rate");
					break;
				case 3:
					testControl.srio_laneSpeedGbps = srio_lane_rate_3p125Gbps;
					System_printf ("3.125Gbaud lane rate");
					break;
				case 5:
					testControl.srio_laneSpeedGbps = srio_lane_rate_5p000Gbps;
					System_printf ("5.0Gbaud lane rate");
					break;
				default:
					System_printf ("\n**Lane rate");
					returnStatus = -1;
					break;
			}
			break;
		case 3:	/* Set the number of seconds to run the test per packet size */
			if ((paramValue >= 1) && (paramValue <= 65535))
			{
				testControl.srio_testTimeInSeconds =  paramValue;
				System_printf ("%d seconds test time per packet size", testControl.srio_testTimeInSeconds);
			}
			else
			{
				System_printf ("\n**Test seconds");
				returnStatus = -1;
			}
			break;
		case 4:	/* Set test mode for which tests to run */
			if ((paramValue >= 0) && (paramValue <= srio_all_available_tests))
			{
				testControl.srio_testsToRun =  (srioTestsToRun_e)paramValue;
				System_printf ("%s will be run", testsToRunDecodeText(testControl.srio_testsToRun));
			}
			else
			{
				System_printf ("\n**Tests to run selection number");
				returnStatus = -1;
			}
			break;
		case 5:	/* Set packet size to start with */
			if ((paramValue >= 4) && (paramValue <= 8192))
			{
				/* Set dio payload start size */
				testControl.srio_dioPayloadSize = paramValue;

				/* Set type11 payload start size */
				if (paramValue < 16)
					testControl.srio_payloadSize = 16 - SOFTWARE_HEADER_BYTES;
				else if (paramValue > 4096)
					testControl.srio_payloadSize = 4096 - SOFTWARE_HEADER_BYTES;
				else
					testControl.srio_payloadSize = paramValue - SOFTWARE_HEADER_BYTES;

				System_printf ("%d bytes start packet size", paramValue);
			}
			else
			{
				System_printf ("\n**Packet start size");
				returnStatus = -1;
			}
			break;
		case 6:	/* Set packet size to end with */
			if ((paramValue >= 4) && (paramValue <= 8192))
			{
				/* Set dio payload end size */
				testControl.srio_dioPayloadEndSize = paramValue;

				/* Set type11 payload end size */
				if (paramValue < 16)
					testControl.srio_payloadEndSize = 16 - SOFTWARE_HEADER_BYTES;
				else if (paramValue > 4096)
					testControl.srio_payloadEndSize = 4096 - SOFTWARE_HEADER_BYTES;
				else
					testControl.srio_payloadEndSize = paramValue - SOFTWARE_HEADER_BYTES;

				System_printf ("%d bytes end packet size", paramValue);
			}
			else
			{
				System_printf ("\n**Packet end size");
				returnStatus = -1;
			}
			break;
		case 7:	/* Set core that will initialize sRIO IP */
			if ((paramValue >= 0) && (paramValue <= 1))
			{
				testControl.srio_initCorenum = paramValue;
				System_printf ("Core %d will initialize the sRIO IP", paramValue);
			}
			else
			{
				System_printf ("\n**sRIO core init value");
				returnStatus = -1;
			}
			break;
		case 8:	/* Set whether test is board to board */
			if ((paramValue >= 0) && (paramValue <= 1))
			{
				testControl.srio_isBoardToBoard = ((paramValue == 1) ? TRUE : FALSE);
				System_printf ("Testing %s", ((testControl.srio_isBoardToBoard) ? "board to board" : "core to core on same EVM"));
			}
			else
			{
				System_printf ("\n**Board to board value");
				returnStatus = -1;
			}
			break;
		case 9:	/* Set whether external SRIO switch is being used for test. */
			if ((paramValue >= 0) && (paramValue <= 1))
			{
				testControl.srio_isExternalSrioSwitch = ((paramValue == 1) ? TRUE : FALSE);
				System_printf ("%s for test", ((testControl.srio_isExternalSrioSwitch) ? "Using external SRIO switch" : "Not using external SRIO switch"));
			}
			else
			{
				System_printf ("\n**External SRIO switch being used value");
				returnStatus = -1;
			}
			break;
	}
	if (returnStatus != 0)
	{
		System_printf (" of %d is invalid, please try again.\n", paramValue);
		System_printf ("   Options available: [port_confg] [lane_rate] [test_secs] [tests_to_run]\n");
		System_printf ("                      [packet_start_size] [packet_end_size] [srio_init_core]\n");
		System_printf ("                      [board_to_board] [srio_switch]\n");
		System_printf ("       Option ranges:\n");
		System_printf (" -------------------------------------------------------------\n");
		System_printf ("        [port_confg]: (1X, 2X, 4X)              default: 4X\n");
		System_printf ("         [lane_rate]: (1.25, 2.50, 3.125, 5.0)  default: 5.0\n");
		System_printf ("         [test_secs]: (1 to 65535)              default: 60\n");
		System_printf ("      [tests_to_run]: (0 to %d)                  default: %d\n", srio_all_available_tests, testControl.srio_testsToRun);
		System_printf ("                       %d for NWRITE, %d for NREAD, %d for NWRITE & NREAD,.\n", srio_nwrite_tests, srio_nread_tests, srio_nwrite_nread_tests);
		System_printf ("                       %d for Type11, %d for all tests.\n", srio_type11_tests, srio_all_available_tests);
		System_printf (" [packet_start_size]: (%d to %d)              default: %d\n", SOFTWARE_HEADER_BYTES, MESSAGE_MAX_DATA_SIZE, MESSAGE_INITIAL_DATA_SIZE);
		System_printf ("   [packet_end_size]: (%d to %d)              default: %d\n", SOFTWARE_HEADER_BYTES, MESSAGE_MAX_DATA_SIZE, MESSAGE_MAX_DATA_SIZE);
		System_printf ("    [srio_init_core]: (%d to %d)                  default: %d\n", 0, 1, 0);
		System_printf ("                       For core to core testing:\n");
		System_printf ("                         0 for RX and TX side.\n");
		System_printf ("                       For board to board testing:\n");
		System_printf ("                         0 for RX side (Consumer).\n");
		System_printf ("                         1 for TX side (Producer).\n");
		System_printf ("    [board_to_board]: (%d to %d)                  default: %d\n", 0, 1, 0);
		System_printf ("                       0 for core to core testing.\n");
		System_printf ("                       1 for board to board testing.\n");
		System_printf ("     [srio_switch]  : (%d to %d)                  default: %d\n", 0, 1, 0);
		System_printf ("                       0 when not using an external SRIO switch.\n");
		System_printf ("                       1 when using an external SRIO switch.\n");
		System_printf ("  Note:All options shown are optional, but they must be specified in the order\n");
		System_printf ("       shown above. For example, in order to use the {test_secs} parameter the\n");
		System_printf ("       {port_config} and {lane_rate} parameters must be specified before it.\n\n");
	}
	return returnStatus;
}

/**
 *  @b Description
 *  @n
 *      Utility function that will set the global variables that determine how the test will be run,
 *      if user passes values to the test.
 *
 *  @param[in]  argc
 *      Count of parameters passed to this application.
 *  @param[in]  argv
 *      Array of parameters passed to this application.
 *  @param[in]  coreNum
 *      Core for which these parameters are being set.
 *
 *  @retval
 *      Success - 0
 *  @retval
 *      Error   - <0
 */
int32_t setStartParameters (int argc, char* argv[], uint32_t coreNum)
{
	int					index;

	if (argc > 0)
		System_printf ("Setting core %d test parameters to:\n", coreNum);

	/* Process all arguments */
	for (index=1; index < argc; index++)
	{
		System_printf("  ");
		if (setOneStartParameter(index, atol(argv[index])) < 0)
			return -1;
		System_printf ("\n");
	}
	if (argc > 0)
		System_printf ("\n");
	return 0;
}

void main (int argc, char* argv[])
{
    Qmss_MemRegInfo     memRegInfo;
    int32_t             result;
    int32_t             eventId;
	uint32_t			coreNum;
	int i;

	int cnt = 0;
	SrioBootCmd = 0;
	/* Get the core number. */
	coreNum = CSL_chipReadReg (CSL_CHIP_DNUM);


	if (setStartParameters(argc, argv, coreNum) < 0 )
		return;

    /* Enable the TSC */
	CSL_tscEnable ();
/*
	//ddr3 config
	for(i = 128 + coreNum * 8; i < 128 + (coreNum + 1) * 8; i ++)
	{
		*(unsigned int *) (0x01848000 + i * 4) |= 0x1;
	}
*/
	gpio_Init();
	gpio_Output(14, 1);
	gpio_Output(15, 1);

    /* Initialize the Time stamp. */
    TSCH = 0;
    TSCL = 0;

	srio_device_ID1 = MASTER_8BIT_DEVICE_ID;
	srio_device_ID2 = SLAVE_8BIT_DEVICE_ID;

	testControl.srio_isLoopbackMode = FALSE;

    /* Initializations depend on the core type. */

		/* Debug Message: */
	System_printf ("*************SRIO CORE %d INIT START*******************\n",coreNum);

	/* Initialize the CPPI and QMSS Modules. */
	if (system_init () < 0)
	{
		System_printf ("*************system_init Initialization Failed!!*******************\n");
		return;
	}

	/* Power on SRIO peripheral before using it */
	if (enable_srio () < 0)
	{
		System_printf ("Error: SRIO PSC Initialization Failed\n");
		return;
	}

        /* Initialize the Host Region. */
        memset ((void *)&master_region, 0, sizeof(master_region));

		/* Memory Region Configuration */
		memRegInfo.descBase         = (uint32_t *)l2_global_address((uint32_t)master_region);
		memRegInfo.descSize         = SIZE_HOST_DESC;
		memRegInfo.descNum          = NUM_HOST_DESC;
		memRegInfo.manageDescFlag   = Qmss_ManageDesc_MANAGE_DESCRIPTOR;
		memRegInfo.memRegion        = Qmss_MemRegion_MEMORY_REGION_NOT_SPECIFIED;

		/* Initialize and inset the memory region. */
		result = Qmss_insertMemoryRegion (&memRegInfo);
		if (result < QMSS_SOK)
		{
			System_printf ("Error inserting memory region: %d\n", result);
			return;
		}

		gpio_Output(14, 0);
		/* Device Specific SRIO Initializations: This should always be called before
		 * initializing the SRIO Driver. */
		if (SrioDevice_init () < 0)
			return;


		/* Initialize the SRIO Driver */
		if (Srio_init () < 0)
			return;

		gpio_Output(14, 1);

        /* Write to the SHARED memory location at this point in time. The other cores cannot execute
         * till the SRIO Driver is up and running. */
        isSRIOInitialized[0] = 1;

        /* The SRIO IP block has been initialized. We need to writeback the cache here because it will
         * ensure that the rest of the cores which are waiting for SRIO to be initialized would now be
         * woken up. */
        CACHE_wbL1d ((void *) &isSRIOInitialized[0], 128, CACHE_FENCE_WAIT);

        /* Create Internal Heap */
        if (initMemPool((Qmss_MemRegion)result) < 0)
            return;

	    /* Clear Errors*/
	    clearSrioStatusErrors ();


    /* Create the Application Managed Configuration. */
    if (setupSRIOAppConfig((Qmss_MemRegion)result) == -1)
        return;

    /* Hook up the interrupts if using interrupt mode. */

    	/* Hook up the SRIO interrupts with the core. */
	EventCombiner_dispatchPlug (48, (EventCombiner_FuncPtr)Srio_rxCompletionIsr, (UArg)hAppManagedSrioDrv, TRUE);
	EventCombiner_enableEvent (48);

	/* SRIO DIO: Interrupts need to be routed from the CPINTC0 to GEM Event.
	 *  - We have configured DIO Interrupts to get routed to Interrupt Destination 0
	 *    (Refer to the CSL_SRIO_SetDoorbellRoute API configuration in the SRIO Initialization)
	 *  - We want this to mapped to Host Interrupt 8
	 *
	 *  Map the System Interrupt i.e. the Interrupt Destination 0 interrupt to the DIO ISR Handler. */
	CpIntc_dispatchPlug(CSL_INTC0_INTDST0, myDIOIsr, (UArg)hAppManagedSrioDrv, TRUE);

	/* SRIO DIO: Configuration is for CPINTC0. We map system interrupt 112 to Host Interrupt 8. */
	CpIntc_mapSysIntToHostInt(0, CSL_INTC0_INTDST0, 8);

	/* SRIO DIO: Enable the Host Interrupt. */
	CpIntc_enableHostInt(0, 8);

	/* SRIO DIO: Get the event id associated with the host interrupt. */
	eventId = CpIntc_getEventId(8);

	/* SRIO DIO: Plug the CPINTC Dispatcher. */
	EventCombiner_dispatchPlug (eventId, CpIntc_dispatch, 8, TRUE);

	/* Debug Message */
	System_printf ("Debug: Interrupts Registration complete\n");


    /* Debug Message: */
    System_printf ("Debug: SRIO Driver handle 0x%x.\n\n\n", hAppManagedSrioDrv);

    /* Create the DIO Management Socket. */
    mgmtSocket = createMgmtSocket ();
    Srio_Slave_init();

    /* Start the appropriate tasks. */
	if (coreNum == SLAVE_CORE)
	{
		gGpioLedFlag = 0;
		while(1)
		{
			if((cnt++ % 10000000) == 0)
			{
				if(gGpioLedFlag)
				{
					gpio_Output(14, 1);
					gpio_Output(15, 0);
					gGpioLedFlag = 0;
				}
				else
				{
					gpio_Output(14, 0);
					gpio_Output(15, 1);
					gGpioLedFlag = 1;
				}

				if(SrioBootCmd==0xc8c8)
				{
					for(i = 1; i < 8; i ++)
					{
					*(unsigned int *) 0x02620038 = 0x83E70B13;
					*(unsigned int *) 0x0262003C = 0x95A4F1E0;

					*(unsigned int *) (0x02620040 + i * 4)     = 0x10800400 + (i << 24);
					*(unsigned int *) (0x1087FFFC + (i << 24)) = 0x10800400 + (i << 24);

					*(unsigned int *) (0x02620240 + i * 4) = 0x1;
					}
					SrioBootCmd = 0x0000;
				}

			}
		}
	}

//    BIOS_start();
}

void timer_isr()
{
	if(gGpioLedFlag)
	{
		gpio_Output(14, 1);
		gpio_Output(15, 0);
		gGpioLedFlag = 0;
	}
	else
	{
		gpio_Output(14, 0);
		gpio_Output(15, 1);
		gGpioLedFlag = 1;
	}
	return ;
}
