00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <bsp/irq-generic.h>
00022
00023 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
00024 bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table [BSP_INTERRUPT_VECTOR_NUMBER];
00025 #endif
00026
00027 bsp_interrupt_handler_entry bsp_interrupt_handler_table [BSP_INTERRUPT_HANDLER_TABLE_SIZE];
00028
00029
00030 static uint8_t bsp_interrupt_handler_unique_table [(BSP_INTERRUPT_HANDLER_TABLE_SIZE + 7 + 1) / 8];
00031
00032 static rtems_id bsp_interrupt_mutex = 0;
00033
00034 static inline int bsp_interrupt_is_handler_unique( rtems_vector_number index)
00035 {
00036 rtems_vector_number i = index / 8;
00037 rtems_vector_number s = index % 8;
00038 return (bsp_interrupt_handler_unique_table [i] >> s) & 0x1;
00039 }
00040
00041 static inline void bsp_interrupt_set_handler_unique( rtems_vector_number index, int unique)
00042 {
00043 rtems_vector_number i = index / 8;
00044 rtems_vector_number s = index % 8;
00045 if (unique) {
00046 bsp_interrupt_handler_unique_table [i] |= 0x1 << s;
00047 } else {
00048 bsp_interrupt_handler_unique_table [i] &= ~((uint8_t) 0x1 << s);
00049 }
00050 }
00051
00052 static inline int bsp_interrupt_is_initialized()
00053 {
00054 return bsp_interrupt_is_handler_unique( BSP_INTERRUPT_HANDLER_TABLE_SIZE);
00055 }
00056
00057 static inline void bsp_interrupt_set_initialized()
00058 {
00059 bsp_interrupt_set_handler_unique( BSP_INTERRUPT_HANDLER_TABLE_SIZE, 1);
00060 }
00061
00062 void bsp_interrupt_handler_empty()
00063 {
00064
00065 }
00066
00067 static inline void bsp_interrupt_clear_handler_entry( rtems_vector_number index)
00068 {
00069 bsp_interrupt_handler_table [index].handler = bsp_interrupt_handler_empty;
00070 bsp_interrupt_handler_table [index].arg = NULL;
00071 bsp_interrupt_handler_table [index].next = NULL;
00072 bsp_interrupt_set_handler_unique( index, 0);
00073 }
00074
00075 static inline int bsp_interrupt_allocate_handler_index( rtems_vector_number vector, rtems_vector_number *index)
00076 {
00077 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
00078 rtems_vector_number i = 0;
00079
00080
00081 for (i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
00082 if (bsp_interrupt_is_empty_handler_entry( &bsp_interrupt_handler_table [i])) {
00083 *index = i;
00084 return 1;
00085 }
00086 }
00087
00088 return 0;
00089 #else
00090 *index = vector;
00091 return 1;
00092 #endif
00093 }
00094
00095 static bsp_interrupt_handler_entry *bsp_interrupt_allocate_handler_entry()
00096 {
00097 #ifdef BSP_INTERRUPT_NO_HEAP_USAGE
00098 rtems_vector_number index = 0;
00099 if (bsp_interrupt_allocate_handler_index( 0, &index)) {
00100 return &bsp_interrupt_handler_table [index];
00101 } else {
00102 return NULL;
00103 }
00104 #else
00105 return malloc( sizeof( bsp_interrupt_handler_entry));
00106 #endif
00107 }
00108
00109 static void bsp_interrupt_free_handler_entry( bsp_interrupt_handler_entry *e)
00110 {
00111 #ifdef BSP_INTERRUPT_NO_HEAP_USAGE
00112 bsp_interrupt_clear_handler_entry( e);
00113 #else
00114 free( e);
00115 #endif
00116 }
00117
00118 static rtems_status_code bsp_interrupt_lock()
00119 {
00120 rtems_status_code sc = RTEMS_SUCCESSFUL;
00121 if (_System_state_Is_up( _System_state_Get())) {
00122 if (bsp_interrupt_mutex == 0) {
00123 sc = rtems_semaphore_create (
00124 rtems_build_name ( 'I', 'N', 'T', 'R'),
00125 1,
00126 RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
00127 RTEMS_NO_PRIORITY,
00128 &bsp_interrupt_mutex
00129 );
00130 if (sc != RTEMS_SUCCESSFUL) {
00131 return sc;
00132 }
00133 }
00134 return rtems_semaphore_obtain( bsp_interrupt_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
00135 } else {
00136 return RTEMS_SUCCESSFUL;
00137 }
00138 }
00139
00140 static rtems_status_code bsp_interrupt_unlock()
00141 {
00142 if (bsp_interrupt_mutex != 0) {
00143 return rtems_semaphore_release( bsp_interrupt_mutex);
00144 } else {
00145 return RTEMS_SUCCESSFUL;
00146 }
00147 }
00148
00149 rtems_status_code bsp_interrupt_initialize()
00150 {
00151 rtems_status_code sc = RTEMS_SUCCESSFUL;
00152 rtems_vector_number index = 0;
00153
00154
00155 sc = bsp_interrupt_lock();
00156 if (sc != RTEMS_SUCCESSFUL) {
00157 return sc;
00158 }
00159
00160
00161 if (bsp_interrupt_is_initialized()) {
00162 bsp_interrupt_unlock();
00163 return RTEMS_INTERNAL_ERROR;
00164 }
00165
00166
00167 for (index = 0; index < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++index) {
00168 bsp_interrupt_clear_handler_entry( index);
00169 }
00170
00171
00172 sc = bsp_interrupt_facility_initialize();
00173 if (sc != RTEMS_SUCCESSFUL) {
00174 bsp_interrupt_unlock();
00175 return sc;
00176 }
00177
00178
00179 bsp_interrupt_set_initialized();
00180
00181
00182 sc = bsp_interrupt_unlock();
00183 if (sc != RTEMS_SUCCESSFUL) {
00184 return sc;
00185 }
00186
00187 return RTEMS_SUCCESSFUL;
00188 }
00189
00202 rtems_status_code bsp_interrupt_handler_install( rtems_vector_number vector, rtems_interrupt_handler handler, void *arg, rtems_boolean shared)
00203 {
00204 rtems_status_code sc = RTEMS_SUCCESSFUL;
00205 rtems_interrupt_level level;
00206 rtems_vector_number index = 0;
00207 bsp_interrupt_handler_entry *head = NULL;
00208 bsp_interrupt_handler_entry *tail = NULL;
00209 bsp_interrupt_handler_entry *current = NULL;
00210 bsp_interrupt_handler_entry *match = NULL;
00211
00212
00213 if (!bsp_interrupt_is_initialized()) {
00214 return RTEMS_INTERNAL_ERROR;
00215 } else if (!bsp_interrupt_is_valid_vector( vector)) {
00216 return RTEMS_INVALID_NUMBER;
00217 } else if (handler == NULL) {
00218 return RTEMS_INVALID_ADDRESS;
00219 } else if (_ISR_Nest_level > 0) {
00220 return RTEMS_CALLED_FROM_ISR;
00221 }
00222
00223
00224 sc = bsp_interrupt_lock();
00225 if (sc != RTEMS_SUCCESSFUL) {
00226 return sc;
00227 }
00228
00229
00230 index = bsp_interrupt_handler_index( vector);
00231
00232
00233 head = &bsp_interrupt_handler_table [index];
00234
00235 if (bsp_interrupt_is_empty_handler_entry( head)) {
00236
00237
00238
00239
00240 if (bsp_interrupt_allocate_handler_index( vector, &index)) {
00241 rtems_interrupt_disable( level);
00242 bsp_interrupt_handler_table [index].handler = handler;
00243 bsp_interrupt_handler_table [index].arg = arg;
00244 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
00245 bsp_interrupt_handler_index_table [vector] = index;
00246 #endif
00247 rtems_interrupt_enable( level);
00248 } else {
00249
00250 bsp_interrupt_unlock();
00251 return RTEMS_NO_MEMORY;
00252 }
00253
00254
00255 sc = bsp_interrupt_vector_enable( vector);
00256 if (sc != RTEMS_SUCCESSFUL) {
00257 bsp_interrupt_unlock();
00258 return sc;
00259 }
00260 } else {
00261
00262 if (!shared || bsp_interrupt_is_handler_unique( index)) {
00263
00264
00265
00266
00267 bsp_interrupt_unlock();
00268 return RTEMS_RESOURCE_IN_USE;
00269 }
00270
00271
00272
00273
00274
00275 current = head;
00276 do {
00277 if (current->handler == handler) {
00278 match = current;
00279 }
00280 tail = current;
00281 current = current->next;
00282 } while (current != NULL);
00283
00284
00285 if (match != NULL) {
00286
00287 bsp_interrupt_unlock();
00288 return RTEMS_TOO_MANY;
00289 }
00290
00291
00292 current = bsp_interrupt_allocate_handler_entry();
00293 if (current == NULL) {
00294
00295 bsp_interrupt_unlock();
00296 return RTEMS_NO_MEMORY;
00297 }
00298
00299
00300 current->handler = handler;
00301 current->arg = arg;
00302 current->next = NULL;
00303
00304
00305 rtems_interrupt_disable( level);
00306 tail->next = current;
00307 rtems_interrupt_enable( level);
00308 }
00309
00310
00311 if (!shared) {
00312 bsp_interrupt_set_handler_unique( index, 1);
00313 }
00314
00315
00316 sc = bsp_interrupt_unlock();
00317 if (sc != RTEMS_SUCCESSFUL) {
00318 return sc;
00319 }
00320
00321 return RTEMS_SUCCESSFUL;
00322 }
00323
00332 rtems_status_code bsp_interrupt_handler_remove( rtems_vector_number vector, rtems_interrupt_handler handler)
00333 {
00334 rtems_status_code sc = RTEMS_SUCCESSFUL;
00335 rtems_interrupt_level level;
00336 rtems_vector_number index = 0;
00337 bsp_interrupt_handler_entry *head = NULL;
00338 bsp_interrupt_handler_entry *current = NULL;
00339 bsp_interrupt_handler_entry *previous = NULL;
00340 bsp_interrupt_handler_entry *match = NULL;
00341
00342
00343 if (!bsp_interrupt_is_initialized()) {
00344 return RTEMS_INTERNAL_ERROR;
00345 } else if (!bsp_interrupt_is_valid_vector( vector)) {
00346 return RTEMS_INVALID_NUMBER;
00347 } else if (handler == NULL) {
00348 return RTEMS_INVALID_ADDRESS;
00349 } else if (_ISR_Nest_level > 0) {
00350 return RTEMS_CALLED_FROM_ISR;
00351 }
00352
00353
00354 sc = bsp_interrupt_lock();
00355 if (sc != RTEMS_SUCCESSFUL) {
00356 return sc;
00357 }
00358
00359
00360 index = bsp_interrupt_handler_index( vector);
00361
00362
00363 head = &bsp_interrupt_handler_table [index];
00364
00365
00366 current = head;
00367 do {
00368 if (current->handler == handler) {
00369 match = current;
00370 break;
00371 }
00372 previous = current;
00373 current = current->next;
00374 } while (current != NULL);
00375
00376
00377 if (match != NULL) {
00378 if (match->next != NULL) {
00379
00380
00381
00382
00383
00384 current = match->next;
00385
00386 rtems_interrupt_disable( level);
00387 *match = *current;
00388 rtems_interrupt_enable( level);
00389
00390 bsp_interrupt_free_handler_entry( current);
00391 } else if (match == head) {
00392
00393
00394
00395
00396
00397
00398
00399
00400 sc = bsp_interrupt_vector_disable( vector);
00401
00402
00403 rtems_interrupt_disable( level);
00404 bsp_interrupt_clear_handler_entry( index);
00405 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
00406 bsp_interrupt_handler_index_table [vector] = 0;
00407 #endif
00408 rtems_interrupt_enable( level);
00409
00410
00411 if (sc != RTEMS_SUCCESSFUL) {
00412 bsp_interrupt_unlock();
00413 return sc;
00414 }
00415 } else {
00416
00417
00418
00419
00420 rtems_interrupt_disable( level);
00421 previous->next = NULL;
00422 rtems_interrupt_enable( level);
00423
00424 bsp_interrupt_free_handler_entry( match);
00425 }
00426 } else {
00427
00428 bsp_interrupt_unlock();
00429 return RTEMS_UNSATISFIED;
00430 }
00431
00432
00433 sc = bsp_interrupt_unlock();
00434 if (sc != RTEMS_SUCCESSFUL) {
00435 return sc;
00436 }
00437
00438 return RTEMS_SUCCESSFUL;
00439 }
00440
00444 int BSP_get_current_rtems_irq_handler( rtems_irq_connect_data *cd)
00445 {
00446 cd->hdl = NULL;
00447 cd->handle = NULL;
00448 cd->on = NULL;
00449 cd->off = NULL;
00450 cd->isOn = NULL;
00451 }
00452
00456 int BSP_install_rtems_irq_handler( const rtems_irq_connect_data *cd)
00457 {
00458 rtems_status_code sc = RTEMS_SUCCESSFUL;
00459 sc = rtems_interrupt_handler_unique_install( cd->name, cd->hdl, cd->handle);
00460 if (sc != RTEMS_SUCCESSFUL) {
00461 return 0;
00462 }
00463 if (cd->on) {
00464 cd->on( cd);
00465 }
00466 return 1;
00467 }
00468
00472 int BSP_install_rtems_shared_irq_handler( const rtems_irq_connect_data *cd)
00473 {
00474 rtems_status_code sc = RTEMS_SUCCESSFUL;
00475 sc = rtems_interrupt_handler_install( cd->name, cd->hdl, cd->handle);
00476 if (sc != RTEMS_SUCCESSFUL) {
00477 return 0;
00478 }
00479 if (cd->on) {
00480 cd->on( cd);
00481 }
00482 return 1;
00483 }
00484
00488 int BSP_remove_rtems_irq_handler( const rtems_irq_connect_data *cd)
00489 {
00490 rtems_status_code sc = RTEMS_SUCCESSFUL;
00491 sc = rtems_interrupt_handler_remove( cd->name, cd->hdl);
00492 if (sc != RTEMS_SUCCESSFUL) {
00493 return 0;
00494 }
00495 if (cd->off) {
00496 cd->off( cd);
00497 }
00498 return 1;
00499 }
00500
00504 int BSP_rtems_irq_mngt_set( rtems_irq_global_settings *config)
00505 {
00506 return 0;
00507 }
00508
00512 int BSP_rtems_irq_mngt_get( rtems_irq_global_settings **config)
00513 {
00514 *config = NULL;
00515 return 0;
00516 }