#include <xdc/std.h>
#include <string.h>
#include <c6x.h>
#include <xdc/runtime/IHeap.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/Memory.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/heaps/HeapBuf.h>
#include <ti/sysbios/heaps/HeapMem.h>
//#include <ti/sysbios/family/c64p/Hwi.h>
#include <ti/sysbios/family/c64p/EventCombiner.h>
#include <ti/sysbios/family/c66/tci66xx/CpIntc.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>

/* SRIO Driver Include File. */
#include <ti/drv/srio/srio_osal.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 SRIO Functional Layer */
#include <ti/csl/csl_srio.h>
#include <ti/csl/csl_srioAux.h>
#include <ti/csl/csl_srioAuxPhyLayer.h>

/* CSL BootCfg Module */
#include <ti/csl/csl_bootcfg.h>
#include <ti/csl/csl_bootcfgAux.h>

/* CSL Chip Functional Layer */
#include <ti/csl/csl_chip.h>

/* CSL Cache Functional Layer */
#include <ti/csl/csl_cacheAux.h>

/* PSC CSL Include Files */
#include <ti/csl/csl_psc.h>
#include <ti/csl/csl_pscAux.h>

/* CSL CPINTC Include Files. */
#include<ti/csl/csl_cpIntc.h>


/* IPC includes */
#include <ti/ipc/GateMP.h>
#include <ti/ipc/Ipc.h>
#include <ti/ipc/ListMP.h>
#include <ti/ipc/SharedRegion.h>
#include <ti/ipc/MultiProc.h>

#include <xdc/cfg/global.h>



#include "SCubeDSP.h"


/**********************************************************************
 ************************* LOCAL Definitions **************************
 **********************************************************************/

/* These are the GARBAGE queues which are used by the TXU to dump the
 * descriptor if there is an error instead of recycling the descriptor
 * to the free queue. */
#define GARBAGE_LEN_QUEUE           905
#define GARBAGE_TOUT_QUEUE          906
#define GARBAGE_RETRY_QUEUE         907
#define GARBAGE_TRANS_ERR_QUEUE     908
#define GARBAGE_PROG_QUEUE          909
#define GARBAGE_SSIZE_QUEUE         910

/* SRIO Device Information
 * - 16 bit Device Identifier.
 * - 8 bit Device Identifier.
 * - Vendor Identifier.
 * - Device Revision. */
//#define DEVICE_VENDOR_ID            0x0E
//#define DEVICE_REVISION             0x4
#define DEVICE_VENDOR_ID            0x30
#define DEVICE_REVISION             0x0

/* SRIO Assembly Information
 * - Assembly Identifier
 * - Assembly Vendor Identifier.
 * - Assembly Device Revision.
 * - Assembly Extension Features */
//#define DEVICE_ASSEMBLY_ID          0x0
//#define DEVICE_ASSEMBLY_VENDOR_ID   0x0
//#define DEVICE_ASSEMBLY_REVISION    0x0
//#define DEVICE_ASSEMBLY_INFO        0x0
#define DEVICE_ASSEMBLY_ID          0x0
#define DEVICE_ASSEMBLY_VENDOR_ID   0x30
#define DEVICE_ASSEMBLY_REVISION    0x0
#define DEVICE_ASSEMBLY_INFO        0x0100

/**********************************************************************
 ************************* Extern Definitions *************************
 **********************************************************************/

extern const uint32_t DEVICE_ID1_16BIT;
extern const uint32_t DEVICE_ID1_8BIT;
extern const uint32_t DEVICE_ID_FPGA_16BIT;
extern const uint32_t DEVICE_ID_DSP_8BIT;

/* Defines number of DIO sockets used in this example */
#define SRIO_DIO_LSU_ISR_NUM_SOCKETS        1

/* Defines number of transfers done by DIO sockets in this example */
#define SRIO_DIO_LSU_ISR_NUM_TRANSFERS      1

/* ISR timeout value (in cycles) used in this example */
#define SRIO_DIO_LSU_ISR_TIMEOUT        200000

CSL_SrioHandle  hSrioCSL;
Srio_SockBindAddrInfo   bindInfo;

/* Array containing SRIO socket handles */
Srio_SockHandle srioSocket[SRIO_DIO_LSU_ISR_NUM_SOCKETS];


/* Source and Destination Data Buffers (payload buffers) */
UInt8* srcDataBuffer[SRIO_DIO_LSU_ISR_NUM_SOCKETS * SRIO_DIO_LSU_ISR_NUM_TRANSFERS];
UInt8* dstDataBuffer[SRIO_DIO_LSU_ISR_NUM_SOCKETS * SRIO_DIO_LSU_ISR_NUM_TRANSFERS];
UInt8  **srcDataBufPtr = NULL, **dstDataBufPtr = NULL;

/* Global debug variable to track number of ISRs raised */
volatile UInt32 srioDbgDioIsrCnt = 0;

/* Global variable to indicate completion of ISR processing */
volatile UInt32 srioLsuIsrServiced = 0;

/* Global variables to count good and bad transfers */
volatile UInt32 srioDioLsuGoodTransfers = 0;
volatile UInt32 srioDioLsuBadTransfers  = 0;

extern UInt32 malloc_counter;
extern UInt32 free_counter;


/* Defines the core number responsible for system initialization. */
#define CORE_SYS_INIT               0

extern int32_t SrioDevice_init (void);
Int32 sendSrio(uint32_t src_addr, uint32_t dst_addr, uint8_t BYTE_SIZE);
Int32 receiveSrio(uint32_t src_addr, uint32_t dst_addr, uint8_t BYTE_SIZE);

UInt32          coreNum = 0xFFFF;

/* These are the device identifiers used in the Example Application */
const uint32_t DEVICE_ID1_16BIT     = 0x0285;
const uint32_t DEVICE_ID1_8BIT      = 0x01;
const uint32_t DEVICE_ID_FPGA_16BIT = 0x02;
const uint32_t DEVICE_ID_DSP_8BIT   = 0x01;
//const uint32_t DEVICE_ID3_16BIT    = 0x1234;
//const uint32_t DEVICE_ID3_8BIT     = 0x12;
//const uint32_t DEVICE_ID4_16BIT    = 0x5678;
//const uint32_t DEVICE_ID4_8BIT     = 0x56;

Srio_DrvHandle  hDrvManagedSrioDrv;

/* Global SRIO and QMSS Configuration */
Qmss_InitCfg   qmssInitConfig;
/* CPPI device specific configuration */
extern Cppi_GlobalConfigParams  cppiGblCfgParams;
/* QMSS device specific configuration */
extern Qmss_GlobalConfigParams  qmssGblCfgParams;


/* This is the Number of host descriptors which are available & configured
 * in the memory region for this example. */
#define NUM_HOST_DESC               128

/* This is the size of each descriptor. */
#define SIZE_HOST_DESC              48

/* MTU of the SRIO Driver. We are currently operating @ MTU of 256 bytes. */
#define SRIO_MAX_MTU                256

/* This is the size of the data buffer which is used for DIO Sockets. */
#define SIZE_TX_DIO_PACKET             24
#define SIZE_RX_DIO_PACKET             16

/* Memory allocated for the descriptors. This is 16 bit aligned. */
#pragma DATA_ALIGN (host_region, 16)
Uint8   host_region[NUM_HOST_DESC * SIZE_HOST_DESC];

/* Shared Memory Variable to ensure synchronizing SRIO initialization
 * with all the other cores. */
/* Created an array to pad the cache line with SRIO_MAX_CACHE_ALIGN size */
#pragma DATA_ALIGN   (isSRIOInitialized, 128)
#pragma DATA_SECTION (isSRIOInitialized, ".srioSharedMem");
volatile Uint32     isSRIOInitialized[(SRIO_MAX_CACHE_ALIGN / sizeof(Uint32))] = { 0 };

/* Memory used for the accumulator list. */
#pragma DATA_ALIGN (gHiPriAccumList, 16)
UInt32              gHiPriAccumList[64];

/* OSAL Data Buffer Memory Initialization. */
extern int32_t Osal_dataBufferInitMemory(uint32_t dataBufferSize);

/* Enable Time Stamp Counter */
extern void CSL_tscEnable(void);

/**********************************************************************
 *********************** DEVICE SRIO FUNCTIONS ***********************
 **********************************************************************/

/** @addtogroup SRIO_DEVICE_API
 @{ */

/**
 *  @b Description
 *  @n
 *      The function provides the initialization sequence for the SRIO IP
 *      block. This can be modified by customers for their application and
 *      configuration.
 *
 *  @retval
 *      Success     -   0
 *  @retval
 *      Error       -   <0
 */


#pragma CODE_SECTION(SrioDevice_init, ".text:SrioDevice_init");
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 };

    /* Get the CSL SRIO Handle. */
    hSrio = CSL_SRIO_Open (0);
    if (hSrio == NULL)
        return -1;

    /* Code to disable SRIO reset isolation */
    if (CSL_PSC_isModuleResetIsolationEnabled(CSL_PSC_LPSC_SRIO))
        CSL_PSC_disableModuleResetIsolation(CSL_PSC_LPSC_SRIO);

    /* 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);

    /* 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);

    /* Configure SRIO ports to operate in loopback mode. */
    //for(i = 0; i < 4; i++)
    //  CSL_SRIO_SetLoopbackMode(hSrio, 0);
    for(i = 0; i < 4; i++)
        CSL_SRIO_SetNormalMode(hSrio, i);

    /* 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 ();

    // program the PLL accordingly.
    //CSL_BootCfgSetSRIOSERDESConfigPLL (0x251); // 5Gbps, half rate, x10
    CSL_BootCfgSetSRIOSERDESConfigPLL (0x229);  // 2.5Gbps, half rate, x5

    // Configure the SRIO SERDES Receive Configuration. */
    for(i = 0; i < 4; i++)
        CSL_BootCfgSetSRIOSERDESRxConfig (i, 0x440495);  // half rate

    // Configure the SRIO SERDES Transmit Configuration. */
    for(i = 0; i < 4; i++)
        CSL_BootCfgSetSRIOSERDESTxConfig (1, 0x00180795);


    //CSL_BootCfgSetSRIOSERDESConfigPLL (0x229);  // 1.25Gbps, quarter rate, x5
    //CSL_BootCfgSetSRIOSERDESConfigPLL (0x251);  // 2.5Gbps, quarter rate, x10
    //CSL_BootCfgSetSRIOSERDESConfigPLL (0x2A1);  // 5.0Gbps, quarter rate, x20
    //for(i = 0; i < 4; i++)
    //  CSL_BootCfgSetSRIOSERDESRxConfig (i, 0x004404a5);  // quarter rate

    //for(i = 0; i < 4; i++)
    //  CSL_BootCfgSetSRIOSERDESTxConfig (i, 0x001807a5);


    //CSL_BootCfgSetSRIOSERDESConfigPLL (0x229);  // 5.0Gbps, full rate, x5
    //for(i = 0; i < 4; i++)
    //  CSL_BootCfgSetSRIOSERDESRxConfig (i, 0x00440485);  // full rate

    //for(i = 0; i < 4; i++)
    //  CSL_BootCfgSetSRIOSERDESTxConfig (i, 0x00180785);


#ifndef SIMULATOR_SUPPORT
    /* Loop around till the SERDES PLL is not locked. */
    while (1)
    {
        uint32_t    status;

        /* Get the SRIO SERDES Status */
        CSL_BootCfgGetSRIOSERDESStatus(&status);
        if (status & 0x1)
            break;
    }
#endif

    /* Clear the LSU pending interrupts. */
    CSL_SRIO_ClearLSUPendingInterrupt (hSrio, 0xFFFFFFFF, 0xFFFFFFFF);

    /* Set the Device Information */
    CSL_SRIO_SetDeviceInfo (hSrio, DEVICE_ID1_16BIT, DEVICE_VENDOR_ID, DEVICE_REVISION);
    //CSL_SRIO_SetDeviceInfo (hSrio, DEVICE_ID_FPGA_16BIT, 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);

    /* TODO: Configure the processing element features
     *  The SRIO RL file is missing the Re-transmit Suppression Support (Bit6) field definition */
    peFeatures.isBridge                          = 0;
    peFeatures.isEndpoint                        = 1;
    peFeatures.isProcessor                       = 1;
    peFeatures.isSwitch                          = 0;
    peFeatures.isMultiport                       = 1;
    peFeatures.isFlowArbiterationSupported       = 0;
    peFeatures.isMulticastSupported              = 0;
    peFeatures.isExtendedRouteConfigSupported    = 0;
    peFeatures.isStandardRouteConfigSupported    = 1;   // SRTC
    peFeatures.isFlowControlSupported            = 1;
    peFeatures.isCRFSupported                    = 1;   // Critical request flow function
    peFeatures.isCTLSSupported                   = 1;   // Common Transfer large system support
    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, DEVICE_ID_DSP_8BIT, DEVICE_ID_FPGA_16BIT);
    CSL_SRIO_SetDeviceIDCSR (hSrio, DEVICE_ID1_8BIT, DEVICE_ID1_16BIT);

    /* 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);
    CSL_SRIO_SetTLMPortBaseRoutingInfo(hSrio, 0, 2, 1, 1, 0);
    CSL_SRIO_SetTLMPortBaseRoutingInfo(hSrio, 0, 3, 1, 1, 0);
    CSL_SRIO_SetTLMPortBaseRoutingInfo(hSrio, 1, 0, 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, DEVICE_ID_FPGA_16BIT, 0xFF);
    CSL_SRIO_SetTLMPortBaseRoutingPatternMatch(hSrio, 0, 2, DEVICE_ID_DSP_8BIT,  0xFF);

    /* 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 Garbage 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, DEVICE_ID_FPGA_16BIT);
    CSL_SRIO_SetHostDeviceID (hSrio, DEVICE_ID1_16BIT);

    /* 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, 0xFFFFFF);
    CSL_SRIO_SetPortResponseTimeoutCSR(hSrio, 0xFFFFFF);
    //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. */
    for(i = 0; i < 4; i++)
    {
        Uint8          baudSel;
        Uint8          portwidth;
        Uint8          InitializedPortWidth;
        Uint8          pathID;
        Uint8          pathConfig;
        Uint8          pathMode;

        //CSL_SRIO_Enable5GBaud(hSrio, i);
        CSL_SRIO_Enable2_5GBaud(hSrio, i);
        //CSL_SRIO_Enable1_25GBaud(hSrio, i);
        CSL_SRIO_SetPLMPortPathControlMode (hSrio, i, 4);
        CSL_SRIO_GetPLMPortPathControl (hSrio, i, &pathID, &pathConfig, &pathMode);
        System_printf ("SrioDevice_init: pathID:%d, pathConfig:%d, pathMode:%d \n", pathID, pathConfig, pathMode);


        CSL_SRIO_GetPortBaudRate(hSrio, 0, &baudSel);
        CSL_SRIO_GetSupportedPortWidth(hSrio, 0, &portwidth);
        CSL_SRIO_GetInitializedPortWidth(hSrio, 0, &InitializedPortWidth);


        System_printf ("SrioDevice_init: baudSel:%d, portwidth:%d, InitializedPortWidth:%d \n", baudSel, portwidth, InitializedPortWidth);
        System_printf ("Debug(Core %d): SerDes Macro Status Register : 0x%x, 0x%x \n", coreNum, *(unsigned int*)(0x02620154), *(unsigned int*)(0x02620360));

    }

    /* Set the LLM Port IP Prescalar. */
    CSL_SRIO_SetLLMPortIPPrescalar (hSrio, 0x21);


    /* Enable the peripheral. */
    CSL_SRIO_EnablePeripheral(hSrio);

    /* Configuration has been completed. */
    CSL_SRIO_SetBootComplete(hSrio, 1);

#ifndef SIMULATOR_SUPPORT
    /* This code checks if the ports are operational or not. The functionality is not supported
     * on the simulator. */

    //for(i = 0; i < 4; i++)
    //{
    //    while (CSL_SRIO_IsPortOk (hSrio, i) != TRUE)
    //    {
    //        Bool isInstallPort = CSL_SRIO_IsPortInitialized(hSrio, i);
    //        static int checkCount = 0;
    //        checkCount++;
    //    }
    //}

#endif

    /* 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);

    /* Set the Doorbell route to determine which routing table is to be used
     * This configuration implies that the Interrupt Routing Table is configured as
     * follows:-
     *  Interrupt Destination 0 - INTDST 16
     *  Interrupt Destination 1 - INTDST 17
     *  Interrupt Destination 2 - INTDST 18
     *  Interrupt Destination 3 - INTDST 19
     */
    CSL_SRIO_SetDoorbellRoute(hSrio, 0);

    /* Route the Doorbell interrupts.
     *  Doorbell Register 0 - All 16 Doorbits are routed to Interrupt Destination 0.
     *  Doorbell Register 1 - All 16 Doorbits are routed to Interrupt Destination 1.
     *  Doorbell Register 2 - All 16 Doorbits are routed to Interrupt Destination 2.
     *  Doorbell Register 3 - All 16 Doorbits are routed to Interrupt Destination 3. */
    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);
    }

    /* Initialization has been completed. */
    return 0;
}



static UInt32 l2_global_address (Uint32 addr)
{
    UInt32 corenum;

    /* Get the core number. */
    corenum = CSL_chipReadReg(CSL_CHIP_DNUM);

    /* Compute the global address. */
    return (addr + (0x10000000 + (corenum*0x1000000)));
}

static void myDioTxCompletionIsr
(
    UArg argument
)
{
    /* Pass the control to the driver DIO Tx Completion ISR handler */
    Srio_dioTxCompletionIsr ((Srio_DrvHandle)argument, hSrioCSL);

    /* Wake up the pending task */
    srioLsuIsrServiced = 1;

    /* Debug: Increment the ISR count */
    srioDbgDioIsrCnt++;

    return;
}

/**
 *  @b Description
 *  @n
 *      The function demonstrates usage of interrupts to indicate
 *      the end of DIO transfers
 *
 *  @param[in]  hSrioDrv
 *      Handle to the SRIO driver
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */

Int32 initBuffer()
{
    uint16_t                counter;

    srcDataBuffer[0] =  (uint8_t*)Osal_srioDataBufferMalloc(SIZE_TX_DIO_PACKET);
    if (srcDataBuffer[0] == NULL)
    {
        System_printf ("Error: Source Buffer (%d) Memory Allocation Failed\n", 0);
        return -1;
    }
    dstDataBuffer[0] =  (uint8_t*)Osal_srioDataBufferMalloc(SIZE_TX_DIO_PACKET);
    if (dstDataBuffer[0] == NULL)
    {
        System_printf ("Error: Destination Buffer (%d) Memory Allocation Failed\n", 0);
        return -1;
    }

    srcDataBuffer[0][0] = 0x00;
    srcDataBuffer[0][1] = 0xD8;
    srcDataBuffer[0][2] = 0x20;
    srcDataBuffer[0][3] = 0x00;
    srcDataBuffer[0][4] = 0x00;
    srcDataBuffer[0][5] = 0x00;
    srcDataBuffer[0][6] = 0x00;
    srcDataBuffer[0][7] = 0x00;

    for (counter = 8; counter < SIZE_TX_DIO_PACKET; counter++)
    {
        srcDataBuffer[0][counter] = (counter-8);
    }

    /* DIO Write operation */
    srcDataBufPtr = &srcDataBuffer[0];
    dstDataBufPtr = &dstDataBuffer[0];

    return 0;

}

void clearBuffer()
{
    /* Cleanup the source & destination buffers. */
    Osal_srioDataBufferFree ((Void*)srcDataBufPtr[0], SIZE_TX_DIO_PACKET);
    Osal_srioDataBufferFree ((Void*)dstDataBufPtr[0], SIZE_TX_DIO_PACKET);
}

Int32 sendSrio(uint32_t src_addr, uint32_t dst_addr, uint8_t BYTE_SIZE)
{
    Srio_SockAddrInfo       to;
    //Uint8*          context;
    //Uint8*          transID;

    /* Populate the DIO Address Information where the data is to be sent. */
    to.dio.rapidIOMSB    = 0x0;
    to.dio.rapidIOLSB    = dst_addr;
    to.dio.dstID         = DEVICE_ID_FPGA_16BIT;
    to.dio.ttype         = Srio_Ttype_Write_NWRITE;
    to.dio.ftype         = Srio_Ftype_WRITE;

    if (Srio_sockSend_DIO (srioSocket[0], (Srio_DrvBuffer)src_addr, BYTE_SIZE, (Srio_SockAddrInfo*)&to) < 0)
    {
        System_printf ("Debug(Core %d): DIO Socket Example Failed\n", coreNum);
        return -1;
    }

/*
    // Make sure there is space in the Shadow registers to write
    while (1)
    {
        if (CSL_SRIO_IsLSUFull (hDrvManagedSrioDrv, 0) == 0)
            break;
    }

    // Get the LSU Context and Transaction Information.
    CSL_SRIO_GetLSUContextTransaction (hDrvManagedSrioDrv, 0,
                                       &context, &transID);

    CSL_SRIO_SetLSUReg0 (hDrvManagedSrioDrv, 0, 0);
    CSL_SRIO_SetLSUReg1 (hDrvManagedSrioDrv, 0, dst_addr);
    CSL_SRIO_SetLSUReg2 (hDrvManagedSrioDrv, 0, (uint32_t)src_addr);
    CSL_SRIO_SetLSUReg3 (hDrvManagedSrioDrv, 0,
                         BYTE_SIZE, 0);
    CSL_SRIO_SetLSUReg4 (hDrvManagedSrioDrv, 0,
                         DEVICE_ID_FPGA_16BIT,
                        0, //ptr_srioSocket->lsuTransfer.srcIDMap,
                        0, //ptr_srioSocket->lsuTransfer.idSize,
                        0, //ptr_srioSocket->lsuTransfer.outPortID,
                        0, //ptr_srioSocket->lsuTransfer.priority,
                        0, //ptr_srioSocket->lsuTransfer.xambs,
                        0, //ptr_srioSocket->lsuTransfer.supInt,
                        1);//ptr_srioSocket->lsuTransfer.intrRequest);
    CSL_SRIO_SetLSUReg5 (hDrvManagedSrioDrv, 0,
                         Srio_Ttype_Write_NWRITE,
                         Srio_Ftype_WRITE,
                        0,
                        0);
*/
    return 0;
}

Int32 receiveSrio(uint32_t src_addr, uint32_t dst_addr, uint8_t BYTE_SIZE)
{
    Srio_SockAddrInfo       to;
    uint8_t                 compCode;

    /* Populate the DIO Address Information where the data is to be sent. */
    to.dio.rapidIOMSB    = 0x0;
    to.dio.rapidIOLSB    = dst_addr;
    to.dio.dstID         = DEVICE_ID_FPGA_16BIT;
    to.dio.ttype         = Srio_Ttype_Request_NREAD;
    to.dio.ftype         = Srio_Ftype_REQUEST;

    if (Srio_sockSend_DIO (srioSocket[0], (Srio_DrvBuffer)src_addr, BYTE_SIZE, (Srio_SockAddrInfo*)&to) < 0)
    {
        System_printf ("Debug(Core %d): DIO Socket Example Failed\n", coreNum);
        return -1;
    }

    // Read the completion code filled by the ISR
    compCode = 0xFF;
    if (Srio_getSockOpt(srioSocket[0], Srio_Opt_DIO_READ_SOCK_COMP_CODE, &compCode, sizeof(uint8_t)) < 0)
    {
        System_printf ("Error: Unable to read the completion code in socket\n");
        return -1;
    }

    if (compCode == 0)
    {
        srioDioLsuGoodTransfers++;
    }
    else
    {
        System_printf ("Debug(Core %d): completion %d \n", coreNum, compCode);
        srioDioLsuBadTransfers++;
    }

    return 0;
}

static Int32 initDioSockets (Srio_DrvHandle hSrioDrv, uint8_t dio_ftype, uint8_t dio_ttype, uint8_t BYTE_SIZE)
{
    //Srio_SockAddrInfo       to;
    //uint8_t                 compCode;
    uint8_t                 counter;
    static int              k;

    /* Get the CSL SRIO Handle. */
    hSrioCSL = CSL_SRIO_Open (0);
    if (hSrioCSL == NULL)
        return -1;

    /* Open DIO SRIO Non-Blocking Socket */
    srioSocket[0] = Srio_sockOpen (hSrioDrv, Srio_SocketType_DIO, FALSE);
    if (srioSocket[0] == NULL)
    {
      System_printf ("Error: Unable to open the DIO socket\n");
      return -1;
    }

    /* DIO Binding Information: Use 16 bit identifiers and we are bound to the first source id.
    * and we are using 16 bit device identifiers. */
    bindInfo.dio.doorbellValid  = 0;
    bindInfo.dio.intrRequest    = 1;
    bindInfo.dio.supInt         = 0;
    bindInfo.dio.xambs          = 0;
    bindInfo.dio.priority       = 0;
    bindInfo.dio.outPortID      = 0;
    bindInfo.dio.idSize         = 0; // 0:8bit, 1:16bit
    bindInfo.dio.srcIDMap       = 0;
    bindInfo.dio.hopCount       = 0;
    bindInfo.dio.doorbellReg    = 0;
    bindInfo.dio.doorbellBit    = 0;

    /* Bind the SRIO socket: DIO sockets do not need any binding information. */
    if (Srio_sockBind_DIO (srioSocket[0], &bindInfo) < 0)
    {
      System_printf ("Error: Binding the SIO socket failed.\n");
      return -1;
    }

    /*********************************************************************************
     * Run multiple iterations of the example to ensure multiple data transfers work
     *********************************************************************************/

    /* Send the DIO Information. */
    for( k = 0; k < 10; k++ )
    {
        sendSrio((uint32_t)srcDataBufPtr[0], 0xF0000 + k*8, BYTE_SIZE);

        System_printf ("Debug(Core %d): rapidIOLSB : %x, ISR Count: %d\n", coreNum, (0xF0000 + srioDioLsuGoodTransfers), srioDbgDioIsrCnt);
        srioDioLsuGoodTransfers++;
/*
        // Populate the DIO Address Information where the data is to be sent.
        to.dio.rapidIOMSB    = 0x0;
        to.dio.rapidIOLSB    = 0xF0000 + k*8;
        to.dio.dstID         = DEVICE_ID_FPGA_16BIT;
        to.dio.ttype         = dio_ttype;
        to.dio.ftype         = dio_ftype;

        for (counter = 8; counter < SIZE_TX_DIO_PACKET; counter++)
        {
            srcDataBuffer[0][counter] = 0x20*k + (counter-8);
        }

        if (Srio_sockSend_DIO (srioSocket[0], srcDataBufPtr[0], BYTE_SIZE, (Srio_SockAddrInfo*)&to) < 0)
        //if (Srio_sockSend_DIO (srioSocket[0], dstDataBufPtr[0], BYTE_SIZE, (Srio_SockAddrInfo*)&to) < 0)
        //if (Srio_sockSend (srioSocket[0], srcDataBufPtr[0], BYTE_SIZE, (Srio_SockAddrInfo*)&to) < 0)
        {
            System_printf ("Debug(Core %d): DIO Socket Example Failed\n", coreNum);
            return -1;
        }
*/
    }

    /* Read the completion code filled by the ISR */
    //compCode = 0xFF;
    //if (Srio_getSockOpt(srioSocket[0], Srio_Opt_DIO_READ_SOCK_COMP_CODE, &compCode, sizeof(uint8_t)) < 0)
    //{
    //    System_printf ("Error: Unable to read the completion code in socket\n");
    //    return -1;
    //}

    //if (compCode == 0)
    //{
    //    srioDioLsuGoodTransfers++;
    //}
    //else
    //{
    //    System_printf ("Debug(Core %d): completion %d \n", coreNum, compCode);
    //    srioDioLsuBadTransfers++;
    //}

    /* Clear the LSU pending interrupt (ICCx) */
    //CSL_SRIO_ClearLSUPendingInterrupt (hSrioCSL, 0xFFFFFFFF, 0xFFFFFFFF);
    //srioLsuIsrServiced = 0;
    /* Debug Message: Display ISR count */
    //System_printf ("Debug(Core %d): rapidIOLSB : %x, ISR Count: %d\n", coreNum, (0xF0000 + srioDioLsuGoodTransfers), srioDbgDioIsrCnt);



    if ((dio_ftype == Srio_Ftype_REQUEST) && (dio_ttype == Srio_Ttype_Request_NREAD) )
    {
        for( counter = 0; counter < 4; counter++ )
        {
            System_printf ("Debug(Core %d): srcDataBufPtr checkValue:0x%x, 0x%x, 0x%x, 0x%x\n", coreNum, srcDataBufPtr[0][4*counter+0], srcDataBufPtr[0][4*counter+1], srcDataBufPtr[0][4*counter+2], srcDataBufPtr[0][4*counter+3]);
        }
    }

    /* Debug Message: Print error counters */
    //System_printf ("Debug(Core %d): Transfer Completion without Errors - %d\n", coreNum, srioDioLsuGoodTransfers);
    System_printf ("Debug(Core %d): Transfer Completion with Errors    - %d\n", coreNum, srioDioLsuBadTransfers);

    Srio_sockClose_DIO (srioSocket[0]);

    return 0;
}

static Int32 dioSocketsWith (Srio_DrvHandle hSrioDrv, uint8_t dio_ftype, uint8_t dio_ttype)
{
    Srio_SockBindAddrInfo   bindInfo;
    Srio_SockAddrInfo       to;
    uint16_t                sockIdx, i, k;
    uint16_t                counter, srcDstBufIdx = 0;
    int32_t                 eventId;//, startTime;
    UInt8                   **srcDataBufPtr = NULL, **dstDataBufPtr = NULL;
    uint8_t                 compCode;
    uint32_t                checkValue;
    UInt8                   BYTE_SIZE;

    //System_printf ("*************************************************************\n");
    //System_printf ("******* DIO Socket Example with Interrupts (Core %d) ********\n", coreNum);
    //System_printf ("*************************************************************\n");

    /* Get the CSL SRIO Handle. */
    hSrioCSL = CSL_SRIO_Open (0);
    if (hSrioCSL == NULL)
        return -1;

     /* 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_RouteLSUInterrupts API configuration in the SRIO Initialization)
     *  - We want this System Interrupt to mapped to Host Interrupt 8 */

    /* Disable Interrupt Pacing for INTDST0 */
    CSL_SRIO_DisableInterruptPacing (hSrioCSL, 0);

    /* Route LSU0 ICR0 to INTDST0 */
    CSL_SRIO_RouteLSUInterrupts (hSrioCSL, 0, 0);

    /* Route LSU0 ICR1 to INTDST0 */
    CSL_SRIO_RouteLSUInterrupts (hSrioCSL, 1, 0);

    /* Route LSU0 ICR2 to INTDST0 */
    CSL_SRIO_RouteLSUInterrupts (hSrioCSL, 2, 0);

    /* Map the System Interrupt i.e. the Interrupt Destination 0 interrupt to the DIO ISR Handler. */
    CpIntc_dispatchPlug(CSL_INTC0_INTDST0, (CpIntc_FuncPtr)myDioTxCompletionIsr, (UArg)hSrioDrv, TRUE);

    /* The configuration is for CPINTC0. We map system interrupt 112 to Host Interrupt 8. */
    CpIntc_mapSysIntToHostInt(0, CSL_INTC0_INTDST0, 8);

    /* Enable the Host Interrupt. */
    CpIntc_enableHostInt(0, 8);

    /* Enable the System Interrupt */
    CpIntc_enableSysInt(0, CSL_INTC0_INTDST0);

    /* Get the event id associated with the host interrupt. */
    eventId = CpIntc_getEventId(8);

    /* Plug the CPINTC Dispatcher. */
    EventCombiner_dispatchPlug (eventId, CpIntc_dispatch, 8, TRUE);

    for (sockIdx = 0; sockIdx < SRIO_DIO_LSU_ISR_NUM_SOCKETS; sockIdx++)
    {
      /* Open DIO SRIO Non-Blocking Socket */
      srioSocket[sockIdx] = Srio_sockOpen (hSrioDrv, Srio_SocketType_DIO, FALSE);
      if (srioSocket[sockIdx] == NULL)
      {
          System_printf ("Error: Unable to open the DIO socket - %d\n", sockIdx);
          return -1;
      }

      /* DIO Binding Information: Use 16 bit identifiers and we are bound to the first source id.
       * and we are using 16 bit device identifiers. */
      bindInfo.dio.doorbellValid  = 0;
      bindInfo.dio.intrRequest    = 1;
      bindInfo.dio.supInt         = 0;
      bindInfo.dio.xambs          = 0;
      bindInfo.dio.priority       = 0;
      bindInfo.dio.outPortID      = 0;
      bindInfo.dio.idSize         = 0; // 0:8bit, 1:16bit
      bindInfo.dio.srcIDMap       = sockIdx;
      bindInfo.dio.hopCount       = 0;
      bindInfo.dio.doorbellReg    = 0;
      bindInfo.dio.doorbellBit    = 0;

      /* Bind the SRIO socket: DIO sockets do not need any binding information. */
      if (Srio_sockBind_DIO (srioSocket[sockIdx], &bindInfo) < 0)
      //if (Srio_sockBind (srioSocket[sockIdx], &bindInfo) < 0)
      {
          System_printf ("Error: Binding the SIO socket failed.\n");
          return -1;
      }
    }

    //CSL_SRIO_SetLSUReg3( hSrioCSL, sockIdx, 128, 0 );

    /* Allocate memory for the Source and Destination Buffers */
    for (i = 0; i < (SRIO_DIO_LSU_ISR_NUM_SOCKETS * SRIO_DIO_LSU_ISR_NUM_TRANSFERS); i++)
    {
        srcDataBuffer[i] =  (uint8_t*)Osal_srioDataBufferMalloc(SIZE_TX_DIO_PACKET);
        if (srcDataBuffer[i] == NULL)
        {
            System_printf ("Error: Source Buffer (%d) Memory Allocation Failed\n", i);
            return -1;
        }
        dstDataBuffer[i] =  (uint8_t*)Osal_srioDataBufferMalloc(SIZE_TX_DIO_PACKET);
        if (dstDataBuffer[i] == NULL)
        {
            System_printf ("Error: Destination Buffer (%d) Memory Allocation Failed\n", i);
            return -1;
        }

        /* Initialize the data buffers */

        //for (counter = 0; counter < 8; counter++)
        //{
        //    srcDataBuffer[i][counter] = 0x20 + (counter * 0x8);
        //    dstDataBuffer[i][counter] = 0;
        //}

        srcDataBuffer[0][0] = 0x00;
        srcDataBuffer[0][1] = 0xD8;
        srcDataBuffer[0][2] = 0x20;
        srcDataBuffer[0][3] = 0x00;
        srcDataBuffer[0][4] = 0x00;
        srcDataBuffer[0][5] = 0x00;
        srcDataBuffer[0][6] = 0x00;
        srcDataBuffer[0][7] = 0x00;

        for (counter = 8; counter < (SIZE_TX_DIO_PACKET-8); counter++)
        {
            srcDataBuffer[i][counter] = k*SIZE_TX_DIO_PACKET + (counter * 0x1);
            dstDataBuffer[i][counter] = 0;
        }
        /* Debug Message: */
        System_printf ("Debug(Core %d): Starting the DIO Data Transfer - Src(%d) 0x%p Dst(%d) 0x%p\n",
                        coreNum, i, srcDataBuffer[i], i, dstDataBuffer[i]);
    }

    if ((dio_ftype == Srio_Ftype_WRITE) && (dio_ttype == Srio_Ttype_Write_NWRITE))//Srio_Ttype_Write_NWRITE_R))
    {
        /* DIO Write operation */
        srcDataBufPtr = &srcDataBuffer[0];
        dstDataBufPtr = &dstDataBuffer[0];
        BYTE_SIZE     = SIZE_TX_DIO_PACKET;
    }
    else if ((dio_ftype == Srio_Ftype_REQUEST) && (dio_ttype == Srio_Ttype_Request_NREAD))
    {
        /* DIO Read operation */
        srcDataBufPtr = &dstDataBuffer[0];
        dstDataBufPtr = &srcDataBuffer[0];
        BYTE_SIZE     = SIZE_RX_DIO_PACKET;
    }
    else
    {
        /* Debug Message: */
        System_printf ("Debug(Core %d): Unexpected combination of FTYPE and TTYPE. Example couldn't run. Exiting!!!\n",
                        coreNum);
        return -1;
    }

    /*********************************************************************************
     * Run multiple iterations of the example to ensure multiple data transfers work
     *********************************************************************************/
    for( k = 0; k < 10; k++ )
    {
        for (counter = 0; counter < SRIO_DIO_LSU_ISR_NUM_TRANSFERS; counter++)
        {
            for (sockIdx = 0; sockIdx < SRIO_DIO_LSU_ISR_NUM_SOCKETS; sockIdx++)
            {
                /* Populate the DIO Address Information where the data is to be sent. */
                to.dio.rapidIOMSB    = 0x0;
                to.dio.rapidIOLSB    = 0xF0000 + k;//(uint32_t)&dstDataBufPtr[srcDstBufIdx][0];
                to.dio.dstID         = DEVICE_ID_FPGA_16BIT;
                to.dio.ttype         = dio_ttype;
                to.dio.ftype         = dio_ftype;

                /* Send the DIO Information. */
                if (Srio_sockSend_DIO (srioSocket[sockIdx], srcDataBufPtr[srcDstBufIdx], BYTE_SIZE, (Srio_SockAddrInfo*)&to) < 0)
                //if (Srio_sockSend_DIO (srioSocket[sockIdx], dstDataBufPtr[srcDstBufIdx], BYTE_SIZE, (Srio_SockAddrInfo*)&to) < 0)
                //if (Srio_sockSend (srioSocket[sockIdx], srcDataBufPtr[srcDstBufIdx], SIZE_DIO_PACKET, (Srio_SockAddrInfo*)&to) < 0)
                {
                    System_printf ("Debug(Core %d): DIO Socket Example Failed\n", coreNum);
                    return -1;
                }

                //if ((dio_ftype == Srio_Ftype_REQUEST) && (dio_ttype == Srio_Ttype_Request_NREAD))
                //    Srio_sockRecv(srioSocket[sockIdx], (Srio_DrvBuffer*)&dstDataBufPtr[srcDstBufIdx],(Srio_SockAddrInfo*)&to);



                /* Wait for the interrupt to occur without touching the peripheral. */
                /* Other useful work could be done here such as by invoking a scheduler */
                //startTime = TSCL;
                //while((! srioLsuIsrServiced) && ((TSCL - startTime) < SRIO_DIO_LSU_ISR_TIMEOUT));

                //if (! srioLsuIsrServiced) {
                //  System_printf ("ISR didn't happen within set time - %d cycles. Example failed !!!\n", SRIO_DIO_LSU_ISR_TIMEOUT);
                //  return -1;
                //}

                /* Debug Message: Data Transfer was completed successfully. */
                System_printf ("Debug(Core %d): DIO Socket (%d) Send for iteration %d\n", coreNum, sockIdx, counter);

                /* Read the completion code filled by the ISR */
                compCode = 0xFF;
                if (Srio_getSockOpt(srioSocket[sockIdx], Srio_Opt_DIO_READ_SOCK_COMP_CODE, &compCode, sizeof(uint8_t)) < 0)
                {
                    System_printf ("Error: Unable to read the completion code in socket\n");
                    return -1;
                }

                //while (1)
                //{
                //    /* Get the completion code. */
                //    if (Srio_getSockOpt(srioSocket[sockIdx], Srio_Opt_DIO_SOCK_COMP_CODE, &compCode, sizeof(uint8_t)) < 0)
                //    {
                //        System_printf ("Error: Unable to get the completion code\n");
                //        return -1;
                //    }
                //    /* Was the transfer complete? */
                //    if (compCode != 0xFF)
                //        break;
                //}

                /* Was the transfer good. */
                if (compCode == 0)
                {
                    srioDioLsuGoodTransfers++;
                }
                else
                {
                    System_printf ("Debug(Core %d): completion %d \n", coreNum, compCode);

                    srioDioLsuBadTransfers++;
                }

                /* Clear the LSU pending interrupt (ICCx) */
                CSL_SRIO_ClearLSUPendingInterrupt (hSrioCSL, 0xFFFFFFFF, 0xFFFFFFFF);
                srioLsuIsrServiced = 0;
                /* Debug Message: Display ISR count */
                System_printf ("Debug(Core %d): ISR Count: %d\n", coreNum, srioDbgDioIsrCnt);

                /* Load next set of payload buffers */
                //srcDstBufIdx++;
                //if (srcDstBufIdx > (SRIO_DIO_LSU_ISR_NUM_SOCKETS * SRIO_DIO_LSU_ISR_NUM_TRANSFERS))
                //{
                //    System_printf ("Debug(Core %d): DIO Socket Example --- Out of SRC and DST buffers\n", coreNum);
                //    return -1;
                //}
            }
        }


    }
    if ((dio_ftype == Srio_Ftype_REQUEST) && (dio_ttype == Srio_Ttype_Request_NREAD) )
    {
        System_printf ("Debug(Core %d): srcDataBufPtr checkValue:%x, %x, %x, %x\n", coreNum, srcDataBufPtr[0][0], srcDataBufPtr[0][1], srcDataBufPtr[0][2], srcDataBufPtr[0][3]);
        System_printf ("Debug(Core %d): dstDataBufPtr checkValue:%x, %x, %x, %x\n", coreNum, dstDataBufPtr[0][0], dstDataBufPtr[0][1], dstDataBufPtr[0][2], dstDataBufPtr[0][3]);
        checkValue = *((unsigned int *)(0xF0000));
        System_printf ("Debug(Core %d): 0xF0000 checkValue:%d\n", coreNum, checkValue);
    }

    /* Validate the received buffer. */
    for (i = 0; i < (SRIO_DIO_LSU_ISR_NUM_SOCKETS * SRIO_DIO_LSU_ISR_NUM_TRANSFERS); i++)
    {
        for (counter = 0; counter < SIZE_TX_DIO_PACKET; counter++)
        {
            if (dstDataBufPtr[i][counter] != srcDataBufPtr[i][counter])
            {
                //System_printf ("Error(Core %d): Data Validation error. Buffer Number (%d): Expected 0x%x got 0x%x @ index %d\n",
                //                coreNum, i, srcDataBufPtr[i][counter], dstDataBufPtr[i][counter], counter);
                //return -1;
            }
        }
    }

    /* Debug Message: Print error counters */
    System_printf ("Debug(Core %d): Transfer Completion without Errors - %d\n", coreNum, srioDioLsuGoodTransfers);
    System_printf ("Debug(Core %d): Transfer Completion with Errors    - %d\n", coreNum, srioDioLsuBadTransfers);

    /* Cleanup the source & destination buffers. */
    for (srcDstBufIdx = 0; srcDstBufIdx < (SRIO_DIO_LSU_ISR_NUM_SOCKETS * SRIO_DIO_LSU_ISR_NUM_TRANSFERS); srcDstBufIdx++)
    {
        Osal_srioDataBufferFree ((Void*)srcDataBufPtr[srcDstBufIdx], SIZE_TX_DIO_PACKET);
        Osal_srioDataBufferFree ((Void*)dstDataBufPtr[srcDstBufIdx], SIZE_TX_DIO_PACKET);
    }

    /* Close the sockets */
    for (sockIdx = 0; sockIdx < SRIO_DIO_LSU_ISR_NUM_SOCKETS; sockIdx++)
    {
        Srio_sockClose_DIO (srioSocket[sockIdx]);
    }

    //if (srioDioLsuBadTransfers > 0)
    //{
    //    System_printf ("Debug(Core %d): DIO Transfer Data NOT completed successfully !!! \n", coreNum);
    //    return -1;
    //}

    /* Debug Message: Data was validated */
    System_printf ("Debug(Core %d): DIO Transfer Data Validated for all iterations\n", coreNum);

    /* Debug Message: Example completed */
    if ((dio_ftype == Srio_Ftype_WRITE) && (dio_ttype == Srio_Ttype_Write_NWRITE))
    {
        System_printf ("Debug(Core %d): DIO Data Transfer (WRITE) with Interrupts Example Passed\n", coreNum);
    }
    else if ((dio_ftype == Srio_Ftype_REQUEST) && (dio_ttype == Srio_Ttype_Request_NREAD))
    {
        System_printf ("Debug(Core %d): DIO Data Transfer (READ) with Interrupts Example Passed\n", coreNum);
    }

    return 0;
}


static Int32 system_init (Void)
{
    Int32               result;
    Qmss_MemRegInfo     memRegInfo;

    /* Initialize the QMSS Configuration block. */
    memset (&qmssInitConfig, 0, sizeof (Qmss_InitCfg));

    /* Initialize the Host Region. */
    memset ((void *)&host_region, 0, sizeof(host_region));

    /* 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;

#ifdef xdc_target__bigEndian
    /* PDSP Configuration: Big Endian */
    qmssInitConfig.pdspFirmware[0].pdspId   = Qmss_PdspId_PDSP1;
    qmssInitConfig.pdspFirmware[0].firmware = &acc48_be;
    qmssInitConfig.pdspFirmware[0].size     = sizeof (acc48_be);
#else
    /* PDSP Configuration: Little Endian */
    qmssInitConfig.pdspFirmware[0].pdspId   = Qmss_PdspId_PDSP1;
    qmssInitConfig.pdspFirmware[0].firmware = &acc48_le;
    qmssInitConfig.pdspFirmware[0].size     = sizeof (acc48_le);
#endif

    /* 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;
    }

    /* Memory Region 0 Configuration */
    memRegInfo.descBase         = (UInt32 *)l2_global_address((UInt32)host_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 -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;
    }

    /* CPPI and Queue Manager are initialized. */
    System_printf ("Debug(Core %d): Queue Manager and CPPI are initialized.\n", coreNum);
    System_printf ("Debug(Core %d): Host Region 0x%x\n", coreNum, host_region);
    return 0;
}

static Int32 enable_srio (void)
{
#ifndef SIMULATOR_SUPPORT
    /* SRIO power domain is turned OFF by default. It needs to be turned on before doing any
     * SRIO device register access. This not required for the simulator. */

    /* 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;
    }
#else
    /* PSC is not supported on simulator. Return success always */
    return 0;
#endif
}

/**
 *  @b Description
 *  @n
 *      This function is application registered SRIO DIO LSU interrupt
 *      handler (ISR) which is used to process the pending DIO Interrupts.
 *      SRIO Driver users need to ensure that this ISR is plugged with
 *      their OS Interrupt Management API. The function expects the
 *      Interrupt Destination information to be passed along to the
 *      API because the DIO interrupt destination mapping is configurable
 *      during SRIO device initialization.
 *
 *  @param[in]  argument
 *      SRIO Driver Handle
 *
 *  @retval
 *      Not Applicable
 */

/**
 *  @b Description
 *  @n
 *      This is the main DIO Example Task
 *
 *  @retval
 *      Not Applicable.
 */

static Void dioExampleTask(UArg arg0, UArg arg1)
{
    UInt8           isAllocated;
    Srio_DrvConfig  drvCfg;
    static UInt8    initSrioDrv = 0;

    int counter;

    /* Initialize the SRIO Driver Configuration. */
    memset ((Void *)&drvCfg, 0, sizeof(Srio_DrvConfig));

    /* Initialize the OSAL */
    if (Osal_dataBufferInitMemory(SRIO_MAX_MTU) < 0)
    {
        System_printf ("Error: Unable to initialize the OSAL. \n");
        return;
    }

    /********************************************************************************
     * The SRIO Driver Instance is going to be created with the following properties:
     * - Driver Managed
     * - Interrupt Support (Pass the Rx Completion Queue as NULL)
     ********************************************************************************/

    /* Setup the SRIO Driver Managed Configuration. */
    drvCfg.bAppManagedConfig = FALSE;

    /* Driver Managed: Receive Configuration */
    drvCfg.u.drvManagedCfg.bIsRxCfgValid             = 1;
    drvCfg.u.drvManagedCfg.rxCfg.rxMemRegion         = Qmss_MemRegion_MEMORY_REGION0;
    drvCfg.u.drvManagedCfg.rxCfg.numRxBuffers        = 4;
    drvCfg.u.drvManagedCfg.rxCfg.rxMTU               = SRIO_MAX_MTU;

    /* Accumulator Configuration. */
    {
        int32_t coreToQueueSelector[4];

      /* This is the table which maps the core to a specific receive queue. */
        coreToQueueSelector[0] = 704;
        coreToQueueSelector[1] = 705;
        coreToQueueSelector[2] = 706;
        coreToQueueSelector[3] = 707;

        /* Since we are programming the accumulator we want this queue to be a HIGH PRIORITY Queue */
        drvCfg.u.drvManagedCfg.rxCfg.rxCompletionQueue = Qmss_queueOpen (Qmss_QueueType_HIGH_PRIORITY_QUEUE,
                                                                         coreToQueueSelector[coreNum], &isAllocated);
        if (drvCfg.u.drvManagedCfg.rxCfg.rxCompletionQueue < 0)
        {
            System_printf ("Error: Unable to open the SRIO Receive Completion Queue\n");
            return;
        }

        /* Accumulator Configuration is VALID. */
        drvCfg.u.drvManagedCfg.rxCfg.bIsAccumlatorCfgValid = 1;

        /* Accumulator Configuration. */
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.channel             = coreNum;
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.command             = Qmss_AccCmd_ENABLE_CHANNEL;
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.queueEnMask         = 0;
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.queMgrIndex         = coreToQueueSelector[coreNum];
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.maxPageEntries      = 2;
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.timerLoadCount      = 0;
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.interruptPacingMode = Qmss_AccPacingMode_LAST_INTERRUPT;
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.listEntrySize       = Qmss_AccEntrySize_REG_D;
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.listCountMode       = Qmss_AccCountMode_ENTRY_COUNT;
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.multiQueueMode      = Qmss_AccQueueMode_SINGLE_QUEUE;

        /* Initialize the accumulator list memory */
        memset ((Void *)&gHiPriAccumList[0], 0, sizeof(gHiPriAccumList));
        drvCfg.u.drvManagedCfg.rxCfg.accCfg.listAddress = l2_global_address((UInt32)&gHiPriAccumList[0]);
    }

    /* Driver Managed: Transmit Configuration */
    drvCfg.u.drvManagedCfg.bIsTxCfgValid             = 1;
    drvCfg.u.drvManagedCfg.txCfg.txMemRegion         = Qmss_MemRegion_MEMORY_REGION0;
    drvCfg.u.drvManagedCfg.txCfg.numTxBuffers        = 4;
    drvCfg.u.drvManagedCfg.txCfg.txMTU               = SRIO_MAX_MTU;

    /* Start the Driver Managed SRIO Driver. */
    if( 0 == initSrioDrv )
    {
        hDrvManagedSrioDrv = Srio_start(&drvCfg);

        initSrioDrv = 1;
    }

    if (hDrvManagedSrioDrv == NULL)
    {
        System_printf ("Error(Core %d): SRIO Driver failed to start\n", coreNum);
        return;
    }

    /* Hook up the SRIO interrupts with the core. */
    EventCombiner_dispatchPlug (48, (EventCombiner_FuncPtr)Srio_rxCompletionIsr, (UArg)hDrvManagedSrioDrv, TRUE);
    EventCombiner_enableEvent(48);

    /* Enable Time Stamp Counter */
    CSL_tscEnable();

    /* Run the loopback data transfers on the system initialization core. */
    if (coreNum == CORE_SYS_INIT)
    {
        initBuffer();

        /* Reset global counters before next run */
        srioDioLsuGoodTransfers = 0;
        srioDioLsuBadTransfers  = 0;

        for( counter = 0; counter < 1; counter++)
        {
            /* DIO Write Operation */
            if (initDioSockets (hDrvManagedSrioDrv, Srio_Ftype_WRITE, Srio_Ttype_Write_NWRITE, SIZE_TX_DIO_PACKET) < 0 )
            {
                System_printf ("Error: Loopback DIO ISR example for Write operation failed\n");
                Task_exit();
            }

            /* DIO Read Operation */
            //if (initDioSockets (hDrvManagedSrioDrv, Srio_Ftype_REQUEST, Srio_Ttype_Request_NREAD, SIZE_RX_DIO_PACKET) < 0)
            //{
            //    System_printf ("Error: Loopback DIO ISR example for Read operation failed\n");
            //    Task_exit();
            //}

            /* Debug Message: Data Transfer was completed successfully. */
            System_printf ("Debug(Core %d): DIO Socket (%d) Send for iteration %d\n", coreNum, 0, counter);
        }

        clearBuffer();
    }

    /* Print out the Malloc & Free Counter */
    System_printf ("Debug(Core %d): Allocation Counter : %d\n", coreNum, malloc_counter);
    System_printf ("Debug(Core %d): Free Counter       : %d\n", coreNum, free_counter);

    /* Check if there is a memory leak? Since we dont implement a 'deinit' API we need to
     * be careful in these calculations
     *  - For the Application Managed Driver Instance
     *      There will be 'numRxBuffers' + 1 (Driver Instance)
     *  - For the Driver Managed Driver Instance
     *      There will be 'numRxBuffers' + 'numTxBuffers' + 1 (Driver Instance)
     *  Take these into account while checking for memory leaks. */
    if (free_counter +
        (drvCfg.u.drvManagedCfg.rxCfg.numRxBuffers + drvCfg.u.drvManagedCfg.txCfg.numTxBuffers + 1) != malloc_counter)
    {
        System_printf ("Error: Memory Leak Detected\n");
        Task_exit();
    }

    /* Control comes here implies that example passed. */
    System_printf ("Debug(Core %d): DIO with Interrupts example completed successfully.\n", coreNum);
    Task_exit();
}

/**
 *  @b Description
 *  @n
 *      Entry point for the example
 *
 *  @retval
 *      Not Applicable.
 */

void initSRIO()
{
    Task_Params     taskParams;

    /* Get the core number. */
    coreNum = CSL_chipReadReg (CSL_CHIP_DNUM);

#ifdef SIMULATOR_SUPPORT
#warn SRIO DIO LSU ISR example is not supported on SIMULATOR !!!
    System_printf ("SRIO DIO LSU ISR example is not supported on SIMULATOR. Exiting!\n");
    return;
#else
    System_printf ("Executing the SRIO DIO example on the DEVICE\n");
#endif

    /* Initialize the system only if the core was configured to do so. */
    if (coreNum == CORE_SYS_INIT)
    {
        System_printf ("Debug(Core %d): System Initialization for CPPI & QMSS\n", coreNum);

        /* System Initialization */
        if (system_init() < 0)
            return;

        /* Power on SRIO peripheral before using it */
        if (enable_srio () < 0)
        {
            System_printf ("Error: SRIO PSC Initialization Failed\n");
            return;
        }

        /* 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)
        {
            System_printf ("Error: SRIO Driver Initialization Failed\n");
            return;
        }

        /* SRIO Driver is operational at this time. */
        System_printf ("Debug(Core %d): SRIO Driver has been initialized\n", coreNum);

        /* 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_WAIT);
    }
    else
    {
        /* All other cores need to wait for the SRIO to be initialized before they proceed. */
        System_printf ("Debug(Core %d): Waiting for SRIO to be initialized.\n", coreNum);

        /* All other cores loop around forever till the SRIO is up and running.
         * We need to invalidate the cache so that we always read this from the memory. */
        while (isSRIOInitialized[0] == 0)
            CACHE_invL1d ((void *) &isSRIOInitialized[0], 128, CACHE_WAIT);

        /* Start the QMSS. */
        if (Qmss_start() != QMSS_SOK)
        {
            System_printf ("Error: Unable to start the QMSS\n");
            return;
        }

        System_printf ("Debug(Core %d): SRIO can now be used.\n", coreNum);
    }

    /* Create the DIO Example Task.*/
    Task_Params_init(&taskParams);
    Task_create(dioExampleTask, &taskParams, NULL);
}




