
#include "csl_srio.h"
#include "csl_srioAux.h"
#include "csl_intc.h"
#include "csl_intcAux.h"
#include "srio.h"

/****************************************************************************
 *                             Local constants                              *
 ****************************************************************************/ 

#define SRIO_SET_DEVICE_ID(base_dev_id, large_base_dev_id)              \
            CSL_FMK(SRIO_BASE_ID_BASE_DEVICEID, base_dev_id) |          \
            CSL_FMK(SRIO_BASE_ID_LARGE_BASE_DEVICEID, large_base_dev_id)  

                                   
#ifdef EVMBOARD_VARIANT01
// 1.2 GHz for this evm revision
#define TOUT1       0x600000
#define TOUT2       0x6000000
#else
#define TOUT1       0x500000
#define TOUT2       0x5000000
#endif


/****************************************************************************
 *                             Local variables                              *
 ****************************************************************************/

#define SRIO_REGS                       ((CSL_SrioRegs *) CSL_SRIO_0_REGS)
             
extern CSL_SrioHandle       hSrio;        ///< Srio handle
volatile Uint32 IntCount0 = 0;            ///< Event 20 interrupt counter
volatile Uint32 srio_complet_isr[4];
int srio_isr_flag = 0;
          ///< Event 21 interrupt counter
extern CSL_SrioPortData response;             ///< Structure holding status of operation
CSL_SrioDirectIO_ConfigXfr lsu_conf = {0}; 

Int32 i32MaintenanceSrcBuf;
Int32 i32MaintenanceDstBuf;


// These are for errors tracking and occurence
// Additionnal error processing may be requiered
volatile Uint32 LsuErrs;
volatile Uint32 LsuErrsCnt;
volatile Uint32 PortErrs;
volatile Uint32 PortErrsCnt;
volatile Uint32 PortErrsDet0;
volatile Uint32 PortErrsDet0Cnt;
volatile Uint32 PortErrsDet1;
volatile Uint32 PortErrsDet1Cnt;
volatile Uint32 PortErrsDet2;
volatile Uint32 PortErrsDet2Cnt;
volatile Uint32 PortErrsDet3;
volatile Uint32 PortErrsDet3Cnt;
volatile Uint32 PortErrsCtlIndep0;
volatile Uint32 PortErrsCtlIndep0Cnt;
volatile Uint32 PortErrsCtlIndep1;
volatile Uint32 PortErrsCtlIndep1Cnt;
volatile Uint32 PortErrsCtlIndep2;
volatile Uint32 PortErrsCtlIndep2Cnt;
volatile Uint32 PortErrsCtlIndep3;
volatile Uint32 PortErrsCtlIndep3Cnt;
volatile Uint32 PortErrsCtlIndepB0;
volatile Uint32 PortErrsCtlIndepB0Cnt;
volatile Uint32 PortErrsCtlIndepB1;
volatile Uint32 PortErrsCtlIndepB1Cnt;
volatile Uint32 PortErrsCtlIndepB2;
volatile Uint32 PortErrsCtlIndepB2Cnt;
volatile Uint32 PortErrsCtlIndepB3;
volatile Uint32 PortErrsCtlIndepB3Cnt; 



/****************************************************************************
 *   NAME : Srio_Init
 ************************************************************************//**
 *
 *   This function initializes the specified SRIO port of the DSP and gives it an ID.
 *   Most of the parameters are given from the setup structure pSetup,
 *   but the additionnals single parameters (portmode, portspeed, etc)
 *   will override defaults values given in pSetup.
 *
 *   WARNING: Parameters must match hardware srio evm powerup configuration that
 *   is related to the port to be used. These evm parameters cannot be changed by
 *   this function, but are needed to configure the dsp correctly for the evm and
 *   the onboard srio switch. If user want to change srio powerup evm configuration,
 *   the configuration must be changed by DSP2 only using BSL functions (this is
 *   possible only for Variant11 boards and later).
 *
 *   @param [in] pSetup
 *      Pointer to CSL SRIO setup structure   
 *
 *   @param [in] blken
 *      Block enable 
 *
 *   @param [in] port
 *      Port to initialize  (only port 0 and 1 are possible on Variant11 boards and later,
 *      on Variant10 boards, dsp 1 can use port 0 only and dsp 2 can use 0,1,2,3)
 * 
 *   @param [in] ID
 *      DSP srio base adress ID (default dsp 1: 0x40 or dsp 2: 0x50)

 *   @param [in] portmode
 *      Port operation mode (0: 4X mode (default) or 1: 1X mode)
 *   
 *   @param [in] portspeed
 *      Port operation speed (0: 1.25,  1: 2.5, 2:3.125 (default) Gbits/s)
 *   
 *   @param [in] loopback
 *      Dsp internal srio loopback mode (1: Yes,  0: No (0 for normal operation))
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/        
void Srio_Init(CSL_SrioHwSetup *pSetup,
    Int32 blken, 
    Int32 port,
    Int32 ID,
    Int32 portmode,
    Int32 portspeed,
    Int32 loopback)
{
    Uint32 index;
    CSL_SrioSerDesPllMply pllmpy;
        
    pSetup->perEn = 1;    // Peripheral enable 
    pSetup->periCntlSetup.swMemSleepOverride = 1; // While in shutdown, put memories in sleep mode 
    pSetup->periCntlSetup.loopback = loopback;    // Internal loopback mode
    pSetup->periCntlSetup.bootComplete = 0;       // Boot process is over (complete)
    pSetup->periCntlSetup.busTransPriority = CSL_SRIO_BUS_TRANS_PRIORITY_1; // Set internal bus priority to 1 (next to lowest)
    
    /* UDI buffers are port based not priority based */
    // Verify if 4X or 1X port mode is needed
    if (portmode==PMODE1X)
    {
        // For 1x mode
        pSetup->periCntlSetup.bufferMode = CSL_SRIO_1X_MODE_PORT;
    }
    else  
    {
        // For 4x mode
        pSetup->periCntlSetup.bufferMode = CSL_SRIO_1X_MODE_PRIORITY;
    }

    pSetup->periCntlSetup.prescalar = CSL_SRIO_CLK_PRESCALE_6; // VBUS clock is of 333 MHz  from TPCC document section 2.3
    
    /* Enable port 0 PLL */
    
    pSetup->periCntlSetup.pllEn = 0xf;    //pSetup->periCntlSetup.pllEn = CSL_SRIO_PLL1_ENABLE; 
    pSetup->gblEn = 1;    // Enable clocks to all domains

    /* Enable clock in each domain */
    pSetup->blkEn[0] = 1;    // MMRs Always enabled 
    for (index=1; index<9; index++) // 9 domains
    {  
        pSetup->blkEn[index] = blken;    // Enable each of it
    }
    pSetup->deviceId1 = SRIO_SET_DEVICE_ID( ID + port, ID + port);
    pSetup->deviceId2 = SRIO_SET_DEVICE_ID( ID + port, ID + port); // for multi-cast

/*
#if TPB
    pSetup->deviceId1 = SRIO_SET_DEVICE_ID( ID + port, ID + port);
    pSetup->deviceId2 = SRIO_SET_DEVICE_ID( ID + port, ID + port); // for multi-cast
#endif

#if IPB
    pSetup->deviceId1 = SRIO_SET_DEVICE_ID( ID + 0, ID + 0);
    pSetup->deviceId2 = SRIO_SET_DEVICE_ID( ID + 1, ID + 1);
    pSetup->deviceId3 = SRIO_SET_DEVICE_ID( ID + 2, ID + 2);
    pSetup->deviceId4 = SRIO_SET_DEVICE_ID( ID + 3, ID + 3);
#endif

#if IPB

	for(index = 0; index < 4; index ++)
	{
		pSetup->pktFwdCntl[index].largeLowBoundDevId = ID + index;
		pSetup->pktFwdCntl[index].largeUpBoundDevId = ID + index;
		pSetup->pktFwdCntl[index].outBoundPort = index;
		pSetup->pktFwdCntl[index].smallLowBoundDevId = ID + index;
		pSetup->pktFwdCntl[index].smallUpBoundDevId = ID + index;
	}
#endif
*/
    /* configure the SERDES registers */

    
    // Setup for 125 MHz ref clock

    // Extract pll settings to match needed port speed for full rate configuration
    switch (portspeed)
    {
        // Speed 0 (1.25 G) (125 MHz * 10)
        case SPEED1_25G:
            pllmpy = CSL_SRIO_SERDES_PLL_MPLY_BY_5;
        break;
        
        // Speed 1 (2.5 G) (125 MHz * 20)
        case SPEED2_50G:
            pllmpy = CSL_SRIO_SERDES_PLL_MPLY_BY_10;
        break;

        // Default is speed 2 (3.125 G) (125 MHz * 25)
        default:
            pllmpy = CSL_SRIO_SERDES_PLL_MPLY_BY_12_5;
        break;
    }

    
    // !!! M.T.
    /* SERDES PLL configuration */
    pSetup->serDesPllCfg.pllEnable = TRUE;
    pSetup->serDesPllCfg.pllMplyFactor = pllmpy;

    /* SERDES RX channel 0 enable */
    pSetup->serDesRxChannelCfg[0].enRx = TRUE; 
    pSetup->serDesRxChannelCfg[0].symAlign = CSL_SRIO_SERDES_SYM_ALIGN_COMMA; 
    pSetup->serDesRxChannelCfg[0].los = CSL_SRIO_SERDES_LOS_DET_DISABLE;
    pSetup->serDesRxChannelCfg[0].clockDataRecovery = 0x00;  /* first order */
    pSetup->serDesRxChannelCfg[0].equalizer = 0x01;
    pSetup->serDesRxChannelCfg[0].rate = RATE;

    /* SERDES TX channel 0 enable */
    pSetup->serDesTxChannelCfg[0].enTx = TRUE;
    pSetup->serDesTxChannelCfg[0].commonMode = CSL_SRIO_SERDES_COMMON_MODE_RAISED; 
    pSetup->serDesTxChannelCfg[0].outputSwing = CSL_SRIO_SERDES_SWING_AMPLITUDE_1000; 
    pSetup->serDesTxChannelCfg[0].enableFixedPhase = TRUE;
    pSetup->serDesTxChannelCfg[0].rate = RATE; 
    
    /* SERDES RX channel 1 enable */
    pSetup->serDesRxChannelCfg[1].enRx = TRUE; 
    pSetup->serDesRxChannelCfg[1].symAlign = CSL_SRIO_SERDES_SYM_ALIGN_COMMA; 
    pSetup->serDesRxChannelCfg[1].los = CSL_SRIO_SERDES_LOS_DET_DISABLE;
    pSetup->serDesRxChannelCfg[1].clockDataRecovery = 0x00;  /* first order */
    pSetup->serDesRxChannelCfg[1].equalizer = 0x01;
    pSetup->serDesRxChannelCfg[1].rate = RATE;

    /* SERDES TX channel 1 enable */
    pSetup->serDesTxChannelCfg[1].enTx = TRUE; 
    pSetup->serDesTxChannelCfg[1].commonMode = CSL_SRIO_SERDES_COMMON_MODE_RAISED; 
    pSetup->serDesTxChannelCfg[1].outputSwing = CSL_SRIO_SERDES_SWING_AMPLITUDE_1000; 
    pSetup->serDesTxChannelCfg[1].enableFixedPhase = TRUE; 
    pSetup->serDesTxChannelCfg[1].rate = RATE; 

    /* SERDES RX channel 2 enable */
    pSetup->serDesRxChannelCfg[2].enRx = TRUE; 
    pSetup->serDesRxChannelCfg[2].symAlign = CSL_SRIO_SERDES_SYM_ALIGN_COMMA; 
    pSetup->serDesRxChannelCfg[2].los = CSL_SRIO_SERDES_LOS_DET_DISABLE;
    pSetup->serDesRxChannelCfg[2].clockDataRecovery = 0x00;   /* first order */
    pSetup->serDesRxChannelCfg[2].equalizer = 0x01;
    pSetup->serDesRxChannelCfg[2].rate = RATE;

    /* SERDES TX channel 2 enable */
    pSetup->serDesTxChannelCfg[2].enTx = TRUE; 
    pSetup->serDesTxChannelCfg[2].commonMode = CSL_SRIO_SERDES_COMMON_MODE_RAISED; 
    pSetup->serDesTxChannelCfg[2].outputSwing = CSL_SRIO_SERDES_SWING_AMPLITUDE_1000; 
    pSetup->serDesTxChannelCfg[2].enableFixedPhase = TRUE;
    pSetup->serDesTxChannelCfg[2].rate = RATE;  

    /* SERDES RX channel 3 enable */
    pSetup->serDesRxChannelCfg[3].enRx = TRUE; 
    pSetup->serDesRxChannelCfg[3].symAlign = CSL_SRIO_SERDES_SYM_ALIGN_COMMA; 
    pSetup->serDesRxChannelCfg[3].los = CSL_SRIO_SERDES_LOS_DET_DISABLE;
    pSetup->serDesRxChannelCfg[3].clockDataRecovery = 0x00; /* first order */
    pSetup->serDesRxChannelCfg[3].equalizer = 0x01;
    pSetup->serDesRxChannelCfg[3].rate = RATE;

    /* SERDES TX channel 3 enable */
    pSetup->serDesTxChannelCfg[3].enTx = TRUE; 
    pSetup->serDesTxChannelCfg[3].commonMode = CSL_SRIO_SERDES_COMMON_MODE_RAISED; 
    pSetup->serDesTxChannelCfg[3].outputSwing = CSL_SRIO_SERDES_SWING_AMPLITUDE_1000; 
    pSetup->serDesTxChannelCfg[3].enableFixedPhase = TRUE;
    pSetup->serDesTxChannelCfg[3].rate = RATE; 

    pSetup->flowCntlIdLen[0] = 1;  // Select flow control ID length 16-bit
    pSetup->flowCntlId[0] = ID  + port;  // Destination ID of flow n, same ids as we are doing loopback

/*
#if TPB
    pSetup->flowCntlIdLen[0] = 1;  // Select flow control ID length 16-bit
    pSetup->flowCntlId[0] = ID  + port;  // Destination ID of flow n, same ids as we are doing loopback
#endif

#if IPB
    pSetup->flowCntlIdLen[0] = 1;  // Select flow control ID length 16-bit
    pSetup->flowCntlId[0] = ID  + 0;  // Destination ID of flow n, same ids as we are doing loopback
    pSetup->flowCntlIdLen[1] = 1;  // Select flow control ID length 16-bit
    pSetup->flowCntlId[1] = ID  + 1;  // Destination ID of flow n, same ids as we are doing loopback
    pSetup->flowCntlIdLen[2] = 1;  // Select flow control ID length 16-bit
    pSetup->flowCntlId[2] = ID  + 2;  // Destination ID of flow n, same ids as we are doing loopback
    pSetup->flowCntlIdLen[3] = 1;  // Select flow control ID length 16-bit
    pSetup->flowCntlId[3] = ID  + 3;  // Destination ID of flow n, same ids as we are doing loopback
#endif
*/
    /* Sets the number of address bits generated by the PE as a source and 
     * processed by the PE as the target of an operation as 34 bits
     */
    pSetup->peLlAddrCtrl = CSL_SRIO_ADDR_SELECT_34BIT;

    /* Base device configuration */
    pSetup->devIdSetup.smallTrBaseDevId =  ID + port;
    pSetup->devIdSetup.largeTrBaseDevId =  ID + port;
    pSetup->devIdSetup.hostBaseDevId =     ID + port;

    /* Port General configuration */
    pSetup->portGenSetup.portLinkTimeout = 0xFFFF;  // 215 ms 
    pSetup->portGenSetup.portRespTimeout = 0xFFFF;  // 215 ms 
    pSetup->portGenSetup.hostEn = 1;                 // It is a host 
    pSetup->portGenSetup.masterEn = 1;     // This device can issue requests 

    /* Port control configuration */
    for (index = 0;index< 4; index++)
    {
        pSetup->portCntlSetup[index].portDis = 0;        // Do not disable Port I */
        pSetup->portCntlSetup[index].outPortEn = 1;      // Output on Port I enabled 
        pSetup->portCntlSetup[index].inPortEn = 1;       // Input on Port I enabled 
        pSetup->portCntlSetup[index].portWidthOverride =
                    CSL_SRIO_PORT_WIDTH_NO_OVERRIDE;      // 4 line port 
        pSetup->portCntlSetup[index].errCheckDis = 0;    // Err check enabled 
        pSetup->portCntlSetup[index].multicastRcvEn = 0; // MltCast receive enabled
        pSetup->portCntlSetup[index].stopOnPortFailEn = 1; // Stop on fail 
        pSetup->portCntlSetup[index].dropPktEn = 1;      // Drop PKT 
        pSetup->portCntlSetup[index].portLockoutEn = 0;  // Send any PKT 
        
   }

    /* Enable all logical/transport errors */
    pSetup->lgclTransErrEn = CSL_SRIO_IO_ERR_RESP_ENABLE |
                             CSL_SRIO_ILL_TRANS_DECODE_ENABLE |
                             CSL_SRIO_ILL_TRANS_TARGET_ERR_ENABLE |
                             CSL_SRIO_PKT_RESP_TIMEOUT_ENABLE |
                             CSL_SRIO_UNSOLICITED_RESP_ENABLE |
                             CSL_SRIO_UNSUPPORTED_TRANS_ENABLE;

    /* Enable all Port errors */
    for (index = 0;index< 4; index++)
    {
 
        pSetup->portErrSetup[index].portErrRateEn =
                                CSL_SRIO_ERR_IMP_SPECIFIC_ENABLE |
                                CSL_SRIO_CORRUPT_CNTL_SYM_ENABLE |
                                CSL_SRIO_CNTL_SYM_UNEXPECTED_ACKID_ENABLE |
                                CSL_SRIO_RCVD_PKT_NOT_ACCPT_ENABLE |
                                CSL_SRIO_PKT_UNEXPECTED_ACKID_ENABLE |
                                CSL_SRIO_RCVD_PKT_WITH_BAD_CRC_ENABLE |
                                CSL_SRIO_RCVD_PKT_OVER_276B_ENABLE |
                                CSL_SRIO_NON_OUTSTANDING_ACKID_ENABLE |
                                CSL_SRIO_PROTOCOL_ERROR_ENABLE |
                                CSL_SRIO_UNSOLICITED_ACK_CNTL_SYM_ENABLE |
                                CSL_SRIO_LINK_TIMEOUT_ENABLE;
    
        pSetup->portErrSetup[index].prtErrRtBias = CSL_SRIO_ERR_RATE_BIAS_1S; // Decrement error rate counter every second
        pSetup->portErrSetup[index].portErrRtRec = CSL_SRIO_ERR_RATE_COUNT_2; // Allow only 2 errors after error threshold is reached
    
        /*  Port error setup */ 
        pSetup->portErrSetup[index].portErrRtFldThresh = 10;   // Err threshold = 10 
        pSetup->portErrSetup[index].portErrRtDegrdThresh = 10; // Err degrade threshold = 10
        
    }
    /* This configures the SP_IP_MODE register */
    /*
       IDLE_ERR_DIS    - 0b0;  IDLE Error checking enabled
       TX_FIFO_BYP ASS - 0b0;  The TX_FIFO is operational
       PW_DIS          - 0b1;  Port-Write Error reporting is disabled
       TGT_ID_DIS      - 0b0;  packet accepted if DestID != BaseID
       SELF_RST        - 0b0;  Self reset disabled
       MLTC_EN         - 0b1;  Multicast-Event Interrupt Enable 
       RST_EN          - 0b1;  Reset Interrupt Enable
       PW_EN           - 0b1;  Port-Write-In Interrupt Enable
    */
     // Verify if port in 1x mode
    if (portmode==PMODE1X)
     {
        // For 1x mode
        pSetup->portIpModeSet = 0x4800003F;
     }
     else
     {
        // For 4x mode
        pSetup->portIpModeSet = 0x0800003F;
     }
     
    /* Configure the SP_IP_PRESCALE register assuming 333 MHz frequency */
    pSetup->portIpPrescalar = 33; 

    /*  Port-Write Timer. The timer defines a period to repeat sending an error
     *  reporting Port-Write request for software assistance. The timer stopped 
     *  by software writing to the error detect registers 900 ms
     */
    pSetup->pwTimer = CSL_SRIO_PW_TIME_8;

    /* Port control independent error reporting enable. Macros can be ORed
     *  to get the value
     */

    /*
       TX_FLW        - 0;     Receive link flow control
       SOFT_REC      - 0;     Hardware controlled error recovery 
       FORCE_REINIT  - 0;     Reinitialization process NOT forced
       TRANS_MODE    - 01;    transfer mode - Store & Forward Mode 
       DEBUG         - 1;     Debug enable
       SEND_DBG_PKT  - 0;     Do not force a debug packet
       ILL_TRANS_EN  - 1;     Illegal Transfer Error reporting Enable
       MAX_RETRY_EN  - 1;     Max_retry_error report enable
       MAX_RETRY_THR - 0x01;  Maximum Retry Threshold Trigger
       IRQ_EN        - 1;     Interrupt error report Enable
    */ 
    // !!! M.T. Retries???
    pSetup->portCntlIndpEn[0] = 0x01A20380; 
    pSetup->portCntlIndpEn[1] = 0x01A20380;
    pSetup->portCntlIndpEn[2] = 0x01A20380;
    pSetup->portCntlIndpEn[3] = 0x01A20380;
}

/****************************************************************************
 *   NAME : Srio_LSUSetup
 ************************************************************************//**
 *
 *   This function sets up the Load Store Unit.
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/    
void Srio_LSUSetup()
{
    // program the ICRR register 
    SRIO_REGS->LSU_ICCR        = 0xFFFFFFFF;    
    SRIO_REGS->LSU_ICRR[0]    = ICRR1;//ICRR0; 
    SRIO_REGS->LSU_ICRR[1]    = ICRR1;//ICRR1; 
    SRIO_REGS->LSU_ICRR[2]    = ICRR1;//ICRR0; 
    SRIO_REGS->LSU_ICRR[3]    = ICRR1;  
}

/****************************************************************************
 *   NAME : Srio_SetupInterrupt
 ************************************************************************//**
 *
 *   This function sets up Srio interrupts
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/ 

void Srio_SetupInterrupt()
{
    // Clears globals irq flags
    LsuErrs=0;
    LsuErrsCnt=0;
    PortErrs=0;
    PortErrsCnt=0;
    PortErrsDet0=0;
    PortErrsDet0Cnt=0;
    PortErrsDet1=0;
    PortErrsDet1Cnt=0;
    PortErrsDet2=0;
    PortErrsDet2Cnt=0;
    PortErrsDet3=0;
    PortErrsDet3Cnt=0;
    PortErrsCtlIndep0=0;
    PortErrsCtlIndep0Cnt=0;
    PortErrsCtlIndep1=0;
    PortErrsCtlIndep1Cnt=0;
    PortErrsCtlIndep2=0;
    PortErrsCtlIndep2Cnt=0;
    PortErrsCtlIndep3=0;
    PortErrsCtlIndep3Cnt=0;
    PortErrsCtlIndepB0=0;
    PortErrsCtlIndepB0Cnt=0;
    PortErrsCtlIndepB1=0;
    PortErrsCtlIndepB1Cnt=0;
    PortErrsCtlIndepB2=0;
    PortErrsCtlIndepB2Cnt=0;
    PortErrsCtlIndepB3=0;
    PortErrsCtlIndepB3Cnt=0;
        
    // Clears int events counter
    IntCount0 = 0;                    ///< Event 20 interrupt counter
    srio_complet_isr[0] = 0;                    ///< Event 21 interrupt counter
	srio_complet_isr[1] = 0;
	srio_complet_isr[2] = 0;
	srio_complet_isr[3] = 0;
	CSL_intcInterruptEnable(CSL_INTC_VECTID_10);
 }
/****************************************************************************
 *   NAME : Srio_CloseInterrupt
 ************************************************************************//**
 *
 *   This function disables the SRIO interrupts
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/ 


/****************************************************************************
 *   NAME : Srio_Event20Isr
 ************************************************************************//**
 *
 *   This function is the event 20 interrupt service routine, checking for errors.
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/ 
void Srio_Event20Isr()
{
    Uint32 data,errlsu,temp,temp1;

    CSL_srioGetLsuIntrStat(hSrio,&data);

    // Check for transaction completed lsu1
    if((temp=(data & ( CSL_FMK(SRIO_LSU_ICSR_ICS0, 1)))))
    {    
        IntCount0++;
        CSL_SrioLsuIntrClear (hSrio, temp);
    }
    
    // Check for transaction completed lsu3
    if((temp=(data & ( CSL_FMK(SRIO_LSU_ICSR_ICS16, 1)))))
    {    
        IntCount0++;
        CSL_SrioLsuIntrClear (hSrio, temp);
    }
     
    // !!! M.T. Validates lsu errors
    if ((errlsu=(data & 0x00FE00FE))!=0)
    {
        // Count of lsu errors received so far...
        LsuErrsCnt++;
        
        // Latch all lsu errors received so far
        LsuErrs|=errlsu;

        // Clears actual lsu errors
        CSL_SrioLsuIntrClear (hSrio, errlsu);
    }
    
    // !!! M.T. Validates Port error handling
    // Warning additionnal processing may be requiered for all following errors/events
    CSL_srioGetErrRstIntrStat(hSrio,&data);
    
    // Keeps valid errors
    temp=data & 0x00010F07;
    
    // Are there any ports error conditions
    if (temp)
    {
        // Count of port errors received so far...
        PortErrsCnt++;
        
        // Latch all port errors received so far
        PortErrs|=temp;
        
        // Clears all possible port errors
        CSL_SrioErrRstIntrClear(hSrio,temp);
        
        // Additionnal errors clearing steps
        
        // Clears Multicast event
        if (temp & 0x1)
        {
            SRIO_REGS->SP_IP_MODE|=0x10;
        }

        // Clears Port Write In event
        if (temp & 0x2)
        {
            SRIO_REGS->SP_IP_MODE|=0x1;
        }

        // Clears Device Reset event
        if (temp & 0x10000)
        {
            SRIO_REGS->SP_IP_MODE|=0x4;
        }
        
        // Clears errors for port0 event
        if (temp & 0x100)
        {
            temp1 = (SRIO_REGS->PORT_ERROR[0].SP_ERR_DET & 0x03000004);
            
            // If any of these errors
            if (temp1)
            {
                // Clears fatal, fail threshold and degraded threshold errors
                SRIO_REGS->PORT_ERROR[0].SP_ERR_DET|=temp1;
            
                // Count of port errors received so far...
                PortErrsDet0Cnt++;
        
                // Latch all port errors received so far
                PortErrsDet0|=temp1;
            }
            
            temp1 = (SRIO_REGS->PORT_OPTION[0].SP_CTL_INDEP & 0x00110000);
            
            // If any of these errors
            if (temp1)
            {
                // Clears illegal and max retry errors
                SRIO_REGS->PORT_OPTION[0].SP_CTL_INDEP|=temp1;
            
                // Count of port errors received so far...
                PortErrsCtlIndep0Cnt++;
        
                // Latch all port errors received so far
                PortErrsCtlIndep0|=temp1;
            }

            temp1 = (SRIO_REGS->PORT_OPTION[0].SP_CTL_INDEP & 0x00000040);
            
            // If any of these errors
            if (temp1)
            {
                // Clears error occured errors
                SRIO_REGS->PORT_OPTION[0].SP_CTL_INDEP|=temp1;
            
                // Count of port errors received so far...
                PortErrsCtlIndepB0Cnt++;
        
                // Latch all port errors received so far
                PortErrsCtlIndepB0|=temp1;
            }
        }
        
        // Clears errors for port1 event
        if (temp & 0x200)
        {
            temp1 = (SRIO_REGS->PORT_ERROR[1].SP_ERR_DET & 0x03000004);
            
            // If any of these errors
            if (temp1)
            {
                // Clears fatal, fail threshold and degraded threshold errors
                SRIO_REGS->PORT_ERROR[1].SP_ERR_DET|=temp1;
            
                // Count of port errors received so far...
                PortErrsDet1Cnt++;
        
                // Latch all port errors received so far
                PortErrsDet1|=temp1;
            }
            
            temp1 = (SRIO_REGS->PORT_OPTION[1].SP_CTL_INDEP & 0x00110000);
            
            // If any of these errors
            if (temp1)
            {
                // Clears illegal and max retry errors
                SRIO_REGS->PORT_OPTION[1].SP_CTL_INDEP|=temp1;
            
                // Count of port errors received so far...
                PortErrsCtlIndep1Cnt++;
        
                // Latch all port errors received so far
                PortErrsCtlIndep1|=temp1;
            }

            temp1 = (SRIO_REGS->PORT_OPTION[1].SP_CTL_INDEP & 0x00000040);
            
            // If any of these errors
            if (temp1)
            {
                // Clears error occured errors
                SRIO_REGS->PORT_OPTION[1].SP_CTL_INDEP|=temp1;
            
                // Count of port errors received so far...
                PortErrsCtlIndepB1Cnt++;
        
                // Latch all port errors received so far
                PortErrsCtlIndepB1|=temp1;
            }
        }
        
        // Clears errors for port2 event
        if (temp & 0x400)
        {
            temp1 = (SRIO_REGS->PORT_ERROR[2].SP_ERR_DET & 0x03000004);
            
            // If any of these errors
            if (temp1)
            {
                // Clears fatal, fail threshold and degraded threshold errors
                SRIO_REGS->PORT_ERROR[2].SP_ERR_DET|=temp1;
            
                // Count of port errors received so far...
                PortErrsDet2Cnt++;
        
                // Latch all port errors received so far
                PortErrsDet2|=temp1;
            }
            
            temp1 = (SRIO_REGS->PORT_OPTION[2].SP_CTL_INDEP & 0x00110000);
            
            // If any of these errors
            if (temp1)
            {
                // Clears illegal and max retry errors
                SRIO_REGS->PORT_OPTION[2].SP_CTL_INDEP|=temp1;
            
                // Count of port errors received so far...
                PortErrsCtlIndep2Cnt++;
        
                // Latch all port errors received so far
                PortErrsCtlIndep2|=temp1;
            }

            temp1 = (SRIO_REGS->PORT_OPTION[2].SP_CTL_INDEP & 0x00000040);
            
            // If any of these errors
            if (temp1)
            {
                // Clears error occured errors
                SRIO_REGS->PORT_OPTION[2].SP_CTL_INDEP|=temp1;
            
                // Count of port errors received so far...
                PortErrsCtlIndepB2Cnt++;
        
                // Latch all port errors received so far
                PortErrsCtlIndepB2|=temp1;
            }
        }
        
        // Clears errors for port3 event
        if (temp & 0x800)
        {
            temp1 = (SRIO_REGS->PORT_ERROR[3].SP_ERR_DET & 0x03000004);
            
            // If any of these errors
            if (temp1)
            {
                // Clears fatal, fail threshold and degraded threshold errors
                SRIO_REGS->PORT_ERROR[3].SP_ERR_DET|=temp1;
            
                // Count of port errors received so far...
                PortErrsDet3Cnt++;
        
                // Latch all port errors received so far
                PortErrsDet3|=temp1;
            }
            
            temp1 = (SRIO_REGS->PORT_OPTION[3].SP_CTL_INDEP & 0x00110000);
            
            // If any of these errors
            if (temp1)
            {
                // Clears illegal and max retry errors
                SRIO_REGS->PORT_OPTION[3].SP_CTL_INDEP|=temp1;
            
                // Count of port errors received so far...
                PortErrsCtlIndep3Cnt++;
        
                // Latch all port errors received so far
                PortErrsCtlIndep3|=temp1;
            }

            temp1 = (SRIO_REGS->PORT_OPTION[3].SP_CTL_INDEP & 0x00000040);
            
            // If any of these errors
            if (temp1)
            {
                // Clears error occured errors
                SRIO_REGS->PORT_OPTION[3].SP_CTL_INDEP|=temp1;
            
                // Count of port errors received so far...
                PortErrsCtlIndepB3Cnt++;
        
                // Latch all port errors received so far
                PortErrsCtlIndepB3|=temp1;
            }
        }
    }
    
    // Sets interrupt rate counter
    SRIO_REGS->INTDST_RATE_CNTL[0] = 0x1;
}

/****************************************************************************
 *   NAME : Srio_Event21Isr
 ************************************************************************//**
 *
 *   This function is the event 21 interrupt service routine, which happens 
 *     upon a complete transaction. 
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/ 
void IsrSrioTest()
{
    srio_isr_flag = 1;
}

/****************************************************************************
 *   NAME : Srio_Write
 ************************************************************************//**
 *
 *   This function writes a array of data in a connected Srio device at the 
 *     specified address
 *
 *   @param [in] src
 *      Address of the data to be sent
 *
 *   @param [in] dst
 *      Destination address in the target's memory space 
 *
 *   @param [in] len
 *      Data buffer length
 * 
 *   @param [in] type
 *      Transaction packet type
 * 
 *   @param [in] srcport
 *      Port used for write on DSP
 * 
 *   @param [in] dstID
 *      Destination ID of the target
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/     
Int32 Srio_ReadWrite(Uint32 src, Uint32 dst, Int32 len, Int32 type, Int32 srcport, Int32 dstID)
{
    Uint8 lsu_no;
    Uint32 data,errlsu,temp;
//    CSL_SrioPortData response;             ///< Structure holding status of operation
//    CSL_SrioDirectIO_ConfigXfr lsu_conf = {0}; 
     
    /* Create an LSU configuration */
    lsu_conf.srcNodeAddr           = src;             /* Local address */
    lsu_conf.dstNodeAddr.addressHi = 0;
    lsu_conf.dstNodeAddr.addressLo = dst;             /* Remote address */
    lsu_conf.byteCnt               = len;
    lsu_conf.idSize                = 0;               /* 16 bit device id */
    lsu_conf.priority              = 2;               /* PKT priority is 2 */
    lsu_conf.xambs                 = 0;               /* Not an extended
                                                          address */
    lsu_conf.dstId                 = dstID;
    lsu_conf.intrReq               = 1;               /*  interrupts */
    lsu_conf.pktType               = type;
                                                      /* write with no
                                                          response */
    lsu_conf.hopCount              = 0;               /* Valid for
                                                          maintainance pkt */
    lsu_conf.doorbellInfo          = 0;               /* Not a doorbell pkt */
    lsu_conf.outPortId             = srcport;         /* Tx on Port 0 */

    lsu_no = srcport;//SELECTED_LSU;
	CSL_intcEventClear(21);
    CSL_srioLsuSetup (hSrio, &lsu_conf, lsu_no);


    /* Wait for the completion of transfer */
    response.index = lsu_no;

    while(1)
    {
	    if(srio_isr_flag || (*(volatile unsigned int *)0x01800000 && 0x00200000))
//	    if(*(volatile unsigned int *)0x01800000 && 0x00200000)
	    {
			CSL_srioGetLsuIntrStat(hSrio,&data); 
		    // Check for transaction completed lsu2
		    if((temp=(data & ( CSL_FMK(SRIO_LSU_ICSR_ICS0, 1)))))
		    {
		        srio_complet_isr[0]++;
		        CSL_SrioLsuIntrClear (hSrio, temp);
		    }

		    // Check for transaction completed lsu2
		    if((temp=(data & ( CSL_FMK(SRIO_LSU_ICSR_ICS8, 1)))))
		    {
		        srio_complet_isr[1]++;
		        CSL_SrioLsuIntrClear (hSrio, temp);
		    }

			 // Check for transaction completed lsu2
		    if((temp=(data & ( CSL_FMK(SRIO_LSU_ICSR_ICS16, 1)))))
		    {
		        srio_complet_isr[2]++;
		        CSL_SrioLsuIntrClear (hSrio, temp);
		    }

		    // Check for transaction completed lsu4
		    if((temp=(data & ( CSL_FMK(SRIO_LSU_ICSR_ICS24, 1)))))
		    {
		        srio_complet_isr[3]++;
		        CSL_SrioLsuIntrClear (hSrio, temp);
		    }

		    // !!! M.T. Validates lsu errors
		    if ((errlsu=(data & 0xFE00FE00))!=0)
		    {
		        // Count of lsu errors received so far...
		        LsuErrsCnt++;
		        
		        // Latch all lsu errors received so far
		        LsuErrs|=errlsu;

		        // Clears actual lsu errors
		        CSL_SrioLsuIntrClear (hSrio, errlsu);
		    }
			*(volatile unsigned int *)0x01800040 = 0x00300000;
		    SRIO_REGS->INTDST_RATE_CNTL[1] = 0x1;
		    srio_isr_flag = 0;
		    break;
	    }
	}	
    // wait till the busy bit goes low.
    do
    {
        CSL_srioGetHwStatus (hSrio, CSL_SRIO_QUERY_LSU_BSY_STAT, &response);
    } while(response.data != 0);

    // check the completion code
    CSL_srioGetHwStatus (hSrio,CSL_SRIO_QUERY_LSU_COMP_CODE_STAT,&response);
    
    // Returns the response code
    return (response.data);
}

/****************************************************************************
 *   NAME : Srio_DoorBell
 ************************************************************************//**
 *
 *   This function generates a doorbell interruption to Srio device at the 
 *     specified address
 *
 *   @param [in] uiDoorBellInfo
 *      Doorbell info to send
 * 
 *   @param [in] srcport
 *      Port used for write on DSP
 * 
 *   @param [in] dstID
 *      Destination ID of the target
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/     
Int32 Srio_DoorBell(Uint32 uiDoorBellInfo, Int32 srcport, Int32 dstID)
{
    Uint8 lsu_no;
//    CSL_SrioPortData response;             ///< Structure holding status of operation
//    CSL_SrioDirectIO_ConfigXfr lsu_conf = {0}; 
     
     /* Create an LSU configuration */
    lsu_conf.dstNodeAddr.addressHi = 0;
    lsu_conf.idSize                = 1;               /* 16 bit device id */
    lsu_conf.priority              = 1;               /* PKT priority is 1 */
    lsu_conf.xambs                 = 0;               /* Not an extended address */
    lsu_conf.dstId                 = dstID;
    lsu_conf.intrReq               = 0;               /* No interrupts */
    lsu_conf.pktType               = REQ_DOORBELL;
                                                      /* write with no response */
    lsu_conf.hopCount              = 0;               /* Valid for
                                                          maintainance pkt */
    lsu_conf.doorbellInfo          = uiDoorBellInfo;              
    lsu_conf.outPortId             = srcport;         /* Tx on Port 0 */
    
    lsu_no = SELECTED_LSU;
    CSL_srioLsuSetup (hSrio, &lsu_conf, lsu_no);
    
    /* Wait for the completion of transfer */
    response.index = lsu_no;
    do
    {
        CSL_srioGetHwStatus (hSrio, CSL_SRIO_QUERY_LSU_BSY_STAT, &response);
    } while(response.data != 1);

    /* wait still the transfer completes */
    do
    {
        CSL_srioGetHwStatus (hSrio, CSL_SRIO_QUERY_LSU_BSY_STAT, &response);
    } while(response.data != 0);

    // check the completion code
    CSL_srioGetHwStatus (hSrio,CSL_SRIO_QUERY_LSU_COMP_CODE_STAT,&response);
    
    // Returns the response code
    return(response.data);
}

/****************************************************************************
 *   NAME : Srio_MaintenanceWrite
 ************************************************************************//**
 *
 *   This function writes a CSR or a CAR register in the destination SRIO
 *           registers
 *
 *   @param [in] i32Port
 *      Port used for write
 *
 *   @param [in] i32ID
 *      Destination ID of the target
 *
 *   @param [in] i32HopCount
 *      Hop Count to reach target 
 * 
 *   @param [in] i32Reg
 *      Register to be written
 * 
 *   @param [in] i32Val
 *      Value to be written
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/ 
Int32 Srio_MaintenanceWrite(Int32 i32Port, Int32 i32ID, Int32 i32HopCount, 
                                        Int32 i32DestReg, Int32 i32Val)
{        

    Uint8 lsu_no;
//    CSL_SrioPortData response;             ///< Structure holding status of operation
//    CSL_SrioDirectIO_ConfigXfr lsu_conf = {0}; 
    volatile Int32 iTimeout;

    i32MaintenanceSrcBuf = i32Val;
    /* Create an LSU configuration */
    lsu_conf.srcNodeAddr           = (Int32)&i32MaintenanceSrcBuf;  /* Local address */
    lsu_conf.dstNodeAddr.addressHi = 0;
    lsu_conf.dstNodeAddr.addressLo = i32DestReg;      /* Remote address */
    lsu_conf.byteCnt               = 4;
    lsu_conf.idSize                = 1;               /* 16 bit device id */
    lsu_conf.priority              = 0;               /* PKT priority is 2 */
    lsu_conf.xambs                 = 0;               /* Not an extended
                                                          address */
    lsu_conf.dstId                 = i32ID;
    lsu_conf.intrReq               = 1;               /*  interrupts */
    lsu_conf.pktType               = REQ_MAINTENANCE_W;
                                                      /* write with no
                                                          response */
    lsu_conf.hopCount              = i32HopCount;     /* Valid for
                                                          maintainance pkt */
    lsu_conf.doorbellInfo          = 0;               /* Not a doorbell pkt */
    lsu_conf.outPortId             = i32Port;         /* Tx on Port 0 */

    lsu_no = SELECTED_LSU;
    CSL_srioLsuSetup (hSrio, &lsu_conf, lsu_no);

    /* Wait for the completion of transfer */
    response.index = lsu_no;
    do
    {
        CSL_srioGetHwStatus (hSrio, CSL_SRIO_QUERY_LSU_BSY_STAT, &response);
    } while(response.data != 1);

    // wait till the busy bit goes low.
    do
    {
        CSL_srioGetHwStatus (hSrio, CSL_SRIO_QUERY_LSU_BSY_STAT, &response);
    } while(response.data != 0);

    // check the completion code
    CSL_srioGetHwStatus (hSrio,CSL_SRIO_QUERY_LSU_COMP_CODE_STAT,&response);

    return(response.data);
}

/****************************************************************************
 *   NAME : Srio_MaintenanceRead
 ************************************************************************//**
 *
 *   This function reads a CSR or a CAR register in the destination SRIO
 *           registers
 *
 *   @param [in] i32Port
 *      Port used for write
 *
 *   @param [in] i32ID
 *      Destination ID of the target
 *
 *   @param [in] i32HopCount
 *      Hop Count to reach target 
 * 
 *   @param [in] i32Reg
 *      Register to be read
 * 
 *   @param [out] i32Val
 *      Value to read
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/ 
Int32 Srio_MaintenanceRead(Int32 i32Port, Int32 i32ID, Int32 i32HopCount, 
                                        Int32 i32Reg, Int32 *i32Val)
{        
    Uint8 lsu_no;
//    CSL_SrioPortData response;             ///< Structure holding status of operation
//    CSL_SrioDirectIO_ConfigXfr lsu_conf = {0}; 
    volatile int iTimeout;

    /* Create an LSU configuration */
    lsu_conf.srcNodeAddr           = (Int32)&i32MaintenanceDstBuf;  /* Local address */
    lsu_conf.dstNodeAddr.addressHi = 0;
    lsu_conf.dstNodeAddr.addressLo = i32Reg;          /* Remote address */
    lsu_conf.byteCnt               = 4;
    lsu_conf.idSize                = 1;               /* 16 bit device id */
    lsu_conf.priority              = 0;               /* PKT priority is 0 */
    lsu_conf.xambs                 = 0;               /* Not an extended
                                                          address */
    lsu_conf.dstId                 = i32ID;           // ID needed to reach target
    lsu_conf.intrReq               = 1;               /*  interrupts */
    lsu_conf.pktType               = REQ_MAINTENANCE_R;
                                                      /* write with no
                                                          response */
    lsu_conf.hopCount              = i32HopCount;     /* Valid for
                                                          maintainance pkt */
    lsu_conf.doorbellInfo          = 0;               /* Not a doorbell pkt */
    lsu_conf.outPortId             = i32Port;         /* Tx on Port 0 */

    lsu_no = SELECTED_LSU;
    CSL_srioLsuSetup (hSrio, &lsu_conf, lsu_no);

    /* Wait for the completion of transfer */
    response.index = lsu_no;
    do
    {
        CSL_srioGetHwStatus (hSrio, CSL_SRIO_QUERY_LSU_BSY_STAT, &response);
    } while(response.data != 1);

    // wait till the busy bit goes low.
    do
    {
        CSL_srioGetHwStatus (hSrio, CSL_SRIO_QUERY_LSU_BSY_STAT, &response);
    } while(response.data != 0);

    // check the completion code
    CSL_srioGetHwStatus (hSrio,CSL_SRIO_QUERY_LSU_COMP_CODE_STAT,&response);

    *i32Val = i32MaintenanceDstBuf;

    return(response.data);
}

/****************************************************************************
 *   NAME : Srio_LockPort
 ************************************************************************//**
 *
 *   This function executes a port lockdown on the selected port. 
 *
 *   @param [in] u32Port
 *      Port used for write
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/
void Srio_LockPort(Uint32 u32Port)
{
    SRIO_REGS->PORT[u32Port].SP_CTL |= 0x2;
}

/****************************************************************************
 *   NAME : Srio_UnlockPort
 ************************************************************************//**
 *
 *   This function disables the port lockdown on the selected port. 
 *
 *   @param [in] u32Port
 *      Port used for write
 *   
 *   @ingroup EVM_SRIO
 *
 ***************************************************************************/
void Srio_UnlockPort(Uint32 u32Port)
{
    SRIO_REGS->PORT[u32Port].SP_CTL &= ~0x2;
}
