/*****************************************************************************
 *   irq.c: Interrupt handler C file for NXP LPC23xx/24xx Family Microprocessors
 *
 *   Copyright(C) 2006, NXP Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2006.07.13  ver 1.00    Prelimnary version, first Release
 *
 ******************************************************************************/ 

/* TODO mthomas - volatiles for vect_addr, vect_cntl? */

#include "LPC23xx.h"			/* LPC23XX/24xx Peripheral Registers */
#include "irq.h"

/* Initialize the interrupt controller */
/******************************************************************************
** Function name:		init_VIC
**
** Descriptions:		Initialize VIC interrupt controller.
** parameters:			None
** Returned value:		None
** 
******************************************************************************/
void init_VIC(void) 
{
    u32 i = 0;
    u32 *vect_addr, *vect_cntl;
   	
    /* initialize VIC*/
    VICIntEnClr = 0xffffffff;
    VICVectAddr = 0;
    VICIntSelect = 0;

    /* set all the vector and vector control register to 0 */
    for ( i = 0; i < VIC_SIZE; i++ )
    {
		vect_addr = (u32 *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4);
		vect_cntl = (u32 *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + i*4);
		*vect_addr = 0x0;	
		*vect_cntl = 0xF;
    }
    return;
}

/******************************************************************************
** Function name:		install_irq
**
** Descriptions:		Install interrupt handler
** parameters:			Interrupt number, interrupt handler address, 
**						interrupt priority
** Returned value:		true or false, return false if IntNum is out of range
** 
******************************************************************************/
u32 install_irq( u32 IntNumber, IRQHandler HandlerAddr, u32 Priority )
{
    u32 *vect_addr;
    u32 *vect_cntl;
      
    VICIntEnClr = 1 << IntNumber;	/* Disable Interrupt */
    if ( IntNumber >= VIC_SIZE )
    {
		return ( 0 );
    }
    else
    {
		/* find correct VIC address for the handler, based on IntNumber */
		vect_addr = (u32 *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4);
		vect_cntl = (u32 *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber*4);
		*vect_addr = (u32)HandlerAddr;	/* set interrupt vector */
		*vect_cntl = Priority;
		VICIntEnable = 1 << IntNumber;	/* Enable Interrupt */
		return( 1 );
    }
}


u32 uninstall_irq( u32 IntNumber )
{
    u32 *vect_addr;
    u32 *vect_cntl;

    VICIntEnClr = 1 << IntNumber;	/* Disable Interrupt */
    if ( IntNumber >= VIC_SIZE )
    {
		return ( 0 );
    }
    else
    {
		/* find correct VIC address for the handler, based on IntNumber */
		vect_addr = (u32 *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4);
		vect_cntl = (u32 *)(VIC_BASE_ADDR + VECT_CNTL_INDEX + IntNumber*4);
		*vect_addr = (u32) 0;	/* don't leave schmutz lying around */
		*vect_cntl = LOWEST_PRIORITY;
		return( 1 );
    }
}

void disableInterruptsFunction() {
  disableInterrupts();
}
#include "SFBAssert.h"
extern u32 interruptVectorTable[16];
void enableInterruptsFunction() {
  /*  enableInterrupts();*/
  __asm__ __volatile__ (                                                  \
               "MRS r0, CPSR\n\t"     /* Read status register */          \
               "BIC r0, r0, #0x80\n\t"/* Clear the I bit to allow IRQ */  \
               "MSR CPSR_c, r0"       /* Update status */                 \
               ::: "r0")              /* We clobbered r0 */

    ;
}
void suspendInterruptsFunction(u32 * pvar) {
  u32 v;
  suspendInterrupts(v);
  *pvar = v;
}
void restoreInterruptsFunction(u32 * pvar) {
  u32 v = *pvar;
  restoreInterrupts(v);
}
/******************************************************************************
**                            End Of File
******************************************************************************/

