/* $Id: xintc_l.c,v 1.3 2002/06/26 21:28:58 meinelte Exp $ */
/******************************************************************************
*
*       XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
*       AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
*       SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,
*       OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
*       APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
*       THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
*       AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
*       FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY
*       WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
*       IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
*       REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
*       INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*       FOR A PARTICULAR PURPOSE.
*
*       (c) Copyright 2002 Xilinx Inc.
*       All rights reserved.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xintc_l.c
*
* This file contains low-level driver functions that can be used to access the
* device.  The user should refer to the hardware device specification for more
* details of the device operation.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver   Who  Date     Changes
* ----- ---- -------- -----------------------------------------------
* 1.00b jhl  04/24/02 First release
* </pre>
*
******************************************************************************/


/***************************** Include Files *********************************/

#include "xparameters.h"
#include "xbasic_types.h"
#include "xintc_l.h"

/************************** Constant Definitions *****************************/


/**************************** Type Definitions *******************************/


/***************** Macros (Inline Functions) Definitions *********************/


/************************** Function Prototypes ******************************/


/************************** Variable Definitions *****************************/

/*****************************************************************************/
/**
*
* This function is an default interrupt handler for the low level driver of the
* interrupt controller. It allows the interrupt vector table to be initialized
* to this function so that unexpected interrupts don't result in a system
* crash.
*
* @param    UnusedInput is an unused input that is necessary for this function
*           to have the signature of an input handler.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
void XIntc_DefaultHandler(void *UnusedInput)
{
}

/*****************************************************************************/
/**
*
* This function is an interrupt handler for the low level driver of the
* interrupt controller.  It must be connected to the interrupt source such
* that is called when an interrupt of the interrupt controller is active.
* It will resolve which interrupts are active and enabled and call the
* appropriate interrupt handler. It acknowledges the interrupt after it has
* been serviced by the interrupt handler.
*
* This function assumes that an interrupt vector table has been previously
* initialized by the user.  It does not verify that entries in the table are
* valid before calling an interrupt handler.
*
* @return
*
* None.
*
* @note
*
* The constants XPAR_INTC_SINGLE_BASEADDR & XPAR_INTC_MAX_ID must be setup for
* this to compile. Interrupt IDs range from 0 - 31 and correspond to the
* interrupt input signals for the interrupt controller. XPAR_INTC_MAX_ID
* specifies the highest numbered interrupt input signal that is used.
*
******************************************************************************/
void XIntc_LowLevelInterruptHandler(void)
{
    Xuint32 IntrStatus;
    Xuint32 IntrMask = 1;
    int IntrNumber;

    /* Get the interrupts that are waiting to be serviced */

    IntrStatus = XIntc_mGetIntrStatus(XPAR_INTC_SINGLE_BASEADDR);

    /* Service each interrupt that is active and enabled by checking each
     * bit in the register from LSB to MSB which corresponds to an interrupt
     * intput signal
     */
    for (IntrNumber = 0;
         IntrNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; IntrNumber++)
    {
        if (IntrStatus & 1)
        {
            XIntc_VectorTableEntry *TablePtr;

            /* If the interrupt has been setup to acknowledge it before
             * servicing the interrupt, then ack it
             */
            if (XIntc_AckBeforeService & IntrMask)
            {
                XIntc_mAckIntr(XPAR_INTC_SINGLE_BASEADDR, IntrMask);
            }

            /* The interrupt is active and enabled, call the interrupt
             * handler that was setup with the specified parameter
             */
            TablePtr = &XIntc_InterruptVectorTable[IntrNumber];
            TablePtr->Handler(TablePtr->CallBackRef);

            /* If the interrupt has been setup to acknowledge it after it
             * has been serviced then ack it
             */
            if ((XIntc_AckBeforeService & IntrMask) == 0)
            {
                XIntc_mAckIntr(XPAR_INTC_SINGLE_BASEADDR, IntrMask);
            }
        }
        /* Move to the next interrupt to check */

        IntrMask <<= 1;
        IntrStatus >>= 1;

        /* If there are no other bits set indicating that all interrupts
         * have been serviced, then exit the loop
         */
        if (IntrStatus == 0)
        {
            break;
        }
    }
}