diff options
Diffstat (limited to 'FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_2/src/xintc.c')
-rw-r--r-- | FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_2/src/xintc.c | 1078 |
1 files changed, 1078 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_2/src/xintc.c b/FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_2/src/xintc.c new file mode 100644 index 000000000..a6d1b7872 --- /dev/null +++ b/FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_2/src/xintc.c @@ -0,0 +1,1078 @@ +/****************************************************************************** +* +* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xintc.c +* +* Contains required functions for the XIntc driver for the Xilinx Interrupt +* Controller. See xintc.h for a detailed description of the driver. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a ecm 08/16/01 First release +* 1.00b jhl 02/21/02 Repartitioned the driver for smaller files +* 1.00b jhl 04/24/02 Made LookupConfig global and compressed ack before table +* in the configuration into a bit mask +* 1.00c rpm 10/17/03 New release. Support the static vector table created +* in the xintc_g.c configuration table. +* 1.00c rpm 04/23/04 Removed check in XIntc_Connect for a previously connected +* handler. Always overwrite the vector table handler with +* the handler provided as an argument. +* 1.10c mta 03/21/07 Updated to new coding style +* 1.11a sv 11/21/07 Updated driver to support access through a DCR bridge +* 2.00a ktn 10/20/09 Updated to use HAL Processor APIs. +* 2.04a bss 01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt +* and XIntc_SetNormalIntrMode for setting to normal +* interrupt mode. +* 2.05a bss 08/16/12 Updated to support relocatable vectors in Microblaze, +* updated XIntc_SetNormalIntrMode to use IntVectorAddr +* which is the interrupt vector address +* 2.06a bss 01/28/13 To support Cascade mode: +* Modified XIntc_Initialize,XIntc_Start,XIntc_Connect +* XIntc_Disconnect,XIntc_Enable,XIntc_Disable, +* XIntc_Acknowledge,XIntc_ConnectFastHandler and +* XIntc_SetNormalIntrMode APIs. +* Added XIntc_InitializeSlaves API. +* 3.0 bss 01/28/13 Modified to initialize IVAR register with +* XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix +* CR#765931 +* +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xintc.h" +#include "xintc_l.h" +#include "xintc_i.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Variable Definitions *****************************/ + +/* + * Array of masks associated with the bit position, improves performance + * in the ISR and acknowledge functions, this table is shared between all + * instances of the driver. XIN_CONTROLLER_MAX_INTRS is the maximum number of + * sources of Interrupt controller + */ +u32 XIntc_BitPosMask[XIN_CONTROLLER_MAX_INTRS]; + +/************************** Function Prototypes ******************************/ + +static void StubHandler(void *CallBackRef); +static void XIntc_InitializeSlaves(XIntc * InstancePtr); + +/*****************************************************************************/ +/** +* +* Initialize a specific interrupt controller instance/driver. The +* initialization entails: +* +* - Initialize fields of the XIntc structure +* - Initial vector table with stub function calls +* - All interrupt sources are disabled +* - Interrupt output is disabled +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param DeviceId is the unique id of the device controlled by this XIntc +* instance. Passing in a device id associates the generic XIntc +* instance to a specific device, as chosen by the caller or +* application developer. +* +* @return +* - XST_SUCCESS if initialization was successful +* - XST_DEVICE_IS_STARTED if the device has already been started +* - XST_DEVICE_NOT_FOUND if device configuration information was +* not found for a device with the supplied device ID. +* +* @note In Cascade mode this function calls XIntc_InitializeSlaves to +* initialiaze Slave Interrupt controllers. +* +******************************************************************************/ +int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId) +{ + u8 Id; + XIntc_Config *CfgPtr; + u32 NextBitMask = 1; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* + * If the device is started, disallow the initialize and return a status + * indicating it is started. This allows the user to stop the device + * and reinitialize, but prevents a user from inadvertently initializing + */ + if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Lookup the device configuration in the CROM table. Use this + * configuration info down below when initializing this component. + */ + CfgPtr = XIntc_LookupConfig(DeviceId); + if (CfgPtr == NULL) { + return XST_DEVICE_NOT_FOUND; + } + + /* + * Set some default values + */ + InstancePtr->IsReady = 0; + InstancePtr->IsStarted = 0; /* not started */ + InstancePtr->CfgPtr = CfgPtr; + + InstancePtr->CfgPtr->Options = XIN_SVC_SGL_ISR_OPTION; + InstancePtr->CfgPtr->IntcType = CfgPtr->IntcType; + + /* + * Save the base address pointer such that the registers of the + * interrupt can be accessed + */ +#if (XPAR_XINTC_USE_DCR_BRIDGE != 0) + InstancePtr->BaseAddress = ((CfgPtr->BaseAddress >> 2)) & 0xFFF; +#else + InstancePtr->BaseAddress = CfgPtr->BaseAddress; +#endif + + /* + * Initialize all the data needed to perform interrupt processing for + * each interrupt ID up to the maximum used + */ + for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) { + + /* + * Initalize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler. Only + * initialize it if the handler is 0 or XNullHandler, which + * means it was not initialized statically by the tools/user. + * Set the callback reference to this instance so that + * unhandled interrupts can be tracked. + */ + if ((InstancePtr->CfgPtr->HandlerTable[Id].Handler == 0) || + (InstancePtr->CfgPtr->HandlerTable[Id].Handler == + XNullHandler)) { + InstancePtr->CfgPtr->HandlerTable[Id].Handler = + StubHandler; + } + InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr; + + /* + * Initialize the bit position mask table such that bit + * positions are lookups only for each interrupt id, with 0 + * being a special case + * (XIntc_BitPosMask[] = { 1, 2, 4, 8, ... }) + */ + XIntc_BitPosMask[Id] = NextBitMask; + NextBitMask *= 2; + } + + /* + * Disable IRQ output signal + * Disable all interrupt sources + * Acknowledge all sources + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, 0); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, 0xFFFFFFFF); + + /* + * If the fast Interrupt mode is enabled then set all the + * interrupts as normal mode. + */ + if(InstancePtr->CfgPtr->FastIntr == TRUE) { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, 0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } +#else + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } +#endif + } + + /* Initialize slaves in Cascade mode*/ + if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + XIntc_InitializeSlaves(InstancePtr); + } + + /* + * Indicate the instance is now ready to use, successfully initialized + */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Starts the interrupt controller by enabling the output from the controller +* to the processor. Interrupts may be generated by the interrupt controller +* after this function is called. +* +* It is necessary for the caller to connect the interrupt handler of this +* component to the proper interrupt source. This function also starts Slave +* controllers in Cascade mode. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Mode determines if software is allowed to simulate interrupts or +* real interrupts are allowed to occur. Note that these modes are +* mutually exclusive. The interrupt controller hardware resets in +* a mode that allows software to simulate interrupts until this +* mode is exited. It cannot be reentered once it has been exited. +* +* One of the following values should be used for the mode. +* - XIN_SIMULATION_MODE enables simulation of interrupts only +* - XIN_REAL_MODE enables hardware interrupts only +* +* @return +* - XST_SUCCESS if the device was started successfully +* - XST_FAILURE if simulation mode was specified and it could not +* be set because real mode has already been entered. +* +* @note Must be called after XIntc initialization is completed. +* +******************************************************************************/ +int XIntc_Start(XIntc * InstancePtr, u8 Mode) +{ + u32 MasterEnable = XIN_INT_MASTER_ENABLE_MASK; + XIntc_Config *CfgPtr; + int Index; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid((Mode == XIN_SIMULATION_MODE) || + (Mode == XIN_REAL_MODE)) + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check for simulation mode + */ + if (Mode == XIN_SIMULATION_MODE) { + if (MasterEnable & XIN_INT_HARDWARE_ENABLE_MASK) { + return XST_FAILURE; + } + } + else { + MasterEnable |= XIN_INT_HARDWARE_ENABLE_MASK; + } + + /* + * Indicate the instance is ready to be used and is started before we + * enable the device. + */ + InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; + + /* Start the Slaves for Cascade Mode */ + if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) + { + CfgPtr = XIntc_LookupConfig(Index); + XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, + MasterEnable); + } + } + + /* Start the master */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, MasterEnable); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Stops the interrupt controller by disabling the output from the controller +* so that no interrupts will be caused by the interrupt controller. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIntc_Stop(XIntc * InstancePtr) +{ + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Stop all interrupts from occurring thru the interrupt controller by + * disabling all interrupts in the MER register + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0); + + InstancePtr->IsStarted = 0; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized. The +* argument provided in this call as the Callbackref is used as the argument +* for the handler when it is called. In Cascade mode, connects handler to +* Slave controller handler table depending on the interrupt Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* @param Handler to the handler for that interrupt. +* @param CallBackRef is the callback reference, usually the instance +* pointer of the connecting driver. +* +* @return +* +* - XST_SUCCESS if the handler was connected correctly. +* +* @note +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +int XIntc_Connect(XIntc * InstancePtr, u8 Id, + XInterruptHandler Handler, void *CallBackRef) +{ + XIntc_Config *CfgPtr; + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Connect Handlers for Slave controllers in Cascade Mode */ + if (Id > 31) { + + CfgPtr = XIntc_LookupConfig(Id/32); + + CfgPtr->HandlerTable[Id%32].Handler = Handler; + CfgPtr->HandlerTable[Id%32].CallBackRef = CallBackRef; + } + /* Connect Handlers for Master/primary controller */ + else { + /* + * The Id is used as an index into the table to select the + * proper handler + */ + InstancePtr->CfgPtr->HandlerTable[Id].Handler = Handler; + InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = + CallBackRef; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Updates the interrupt table with the Null Handler and NULL arguments at the +* location pointed at by the Id. This effectively disconnects that interrupt +* source from any handler. The interrupt is disabled also. In Cascade mode, +* disconnects handler from Slave controller handler table depending on the +* interrupt Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Disconnect(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Disable the interrupt such that it won't occur while disconnecting + * the handler, only disable the specified interrupt id without + * modifying the other interrupt ids + */ + + /* Disconnect Handlers for Slave controllers in Cascade Mode */ + if (Id > 31) { + + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + /* + * Disconnect the handler and connect a stub, the callback + * reference must be set to this instance to allow unhandled + * interrupts to be tracked + */ + CfgPtr->HandlerTable[Id%32].Handler = StubHandler; + CfgPtr->HandlerTable[Id%32].CallBackRef = InstancePtr; + } + /* Disconnect Handlers for Master/primary controller */ + else { + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[Id]; + + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + InstancePtr->CfgPtr->HandlerTable[Id%32].Handler = + StubHandler; + InstancePtr->CfgPtr->HandlerTable[Id%32].CallBackRef = + InstancePtr; + } + +} + +/*****************************************************************************/ +/** +* +* Enables the interrupt source provided as the argument Id. Any pending +* interrupt condition for the specified Id will occur after this function is +* called. In Cascade mode, enables corresponding interrupt of Slave controllers +* depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Enable(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } + else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Enable the selected interrupt source by reading the + * interrupt enable register and then modifying only the + * specified interrupt id enable + */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER | Mask)); + } +} + +/*****************************************************************************/ +/** +* +* Disables the interrupt source provided as the argument Id such that the +* interrupt controller will not cause interrupts for the specified Id. The +* interrupt controller will continue to hold an interrupt condition for the +* Id, but will not cause an interrupt.In Cascade mode, disables corresponding +* interrupt of Slave controllers depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the +* highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Disable(XIntc * InstancePtr, u8 Id) +{ + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. Id currently limited to 0 - 31 + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Disable the selected interrupt source by reading the + * interrupt enable register and then modifying only the + * specified interrupt id + */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, + (CurrentIER & ~Mask)); + } +} + +/*****************************************************************************/ +/** +* +* Acknowledges the interrupt source provided as the argument Id. When the +* interrupt is acknowledged, it causes the interrupt controller to clear its +* interrupt condition.In Cascade mode, acknowledges corresponding interrupt +* source of Slave controllers depending on the Id. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id) +{ + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, Mask); + } else { + /* + * The Id is used to create the appropriate mask for the + * desired bit position. + */ + Mask = XIntc_BitPosMask[Id]; + + /* + * Acknowledge the selected interrupt source, no read of the + * acknowledge register is necessary since only the bits set + * in the mask will be affected by the write + */ + XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, Mask); + } +} + +/*****************************************************************************/ +/** +* +* A stub for the asynchronous callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubHandler(void *CallBackRef) +{ + /* + * Verify that the inputs are valid + */ + Xil_AssertVoid(CallBackRef != NULL); + + /* + * Indicate another unhandled interrupt for stats + */ + ((XIntc *) CallBackRef)->UnhandledInterrupts++; +} + +/*****************************************************************************/ +/** +* +* Looks up the device configuration based on the unique device ID. A table +* contains the configuration info for each device in the system. +* +* @param DeviceId is the unique identifier for a device. +* +* @return A pointer to the XIntc configuration structure for the specified +* device, or NULL if the device was not found. +* +* @note None. +* +******************************************************************************/ +XIntc_Config *XIntc_LookupConfig(u16 DeviceId) +{ + XIntc_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) { + if (XIntc_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XIntc_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} + +/*****************************************************************************/ +/** +* +* Makes the connection between the Id of the interrupt source and the +* associated handler that is to run when the interrupt is recognized.In Cascade +* mode, connects handler to corresponding Slave controller IVAR register +* depending on the Id and sets all interrupt sources of the Slave controller as +* fast interrupts. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being +* the highest priority interrupt. +* @param Handler to the handler for that interrupt. +* +* @return +* - XST_SUCCESS +* +* @note +* Slave controllers in Cascade Mode should have all as Fast +* interrupts or Normal interrupts, mixed interrupts are not +* supported +* +* WARNING: The handler provided as an argument will overwrite any handler +* that was previously connected. +* +****************************************************************************/ +int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id, + XFastInterruptHandler Handler) +{ + u32 Imr; + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertNonvoid(Handler != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr->CfgPtr->FastIntr == TRUE); + + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + if (CfgPtr->FastIntr != TRUE) { + /*Fast interrupts of slave controller are not enabled*/ + return XST_FAILURE; + } + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + ((Id%32) * 4), (u32) Handler); + + /* Slave controllers in Cascade Mode should have all as Fast + * interrupts or Normal interrupts, mixed interrupts are not + * supported + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF); + + /* Enable the Interrupt if it was enabled before calling this + * function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + } + else { + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + + XIN_IER_OFFSET); + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[Id]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), (u32) Handler); + + Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, + Imr | Mask); + + /* Enable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* +* Sets the normal interrupt mode for the specified interrupt in the Interrupt +* Mode Register. In Cascade mode disconnects handler from corresponding Slave +* controller IVAR register depending on the Id and sets all interrupt sources +* of the Slave controller as normal interrupts. +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* @param Id contains the ID of the interrupt source and should be in the +* range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the +* highest priority interrupt. +* +* @return None. +* +* @note +* Slave controllers in Cascade Mode should have all as Fast +* interrupts or Normal interrupts, mixed interrupts are not +* supported +* +****************************************************************************/ +void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id) +{ + u32 Imr; + u32 CurrentIER; + u32 Mask; + XIntc_Config *CfgPtr; + + /* + * Assert the arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr->CfgPtr->FastIntr == TRUE); + + if (Id > 31) { + /* Enable user required Id in Slave controller */ + CfgPtr = XIntc_LookupConfig(Id/32); + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); + + /* Convert from integer id to bit mask */ + Mask = XIntc_BitPosMask[(Id%32)]; + + /* Disable the Interrupt if it was enabled before calling + * this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + /* Slave controllers in Cascade Mode should have all as Fast + * interrupts or Normal interrupts, mixed interrupts are not + * supported + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0x0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } +#else + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } +#endif + + /* Enable the Interrupt if it was enabled before calling this + * function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + + } + else { + + /* Get the Enabled Interrupts */ + CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET); + Mask = XIntc_BitPosMask[Id];/* Convert from integer id to bit mask */ + + + /* Disable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Disable(InstancePtr, Id); + } + + /* + * Disable the selected interrupt as Fast Interrupt by reading the + * interrupt mode register and then modifying only the + * specified interrupt id + */ + Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET); + XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, + Imr & ~Mask); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + + 0x10); + } +#else + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + + (Id * 4), 0x10); + } +#endif + /* Enable the Interrupt if it was enabled before + * calling this function + */ + if (CurrentIER & Mask) { + XIntc_Enable(InstancePtr, Id); + } + } +} + +/*****************************************************************************/ +/** +* +* Initializes Slave controllers in Cascade mode. The initialization entails: +* - Initial vector table with stub function calls +* - All interrupt sources are disabled for last controller. +* - All interrupt sources are disabled except sources to 31 pin of +* primary and secondary controllers +* - Interrupt outputs are disabled +* +* @param InstancePtr is a pointer to the XIntc instance to be worked on. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void XIntc_InitializeSlaves(XIntc * InstancePtr) +{ + int Index; + u32 Mask; + XIntc_Config *CfgPtr; + int Id; + + Mask = XIntc_BitPosMask[31]; /* Convert from integer id to bit mask */ + + /* Enable interrupt id with 31 for Master + * interrupt controller + */ + XIntc_Out32(InstancePtr->CfgPtr->BaseAddress + XIN_IER_OFFSET, Mask); + + for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) { + CfgPtr = XIntc_LookupConfig(Index); + + XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, + 0xFFFFFFFF); + if (CfgPtr->IntcType != XIN_INTC_LAST) { + + /* Enable interrupt ids with 31 for secondary + * interrupt controllers + */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, + Mask); + } else { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, 0x0); + } + + /* Disable Interrupt output */ + XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, 0); + + /* Set all interrupts as normal mode if Fast Interrupts + * are enabled + */ + if(CfgPtr->FastIntr == TRUE) { + XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0); + +#ifdef XPAR_MICROBLAZE_BASE_VECTORS + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + + XIN_IVAR_OFFSET + (Id * 4), + XPAR_MICROBLAZE_BASE_VECTORS + 0x10); + } +#else + for (Id = 0; Id < 32 ; Id++) + { + XIntc_Out32(CfgPtr->BaseAddress + + XIN_IVAR_OFFSET + (Id * 4), 0x10); + } +#endif + } + + /* + * Initialize all the data needed to perform interrupt + * processing for each interrupt ID up to the maximum used + */ + for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) { + + /* + * Initalize the handler to point to a stub to handle an + * interrupt which has not been connected to a handler. + * Only initialize it if the handler is 0 or + * XNullHandler, which means it was not initialized + * statically by the tools/user.Set the callback + * reference to this instance so that unhandled + * interrupts can be tracked. + */ + if ((CfgPtr->HandlerTable[Id].Handler == 0) || + (CfgPtr->HandlerTable[Id].Handler == + XNullHandler)) { + CfgPtr->HandlerTable[Id].Handler = StubHandler; + } + CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr; + } + } +} |