]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_2/src/xintc_l.c
Update some more standard demos for use on 64-bit architectures.
[freertos] / FreeRTOS / Demo / MicroBlaze_Kintex7_EthernetLite / BSP / microblaze_0 / libsrc / intc_v3_2 / src / xintc_l.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2002 - 2014 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xintc_l.c
36 *
37 * This file contains low-level driver functions that can be used to access the
38 * device.  The user should refer to the hardware device specification for more
39 * details of the device operation.
40 *
41 * <pre>
42 * MODIFICATION HISTORY:
43 *
44 * Ver   Who  Date     Changes
45 * ----- ---- -------- -------------------------------------------------------
46 * 1.00b jhl  04/24/02 First release
47 * 1.00c rpm  10/17/03 New release. Support the static vector table created
48 *                     in the xintc_g.c configuration table.
49 * 1.00c rpm  04/09/04 Added conditional compilation around the old handler
50 *                     XIntc_LowLevelInterruptHandler(). This handler will only
51 *                     be include/compiled if XPAR_INTC_SINGLE_DEVICE_ID is
52 *                     defined.
53 * 1.10c mta  03/21/07 Updated to new coding style
54 * 1.10c ecm  07/09/07 Read the ISR after the Acknowledge in the interrupt
55 *                     handler to support architectures with posted write bus
56 *                     access issues.
57 * 2.00a ktn  10/20/09 Updated to use HAL Processor APIs and  _m is removed
58 *                     from all the macro definitions.
59 * 2.04a bss  01/13/12 Removed the unused Register variable for warnings.
60 * 2.05a bss  08/18/12 Added XIntc_RegisterFastHandler API to register fast
61 *                     interrupt handlers using base address.
62 * 2.06a bss  01/28/13 To support Cascade mode:
63 *                     Modified XIntc_DeviceInterruptHandler,
64 *                     XIntc_SetIntrSvcOption,XIntc_RegisterHandler and
65 *                     XIntc_RegisterFastHandler APIs.
66 *                     Added XIntc_CascadeHandler API.
67 * 2.07a bss  10/18/13 Modified XIntc_DeviceInterruptHandler to support
68 *                     nested interrupts.
69 *
70 * </pre>
71 *
72 ******************************************************************************/
73
74
75 /***************************** Include Files *********************************/
76
77 #include "xparameters.h"
78 #include "xil_types.h"
79 #include "xil_assert.h"
80 #include "xintc.h"
81 #include "xintc_i.h"
82
83 /************************** Constant Definitions *****************************/
84
85 /**************************** Type Definitions *******************************/
86
87
88 /***************** Macros (Inline Functions) Definitions *********************/
89
90
91 /************************** Function Prototypes ******************************/
92
93 static XIntc_Config *LookupConfigByBaseAddress(u32 BaseAddress);
94
95 #if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE
96 static void XIntc_CascadeHandler(void *DeviceId);
97 #endif
98
99 /************************** Variable Definitions *****************************/
100
101 /*****************************************************************************/
102 /**
103 *
104 * This is the interrupt handler for the driver interface provided in this file
105 * when there can be no argument passed to the handler. In this case, we just
106 * use the globally defined device ID for the interrupt controller. This function
107 * is provided mostly for backward compatibility. The user should use
108 * XIntc_DeviceInterruptHandler() if possible.
109 *
110 * This function does not support multiple interrupt controller instances to be
111 * handled.
112 *
113 * The user must connect this function to the interrupt system such that it is
114 * called whenever the devices which are connected to it cause an interrupt.
115 *
116 * @return       None.
117 *
118 * @note
119 *
120 * The constant XPAR_INTC_SINGLE_DEVICE_ID must be defined for this handler
121 * to be included in the driver compilation.
122 *
123 ******************************************************************************/
124 #ifdef XPAR_INTC_SINGLE_DEVICE_ID
125 void XIntc_LowLevelInterruptHandler(void)
126 {
127         /*
128          * A level of indirection here because the interrupt handler used with
129          * the driver interface given in this file needs to remain void - no
130          * arguments.  So we need the globally defined device ID of THE
131          * interrupt controller.
132          */
133         XIntc_DeviceInterruptHandler((void *) XPAR_INTC_SINGLE_DEVICE_ID);
134 }
135 #endif
136
137 /*****************************************************************************/
138 /**
139 *
140 * This function is the primary interrupt handler for the driver. It must be
141 * connected to the interrupt source such that is called when an interrupt of
142 * the interrupt controller is active. It will resolve which interrupts are
143 * active and enabled and call the appropriate interrupt handler. It uses
144 * the AckBeforeService flag in the configuration data to determine when to
145 * acknowledge the interrupt. Highest priority interrupts are serviced first.
146 * This function assumes that an interrupt vector table has been previously
147 * initialized.It does not verify that entries in the table are valid before
148 * calling an interrupt handler. In Cascade mode this function calls
149 * XIntc_CascadeHandler to handle interrupts of Master and Slave controllers.
150 * This functions also handles interrupts nesting by  saving and restoring link
151 * register of Microblaze and Interrupt Level register of interrupt controller
152 * properly.
153
154 * @param        DeviceId is the zero-based device ID defined in xparameters.h
155 *               of the interrupting interrupt controller. It is used as a direct
156 *               index into the configuration data, which contains the vector
157 *               table for the interrupt controller. Note that even though the
158 *               argument is a void pointer, the value is not a pointer but the
159 *               actual device ID.  The void pointer type is necessary to meet
160 *               the XInterruptHandler typedef for interrupt handlers.
161 *
162 * @return       None.
163 *
164 * @note         For nested interrupts, this function saves microblaze r14
165 *               register on entry and restores on exit. This is required since
166 *               compiler does not support nesting. This function enables
167 *               Microblaze interrupts after blocking further interrupts
168 *               from the current interrupt number and interrupts below current
169 *               interrupt proirity by writing to Interrupt Level Register of
170 *               INTC on entry. On exit, it disables microblaze interrupts and
171 *               restores ILR register default value(0xFFFFFFFF)back. It is
172 *               recommended to increase STACK_SIZE in linker script for nested
173 *               interrupts.
174 *
175 ******************************************************************************/
176 void XIntc_DeviceInterruptHandler(void *DeviceId)
177 {
178         u32 IntrStatus;
179         u32 IntrMask = 1;
180         int IntrNumber;
181         XIntc_Config *CfgPtr;
182         u32 Imr;
183
184         /* Get the configuration data using the device ID */
185         CfgPtr = &XIntc_ConfigTable[(u32)DeviceId];
186
187 #if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE
188         if (CfgPtr->IntcType != XIN_INTC_NOCASCADE) {
189                 XIntc_CascadeHandler(DeviceId);
190         }
191         else
192 #endif
193         { /* This extra brace is required for compilation in Cascade Mode */
194
195 #if XPAR_XINTC_HAS_ILR == TRUE
196 #ifdef __MICROBLAZE__
197                 volatile u32 R14_register;
198                 /* Save r14 register */
199                 R14_register = mfgpr(r14);
200 #endif
201                 volatile u32 ILR_reg;
202                 /* Save ILR register */
203                 ILR_reg = Xil_In32(CfgPtr->BaseAddress + XIN_ILR_OFFSET);
204 #endif
205                 /* Get the interrupts that are waiting to be serviced */
206                 IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress);
207
208                 /* Mask the Fast Interrupts */
209                 if (CfgPtr->FastIntr == TRUE) {
210                         Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET);
211                         IntrStatus &=  ~Imr;
212                 }
213
214                 /* Service each interrupt that is active and enabled by
215                  * checking each bit in the register from LSB to MSB which
216                  * corresponds to an interrupt input signal
217                  */
218                 for (IntrNumber = 0; IntrNumber < CfgPtr->NumberofIntrs;
219                                                                 IntrNumber++) {
220                         if (IntrStatus & 1) {
221                                 XIntc_VectorTableEntry *TablePtr;
222 #if XPAR_XINTC_HAS_ILR == TRUE
223                                 /* Write to ILR the current interrupt
224                                 * number
225                                 */
226                                 Xil_Out32(CfgPtr->BaseAddress +
227                                                 XIN_ILR_OFFSET, IntrNumber);
228
229                                 /* Read back ILR to ensure the value
230                                 * has been updated and it is safe to
231                                 * enable interrupts
232                                 */
233
234                                 Xil_In32(CfgPtr->BaseAddress +
235                                                 XIN_ILR_OFFSET);
236
237                                 /* Enable interrupts */
238                                 Xil_ExceptionEnable();
239 #endif
240                                 /* If the interrupt has been setup to
241                                  * acknowledge it before servicing the
242                                  * interrupt, then ack it */
243                                 if (CfgPtr->AckBeforeService & IntrMask) {
244                                         XIntc_AckIntr(CfgPtr->BaseAddress,
245                                                                 IntrMask);
246                                 }
247
248                                 /* The interrupt is active and enabled, call
249                                  * the interrupt handler that was setup with
250                                  * the specified parameter
251                                  */
252                                 TablePtr = &(CfgPtr->HandlerTable[IntrNumber]);
253                                 TablePtr->Handler(TablePtr->CallBackRef);
254
255                                 /* If the interrupt has been setup to
256                                  * acknowledge it after it has been serviced
257                                  * then ack it
258                                  */
259                                 if ((CfgPtr->AckBeforeService &
260                                                         IntrMask) == 0) {
261                                         XIntc_AckIntr(CfgPtr->BaseAddress,
262                                                                 IntrMask);
263                                 }
264
265 #if XPAR_XINTC_HAS_ILR == TRUE
266                                 /* Disable interrupts */
267                                 Xil_ExceptionDisable();
268                                 /* Restore ILR */
269                                 Xil_Out32(CfgPtr->BaseAddress + XIN_ILR_OFFSET,
270                                                                 ILR_reg);
271 #endif
272                                 /*
273                                  * Read the ISR again to handle architectures
274                                  * with posted write bus access issues.
275                                  */
276                                  XIntc_GetIntrStatus(CfgPtr->BaseAddress);
277
278                                 /*
279                                  * If only the highest priority interrupt is to
280                                  * be serviced, exit loop and return after
281                                  * servicing
282                                  * the interrupt
283                                  */
284                                 if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) {
285
286 #if XPAR_XINTC_HAS_ILR == TRUE
287 #ifdef __MICROBLAZE__
288                                         /* Restore r14 */
289                                         mtgpr(r14, R14_register);
290 #endif
291 #endif
292                                         return;
293                                 }
294                         }
295
296                         /* Move  to the next interrupt to check */
297                         IntrMask <<= 1;
298                         IntrStatus >>= 1;
299
300                         /* If there are no other bits set indicating that all
301                          * interrupts have been serviced, then exit the loop
302                          */
303                         if (IntrStatus == 0) {
304                                 break;
305                         }
306                 }
307 #if XPAR_XINTC_HAS_ILR == TRUE
308 #ifdef __MICROBLAZE__
309                 /* Restore r14 */
310                 mtgpr(r14, R14_register);
311 #endif
312 #endif
313         }
314 }
315
316 /*****************************************************************************/
317 /**
318 *
319 * Set the interrupt service option, which can configure the driver so that it
320 * services only a single interrupt at a time when an interrupt occurs, or
321 * services all pending interrupts when an interrupt occurs. The default
322 * behavior when using the driver interface given in xintc.h file is to service
323 * only a single interrupt, whereas the default behavior when using the driver
324 * interface given in this file is to service all outstanding interrupts when an
325 * interrupt occurs. In Cascade mode same Option is set to Slave controllers.
326 *
327 * @param        BaseAddress is the unique identifier for a device.
328 * @param        Option is XIN_SVC_SGL_ISR_OPTION if you want only a single
329 *               interrupt serviced when an interrupt occurs, or
330 *               XIN_SVC_ALL_ISRS_OPTION if you want all pending interrupts
331 *               serviced when an interrupt occurs.
332 *
333 * @return       None.
334 *
335 * @note
336 *
337 * Note that this function has no effect if the input base address is invalid.
338 *
339 ******************************************************************************/
340 void XIntc_SetIntrSvcOption(u32 BaseAddress, int Option)
341 {
342         XIntc_Config *CfgPtr;
343
344         CfgPtr = LookupConfigByBaseAddress(BaseAddress);
345         if (CfgPtr != NULL) {
346                 CfgPtr->Options = Option;
347                 /* If Cascade mode set the option for all Slaves */
348                 if (CfgPtr->IntcType != XIN_INTC_NOCASCADE) {
349                         int Index;
350                         for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1;
351                                         Index++) {
352                                 CfgPtr = XIntc_LookupConfig(Index);
353                                 CfgPtr->Options = Option;
354                         }
355                 }
356         }
357 }
358
359 /*****************************************************************************/
360 /**
361 *
362 * Register a handler function for a specific interrupt ID.  The vector table
363 * of the interrupt controller is updated, overwriting any previous handler.
364 * The handler function will be called when an interrupt occurs for the given
365 * interrupt ID.
366 *
367 * This function can also be used to remove a handler from the vector table
368 * by passing in the XIntc_DefaultHandler() as the handler and NULL as the
369 * callback reference.
370 * In Cascade mode Interrupt Id is used to set Handler for corresponding Slave
371 * Controller
372 *
373 * @param        BaseAddress is the base address of the interrupt controller
374 *               whose vector table will be modified.
375 * @param        InterruptId is the interrupt ID to be associated with the input
376 *               handler.
377 * @param        Handler is the function pointer that will be added to
378 *               the vector table for the given interrupt ID.
379 * @param        CallBackRef is the argument that will be passed to the new
380 *               handler function when it is called. This is user-specific.
381 *
382 * @return       None.
383 *
384 * @note
385 *
386 * Note that this function has no effect if the input base address is invalid.
387 *
388 ******************************************************************************/
389 void XIntc_RegisterHandler(u32 BaseAddress, int InterruptId,
390                            XInterruptHandler Handler, void *CallBackRef)
391 {
392         XIntc_Config *CfgPtr;
393
394         CfgPtr = LookupConfigByBaseAddress(BaseAddress);
395
396         if (CfgPtr != NULL) {
397
398                 if (InterruptId > 31) {
399                         CfgPtr = XIntc_LookupConfig(InterruptId/32);
400                         CfgPtr->HandlerTable[InterruptId%32].Handler = Handler;
401                         CfgPtr->HandlerTable[InterruptId%32].CallBackRef =
402                                                                 CallBackRef;
403                 }
404                 else {
405                         CfgPtr->HandlerTable[InterruptId].Handler = Handler;
406                         CfgPtr->HandlerTable[InterruptId].CallBackRef =
407                                                                 CallBackRef;
408                 }
409         }
410 }
411
412
413 /*****************************************************************************/
414 /**
415 *
416 * Looks up the device configuration based on the base address of the device.
417 * A table contains the configuration info for each device in the system.
418 *
419 * @param        BaseAddress is the unique identifier for a device.
420 *
421 * @return
422 *
423 * A pointer to the configuration structure for the specified device, or
424 * NULL if the device was not found.
425 *
426 * @note         None.
427 *
428 ******************************************************************************/
429 static XIntc_Config *LookupConfigByBaseAddress(u32 BaseAddress)
430 {
431         XIntc_Config *CfgPtr = NULL;
432         int Index;
433
434         for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) {
435                 if (XIntc_ConfigTable[Index].BaseAddress == BaseAddress) {
436                         CfgPtr = &XIntc_ConfigTable[Index];
437                         break;
438                 }
439         }
440
441         return CfgPtr;
442 }
443
444 /*****************************************************************************/
445 /**
446 *
447 * Register a fast handler function for a specific interrupt ID. The handler
448 * function will be called when an interrupt occurs for the given interrupt ID.
449 * In Cascade mode Interrupt Id is used to set Handler for corresponding Slave
450 * Controller
451 *
452 * @param        BaseAddress is the base address of the interrupt controller
453 *               whose vector table will be modified.
454 * @param        InterruptId is the interrupt ID to be associated with the input
455 *               handler.
456 * @param        FastHandler is the function pointer that will be called when
457 *               interrupt occurs
458 *
459 * @return       None.
460 *
461 * @note
462 *
463 * Note that this function has no effect if the input base address is invalid.
464 *
465 ******************************************************************************/
466 void XIntc_RegisterFastHandler(u32 BaseAddress, u8 Id,
467                                         XFastInterruptHandler FastHandler)
468 {
469         u32 CurrentIER;
470         u32 Mask;
471         u32 Imr;
472         XIntc_Config *CfgPtr;
473
474
475         if (Id > 31) {
476                 /* Enable user required Id in Slave controller */
477                 CfgPtr = XIntc_LookupConfig(Id/32);
478
479                 /* Get the Enabled Interrupts */
480                 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
481
482                 /* Convert from integer id to bit mask */
483                 Mask = XIntc_BitPosMask[(Id%32)];
484
485                 /* Disable the Interrupt if it was enabled before calling
486                  * this function
487                  */
488                 if (CurrentIER & Mask) {
489                         XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
490                                                         (CurrentIER & ~Mask));
491                 }
492
493                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET +
494                                         ((Id%32) * 4), (u32) FastHandler);
495
496                 /* Slave controllers in Cascade Mode should have all as Fast
497                  * interrupts or Normal interrupts, mixed interrupts are not
498                  * supported
499                  */
500                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF);
501
502                 /* Enable the Interrupt if it was enabled before calling this
503                  * function
504                  */
505                 if (CurrentIER & Mask) {
506                         XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
507                                                 (CurrentIER | Mask));
508                 }
509         }
510         else {
511
512                 CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET);
513
514                 /* Convert from integer id to bit mask */
515                 Mask = XIntc_BitPosMask[Id];
516
517                 if (CurrentIER & Mask) {
518                         /* Disable Interrupt if it was enabled */
519                         CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET);
520                         XIntc_Out32(BaseAddress + XIN_IER_OFFSET,
521                                                         (CurrentIER & ~Mask));
522                 }
523
524                 XIntc_Out32(BaseAddress + XIN_IVAR_OFFSET + (Id * 4),
525                                                 (u32) FastHandler);
526
527                 Imr = XIntc_In32(BaseAddress + XIN_IMR_OFFSET);
528                 XIntc_Out32(BaseAddress + XIN_IMR_OFFSET, Imr | Mask);
529
530
531                 /* Enable Interrupt if it was enabled before calling
532                  * this function
533                  */
534                 if (CurrentIER & Mask) {
535                         CurrentIER = XIntc_In32(BaseAddress + XIN_IER_OFFSET);
536                         XIntc_Out32(BaseAddress + XIN_IER_OFFSET,
537                                                         (CurrentIER | Mask));
538                 }
539         }
540 }
541
542 #if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE
543 /*****************************************************************************/
544 /**
545 *
546 * This function is called by primary interrupt handler for the driver to handle
547 * all Controllers in Cascade mode.It will resolve which interrupts are active
548 * and enabled and call the appropriate interrupt handler. It uses the
549 * AckBeforeService flag in the configuration data to determine when to
550 * acknowledge the interrupt. Highest priority interrupts are serviced first.
551 * This function assumes that an interrupt vector table has been previously
552 * initialized.  It does not verify that entries in the table are valid before
553 * calling an interrupt handler.This function calls itself recursively to handle
554 * all interrupt controllers.
555 *
556 * @param        DeviceId is the zero-based device ID defined in xparameters.h
557 *               of the interrupting interrupt controller. It is used as a direct
558 *               index into the configuration data, which contains the vector
559 *               table for the interrupt controller.
560 *
561 * @return       None.
562 *
563 * @note
564 *
565 ******************************************************************************/
566 static void XIntc_CascadeHandler(void *DeviceId)
567 {
568         u32 IntrStatus;
569         u32 IntrMask = 1;
570         int IntrNumber;
571         u32 Imr;
572         XIntc_Config *CfgPtr;
573         static int Id = 0;
574
575         /* Get the configuration data using the device ID */
576         CfgPtr = &XIntc_ConfigTable[(u32)DeviceId];
577
578         /* Get the interrupts that are waiting to be serviced */
579         IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress);
580
581         /* Mask the Fast Interrupts */
582         if (CfgPtr->FastIntr == TRUE) {
583                 Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET);
584                 IntrStatus &=  ~Imr;
585         }
586
587         /* Service each interrupt that is active and enabled by
588          * checking each bit in the register from LSB to MSB which
589          * corresponds to an interrupt input signal
590          */
591         for (IntrNumber = 0; IntrNumber < CfgPtr->NumberofIntrs; IntrNumber++) {
592                 if (IntrStatus & 1) {
593                         XIntc_VectorTableEntry *TablePtr;
594
595                         /* In Cascade mode call this function recursively
596                          * for interrupt id 31 and until interrupts of last
597                          * instance/controller are handled
598                          */
599                         if ((IntrNumber == 31) &&
600                           (CfgPtr->IntcType != XIN_INTC_LAST) &&
601                           (CfgPtr->IntcType != XIN_INTC_NOCASCADE)) {
602                                 XIntc_CascadeHandler((void *)++Id);
603                                 Id--;
604                         }
605
606                         /* If the interrupt has been setup to
607                          * acknowledge it before servicing the
608                          * interrupt, then ack it */
609                         if (CfgPtr->AckBeforeService & IntrMask) {
610                                 XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask);
611                         }
612
613                         /* Handler of 31 interrupt Id has to be called only
614                          * for Last controller in cascade Mode
615                          */
616                         if (!((IntrNumber == 31) &&
617                           (CfgPtr->IntcType != XIN_INTC_LAST) &&
618                           (CfgPtr->IntcType != XIN_INTC_NOCASCADE))) {
619
620                                 /* The interrupt is active and enabled, call
621                                  * the interrupt handler that was setup with
622                                  * the specified parameter
623                                  */
624                                 TablePtr = &(CfgPtr->HandlerTable[IntrNumber]);
625                                 TablePtr->Handler(TablePtr->CallBackRef);
626                         }
627                         /* If the interrupt has been setup to acknowledge it
628                          * after it has been serviced then ack it
629                          */
630                         if ((CfgPtr->AckBeforeService & IntrMask) == 0) {
631                                 XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask);
632                         }
633
634                         /*
635                          * Read the ISR again to handle architectures with
636                          * posted write bus access issues.
637                          */
638                          XIntc_GetIntrStatus(CfgPtr->BaseAddress);
639
640                         /*
641                          * If only the highest priority interrupt is to be
642                          * serviced, exit loop and return after servicing
643                          * the interrupt
644                          */
645                         if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) {
646                                 return;
647                         }
648                 }
649
650                 /* Move  to the next interrupt to check */
651                 IntrMask <<= 1;
652                 IntrStatus >>= 1;
653
654                 /* If there are no other bits set indicating that all interrupts
655                  * have been serviced, then exit the loop
656                  */
657                 if (IntrStatus == 0) {
658                         break;
659                 }
660         }
661 }
662 #endif