Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:42

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSImplClassicIntr
0007  *
0008  * @brief This header file provides interfaces of the Interrupt Manager
0009  *   implementation.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2016 Chris Johns <chrisj@rtems.org>
0014  *
0015  * Copyright (C) 2008, 2024 embedded brains GmbH & Co. KG
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 /*
0040  * The API is based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
0041  */
0042 
0043 #ifndef LIBBSP_SHARED_IRQ_GENERIC_H
0044 #define LIBBSP_SHARED_IRQ_GENERIC_H
0045 
0046 #include <stdbool.h>
0047 
0048 #include <rtems/irq-extension.h>
0049 #include <rtems/score/assert.h>
0050 #include <rtems/score/processormask.h>
0051 
0052 #ifdef RTEMS_SMP
0053   #include <rtems/score/atomic.h>
0054 #endif
0055 
0056 #include <bsp/irq.h>
0057 
0058 #ifdef __cplusplus
0059 extern "C" {
0060 #endif /* __cplusplus */
0061 
0062 #if !defined(BSP_INTERRUPT_VECTOR_COUNT)
0063   #error "BSP_INTERRUPT_VECTOR_COUNT shall be defined"
0064 #endif
0065 
0066 #if defined(BSP_INTERRUPT_USE_INDEX_TABLE) && !defined(BSP_INTERRUPT_DISPATCH_TABLE_SIZE)
0067   #error "if you define BSP_INTERRUPT_USE_INDEX_TABLE, you have to define BSP_INTERRUPT_DISPATCH_TABLE_SIZE etc. as well"
0068 #endif
0069 
0070 #ifndef BSP_INTERRUPT_DISPATCH_TABLE_SIZE
0071   #define BSP_INTERRUPT_DISPATCH_TABLE_SIZE BSP_INTERRUPT_VECTOR_COUNT
0072 #endif
0073 
0074 #if !defined(BSP_IRQ_HAVE_GET_SET_AFFINITY) && defined(RTEMS_SMP)
0075   #define BSP_IRQ_HAVE_GET_SET_AFFINITY
0076 #endif
0077 
0078 #define bsp_interrupt_assert(e) _Assert(e)
0079 
0080 /**
0081  * @brief Each member of this table references the first installed entry at the
0082  *   corresponding interrupt vector or is NULL.
0083  */
0084 extern rtems_interrupt_entry *bsp_interrupt_dispatch_table[];
0085 
0086 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
0087   #if BSP_INTERRUPT_DISPATCH_TABLE_SIZE < 0x100
0088     typedef uint8_t bsp_interrupt_dispatch_index_type;
0089   #elif BSP_INTERRUPT_DISPATCH_TABLE_SIZE < 0x10000
0090     typedef uint16_t bsp_interrupt_dispatch_index_type;
0091   #else
0092     typedef uint32_t bsp_interrupt_dispatch_index_type;
0093   #endif
0094   extern bsp_interrupt_dispatch_index_type bsp_interrupt_dispatch_index_table [];
0095 #endif
0096 
0097 static inline rtems_vector_number bsp_interrupt_dispatch_index(
0098   rtems_vector_number vector
0099 )
0100 {
0101   #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
0102     return bsp_interrupt_dispatch_index_table [vector];
0103   #else
0104     return vector;
0105   #endif
0106 }
0107 
0108 /**
0109  * @defgroup RTEMSImplClassicIntr Interrupt Manager
0110  *
0111  * @ingroup RTEMSImplClassic
0112  *
0113  * @brief This group contains the Interrupt Manager implementation.
0114  *
0115  * The Interrupt Manager implementation manages a sequence of interrupt vector
0116  * numbers greater than or equal to zero and less than
0117  * ``BSP_INTERRUPT_VECTOR_COUNT``.  It provides methods to install, remove, and
0118  * dispatch interrupt entries for each vector number, see
0119  * bsp_interrupt_dispatch_entries().
0120  *
0121  * The entry points to a list of interrupt entries are stored in a table
0122  * (= dispatch table).
0123  *
0124  * You have to configure the Interrupt Manager implementation in the <bsp/irq.h> file
0125  * for each BSP.  For a minimum configuration you have to provide
0126  * ``BSP_INTERRUPT_VECTOR_COUNT``.
0127  *
0128  * For boards with small memory requirements you can define
0129  * ``BSP_INTERRUPT_USE_INDEX_TABLE``.  With an enabled index table the
0130  * dispatch table will be accessed via a small index table.  You can define the
0131  * size of the dispatch table with ``BSP_INTERRUPT_DISPATCH_TABLE_SIZE``.
0132  *
0133  * You have to provide some special routines in your BSP (follow the links for
0134  * the details):
0135  * - bsp_interrupt_facility_initialize()
0136  * - bsp_interrupt_vector_enable()
0137  * - bsp_interrupt_vector_disable()
0138  * - bsp_interrupt_handler_default()
0139  *
0140  * Optionally, the BSP may define the following macros to customize the vector
0141  * installation after installing the first entry and the vector removal before
0142  * removing the last entry:
0143  * - bsp_interrupt_vector_install()
0144  * - bsp_interrupt_vector_remove()
0145  *
0146  * The following now deprecated functions are provided for backward
0147  * compatibility:
0148  * - BSP_get_current_rtems_irq_handler()
0149  * - BSP_install_rtems_irq_handler()
0150  * - BSP_install_rtems_shared_irq_handler()
0151  * - BSP_remove_rtems_irq_handler()
0152  * - BSP_rtems_irq_mngt_set()
0153  * - BSP_rtems_irq_mngt_get()
0154  *
0155  * @{
0156  */
0157 
0158 #ifdef BSP_INTERRUPT_CUSTOM_VALID_VECTOR
0159   bool bsp_interrupt_is_valid_vector(rtems_vector_number vector);
0160 #else
0161   /**
0162    * @brief Returns true if the interrupt vector with number @a vector is
0163    * valid.
0164    */
0165   static inline bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
0166   {
0167     return vector < (rtems_vector_number) BSP_INTERRUPT_VECTOR_COUNT;
0168   }
0169 #endif
0170 
0171 /**
0172  * @brief Default interrupt handler.
0173  *
0174  * This routine will be called from bsp_interrupt_handler_dispatch() with the
0175  * current vector number @a vector when the handler list for this vector is
0176  * empty or the vector number is out of range.
0177  *
0178  * @note This function must cope with arbitrary vector numbers @a vector.
0179  */
0180 void bsp_interrupt_handler_default(rtems_vector_number vector);
0181 
0182 /**
0183  * @brief Initialize Interrupt Manager implementation.
0184  *
0185  * You must call this function before you can install, remove and dispatch
0186  * interrupt entries.  There is no protection against concurrent
0187  * initialization.  This function must be called at most once.  The BSP
0188  * specific bsp_interrupt_facility_initialize() function will be called after
0189  * all internals are initialized.  If the BSP specific initialization fails,
0190  * then this is a fatal error.  The fatal error source is
0191  * RTEMS_FATAL_SOURCE_BSP and the fatal error code is
0192  * BSP_FATAL_INTERRUPT_INITIALIZATION.
0193  */
0194 void bsp_interrupt_initialize(void);
0195 
0196 /**
0197  * @brief BSP specific initialization.
0198  *
0199  * This routine will be called form bsp_interrupt_initialize() and shall do the
0200  * following:
0201  * - Initialize the facilities that call bsp_interrupt_handler_dispatch().  For
0202  * example on PowerPC the external exception handler.
0203  * - Initialize the interrupt controller.  You shall set the interrupt
0204  * controller in a state such that interrupts are disabled for all vectors.
0205  * The vectors will be enabled with your bsp_interrupt_vector_enable() function
0206  * and disabled via your bsp_interrupt_vector_disable() function.  These
0207  * functions have to work afterwards.
0208  */
0209 void bsp_interrupt_facility_initialize(void);
0210 
0211 /**
0212  * @brief Gets the attributes of the interrupt vector.
0213  *
0214  * @param vector is the interrupt vector number.  It shall be valid.
0215  *
0216  * @param[out] attributes is the pointer to an rtems_interrupt_attributes
0217  *   object.  When the function call is successful, the attributes of the
0218  *   interrupt vector will be stored in this object.  The pointer shall not be
0219  *   NULL.  The object shall be cleared to zero by the caller.
0220  *
0221  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0222  */
0223 rtems_status_code bsp_interrupt_get_attributes(
0224   rtems_vector_number         vector,
0225   rtems_interrupt_attributes *attributes
0226 );
0227 
0228 /**
0229  * @brief Checks if the interrupt is enabled.
0230  *
0231  * The function checks if the interrupt associated with the interrupt vector
0232  * specified by ``vector`` was enabled for the processor executing the function
0233  * call at some time point during the call.
0234  *
0235  * @param vector is the interrupt vector number.  It shall be valid.
0236  *
0237  * @param[out] enabled is the pointer to a ``bool`` object.  It shall not be
0238  *   ``NULL``.  When the function call is successful, the enabled status of
0239  *   the interrupt associated with the interrupt vector specified by ``vector``
0240  *   will be stored in this object.  When the interrupt was enabled for the
0241  *   processor executing the function call at some time point during the call,
0242  *   the object will be set to true, otherwise to false.
0243  *
0244  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0245  */
0246 rtems_status_code bsp_interrupt_vector_is_enabled(
0247   rtems_vector_number vector,
0248   bool               *enabled
0249 );
0250 
0251 /**
0252  * @brief Enables the interrupt vector.
0253  *
0254  * This function shall enable the vector at the corresponding facility (in most
0255  * cases the interrupt controller).  It will be called then the first entry
0256  * is installed for the vector in rtems_interrupt_entry_install() for example.
0257  *
0258  * @note The implementation should use
0259  * bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ) to validate
0260  * the vector number in ::RTEMS_DEBUG configurations.
0261  *
0262  * @param vector is the interrupt vector number.
0263  *
0264  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0265  *
0266  * @retval ::RTEMS_UNSATISFIED The request to enable the interrupt vector has
0267  *   not been satisfied.  The presence of this error condition is
0268  *   implementation-defined.  The interrupt vector attributes obtained by
0269  *   rtems_interrupt_get_attributes() should indicate if it is possible to
0270  *   enable a particular interrupt vector.
0271  */
0272 rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector );
0273 
0274 /**
0275  * @brief Disables the interrupt vector.
0276  *
0277  * This function shall disable the vector at the corresponding facility (in
0278  * most cases the interrupt controller).  It will be called then the last
0279  * entry is removed for the vector in rtems_interrupt_entry_remove() for
0280  * example.
0281  *
0282  * @note The implementation should use
0283  * bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ) to validate
0284  * the vector number in ::RTEMS_DEBUG configurations.
0285  *
0286  * @param vector is the interrupt vector number.
0287  *
0288  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0289  *
0290  * @retval ::RTEMS_UNSATISFIED The request to disable the interrupt vector has
0291  *   not been satisfied.  The presence of this error condition is
0292  *   implementation-defined.  The interrupt vector attributes obtained by
0293  *   rtems_interrupt_get_attributes() should indicate if it is possible to
0294  *   disable a particular interrupt vector.
0295  */
0296 rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number vector );
0297 
0298 /**
0299  * @brief Checks if the interrupt is pending.
0300  *
0301  * The function checks if the interrupt associated with the interrupt vector
0302  * specified by ``vector`` was pending for the processor executing the function
0303  * call at some time point during the call.
0304  *
0305  * @param vector is the interrupt vector number.  It shall be valid.
0306  *
0307  * @param[out] pending is the pointer to a ``bool`` object.  It shall not be
0308  *   ``NULL``.  When the function call is successful, the pending status of
0309  *   the interrupt associated with the interrupt vector specified by ``vector``
0310  *   will be stored in this object.  When the interrupt was pending for the
0311  *   processor executing the function call at some time point during the call,
0312  *   the object will be set to true, otherwise to false.
0313  *
0314  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0315  *
0316  * @retval ::RTEMS_UNSATISFIED The request to get the pending status has not
0317  *   been satisfied.
0318  */
0319 rtems_status_code bsp_interrupt_is_pending(
0320   rtems_vector_number vector,
0321   bool               *pending
0322 );
0323 
0324 /**
0325  * @brief Causes the interrupt vector.
0326  *
0327  * @param vector is the number of the interrupt vector to cause.  It shall be
0328  *   valid.
0329  *
0330  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0331  *
0332  * @retval ::RTEMS_UNSATISFIED The request to raise the interrupt vector has
0333  *   not been satisfied.  The presence of this error condition is
0334  *   implementation-defined.  The interrupt vector attributes obtained by
0335  *   rtems_interrupt_get_attributes() should indicate if it is possible to
0336  *   raise a particular interrupt vector.
0337  */
0338 rtems_status_code bsp_interrupt_raise( rtems_vector_number vector );
0339 
0340 #if defined(RTEMS_SMP)
0341 /**
0342  * @brief Causes the interrupt vector on the processor.
0343  *
0344  * @param vector is the number of the interrupt vector to cause.  It shall be
0345  *   valid.
0346  *
0347  * @param cpu_index is the index of the target processor of the interrupt
0348  *   vector to cause.  It shall be valid.
0349  *
0350  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0351  *
0352  * @retval ::RTEMS_UNSATISFIED The request to cause the interrupt vector has
0353  *   not been satisfied.  The presence of this error condition is
0354  *   implementation-defined.  The interrupt vector attributes obtained by
0355  *   rtems_interrupt_get_attributes() should indicate if it is possible to
0356  *   raise a particular interrupt vector on a specific processor.
0357  */
0358 rtems_status_code bsp_interrupt_raise_on(
0359   rtems_vector_number vector,
0360   uint32_t            cpu_index
0361 );
0362 #endif
0363 
0364 /**
0365  * @brief Clears the interrupt vector.
0366  *
0367  * @param vector is the number of the interrupt vector to clear.  It shall be
0368  *   valid.
0369  *
0370  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0371  *
0372  * @retval ::RTEMS_UNSATISFIED The request to cause the interrupt vector has
0373  *   not been satisfied.  The presence of this error condition is
0374  *   implementation-defined.  The interrupt vector attributes obtained by
0375  *   rtems_interrupt_get_attributes() should indicate if it is possible to
0376  *   clear a particular interrupt vector.
0377  */
0378 rtems_status_code bsp_interrupt_clear( rtems_vector_number vector );
0379 
0380 /**
0381  * @brief Gets the priority of the interrupt vector.
0382  *
0383  * The return status shall correspond to the
0384  * rtems_interrupt_attributes::can_get_priority value of the interrupt vector.
0385  *
0386  * @param vector is the interrupt vector number.  The vector number shall be
0387  *   less than BSP_INTERRUPT_VECTOR_COUNT.
0388  *
0389  * @param[out] priority is the pointer to an uint32_t object.  When the
0390  *   directive call is successful, the priority of the interrupt vector will be
0391  *   stored in this object.  The pointer shall be valid.
0392  *
0393  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0394  *
0395  * @retval ::RTEMS_UNSATISFIED There is no priority associated with the
0396  *   interrupt vector.  This status shall be returned if the function is not
0397  *   implemented by the BSP.
0398  */
0399 rtems_status_code bsp_interrupt_get_priority(
0400   rtems_vector_number vector,
0401   uint32_t           *priority
0402 );
0403 
0404 /**
0405  * @brief Sets the priority of the interrupt vector.
0406  *
0407  * The return status shall correspond to the
0408  * rtems_interrupt_attributes::can_set_priority value of the interrupt vector.
0409  *
0410  * @param vector is the interrupt vector number.  The vector number shall be
0411  *   less than BSP_INTERRUPT_VECTOR_COUNT.
0412  *
0413  * @param priority is the new priority for the interrupt vector.
0414  *
0415  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0416  *
0417  * @retval ::RTEMS_INVALID_PRIORITY The priority specified by ``priority`` was
0418  *   not a valid new priority for the interrupt vector.
0419  *
0420  * @retval ::RTEMS_UNSATISFIED The request to set the priority of the interrupt
0421  *   vector has not been satisfied.  This status shall be returned if the
0422  *   function is not implemented by the BSP.
0423  */
0424 rtems_status_code bsp_interrupt_set_priority(
0425   rtems_vector_number vector,
0426   uint32_t            priority
0427 );
0428 
0429 /**
0430  * @brief Gets the processor affinity set of the interrupt vector.
0431  *
0432  * The function may have no implementation in uniprocessor configurations.
0433  *
0434  * @param vector is the interrupt vector number.
0435  *
0436  * @param[out] affinity is the pointer to a Processor_mask object.  When the
0437  *   directive call is successful, the processor affinity set of the interrupt
0438  *   vector will be stored in this object.  A set bit in the processor set
0439  *   means that the corresponding processor is in the processor affinity set of
0440  *   the interrupt vector, otherwise the bit is cleared.
0441  *
0442  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0443  *
0444  * @retval ::RTEMS_UNSATISFIED The request to get the processor affinity of the
0445  *   interrupt vector has not been satisfied.
0446  */
0447 rtems_status_code bsp_interrupt_get_affinity(
0448   rtems_vector_number  vector,
0449   Processor_mask      *affinity
0450 );
0451 
0452 /**
0453  * @brief Sets the processor affinity set of the interrupt vector.
0454  *
0455  * The function may have no implementation in uniprocessor configurations.
0456  *
0457  * @param vector is the interrupt vector number.  It shall be valid.
0458  *
0459  * @param affinity is the pointer to a Processor_mask object.  The processor set
0460  *   defines the new processor affinity set of the interrupt vector.  A set bit
0461  *   in the processor set means that the corresponding processor shall be in
0462  *   the processor affinity set of the interrupt vector, otherwise the bit
0463  *   shall be cleared.
0464  *
0465  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0466  *
0467  * @retval ::RTEMS_INVALID_NUMBER The referenced processor set was not a valid
0468  *   new processor affinity set for the interrupt vector.
0469  *
0470  * @retval ::RTEMS_UNSATISFIED The request to set the processor affinity of the
0471  *   interrupt vector has not been satisfied.
0472  */
0473 rtems_status_code bsp_interrupt_set_affinity(
0474   rtems_vector_number   vector,
0475   const Processor_mask *affinity
0476 );
0477 
0478 #if defined(RTEMS_SMP)
0479 /**
0480  * @brief Handles a spurious interrupt.
0481  *
0482  * @param vector is the vector number.
0483  */
0484 void bsp_interrupt_spurious( rtems_vector_number vector );
0485 #endif
0486 
0487 /**
0488  * @brief Loads the interrupt entry with atomic acquire semantic.
0489  *
0490  * @param ptr is the pointer to an ::rtems_interrupt_entry pointer.
0491  *
0492  * @return Returns the pointer value.
0493  */
0494 static inline rtems_interrupt_entry *bsp_interrupt_entry_load_acquire(
0495   rtems_interrupt_entry * const *ptr
0496 )
0497 {
0498 #if defined(RTEMS_SMP)
0499   return (rtems_interrupt_entry *) _Atomic_Load_uintptr(
0500     (const Atomic_Uintptr *) ptr,
0501     ATOMIC_ORDER_ACQUIRE
0502   );
0503 #else
0504   return *ptr;
0505 #endif
0506 }
0507 
0508 /**
0509  * @brief Stores the interrupt entry with atomic release semantic.
0510  *
0511  * @param[out] ptr is the pointer to an ::rtems_interrupt_entry pointer.
0512  *
0513  * @param value is the pointer value.
0514  */
0515 static inline void bsp_interrupt_entry_store_release(
0516   rtems_interrupt_entry **ptr,
0517   rtems_interrupt_entry  *value
0518 )
0519 {
0520 #if defined(RTEMS_SMP)
0521   _Atomic_Store_uintptr(
0522     (Atomic_Uintptr *) ptr,
0523     (uintptr_t) value,
0524     ATOMIC_ORDER_RELEASE
0525   );
0526 #else
0527   rtems_interrupt_level level;
0528 
0529   rtems_interrupt_local_disable( level );
0530   *ptr = value;
0531   rtems_interrupt_local_enable( level );
0532 #endif
0533 }
0534 
0535 /**
0536  * @brief Loads the first interrupt entry installed at the interrupt vector.
0537  *
0538  * @param vector is the vector number.
0539  *
0540  * @return Returns the first entry or NULL.
0541  */
0542 static inline rtems_interrupt_entry *bsp_interrupt_entry_load_first(
0543   rtems_vector_number vector
0544 )
0545 {
0546   rtems_vector_number index;
0547 
0548   index = bsp_interrupt_dispatch_index( vector );
0549 
0550   return bsp_interrupt_entry_load_acquire(
0551     &bsp_interrupt_dispatch_table[ index ]
0552   );
0553 }
0554 
0555 /**
0556  * @brief Sequentially calls all interrupt handlers of the entry its
0557  *   successors.
0558  *
0559  * In uniprocessor configurations, you can call this function within every
0560  * context which can be disabled via rtems_interrupt_local_disable().
0561  *
0562  * In SMP configurations, you can call this function in every context.
0563  *
0564  * @param entry is the first entry.
0565  */
0566 static inline void bsp_interrupt_dispatch_entries(
0567   const rtems_interrupt_entry *entry
0568 )
0569 {
0570   do {
0571     ( *entry->handler )( entry->arg );
0572     entry = bsp_interrupt_entry_load_acquire( &entry->next );
0573   } while ( RTEMS_PREDICT_FALSE( entry != NULL ) );
0574 }
0575 
0576 /**
0577  * @brief Sequentially calls all interrupt handlers installed at the vector.
0578  *
0579  * This function does not validate the vector number.  If the vector number is
0580  * out of range, then the behaviour is undefined.
0581  *
0582  * The function assumes that no interrupt entries are installed at the vector.
0583  * In this case, no operation is performed.
0584  *
0585  * In uniprocessor configurations, you can call this function within every
0586  * context which can be disabled via rtems_interrupt_local_disable().
0587  *
0588  * In SMP configurations, you can call this function in every context.
0589  *
0590  * @param vector is the vector number.
0591  */
0592 static inline void bsp_interrupt_handler_dispatch_unlikely(
0593   rtems_vector_number vector
0594 )
0595 {
0596   const rtems_interrupt_entry *entry;
0597 
0598   entry = bsp_interrupt_entry_load_first( vector );
0599 
0600   if ( RTEMS_PREDICT_FALSE( entry != NULL ) ) {
0601     bsp_interrupt_dispatch_entries( entry );
0602   }
0603 }
0604 
0605 /**
0606  * @brief Sequentially calls all interrupt handlers installed at the vector.
0607  *
0608  * This function does not validate the vector number.  If the vector number is
0609  * out of range, then the behaviour is undefined.
0610  *
0611  * In uniprocessor configurations, you can call this function within every
0612  * context which can be disabled via rtems_interrupt_local_disable().
0613  *
0614  * In SMP configurations, you can call this function in every context.
0615  *
0616  * @param vector is the vector number.
0617  */
0618 static inline void bsp_interrupt_handler_dispatch_unchecked(
0619   rtems_vector_number vector
0620 )
0621 {
0622   const rtems_interrupt_entry *entry;
0623 
0624   entry = bsp_interrupt_entry_load_first( vector );
0625 
0626   if ( RTEMS_PREDICT_TRUE( entry != NULL ) ) {
0627     bsp_interrupt_dispatch_entries( entry );
0628   } else {
0629 #if defined(RTEMS_SMP)
0630     bsp_interrupt_spurious( vector );
0631 #else
0632     bsp_interrupt_handler_default( vector );
0633 #endif
0634   }
0635 }
0636 
0637 /**
0638  * @brief Sequentially calls all interrupt handlers installed at the vector.
0639  *
0640  * If the vector number is out of range or the interrupt entry list is empty,
0641  * then bsp_interrupt_handler_default() will be called with the vector number
0642  * as argument.
0643  *
0644  * In uniprocessor configurations, you can call this function within every
0645  * context which can be disabled via rtems_interrupt_local_disable().
0646  *
0647  * In SMP configurations, you can call this function in every context.
0648  *
0649  * @param vector is the vector number.
0650  */
0651 static inline void bsp_interrupt_handler_dispatch( rtems_vector_number vector )
0652 {
0653   if ( bsp_interrupt_is_valid_vector( vector ) ) {
0654     bsp_interrupt_handler_dispatch_unchecked( vector );
0655   } else {
0656     bsp_interrupt_handler_default( vector );
0657   }
0658 }
0659 
0660 /** @} */
0661 
0662 /**
0663  * @brief Acquires the interrupt support lock.
0664  *
0665  * The interrupt support lock is a mutex.  The mutex is only acquired if the
0666  * system is the ::SYSTEM_STATE_UP state.
0667  */
0668 void bsp_interrupt_lock(void);
0669 
0670 /**
0671  * @brief Releases the interrupt support lock.
0672  *
0673  * The mutex is only released if the system is the ::SYSTEM_STATE_UP state.
0674  */
0675 void bsp_interrupt_unlock(void);
0676 
0677 /**
0678  * @brief Checks the vector and routine.  When the checks were successful, the
0679  *   interrupt support lock will be obtained.
0680  *
0681  * @param vector is the interrupt vector number to check.
0682  *
0683  * @param routine is the routine to check.
0684  *
0685  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0686  *
0687  * @retval ::RTEMS_INCORRECT_STATE The interrupt support was not initialized.
0688  *
0689  * @retval ::RTEMS_CALLED_FROM_ISR The function was called from within
0690  *   interrupt context.
0691  *
0692  * @retval ::RTEMS_INVALID_ADDRESS The ``routine`` parameter was NULL.
0693  *
0694  * @retval ::RTEMS_INVALID_ID There was no interrupt vector associated with the
0695  *   number specified by ``vector``.
0696  */
0697 rtems_status_code bsp_interrupt_check_and_lock(
0698   rtems_vector_number     vector,
0699   rtems_interrupt_handler handler
0700 );
0701 
0702 /* For internal use only */
0703 rtems_interrupt_entry *bsp_interrupt_entry_find(
0704   rtems_vector_number      vector,
0705   rtems_interrupt_handler  routine,
0706   void                    *arg,
0707   rtems_interrupt_entry ***previous_next
0708 );
0709 
0710 /* For internal use only */
0711 void bsp_interrupt_entry_remove(
0712   rtems_vector_number     vector,
0713   rtems_interrupt_entry  *entry,
0714   rtems_interrupt_entry **previous_next
0715 );
0716 
0717 /**
0718  * @brief This table contains a bit map which indicates if an entry is unique
0719  *   or shared.
0720  *
0721  * If the bit associated with a vector is set, then the entry is unique,
0722  * otherwise it may be shared.  If the bit with index
0723  * #BSP_INTERRUPT_DISPATCH_TABLE_SIZE is set, then the interrupt support is
0724  * initialized, otherwise it is not initialized.
0725  */
0726 extern uint8_t bsp_interrupt_handler_unique_table[];
0727 
0728 /**
0729  * @brief Checks if the handler entry associated with the hander index is
0730  *   unique.
0731  *
0732  * @param index is the handler index to check.
0733  *
0734  * @return Returns true, if handler entry associated with the hander index is
0735  *   unique, otherwise false.
0736  */
0737 static inline bool bsp_interrupt_is_handler_unique( rtems_vector_number index )
0738 {
0739   rtems_vector_number table_index;
0740   uint8_t             bit;
0741 
0742   table_index = index / 8;
0743   bit = (uint8_t) ( 1U << ( index % 8 ) );
0744 
0745   return ( bsp_interrupt_handler_unique_table[ table_index ] & bit ) != 0;
0746 }
0747 
0748 /**
0749  * @brief Sets the unique status of the handler entry.
0750  *
0751  * @param index is the handler index.
0752  *
0753  * @param unique is the unique status to set.
0754  */
0755 static inline void bsp_interrupt_set_handler_unique(
0756   rtems_vector_number index,
0757   bool                unique
0758 )
0759 {
0760   rtems_vector_number table_index;
0761   uint8_t             bit;
0762 
0763   table_index = index / 8;
0764   bit = (uint8_t) ( 1U << ( index % 8 ) );
0765 
0766   if (unique) {
0767     bsp_interrupt_handler_unique_table[ table_index ] |= bit;
0768   } else {
0769     bsp_interrupt_handler_unique_table[ table_index ] &= ~bit;
0770   }
0771 }
0772 
0773 /**
0774  * @brief Checks if the interrupt support is initialized.
0775  *
0776  * @return Returns true, if the interrupt support is initialized, otherwise
0777  *   false.
0778  */
0779 static inline bool bsp_interrupt_is_initialized( void )
0780 {
0781   return bsp_interrupt_is_handler_unique( BSP_INTERRUPT_DISPATCH_TABLE_SIZE );
0782 }
0783 
0784 /**
0785  * @brief Gets a reference to the interrupt handler table slot associated with
0786  *   the index.
0787  *
0788  * @return Returns a reference to the interrupt handler table slot associated
0789  *   with the index.
0790  */
0791 rtems_interrupt_entry **bsp_interrupt_get_dispatch_table_slot(
0792   rtems_vector_number index
0793 );
0794 
0795 #ifdef __cplusplus
0796 }
0797 #endif /* __cplusplus */
0798 
0799 #endif /* LIBBSP_SHARED_IRQ_GENERIC_H */