File indexing completed on 2025-05-11 08:24:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <bsp/irq-generic.h>
0038
0039 #include <rtems/malloc.h>
0040
0041 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
0042 bsp_interrupt_dispatch_index_type bsp_interrupt_dispatch_index_table
0043 [BSP_INTERRUPT_VECTOR_COUNT];
0044 #endif
0045
0046 rtems_interrupt_entry *
0047 bsp_interrupt_dispatch_table[ BSP_INTERRUPT_DISPATCH_TABLE_SIZE ];
0048
0049 RTEMS_WEAK rtems_interrupt_entry **bsp_interrupt_get_dispatch_table_slot(
0050 rtems_vector_number index
0051 )
0052 {
0053 return &bsp_interrupt_dispatch_table[ index ];
0054 }
0055
0056
0057 uint8_t bsp_interrupt_handler_unique_table
0058 [ ( BSP_INTERRUPT_DISPATCH_TABLE_SIZE + 7 + 1 ) / 8 ];
0059
0060 static inline void bsp_interrupt_set_initialized(void)
0061 {
0062 bsp_interrupt_set_handler_unique(BSP_INTERRUPT_DISPATCH_TABLE_SIZE, true);
0063 }
0064
0065 #if defined(BSP_INTERRUPT_USE_INDEX_TABLE)
0066 static inline rtems_vector_number bsp_interrupt_allocate_handler_index( void )
0067 {
0068 rtems_vector_number i;
0069
0070
0071 for ( i = 1; i < BSP_INTERRUPT_DISPATCH_TABLE_SIZE; ++i ) {
0072 if ( bsp_interrupt_dispatch_table[ i ] == NULL ) {
0073 break;
0074 }
0075 }
0076
0077 return i;
0078 }
0079 #endif
0080
0081 #if defined(RTEMS_SMP)
0082 RTEMS_STATIC_ASSERT(
0083 sizeof( Atomic_Uintptr ) == sizeof( rtems_interrupt_entry * ),
0084 rtems_interrupt_entry_pointer_size
0085 );
0086
0087 void bsp_interrupt_spurious( rtems_vector_number vector )
0088 {
0089 Atomic_Uintptr *ptr;
0090 rtems_interrupt_entry *first;
0091
0092
0093
0094
0095
0096 ptr = (Atomic_Uintptr *) bsp_interrupt_get_dispatch_table_slot(
0097 bsp_interrupt_dispatch_index( vector )
0098 );
0099 first = (rtems_interrupt_entry *)
0100 _Atomic_Fetch_add_uintptr( ptr, 0, ATOMIC_ORDER_ACQUIRE );
0101
0102 if ( first == NULL ) {
0103 bsp_interrupt_handler_default( vector );
0104 } else {
0105 bsp_interrupt_dispatch_entries( first );
0106 }
0107 }
0108 #endif
0109
0110 rtems_status_code bsp_interrupt_check_and_lock(
0111 rtems_vector_number vector,
0112 rtems_interrupt_handler routine
0113 )
0114 {
0115 if ( !bsp_interrupt_is_initialized() ) {
0116 return RTEMS_INCORRECT_STATE;
0117 }
0118
0119 if ( routine == NULL ) {
0120 return RTEMS_INVALID_ADDRESS;
0121 }
0122
0123 if ( !bsp_interrupt_is_valid_vector( vector ) ) {
0124 return RTEMS_INVALID_ID;
0125 }
0126
0127 if ( rtems_interrupt_is_in_progress() ) {
0128 return RTEMS_CALLED_FROM_ISR;
0129 }
0130
0131 bsp_interrupt_lock();
0132
0133 return RTEMS_SUCCESSFUL;
0134 }
0135
0136 rtems_interrupt_entry *bsp_interrupt_entry_find(
0137 rtems_vector_number vector,
0138 rtems_interrupt_handler routine,
0139 void *arg,
0140 rtems_interrupt_entry ***previous_next
0141 )
0142 {
0143 rtems_vector_number index;
0144 rtems_interrupt_entry *entry;
0145
0146 bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
0147 index = bsp_interrupt_dispatch_index( vector );
0148 *previous_next = bsp_interrupt_get_dispatch_table_slot( index );
0149 entry = **previous_next;
0150
0151 while ( entry != NULL ) {
0152 if ( entry->handler == routine && entry->arg == arg ) {
0153 return entry;
0154 }
0155
0156 *previous_next = &entry->next;
0157 entry = entry->next;
0158 }
0159
0160 return NULL;
0161 }
0162
0163 void bsp_interrupt_initialize( void )
0164 {
0165 bsp_interrupt_facility_initialize();
0166 bsp_interrupt_set_initialized();
0167 }
0168
0169 static rtems_status_code bsp_interrupt_entry_install_first(
0170 rtems_vector_number vector,
0171 rtems_option options,
0172 rtems_interrupt_entry *entry
0173 )
0174 {
0175 rtems_vector_number index;
0176
0177 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
0178 index = bsp_interrupt_allocate_handler_index();
0179
0180 if ( index == BSP_INTERRUPT_DISPATCH_TABLE_SIZE ) {
0181
0182 return RTEMS_NO_MEMORY;
0183 }
0184 #else
0185 index = vector;
0186 #endif
0187
0188 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
0189 bsp_interrupt_dispatch_index_table[ vector ] = index;
0190 #endif
0191 bsp_interrupt_entry_store_release(
0192 bsp_interrupt_get_dispatch_table_slot( index ),
0193 entry
0194 );
0195
0196 bsp_interrupt_set_handler_unique(
0197 index,
0198 RTEMS_INTERRUPT_IS_UNIQUE( options )
0199 );
0200 #if defined(bsp_interrupt_vector_install)
0201 bsp_interrupt_vector_install( vector );
0202 #else
0203 bsp_interrupt_vector_enable( vector );
0204 #endif
0205
0206 return RTEMS_SUCCESSFUL;
0207 }
0208
0209 static rtems_status_code bsp_interrupt_entry_install(
0210 rtems_vector_number vector,
0211 rtems_option options,
0212 rtems_interrupt_entry *entry
0213 )
0214 {
0215 rtems_vector_number index;
0216 rtems_interrupt_entry *first;
0217 rtems_interrupt_entry *other;
0218 rtems_interrupt_entry **previous_next;
0219
0220 if ( RTEMS_INTERRUPT_IS_REPLACE( options ) ) {
0221 return RTEMS_INVALID_NUMBER;
0222 }
0223
0224 index = bsp_interrupt_dispatch_index( vector );
0225 first = *bsp_interrupt_get_dispatch_table_slot( index );
0226
0227 if ( first == NULL ) {
0228 return bsp_interrupt_entry_install_first( vector, options, entry );
0229 }
0230
0231 if ( RTEMS_INTERRUPT_IS_UNIQUE( options ) ) {
0232
0233 return RTEMS_RESOURCE_IN_USE;
0234 }
0235
0236 if ( bsp_interrupt_is_handler_unique( index ) ) {
0237
0238
0239
0240
0241 return RTEMS_RESOURCE_IN_USE;
0242 }
0243
0244 other = bsp_interrupt_entry_find(
0245 vector,
0246 entry->handler,
0247 entry->arg,
0248 &previous_next
0249 );
0250
0251 if ( other != NULL ) {
0252
0253
0254
0255
0256 return RTEMS_TOO_MANY;
0257 }
0258
0259 bsp_interrupt_entry_store_release( previous_next, entry );
0260
0261 return RTEMS_SUCCESSFUL;
0262 }
0263
0264 rtems_status_code rtems_interrupt_entry_install(
0265 rtems_vector_number vector,
0266 rtems_option options,
0267 rtems_interrupt_entry *entry
0268 )
0269 {
0270 rtems_status_code sc;
0271
0272 if ( entry == NULL ) {
0273 return RTEMS_INVALID_ADDRESS;
0274 }
0275
0276 sc = bsp_interrupt_check_and_lock( vector, entry->handler );
0277
0278 if ( sc != RTEMS_SUCCESSFUL ) {
0279 return sc;
0280 }
0281
0282 sc = bsp_interrupt_entry_install( vector, options, entry );
0283 bsp_interrupt_unlock();
0284
0285 return sc;
0286 }