/**
 *   @file  infrastructure_mode.c
 *
 *   @brief   
 *      This is the QMSS infrastructure mode example code. Runs both in polling and accumulator mode.
 *      Uses both host and monolithic descriptors for data transfer.
 *
 *  \par
 *  ============================================================================
 *  @n   (C) Copyright 2009, Texas Instruments, Inc.
 * 
 *  Redistribution and use in source and binary forms, with or without 
 *  modification, are permitted provided that the following conditions 
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the 
 *    documentation and/or other materials provided with the   
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  \par
*/

#include <xdc/std.h>
#include <xdc/runtime/IHeap.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Memory.h>
#include <xdc/runtime/Error.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 <xdc/cfg/global.h>
#include <string.h>

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


/* CPPI LLD include */
#include <ti/drv/cppi/cppi_drv.h>
#include <ti/drv/cppi/cppi_desc.h>

/* CSL RL includes */
#include <ti/csl/csl_chip.h>

/************************ USER DEFINES ********************/

#define CPPI_COMPLETION_QUE_MGR     0
#define CPPI_COMPLETION_QUE_NUM     1000

#define NUM_HOST_DESC               32
#define SIZE_HOST_DESC              64
#define NUM_MONOLITHIC_DESC         32
#define SIZE_MONOLITHIC_DESC        160
#define MONOLITHIC_DESC_DATA_OFFSET 12
#define SIZE_DATA_BUFFER            16
#define NUM_PACKETS                 8
#define ACC_ENTRY_SIZE              NUM_PACKETS / 2 + 1 



/************************ GLOBAL VARIABLES ********************/
#pragma DATA_ALIGN (linkingRAM0, 16)
UInt64              linkingRAM0[NUM_HOST_DESC + NUM_MONOLITHIC_DESC];
/* Descriptor pool [Size of descriptor * Number of descriptors] */
#pragma DATA_ALIGN (hostDesc, 16)
UInt8                   hostDesc[SIZE_HOST_DESC * NUM_HOST_DESC];
#pragma DATA_ALIGN (monolithicDesc, 16)
UInt8                   monolithicDesc[SIZE_MONOLITHIC_DESC * NUM_MONOLITHIC_DESC];
#pragma DATA_ALIGN (txDataBuff, 16)
UInt8                   txDataBuff[SIZE_DATA_BUFFER];
#pragma DATA_ALIGN (rxDataBuff, 16)
UInt8                   rxDataBuff[SIZE_DATA_BUFFER * NUM_PACKETS];
/* CPDMA configuration */
Cppi_CpDmaInitCfg       cpdmaCfg;
/* Tx channel configuration */
Cppi_TxChInitCfg        txChCfg;
/* Rx channel configuration */
Cppi_RxChInitCfg        rxChCfg;
/* Rx flow configuration */
Cppi_RxFlowCfg          rxFlowCfg;
/* QMSS configuration */
Qmss_InitCfg            qmssInitConfig;
/* Memory region configuration information */
Qmss_MemRegInfo         monoMemInfo;
/* Memory region configuration information */
Qmss_MemRegInfo         hostMemInfo;
/* Handle to CPPI heap */
IHeap_Handle            cppiHeap;
/* Core number */
UInt32                  coreNum;
/* Accumulator configuration */
#ifdef CONFIG_ACC
Qmss_AccCmdCfg          cfg;
/* List address for accumulator - twice the number of entries for Ping and Pong page */
#pragma DATA_ALIGN (hiPrioList, 16)
Uint32                  hiPrioList[(NUM_PACKETS + 1) * 2];
#endif

/************************ EXTERN VARIABLES ********************/

/* QMSS device specific configuration */
extern Qmss_GlobalConfigParams  qmssGblCfgParams;
/* CPPI device specific configuration */
extern Cppi_GlobalConfigParams  cppiGblCfgParams;

/*************************** FUNCTIONS ************************/
/**
 *  @b Description
 *  @n  
 *      The function is used to get the handle to the CPPI memory heap.
 *      If the application is run on a multiple cores then place the CPPI global 
 *      variables in shared memory.  
 *
 *  @retval
 *      None
 */
static Void cppiHeapInit ()
{
    cppiHeap = HeapMem_Handle_upCast (cppiLocalHeap);
}

/**
 *  @b Description
 *  @n  
 *      Utility function which converts a local GEM L2 memory address 
 *      to global memory address.
 *
 *  @param[in]  addr
 *      Local address to be converted
 *
 *  @retval
 *      Computed L2 global Address
 */
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)));
}

#ifdef CONFIG_ACC
Void testQueueReclaim (Qmss_QueueHnd freeHostQueHnd)
{
    Qmss_Result             result;
    Qmss_QueueHnd           reclaimQueHnd, returnQueHnd;
    Cppi_Desc               *hostDescPtr, *rxPkt;
    Qmss_Queue              queInfo;
    UInt8                   isAllocated;

    /* Opens reclamation queue. */
    if ((reclaimQueHnd = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
	{
        System_printf ("Error Core %d : Opening reclamation Queue Number\n", coreNum);
		return;
	}
    else
        System_printf ("Core %d : Reclaimation Queue Number : %d opened\n", coreNum, reclaimQueHnd);

    /* Opens return queue. */
    if ((returnQueHnd = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
	{
        System_printf ("Error Core %d : Opening return Queue Number\n", coreNum);
		return;
	}
    else
        System_printf ("Core %d : Return Queue Number : %d opened\n", coreNum, returnQueHnd);

   
    if ((result = Qmss_programReclaimQueue (Qmss_PdspId_PDSP1, reclaimQueHnd)) != QMSS_ACC_SOK)
	{
        System_printf ("Error Core %d : Configuring reclamation queue : %d error code : %d\n",
                        coreNum, reclaimQueHnd, result);
		return;
	}
    else
        System_printf ("Core %d : Configured reclamation queue : %d\n", 
                        coreNum, reclaimQueHnd);

    if ((hostDescPtr = (Cppi_Desc *) Qmss_queuePop (freeHostQueHnd)) == NULL)
    {
        System_printf ("Error Core %d : Getting descriptor from Queue Number %d\n", coreNum, freeHostQueHnd);
        return;
    }
    else
        System_printf ("Core %d : Descriptor address 0x%p\n", coreNum, hostDescPtr);

    queInfo = Qmss_getQueueNumber (returnQueHnd);
    
    Cppi_setReturnQueue (Cppi_DescType_HOST, hostDescPtr, queInfo);

    /* Push descriptor to Tx free queue */
    Qmss_queuePushDesc (reclaimQueHnd, (UInt32 *) hostDescPtr);
    while (Qmss_getQueueEntryCount (returnQueHnd) == 0);

    while ((rxPkt = (Cppi_Desc *) QMSS_DESC_PTR (Qmss_queuePop (returnQueHnd))) != NULL) 
    {
        System_printf ("Core %d : Reclaimed descriptor address 0x%p\n", coreNum, rxPkt);
    }

    if ((result = Qmss_programReclaimQueue (Qmss_PdspId_PDSP1, 0)) != QMSS_ACC_SOK)
    {
        System_printf ("Error Core %d : Disabling reclamation queue : %d error code : %d\n",
                        coreNum, reclaimQueHnd, result);
		return;
	}
    else
        System_printf ("Core %d : Disabled reclamation queue : %d\n", 
                        coreNum, reclaimQueHnd);
    if ((hostDescPtr = (Cppi_Desc *) Qmss_queuePop (freeHostQueHnd)) == NULL)
    {
        System_printf ("Error Core %d : Getting descriptor from Queue Number %d\n", coreNum, freeHostQueHnd);
        return;
    }
    else
        System_printf ("Core %d : Descriptor address 0x%p\n", coreNum, hostDescPtr);

    Cppi_setReturnQueue (Cppi_DescType_HOST, hostDescPtr, queInfo);

    /* Push descriptor to Tx free queue */
    Qmss_queuePushDesc (reclaimQueHnd, (UInt32 *) hostDescPtr);
   
    /* Descriptor should not be reclaimed */ 
    if ((Qmss_getQueueEntryCount (returnQueHnd) != 0))
    {
        System_printf ("Error Core %d : Descriptor count on return queue %d is %d\n", 
                        coreNum, returnQueHnd, Qmss_getQueueEntryCount (returnQueHnd));
        return;
    }

    System_printf ("\nCore %d : Queue reclamation feature Passed\n", coreNum);
    return;
}
#endif

/**
 *  @b Description
 *  @n  
 *      Data transfer using host descriptors 
 *
 *  @param[in]  cppiHnd
 *      Handle to access CPPI queue manager CPDMA
 *
 *  @retval
 *      None
 */
Void hostModeTransfer (Cppi_Handle cppiHnd)
{
    Qmss_Result             result;
    UInt32                  numAllocated, i, length, destLen;
    UInt8                   isAllocated;
    UInt8                   *dataBuffPtr;
    Cppi_ChHnd              rxChHnd, txChHnd;
    Qmss_QueueHnd           txQueHnd, rxQueHnd, freeQueHnd, txCmplQueHnd, txFreeQueHnd;
    Cppi_DescCfg            descCfg;
    Cppi_Desc               *hostDescPtr;
    Cppi_FlowHnd            rxFlowHnd;
    Qmss_Queue              queInfo;
    Cppi_Desc               *rxPkt;
    
#ifdef CONFIG_ACC
    UInt32                  index, base, count, packetCount;
    Bool                    usePing = TRUE;
    volatile UInt32         temp;
#endif

    System_printf ("\n*************** Data transfer host mode *****************\n\n");

    /* Setup the descriptors for transmit free queue */
    /* Memory region obtained is zero since there is only Qmss_insertMemoryRegion() call. 
     * else find the memory region using Qmss_getMemoryRegionCfg() */
    descCfg.memRegion = Qmss_MemRegion_MEMORY_REGION0;
    descCfg.descNum = NUM_PACKETS;
    descCfg.destQueueNum = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.queueType = Qmss_QueueType_STARVATION_COUNTER_QUEUE;
    descCfg.initDesc = Cppi_InitDesc_INIT_DESCRIPTOR;
    descCfg.descType = Cppi_DescType_HOST;
    descCfg.epibPresent = Cppi_EPIB_NO_EPIB_PRESENT;

    /* Descriptor should be recycled back to Queue Number 1000 */
    descCfg.returnQueue.qMgr = CPPI_COMPLETION_QUE_MGR;
    descCfg.returnQueue.qNum = CPPI_COMPLETION_QUE_NUM;

    /* Initialize the descriptors and push to free Queue */
    if ((txFreeQueHnd = Cppi_initDescriptor (&descCfg, &numAllocated)) < 0)
	{
        System_printf ("Error Core %d : Initializing Tx descriptor error code: %d \n", coreNum, txFreeQueHnd);
		return;
	}
    else
        System_printf ("Core %d : Number of Tx descriptors requested : %d. Number of descriptors allocated : %d \n", 
            coreNum, descCfg.descNum, numAllocated);

    /* Setup the descriptors for receive free queue */
    descCfg.memRegion = Qmss_MemRegion_MEMORY_REGION0;
    descCfg.descNum = NUM_HOST_DESC - NUM_PACKETS;
    descCfg.destQueueNum = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.queueType = Qmss_QueueType_STARVATION_COUNTER_QUEUE;
    descCfg.initDesc = Cppi_InitDesc_INIT_DESCRIPTOR;
    descCfg.descType = Cppi_DescType_HOST;
    descCfg.epibPresent = Cppi_EPIB_NO_EPIB_PRESENT;
    
    /* Descriptor should be recycled back to queue allocated above */
    descCfg.returnQueue.qMgr = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.returnQueue.qNum = QMSS_PARAM_NOT_SPECIFIED;
    
    /* Initialize the descriptors and push to free Queue */
    if ((freeQueHnd = Cppi_initDescriptor (&descCfg, &numAllocated)) < 0)
	{
        System_printf ("Error Core %d : Initializing Rx descriptor error code: %d \n", coreNum, freeQueHnd);
		return;
	}
    else
        System_printf ("Core %d : Number of Rx descriptors requested : %d. Number of descriptors allocated : %d \n", 
            coreNum, descCfg.descNum, numAllocated);

    /* Setup Rx descriptors with receive buffers */
    for (i = 0; i < numAllocated; i++)
    {
        Ptr dataPtr = rxDataBuff + i * SIZE_DATA_BUFFER;

        /* Get a descriptor */
        if ((hostDescPtr = (Cppi_Desc *) Qmss_queuePop (freeQueHnd)) == NULL)
        {
            System_printf ("Error Core %d : Getting descriptor from Queue Number\n", coreNum, freeQueHnd);
            return;
        }

        /* Add data buffer */
        Cppi_setData (Cppi_DescType_HOST, hostDescPtr, (UInt8 *) l2_global_address ((UInt32) dataPtr), SIZE_DATA_BUFFER);

        /* Save original buffer information */
        Cppi_setOriginalBufInfo (Cppi_DescType_HOST, hostDescPtr, (UInt8 *) l2_global_address ((UInt32) dataPtr), SIZE_DATA_BUFFER);

        /* Push descriptor to Rx free queue */
        Qmss_queuePushDesc (freeQueHnd, (UInt32 *) hostDescPtr);
    }
    
    /* Set up Rx Channel parameters */
    rxChCfg.channelNum = CPPI_PARAM_NOT_SPECIFIED;
    rxChCfg.rxEnable = Cppi_ChState_CHANNEL_DISABLE;
    
    /* Open Rx Channel */
    rxChHnd = (Cppi_ChHnd) Cppi_rxChannelOpen (cppiHnd, &rxChCfg, &isAllocated);
    if (rxChHnd == NULL)
    {
        System_printf ("Error Core %d : Opening Rx channel : %d\n", coreNum, rxChCfg.channelNum);
        return;
    }
    else 
        System_printf ("Core %d : Opened Rx channel : %d\n", coreNum, Cppi_getChannelNumber (rxChHnd));


    /* Set up Tx Channel parameters */
    txChCfg.channelNum = CPPI_PARAM_NOT_SPECIFIED;
    txChCfg.priority = 0;
    txChCfg.filterEPIB = 0;
    txChCfg.filterPS = 0;
    txChCfg.aifMonoMode = 0;
    txChCfg.txEnable = Cppi_ChState_CHANNEL_DISABLE;
    
    /* Open Tx Channel */
    txChHnd = (Cppi_ChHnd) Cppi_txChannelOpen (cppiHnd, &txChCfg, &isAllocated);
    if (txChHnd == NULL)
    {
        System_printf ("Error Core %d : Opening Tx channel : %d\n", coreNum, txChCfg.channelNum);
        return;
    }
    else 
        System_printf ("Core %d : Opened Tx channel : %d\n", coreNum, Cppi_getChannelNumber (txChHnd));

    /* Opens transmit queue. This is the infrastructure queue */
    if ((txQueHnd = Qmss_queueOpen (Qmss_QueueType_INFRASTRUCTURE_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
	{
        System_printf ("Error Core %d : Opening Transmit Queue Number\n", coreNum);
		return;
	}
    else
        System_printf ("Core %d : Transmit Queue Number : %d opened\n", coreNum, txQueHnd);

    /* Opens receive queue */
    if ((rxQueHnd = Qmss_queueOpen (Qmss_QueueType_HIGH_PRIORITY_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
	{
        System_printf ("Error Core %d : Opening Receive Queue Number\n", coreNum);
        return;
	}
    else
        System_printf ("Core %d : Receive Queue Number : %d opened\n", coreNum, rxQueHnd);

    /* Opens transmit completion queue. */
    if ((txCmplQueHnd = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, CPPI_COMPLETION_QUE_NUM, &isAllocated)) < 0)
	{
        System_printf ("Error Core %d : Opening Tx Completion Queue Number\n", coreNum);
		return;
	}
    else
        System_printf ("Core %d : Tx Completion Queue Number : %d opened\n", coreNum, txCmplQueHnd);

    System_printf ("Core %d : Free Queue Number : %d opened\n", coreNum, freeQueHnd);
    System_printf ("Core %d : Transmit Free Queue Number : %d opened\n", coreNum, txFreeQueHnd);

#ifdef CONFIG_ACC

    if ((result = Qmss_configureAccTimer (Qmss_PdspId_PDSP1, 3500)) != QMSS_ACC_SOK)
	{
        System_printf ("Error Core %d : Changing accumulator tick to 20us error code : %d\n",
                        coreNum, cfg.channel, cfg.queMgrIndex, result);
		return;
	}
    else
        System_printf ("Core %d : Changed accumulator tick to 20us\n", coreNum);


    /* program the high priority accumulator */
    memset ((Void *) &hiPrioList, 0, sizeof (hiPrioList));
    cfg.channel = 0;
    cfg.command = Qmss_AccCmd_ENABLE_CHANNEL;
    cfg.queueEnMask = 0;
    cfg.listAddress = l2_global_address ((UInt32) hiPrioList); /* Should be global if reading on another core */
    /* Get queue manager and queue number from handle */
    queInfo = Qmss_getQueueNumber (rxQueHnd);
    cfg.queMgrIndex = queInfo.qNum;
    cfg.maxPageEntries = ACC_ENTRY_SIZE;
    cfg.timerLoadCount = 0;
    cfg.interruptPacingMode = Qmss_AccPacingMode_NONE;
    cfg.listEntrySize = Qmss_AccEntrySize_REG_D;
    cfg.listCountMode = Qmss_AccCountMode_ENTRY_COUNT;
    cfg.multiQueueMode = Qmss_AccQueueMode_SINGLE_QUEUE;
    
    if ((result = Qmss_programAccumulator (Qmss_PdspId_PDSP1, &cfg)) != QMSS_ACC_SOK)
	{
        System_printf ("Error Core %d : Programming high priority accumulator for channel : %d queue : %d error code : %d\n",
                        coreNum, cfg.channel, cfg.queMgrIndex, result);
		return;
	}
    else
        System_printf ("Core %d : high priority accumulator programmed for channel : %d queue : %d\n", 
                        coreNum, cfg.channel, cfg.queMgrIndex);
#endif

    /* Set transmit queue threshold to high and when there is atleast one packet */
    /* Setting threshold on transmit queue is not required anymore. tx pending queue is not hooked to threshold. 
     * Qmss_setQueueThreshold (txQueHnd, 1, 1);
     */ 
            
    /* Setup Rx flow parameters */
    memset ((Void *) &rxFlowCfg, 0, sizeof (Cppi_RxFlowCfg));

    /* Don't specify flow number and let CPPI allocate the next available one */
    rxFlowCfg.flowIdNum = CPPI_PARAM_NOT_SPECIFIED;
    /* Get queue manager and queue number from handle */
    queInfo = Qmss_getQueueNumber (rxQueHnd);
    rxFlowCfg.rx_dest_qnum = queInfo.qNum;
    rxFlowCfg.rx_dest_qmgr = queInfo.qMgr;
    rxFlowCfg.rx_desc_type = Cppi_DescType_HOST; 
    /* Get queue manager and queue number from handle */
    queInfo = Qmss_getQueueNumber (freeQueHnd);
    rxFlowCfg.rx_fdq0_sz0_qnum = queInfo.qNum;
    rxFlowCfg.rx_fdq0_sz0_qmgr = queInfo.qMgr;

    /* Configure Rx flow */
    rxFlowHnd = (Cppi_FlowHnd) Cppi_configureRxFlow (cppiHnd, &rxFlowCfg, &isAllocated);
    if (rxFlowHnd == NULL)
    {
        System_printf ("Error Core %d : Opening Rx flow : %d\n", coreNum, rxFlowCfg.flowIdNum);
        return;
    }
    else 
        System_printf ("Core %d : Opened Rx flow : %d\n", coreNum, Cppi_getFlowId(rxFlowHnd));
    
    /* Enable transmit channel */
    if (Cppi_channelEnable (txChHnd) != CPPI_SOK)
        System_printf ("Error Core %d : Enabling Tx channel : %d\n", coreNum, Cppi_getChannelNumber (txChHnd));
    else 
        System_printf ("Core %d : Tx channel : %d enabled \n", coreNum, Cppi_getChannelNumber (txChHnd));

    /* Enable receive channel */
    if (Cppi_channelEnable (rxChHnd) != CPPI_SOK)
        System_printf ("Error Core %d : Enabling Rx channel : %d\n", coreNum, Cppi_getChannelNumber (rxChHnd));
    else 
        System_printf ("Core %d : Rx channel : %d enabled \n", coreNum, Cppi_getChannelNumber (rxChHnd));


    /* Fill in some data */
    for (i = 0; i < SIZE_DATA_BUFFER; i++) 
        txDataBuff[i] = i;

    System_printf ("\n--------------------Transmitting packets----------------------\n");
    /* Send out 8 packets */
    for (i = 0; i < NUM_PACKETS; i++)
    {
        /* Get a free descriptor */
        if ((hostDescPtr = (Cppi_Desc *) Qmss_queuePop (txFreeQueHnd)) == NULL)
        {
            System_printf ("Error Core %d : Getting descriptor from Queue Number\n", coreNum, txFreeQueHnd);
            return;
        }

        /* Add data buffer */
        Cppi_setData (Cppi_DescType_HOST, hostDescPtr, (UInt8 *) l2_global_address ((UInt32) txDataBuff), SIZE_DATA_BUFFER);

        Cppi_setOriginalBufInfo (Cppi_DescType_HOST, hostDescPtr, (UInt8 *) l2_global_address ((UInt32) txDataBuff), SIZE_DATA_BUFFER);

        /* Set packet length */
        Cppi_setPacketLen (Cppi_DescType_HOST, hostDescPtr, SIZE_DATA_BUFFER);

        System_printf ("Core %d : Transmitting descriptor 0x%p\n", coreNum, hostDescPtr);

        /* Push descriptor to Tx queue */
        Qmss_queuePushDescSize (txQueHnd, (UInt32 *) hostDescPtr, SIZE_HOST_DESC);
    }

    System_printf ("\n-------------------------Queue status-------------------------\n");
    result = Qmss_getQueueEntryCount (txQueHnd);
    System_printf ("Transmit Queue %d Entry Count : %d \n", txQueHnd, result);

    result = Qmss_getQueueEntryCount (txFreeQueHnd);
    System_printf ("Tx Free Queue %d Entry Count : %d \n", txFreeQueHnd, result);

    result = Qmss_getQueueEntryCount (freeQueHnd);
    System_printf ("Rx Free Queue %d Entry Count : %d \n", freeQueHnd, result);

    result = Qmss_getQueueEntryCount (rxQueHnd);
    System_printf ("Receive Queue %d Entry Count : %d \n", rxQueHnd, result);

    result = Qmss_getQueueEntryCount (txCmplQueHnd);
    System_printf ("Tx completion Queue %d Entry Count : %d \n", txCmplQueHnd, result);

    System_printf ("\n--------------------Receiving packets-------------------------\n");

#ifndef CONFIG_ACC
    while (Qmss_getQueueEntryCount (rxQueHnd) == 0);
    
    /* Get the rx packet */
    while ((rxPkt = (Cppi_Desc *) QMSS_DESC_PTR (Qmss_queuePop (rxQueHnd))) != NULL)
    {
        length = Cppi_getPacketLen (Cppi_DescType_HOST, rxPkt);

        System_printf ("Core %d : Received descriptor 0x%p of length : %d\n", coreNum, rxPkt, length);

        /* Get data buffer */
        Cppi_getData (Cppi_DescType_HOST, rxPkt, &dataBuffPtr, &destLen);

        /* Compare */
        for (i = 0; i < destLen; i++)
        {
            if (txDataBuff[i] != dataBuffPtr[i])
                System_printf ("Error Core %d : In data buffer Tx: %02X - Rx: %02X \n", coreNum, txDataBuff[i], dataBuffPtr[i]);
        }
        
        /* Recycle the descriptors */
        queInfo = Cppi_getReturnQueue (Cppi_DescType_HOST, rxPkt);
        
        /* Push descriptor back to Rx free queue */
        Qmss_queuePushDesc (Qmss_getQueueHandle(queInfo), (UInt32 *) rxPkt);
    }
#else
    {
        /* Burn some time for the accumulators to run. */
#if 1 
		temp = 0;
        for (i = 0; i < 50000; i++)
        {
          temp = i;
        }
        temp = 1;
#endif
    }

    /* Get the Rx packet */
    /* 8 packets were sent out. Check how many where received. Count should be the first entry since acc 
     * is programmed in entry count. Start with the ping side */
    packetCount = 0;
    while (1)
    {
        if (usePing == TRUE)
        {
            /* Use Ping side */
            base = 0;
            usePing = FALSE;
            System_printf ("Core %d : Processing ping page\n", coreNum);
        }
        else
        {
            /* Switch to pong side */
            base = ACC_ENTRY_SIZE; 
            usePing = TRUE;
            System_printf ("Core %d : Processing pong page\n", coreNum);
        }
        
        /* Using Entry count mode */
        count = hiPrioList[base];
        hiPrioList[base] = 0;
        for (index = base + 1; index <= base + count; index++)
        {
            rxPkt = (Cppi_Desc *) QMSS_DESC_PTR (hiPrioList[index]);
            hiPrioList[index] = 0;

            /* Get packet length */
            length = Cppi_getPacketLen (Cppi_DescType_HOST, rxPkt);

            System_printf ("Core %d : Received descriptor 0x%p of length : %d\n", coreNum, rxPkt, length);

            /* Get data buffer */
            Cppi_getData (Cppi_DescType_HOST, rxPkt, &dataBuffPtr, &destLen);

            /* Compare */
            for (i = 0; i < destLen; i++)
            {
                if (txDataBuff[i] != dataBuffPtr[i])
                 System_printf ("Error Core %d : In data buffer Tx: %02X - Rx: %02X \n", coreNum, txDataBuff[i], dataBuffPtr[i]);
            }
        
            /* Recycle the descriptors */
            queInfo = Cppi_getReturnQueue (Cppi_DescType_HOST, rxPkt);
       
            /* Push descriptor back to Rx free queue */
            Qmss_queuePushDesc (Qmss_getQueueHandle(queInfo), (UInt32 *) rxPkt);
            packetCount++;
        }
        Qmss_ackInterrupt (cfg.channel, 1);
        Qmss_setEoiVector (Qmss_IntdInterruptType_HIGH, cfg.channel);

        if (packetCount == NUM_PACKETS)
            break;
    }
#endif

    System_printf ("\n--------------------Deinitializing----------------------------\n");

    result = Qmss_getQueueEntryCount (txQueHnd);
    System_printf ("Transmit Queue %d Entry Count : %d \n", txQueHnd, result);

    result = Qmss_getQueueEntryCount (txFreeQueHnd);
    System_printf ("Tx Free Queue %d Entry Count : %d \n", txFreeQueHnd, result);

    result = Qmss_getQueueEntryCount (freeQueHnd);
    System_printf ("Rx Free Queue %d Entry Count : %d \n", freeQueHnd, result);

    result = Qmss_getQueueEntryCount (rxQueHnd);
    System_printf ("Receive Queue %d Entry Count : %d \n", rxQueHnd, result);

    result = Qmss_getQueueEntryCount (txCmplQueHnd);
    System_printf ("Tx completion Queue %d Entry Count : %d \n", txCmplQueHnd, result);

#ifdef CONFIG_ACC
    /* Disable accumulator */
    if ((result = Qmss_disableAccumulator (Qmss_PdspId_PDSP1, cfg.channel)) != QMSS_ACC_SOK)
	{
        System_printf ("Error Core %d : Disabling high priority accumulator for channel : %d queue : %d error code: %d\n",
                        coreNum, cfg.channel, cfg.queMgrIndex, result);
		return;
	}
    else
        System_printf ("Core %d : high priority accumulator disabled for channel : %d queue : %d\n", 
                        coreNum, cfg.channel, cfg.queMgrIndex);
#endif

#ifdef CONFIG_ACC
    /* Test queue reclamation feature */
    testQueueReclaim (txCmplQueHnd);
#endif

    /* Flush the queues */
    Qmss_queueEmpty (txFreeQueHnd);
    Qmss_queueEmpty (freeQueHnd);
    Qmss_queueEmpty (txCmplQueHnd);

    /* Close Tx channel */
    if ((result = Cppi_channelClose (txChHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing Tx channel error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Tx Channel closed successfully. Ref count : %d\n", coreNum, result);

    /* Close Rx channel */
    if ((result = Cppi_channelClose (rxChHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing Rx channel error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Rx Channel closed successfully. Ref count : %d\n", coreNum, result);

    /* Close Rx flow */
    if ((result = Cppi_closeRxFlow (rxFlowHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing Rx flow error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Rx flow closed successfully. Ref count : %d\n", coreNum, result);
    
    /* Close the queues */
    if ((result = Qmss_queueClose (rxQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing Rx queue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Rx queue closed successfully. Ref count : %d\n", coreNum, result);
    
    if ((result = Qmss_queueClose (txQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing tx queue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Tx queue closed successfully. Ref count : %d\n", coreNum, result);

    if ((result = Qmss_queueClose (freeQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing free queue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Free queue closed successfully. Ref count : %d\n", coreNum, result);

    if ((result = Qmss_queueClose (txCmplQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing transmit completion queue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Transmit completion queue closed successfully. Ref count : %d\n", coreNum, result);

    if ((result = Qmss_queueClose (txFreeQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing transmit freequeue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Transmit free queue closed successfully. Ref count : %d\n", coreNum, result);
}

/**
 *  @b Description
 *  @n  
 *      Data transfer using monolithic descriptors 
 *
 *  @param[in]  cppiHnd
 *      Handle to access CPPI queue manager CPDMA
 *
 *  @retval
 *      None
 */

Void monoModeTransfer (Cppi_Handle cppiHnd)
{
    Qmss_Result             result;
    UInt32                  numAllocated, i, length, destLen;
    UInt8                   isAllocated;
    UInt8                   *dataBuffPtr;
    Cppi_ChHnd              rxChHnd, txChHnd;
    Qmss_QueueHnd           txQueHnd, rxQueHnd, freeQueHnd, txCmplQueHnd, txFreeQueHnd;
    Cppi_DescCfg            descCfg;
    Cppi_Desc               *monoDescPtr;
    Cppi_FlowHnd            rxFlowHnd;
    Qmss_Queue              queInfo;
    Cppi_Desc               *rxPkt;
#ifdef CONFIG_ACC
    UInt32                  index, base, packetCount;
    Bool                    usePing = TRUE;
    volatile UInt32         temp; 
#endif

    System_printf ("\n***************** Data transfer monolithic mode ***************\n\n");

    /* Setup the descriptors for transmit free queue */
    /* Memory region obtained is zero since there is only Qmss_insertMemoryRegion() call. 
     * else find the memory region using Qmss_getMemoryRegionCfg() */
    descCfg.memRegion = Qmss_MemRegion_MEMORY_REGION1;
    descCfg.descNum = NUM_PACKETS;
    descCfg.destQueueNum = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.queueType = Qmss_QueueType_STARVATION_COUNTER_QUEUE;
    descCfg.initDesc = Cppi_InitDesc_INIT_DESCRIPTOR;
    descCfg.descType = Cppi_DescType_MONOLITHIC;
    descCfg.epibPresent = Cppi_EPIB_NO_EPIB_PRESENT;

    descCfg.cfg.mono.dataOffset = MONOLITHIC_DESC_DATA_OFFSET;
    
    /* Descriptor should be recycled back to Queue Number 1000 */
    descCfg.returnQueue.qMgr = CPPI_COMPLETION_QUE_MGR;
    descCfg.returnQueue.qNum = CPPI_COMPLETION_QUE_NUM;

    
    /* Initialize the descriptors and push to free Queue */
    if ((txFreeQueHnd = Cppi_initDescriptor (&descCfg, &numAllocated)) < 0)
	{
        System_printf ("Error Core %d : Initializing Tx descriptor error code: %d \n", coreNum, txFreeQueHnd);
		return;
	}
    else
        System_printf ("Core %d : Number of Tx descriptors requested : %d. Number of descriptors allocated : %d \n", 
            coreNum, descCfg.descNum, numAllocated);

    /* Setup the descriptors for receive free queue */
    descCfg.memRegion = Qmss_MemRegion_MEMORY_REGION1;
    descCfg.descNum = NUM_MONOLITHIC_DESC - NUM_PACKETS;
    descCfg.destQueueNum = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.queueType = Qmss_QueueType_STARVATION_COUNTER_QUEUE;
    descCfg.initDesc = Cppi_InitDesc_INIT_DESCRIPTOR;
    descCfg.descType = Cppi_DescType_MONOLITHIC;
    descCfg.epibPresent = Cppi_EPIB_NO_EPIB_PRESENT;
    descCfg.cfg.mono.dataOffset = MONOLITHIC_DESC_DATA_OFFSET;
    
    /* Descriptor should be recycled back to queue allocated above */
    descCfg.returnQueue.qMgr = QMSS_PARAM_NOT_SPECIFIED;
    descCfg.returnQueue.qNum = QMSS_PARAM_NOT_SPECIFIED;
    
    /* Initialize the descriptors and push to free Queue */
    if ((freeQueHnd = Cppi_initDescriptor (&descCfg, &numAllocated)) < 0)
	{
        System_printf ("Error Core %d : Initializing Rx descriptor error code: %d \n", coreNum, freeQueHnd);
		return;
	}
    else
        System_printf ("Core %d : Number of Rx descriptors requested : %d. Number of descriptors allocated : %d \n", 
            coreNum, descCfg.descNum, numAllocated);

    /* Set up Rx Channel parameters */
    rxChCfg.channelNum = CPPI_PARAM_NOT_SPECIFIED;
    rxChCfg.rxEnable = Cppi_ChState_CHANNEL_DISABLE;
    
    /* Open Rx Channel */
    rxChHnd = (Cppi_ChHnd) Cppi_rxChannelOpen (cppiHnd, &rxChCfg, &isAllocated);
    if (rxChHnd == NULL)
    {
        System_printf ("Error Core %d : Opening Rx channel : %d\n", coreNum, rxChCfg.channelNum);
        return;
    }
    else 
        System_printf ("Core %d : Opened Rx channel : %d\n", coreNum, Cppi_getChannelNumber (rxChHnd));


    /* Set up Tx Channel parameters */
    txChCfg.channelNum = CPPI_PARAM_NOT_SPECIFIED;
    txChCfg.priority = 0;
    txChCfg.filterEPIB = 0;
    txChCfg.filterPS = 0;
    txChCfg.aifMonoMode = 0;
    txChCfg.txEnable = Cppi_ChState_CHANNEL_DISABLE;
    
    /* Open Tx Channel */
    txChHnd = (Cppi_ChHnd) Cppi_txChannelOpen (cppiHnd, &txChCfg, &isAllocated);
    if (txChHnd == NULL)
    {
        System_printf ("Error Core %d : Opening Tx channel : %d\n", coreNum, txChCfg.channelNum);
        return;
    }
    else 
        System_printf ("Core %d : Opened Tx channel : %d\n", coreNum, Cppi_getChannelNumber (txChHnd));

    /* Opens transmit queue. This is the infrastructure queue */
    if ((txQueHnd = Qmss_queueOpen (Qmss_QueueType_INFRASTRUCTURE_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
	{
        System_printf ("Error Core %d : Opening Transmit Queue Number\n", coreNum);
		return;
	}
    else
        System_printf ("Core %d : Transmit Queue Number : %d opened\n", coreNum, txQueHnd);

    /* Opens receive queue */
    if ((rxQueHnd = Qmss_queueOpen (Qmss_QueueType_HIGH_PRIORITY_QUEUE, QMSS_PARAM_NOT_SPECIFIED, &isAllocated)) < 0)
	{
        System_printf ("Error Core %d : Opening Receive Queue Number\n", coreNum);
        return;
	}
    else
        System_printf ("Core %d : Receive Queue Number : %d opened\n", coreNum, rxQueHnd);

    /* Opens transmit completion queue. */
    if ((txCmplQueHnd = Qmss_queueOpen (Qmss_QueueType_GENERAL_PURPOSE_QUEUE, CPPI_COMPLETION_QUE_NUM, &isAllocated)) < 0)
	{
        System_printf ("Error Core %d : Opening Tx Completion Queue Number\n", coreNum);
		return;
	}
    else
        System_printf ("Core %d : Tx Completion Queue Number : %d opened\n", coreNum, txCmplQueHnd);

    System_printf ("Core %d : Free Queue Number : %d opened\n", coreNum, freeQueHnd);
    System_printf ("Core %d : Transmit Free Queue Number : %d opened\n", coreNum, txFreeQueHnd);

#ifdef CONFIG_ACC
    /* program the high priority accumulator */
    memset ((Void *) &hiPrioList, 0, sizeof (hiPrioList));
    cfg.channel = 0;
    cfg.command = Qmss_AccCmd_ENABLE_CHANNEL;
    cfg.queueEnMask = 0;
    cfg.listAddress = l2_global_address ((UInt32) hiPrioList); /* Should be global if reading on another core */
    /* Get queue manager and queue number from handle */
    queInfo = Qmss_getQueueNumber (rxQueHnd);
    cfg.queMgrIndex = queInfo.qNum;
    cfg.maxPageEntries = ACC_ENTRY_SIZE;
    cfg.timerLoadCount = 0;
    cfg.interruptPacingMode = Qmss_AccPacingMode_NONE;
    cfg.listEntrySize = Qmss_AccEntrySize_REG_D;
    cfg.listCountMode = Qmss_AccCountMode_NULL_TERMINATE;
    cfg.multiQueueMode = Qmss_AccQueueMode_SINGLE_QUEUE;
    
    if ((result = Qmss_programAccumulator (Qmss_PdspId_PDSP1, &cfg)) != QMSS_ACC_SOK)
	{
        System_printf ("Error Core %d : Programming high priority accumulator for channel : %d queue : %d error code : %d\n",
                        coreNum, cfg.channel, cfg.queMgrIndex, result);
		return;
	}
    else
        System_printf ("Core %d : high priority accumulator programmed for channel : %d queue : %d\n", 
                        coreNum, cfg.channel, cfg.queMgrIndex);
#endif

    /* Set transmit queue threshold to high and when there is atleast one packet */
    /* Setting threshold on transmit queue is not required anymore. tx pending queue is not hooked to threshold. 
     * Qmss_setQueueThreshold (txQueHnd, 1, 1);
     */ 
            
    /* Setup Rx flow parameters */
    memset ((Void *) &rxFlowCfg, 0, sizeof (Cppi_RxFlowCfg));

    /* Don't specify flow number and let CPPI allocate the next available one */
    rxFlowCfg.flowIdNum = CPPI_PARAM_NOT_SPECIFIED;
    /* Get queue manager and queue number from handle */
    queInfo = Qmss_getQueueNumber (rxQueHnd);
    rxFlowCfg.rx_dest_qnum = queInfo.qNum;
    rxFlowCfg.rx_dest_qmgr = queInfo.qMgr;
    rxFlowCfg.rx_sop_offset = MONOLITHIC_DESC_DATA_OFFSET;
    rxFlowCfg.rx_desc_type = Cppi_DescType_MONOLITHIC; 
    /* Get queue manager and queue number from handle */
    queInfo = Qmss_getQueueNumber (freeQueHnd);
    rxFlowCfg.rx_fdq0_sz0_qnum = queInfo.qNum;
    rxFlowCfg.rx_fdq0_sz0_qmgr = queInfo.qMgr;

    /* Configure Rx flow */
    rxFlowHnd = (Cppi_FlowHnd) Cppi_configureRxFlow (cppiHnd, &rxFlowCfg, &isAllocated);
    if (rxFlowHnd == NULL)
    {
        System_printf ("Error Core %d : Opening Rx flow : %d\n", coreNum, rxFlowCfg.flowIdNum);
        return;
    }
    else 
        System_printf ("Core %d : Opened Rx flow : %d\n", coreNum, Cppi_getFlowId(rxFlowHnd));
    
    /* Enable transmit channel */
    if (Cppi_channelEnable (txChHnd) != CPPI_SOK)
        System_printf ("Error Core %d : Enabling Tx channel : %d\n", coreNum, Cppi_getChannelNumber (txChHnd));
    else 
        System_printf ("Core %d : Tx channel : %d enabled \n", coreNum, Cppi_getChannelNumber (txChHnd));

    /* Enable receive channel */
    if (Cppi_channelEnable (rxChHnd) != CPPI_SOK)
        System_printf ("Error Core %d : Enabling Rx channel : %d\n", coreNum, Cppi_getChannelNumber (rxChHnd));
    else 
        System_printf ("Core %d : Rx channel : %d enabled \n", coreNum, Cppi_getChannelNumber (rxChHnd));


    /* Fill in some data */
    for (i = 0; i < SIZE_DATA_BUFFER; i++) 
        txDataBuff[i] = i;

    System_printf ("\n--------------------Transmitting packets----------------------\n");
    /* Send out 8 packets */
    for (i = 0; i < NUM_PACKETS; i++)
    {
        /* Get a free descriptor */
        if ((monoDescPtr = (Cppi_Desc *) Qmss_queuePop (txFreeQueHnd)) == NULL)
        {
            System_printf ("Error Core %d : Getting descriptor from Queue Number\n", coreNum, txFreeQueHnd);
            return;
        }

        /* Add data buffer */
        Cppi_setData (Cppi_DescType_MONOLITHIC, monoDescPtr, (UInt8 *) &txDataBuff, SIZE_DATA_BUFFER);

        /* Set packet length */
        Cppi_setPacketLen (Cppi_DescType_MONOLITHIC, monoDescPtr, SIZE_DATA_BUFFER);

        System_printf ("Core %d : Transmitting descriptor 0x%p\n", coreNum, monoDescPtr);

        /* Push descriptor to Tx queue */
        Qmss_queuePushDescSize (txQueHnd, (UInt32 *) monoDescPtr, 16);
    }

    System_printf ("\n-------------------------Queue status-------------------------\n");
    result = Qmss_getQueueEntryCount (txQueHnd);
    System_printf ("Transmit Queue %d Entry Count : %d \n", txQueHnd, result);

    result = Qmss_getQueueEntryCount (txFreeQueHnd);
    System_printf ("Tx Free Queue %d Entry Count : %d \n", txFreeQueHnd, result);

    result = Qmss_getQueueEntryCount (freeQueHnd);
    System_printf ("Rx Free Queue %d Entry Count : %d \n", freeQueHnd, result);

    result = Qmss_getQueueEntryCount (rxQueHnd);
    System_printf ("Receive Queue %d Entry Count : %d \n", rxQueHnd, result);

    result = Qmss_getQueueEntryCount (txCmplQueHnd);
    System_printf ("Tx completion Queue %d Entry Count : %d \n", txCmplQueHnd, result);

    System_printf ("\n--------------------Receiving packets-------------------------\n");

#ifndef CONFIG_ACC
    while (Qmss_getQueueEntryCount (rxQueHnd) == 0);
    
    /* Get the rx packet */
    while ((rxPkt = (Cppi_Desc *) QMSS_DESC_PTR (Qmss_queuePop (rxQueHnd))) != NULL)
    {
        length = Cppi_getPacketLen (Cppi_DescType_MONOLITHIC, rxPkt);

        System_printf ("Core %d : Received descriptor 0x%p of length : %d\n", coreNum, rxPkt, length);

        /* Get data buffer */
        Cppi_getData (Cppi_DescType_MONOLITHIC, rxPkt, &dataBuffPtr, &destLen);

        /* Compare */
        for (i = 0; i < destLen; i++)
        {
            if (txDataBuff[i] != dataBuffPtr[i])
                System_printf ("Error Core %d : In data buffer Tx: %02X - Rx: %02X \n", coreNum, txDataBuff[i], dataBuffPtr[i]);
        }
        
        /* Recycle the descriptors */
        queInfo = Cppi_getReturnQueue (Cppi_DescType_MONOLITHIC, rxPkt);
        
        /* Push descriptor back to free queue */
        Qmss_queuePushDesc (Qmss_getQueueHandle(queInfo), (UInt32 *) rxPkt);
    }
#else
    {
        /* Burn some time for the accumulators to run. */
#if 1 
		temp = 0;
        for (i = 0; i < 50000; i++)
        {
          temp = i;
        }
        temp = 1;
#endif
    }

    /* Get the Rx packet */
    /* 8 packets were sent out. The list is NULL terminated. Start with the ping side */

    packetCount = 0;
    while (1)
    {
        if (usePing == TRUE)
        {
            /* Use ping side */
            base = 0;
            usePing = FALSE;
            System_printf ("Core %d : Processing ping page\n", coreNum);
        }
        else
        {
            /* Switch to pong side */
            base = ACC_ENTRY_SIZE;
            usePing = TRUE;
            System_printf ("Core %d : Processing pong page\n", coreNum);
        }

        /* Using Null terminate mode */
        index = base;
        while (hiPrioList[index] != NULL)
        {
            rxPkt = (Cppi_Desc *) QMSS_DESC_PTR (hiPrioList[index]);
            hiPrioList[index] = 0;

            /* Get packet length */
            length = Cppi_getPacketLen (Cppi_DescType_MONOLITHIC, rxPkt);

            System_printf ("Core %d : Received descriptor 0x%p of length : %d\n", coreNum, rxPkt, length);

            /* Get data buffer */
            Cppi_getData (Cppi_DescType_MONOLITHIC, rxPkt, &dataBuffPtr, &destLen);

            /* Compare */
            for (i = 0; i < destLen; i++)
            {
                if (txDataBuff[i] != dataBuffPtr[i])
                 System_printf ("Error Core %d : In data buffer Tx: %02X - Rx: %02X \n", coreNum, txDataBuff[i], dataBuffPtr[i]);
            }
        
            /* Recycle the descriptors */
            queInfo = Cppi_getReturnQueue (Cppi_DescType_MONOLITHIC, rxPkt);
       
            /* Push descriptor back to free queue */
            Qmss_queuePushDesc (Qmss_getQueueHandle(queInfo), (UInt32 *) rxPkt);
            index++;
            packetCount++;
        }
        Qmss_ackInterrupt (cfg.channel, 1);
        Qmss_setEoiVector (Qmss_IntdInterruptType_HIGH, cfg.channel);

        if (packetCount == NUM_PACKETS)
            break;
    }
    Qmss_ackInterrupt (cfg.channel, 1);
    Qmss_setEoiVector (Qmss_IntdInterruptType_HIGH, cfg.channel);
#endif

    System_printf ("\n--------------------Deinitializing----------------------------\n");
#ifdef CONFIG_ACC
    /* Disable accumulator */
    if ((result = Qmss_disableAccumulator (Qmss_PdspId_PDSP1, cfg.channel)) != QMSS_ACC_SOK)
	{
        System_printf ("Error Core %d : Disabling high priority accumulator for channel : %d queue : %d error code: %d\n",
                        coreNum, cfg.channel, cfg.queMgrIndex, result);
		return;
	}
    else
        System_printf ("Core %d : high priority accumulator disabled for channel : %d queue : %d\n", 
                        coreNum, cfg.channel, cfg.queMgrIndex);
#endif

    result = Qmss_getQueueEntryCount (txQueHnd);
    System_printf ("Transmit Queue %d Entry Count : %d \n", txQueHnd, result);

    result = Qmss_getQueueEntryCount (txFreeQueHnd);
    System_printf ("Tx Free Queue %d Entry Count : %d \n", txFreeQueHnd, result);

    result = Qmss_getQueueEntryCount (freeQueHnd);
    System_printf ("Rx Free Queue %d Entry Count : %d \n", freeQueHnd, result);

    result = Qmss_getQueueEntryCount (rxQueHnd);
    System_printf ("Receive Queue %d Entry Count : %d \n", rxQueHnd, result);

    result = Qmss_getQueueEntryCount (txCmplQueHnd);
    System_printf ("Tx completion Queue %d Entry Count : %d \n", txCmplQueHnd, result);

    /* Close Tx channel */
    if ((result = Cppi_channelClose (txChHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing Tx channel error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Tx Channel closed successfully. Ref count : %d\n", coreNum, result);

    /* Close Rx channel */
    if ((result = Cppi_channelClose (rxChHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing Rx channel error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Rx Channel closed successfully. Ref count : %d\n", coreNum, result);

    /* Close Rx flow */
    if ((result = Cppi_closeRxFlow (rxFlowHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing Rx flow error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Rx flow closed successfully. Ref count : %d\n", coreNum, result);
    
    /* Close the queues */
    if ((result = Qmss_queueClose (rxQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing Rx queue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Rx queue closed successfully. Ref count : %d\n", coreNum, result);
    
    if ((result = Qmss_queueClose (txQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing tx queue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Tx queue closed successfully. Ref count : %d\n", coreNum, result);

    if ((result = Qmss_queueClose (freeQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing free queue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Free queue closed successfully. Ref count : %d\n", coreNum, result);

    if ((result = Qmss_queueClose (txCmplQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing transmit completion queue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Transmit completion queue closed successfully. Ref count : %d\n", coreNum, result);

    if ((result = Qmss_queueClose (txFreeQueHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing transmit freequeue error code : %d\n", coreNum, result);
    else
        System_printf ("Core %d : Transmit free queue closed successfully. Ref count : %d\n", coreNum, result);
}

/**
 *  @b Description
 *  @n  
 *      Entry point for the example code.
 *      This is an QMSS infrastructure mode example. Works in both polled or accumulated mode
 *
 *      It performs the following
 *          - Initializes the Queue Manager low level driver.
 *          - Initializes the CPPI low level driver.
 *          - Opens the CPPI CPDMA in queue manager
 *          - Initializes descriptors and pushes to free queue
 *          - Programs accumulator
 *          - Pushes packets on Tx channel          
 *          - Processes the accumulated packets from Rx channel
 *          - Closes Rx and Tx channel
 *          - Closes all open queues
 *          - Closes CPDMA instance
 *          - Deinitializes CPPI LLD
 *  @retval
 *      Not Applicable.
 */
Void main (Void)
{
    Qmss_Result             result;
    Cppi_Handle             cppiHnd;

    System_printf ("**************************************************\n");
    System_printf ("*********QMSS Infrastructure Mode Example ********\n");
    System_printf ("**************************************************\n");

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

    /* Initialize the heap in shared memory for CPPI data structures */ 
    cppiHeapInit ();

    System_printf ("********************Test running on Core %d ********************\n", coreNum);

    System_printf ("\n-----------------------Initializing---------------------------\n");
    
    memset ((Void *) &qmssInitConfig, 0, sizeof (Qmss_InitCfg));

    memset ((Void *) &linkingRAM0, 0, sizeof (linkingRAM0));
    /* 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 */
#ifdef INTERNAL_LINKING_RAM 
    qmssInitConfig.linkingRAM0Base = 0;
    qmssInitConfig.linkingRAM0Size = 0;
    qmssInitConfig.linkingRAM1Base = 0;
    qmssInitConfig.maxDescNum      = NUM_MONOLITHIC_DESC + NUM_HOST_DESC;
#else
    qmssInitConfig.linkingRAM0Base = (UInt32) l2_global_address((Uint32)&linkingRAM0[0]);
    qmssInitConfig.linkingRAM0Size = 0x3FFF;
    qmssInitConfig.linkingRAM1Base = 0;
    qmssInitConfig.maxDescNum      = NUM_MONOLITHIC_DESC + NUM_HOST_DESC;
#endif

#ifdef xdc_target__bigEndian
    qmssInitConfig.pdspFirmware[0].pdspId = Qmss_PdspId_PDSP1;
    qmssInitConfig.pdspFirmware[0].firmware = &acc48_be;
    qmssInitConfig.pdspFirmware[0].size = sizeof (acc48_be);
#else
    qmssInitConfig.pdspFirmware[0].pdspId = Qmss_PdspId_PDSP1;
    qmssInitConfig.pdspFirmware[0].firmware = &acc48_le;
    qmssInitConfig.pdspFirmware[0].size = sizeof (acc48_le);
#endif

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

    /* Start Queue Manager SubSystem */
    result = Qmss_start ();
    if (result != QMSS_SOK)
    {
        System_printf ("Core %d : Error starting Queue Manager error code : %d\n", coreNum, result);
    }

    /* Initialize CPPI LLD */
    result = Cppi_init (&cppiGblCfgParams);
    if (result != CPPI_SOK)
    {
        System_printf ("Error Core %d : Initializing CPPI LLD error code : %d\n", coreNum, result);
    }

    /* Set up QMSS CPDMA configuration */
    memset ((Void *) &cpdmaCfg, 0, sizeof (Cppi_CpDmaInitCfg));
    cpdmaCfg.dmaNum = Cppi_CpDma_QMSS_CPDMA;

    /* Open QMSS CPDMA */
    cppiHnd = (Cppi_Handle) Cppi_open (&cpdmaCfg);
    if (cppiHnd == NULL)
    {
        System_printf ("Error Core %d : Initializing QMSS CPPI CPDMA %d\n", coreNum, cpdmaCfg.dmaNum);
        return;
    }

    /* Setup memory region for host descriptors */
    memset ((Void *) &hostDesc, 0, SIZE_HOST_DESC * NUM_HOST_DESC);
    hostMemInfo.descBase = (UInt32 *) l2_global_address ((UInt32) hostDesc);
    hostMemInfo.descSize = SIZE_HOST_DESC;
    hostMemInfo.descNum = NUM_HOST_DESC;
    hostMemInfo.manageDescFlag = Qmss_ManageDesc_MANAGE_DESCRIPTOR;
    hostMemInfo.memRegion = Qmss_MemRegion_MEMORY_REGION_NOT_SPECIFIED;
    hostMemInfo.startIndex = 0;

    result = Qmss_insertMemoryRegion (&hostMemInfo);
    if (result < QMSS_SOK)
    {
        System_printf ("Error Core %d : Inserting memory region %d error code : %d\n", coreNum, hostMemInfo.memRegion, result);
    }
    else
        System_printf ("Core %d : Memory region %d inserted\n", coreNum, result);


    /* Setup memory region for monolithic descriptors */
    memset ((Void *) &monolithicDesc, 0, SIZE_MONOLITHIC_DESC * NUM_MONOLITHIC_DESC);
    monoMemInfo.descBase = (UInt32 *) l2_global_address ((UInt32) monolithicDesc);
    monoMemInfo.descSize = SIZE_MONOLITHIC_DESC;
    monoMemInfo.descNum = NUM_MONOLITHIC_DESC;
    monoMemInfo.manageDescFlag = Qmss_ManageDesc_MANAGE_DESCRIPTOR;
    monoMemInfo.memRegion = Qmss_MemRegion_MEMORY_REGION_NOT_SPECIFIED;
    monoMemInfo.startIndex = 0;

    result = Qmss_insertMemoryRegion (&monoMemInfo);
    if (result < QMSS_SOK)
    {
        System_printf ("Error Core %d : Inserting memory region %d error code : %d\n", coreNum, monoMemInfo.memRegion, result);
    }
    else
        System_printf ("Core %d : Memory region %d inserted\n", coreNum, result);

    /* Transfer data using host descriptors */
    hostModeTransfer (cppiHnd);

    /* Transfer data using monolithic descriptors */
    monoModeTransfer (cppiHnd);

    /* Close CPPI CPDMA instance */
    if ((result = Cppi_close (cppiHnd)) != CPPI_SOK)
        System_printf ("Error Core %d : Closing CPPI CPDMA error code : %d\n", coreNum, result);
    else 
        System_printf ("Core %d : CPPI CPDMA closed successfully\n", coreNum);

    /* Deinitialize CPPI LLD */
    if ((result = Cppi_exit ()) != CPPI_SOK)
        System_printf ("Error Core %d : Exiting CPPI error code : %d\n", coreNum, result);
    else 
        System_printf ("Core %d : CPPI exit successful\n", coreNum);

    System_printf ("*******************************************************\n");
    System_printf ("*********QMSS Infrastructure Mode Example Done*********\n");
    System_printf ("*******************************************************\n");
}


