/*  ============================================================================
 *   Copyright (c) Texas Instruments Inc 2010
 *
 *   Use of this software is controlled by the terms and conditions found in the
 *   license agreement under which this software has been supplied.
 *   ===========================================================================
 */

/** ============================================================================
 *
 *   @file  edmaIntDispatcher.c
 *
 *   @path  
 *
 *   @desc This is a utility function used by edma as interrupt dispatcher 
 *
 * ============================================================================
 */

#include <csl_edma3.h>
#include <csl_chip.h>
#include <csl_tsc.h>
#include "EdmaIntDispatcher.h"
#include "timestamp.h"

/* Global Edma Tcc handler table */
#pragma DATA_SECTION(TccHandlerTable,".far:TccHandlerTable");
EdmaTccHandler TccHandlerTable[64];

/*
 * =============================================================================
 *   @func  edmaIntDispatcher
 *  
 *   @arg
 *      handle        - Edma module handle
 *
 *   @desc
 *      This is the interrupt dispatcher routine for edma interrupts
 *
 *   @return
 *      NONE
 *
 * =============================================================================
 */
void edmaIntDispatcher (
    void        *handle
)
{
    CSL_Edma3Handle     hModule = (CSL_Edma3Handle)handle;
    CSL_Edma3CmdIntr    regionIntr;
    Uint32              tcc;
    Uint32              intr;
    Uint32              intrh;
	Int32				EdmaRegion;
    
    
//    printf("EDMAIntDispatcher invoked\n");
	ts6 = CSL_tscRead();
    
    /* Read the IPR & mask with IER */
	EdmaRegion = EDMA_REGION;

    regionIntr.region = EdmaRegion;
    CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND, &regionIntr);

	// read IER and keep only enabled interrupts from IPR
	if ( EdmaRegion == CSL_EDMA3_REGION_GLOBAL )
	{
	    regionIntr.intr  &= hModule->regs->IER;
	    regionIntr.intrh &= hModule->regs->IERH;
	}
	else  // get the IER from the shadow region
	{
		regionIntr.intr  &= hModule->regs->SHADOW[EdmaRegion].IER;
	    regionIntr.intrh &= hModule->regs->SHADOW[EdmaRegion].IERH;
	}
    
#if EDMADISPATCH_METHOD == EDMADISPATCH_REREAD_IPR
    while (regionIntr.intr || regionIntr.intrh)
    {
#endif
        intr  = regionIntr.intr;
        intrh = regionIntr.intrh;
        
		// clear any set & enabled IPR bits quickly to allow repetition
        CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR,&regionIntr);       

        for ( tcc = 0; intr != 0; intr >>= 1, tcc++ )
            if ( intr & 1 )
                InvokeHandle( tcc );
        
        for ( tcc = 32; intrh != 0; intrh >>= 1, tcc++ )
            if ( intrh & 1 )
                InvokeHandle( tcc );
        
#if EDMADISPATCH_METHOD == EDMADISPATCH_REREAD_IPR
		// re-read IPR
        CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,&regionIntr);         

		// read IER and keep only enabled interrupts from IPR
		if ( EdmaRegion == CSL_EDMA3_REGION_GLOBAL )
		{
		    regionIntr.intr  &= hModule->regs->IER;
		    regionIntr.intrh &= hModule->regs->IERH;
		}
		else  // get the IER from the shadow region
		{
			regionIntr.intr  &= hModule->regs->SHADOW[EdmaRegion].IER;
		    regionIntr.intrh &= hModule->regs->SHADOW[EdmaRegion].IERH;
		}
    }           
#else  // EDMADISPATCH_IEVAL
		// write to the EVAL bit of the IEVAL register for this region
		if ( EdmaRegion == CSL_EDMA3_REGION_GLOBAL )
		{
		    hModule->regs->IEVAL = 1;
		}
		else
		{
			hModule->regs->SHADOW[EdmaRegion].IEVAL = 1;
		}
#endif
	
	ts7 = CSL_tscRead();
}

/*
 * =============================================================================
 *   @func  edmaEventHook
 *  
 *   @arg
 *      tcc        - Tcc number
 *      fxn        - Pointer to function which points to edma isr
 *
 *   @desc
 *      This loads the hook table for the edma interrupt dispatcher
 *
 *   @return
 *      NONE
 *
 * =============================================================================
 */
void edmaEventHook (
    Uint16            tcc, 
    EdmaTccHandler    fxn
)
{
    TccHandlerTable[tcc] = (fxn);
}

