// Copyright (c) 2001-2005 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.
//
////////////////////////////////////////////////////////////////////////////////
//                Freescale MC9328MXL Interrupt Function
//
// Description
// -----------
// This module contains functions for setting up interrupts on the 
// MC9328MXL.
//
////////////////////////////////////////////////////////////////////////////////

#include <targets/MC9328MXL.h>
#include "interrupt.h"

#define INTERRUPT_SOURCES 64

static isr_fn_t isr_vectors[INTERRUPT_SOURCES];

void irq_handler(void) __attribute__ ((interrupt ("IRQ")));

static void
default_isr(void)
{
  while (1);
}

void
irq_handler(void)
{
  isr_vectors[AITC_NIVECSR >> 16]();
}

void
interrupt_init(void)
{
  int i;
  for (i = 0; i < INTERRUPT_SOURCES; ++i)
    isr_vectors[i] = default_isr;
  AITC_INTENABLEH = 0;
  AITC_INTENABLEL = 0;
  __ARMLIB_enableIRQ();
}

void
interrupt_set_isr(int n, isr_fn_t fn)
{
  isr_vectors[n] = fn;
}

void
interrupt_enable(int n, int fiq)
{
  if (n >= 32)
    {
      AITC_INTENABLEH |= 1 << (n - 32);
      if (fiq)
        AITC_INTTYPEH |= (1 << (n - 32));
      else
        AITC_INTTYPEH &= ~(1 << (n - 32));
    }
  else
    {
      AITC_INTENABLEL |= 1 << n;
      if (fiq)
        AITC_INTTYPEL |= 1 << n;
      else
        AITC_INTTYPEL &= ~(1 << n);
    }
}

void
interrupt_disable(int n)
{
  if (n >= 32)
    AITC_INTENABLEH &= ~(1 << (n - 32));
  else
    AITC_INTENABLEL &= ~(1 << n);
}

