// CrossWorks Tasking Library.
//
// Copyright (c) 2004 Rowley Associates Limited.
//
// This file may be distributed under the terms of the License Agreement
// provided with this software.
//
// THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#include "ctl_api.h"
#include <targets/LH79520.h>

typedef volatile unsigned int *reg32_t;

#define VectAddrn(n) (*(&VectAddr0 + n))
#define VectCntl(n) (*(&VectCntl0 + n))

#define INTERRUPT_SOURCE_COUNT 32

static unsigned int currentVector;

void irq_handler(void) __attribute__((naked));

void
irq_handler(void)
{
  asm("stmfd sp!, {r0-r12, lr}"); 
  asm("mrs r0, spsr");
  asm("stmfd sp!, {r0}");
  ctl_interrupt_count++;
  ((CTL_ISR_FN_t)VectorAddr)();
  VectorAddr = 0;
  asm("mov r0, sp");
  asm("ldr r1, =ctl_exit_isr");
  asm("bx r1");
}

int
ctl_set_isr(unsigned int vector, unsigned int priority, CTL_ISR_TRIGGER_t trigger, CTL_ISR_FN_t isr, CTL_ISR_FN_t *oldisr)
{
  if (oldisr)
    {
      int i;
      *oldisr = 0;
      for (i = 0; i < INTERRUPT_SOURCE_COUNT; ++i)
        if ((VectCntl(i) & 0x1F) == vector)
          *oldisr = (CTL_ISR_FN_t)VectAddrn(i);
    }
  if (isr)
    {
      /* Installing an ISR */
#ifdef CHECK_INTERRUPT_INSTALLED
      if (VectCntl(priority))
        return 0; /* ISR already installed at this interrupt priority */
#endif
      IntSelect &= ~(1 << vector); /* IRQ Interrupt */
      VectCntl(priority) = (1 << 5) | vector;
      VectAddrn(priority) = (unsigned int)isr;
    }
  else
    {
      /* Removing an ISR */
      VectCntl(priority) = 0;
      VectAddrn(priority) = 0;
    }
   
  return 1;
}

int
ctl_unmask_isr(unsigned int vector)
{
  IntEnable = 1 << vector;
  return 1;
}

int
ctl_mask_isr(unsigned int vector)
{
  IntClear = 1 << vector;
  return 1;
}
