Changeset e518323 in rtems


Ignore:
Timestamp:
06/25/21 13:52:16 (3 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
b910e60
Parents:
70357f1
git-author:
Sebastian Huber <sebastian.huber@…> (06/25/21 13:52:16)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/26/21 17:57:31)
Message:

bsps/irq: Add rtems_interrupt_entry_install()

Add rtems_interrupt_entry_remove(). Split up irq-generic.c into several files.
In particular, place all functions which use dynamic memory into their own
file.

Add optional macros to let the BSP customize the vector installation after
installing the first entry and the vector removal before removing the last
entry:

  • bsp_interrupt_vector_install()
  • bsp_interrupt_vector_remove()

Use these new customization options in the m68k/genmcf548x BSP so re-use the
generic interrupt controller support.

Update #3269.

Files:
3 added
14 edited

Legend:

Unmodified
Added
Removed
  • bsps/i386/shared/irq/irq.c

    r70357f1 re518323  
    354354static bool bsp_interrupt_handler_is_empty(rtems_vector_number vector)
    355355{
    356   rtems_vector_number index;
    357   rtems_interrupt_entry *head;
    358 
    359   index = bsp_interrupt_handler_index(vector);
    360   head = &bsp_interrupt_handler_table[index];
    361 
    362   return bsp_interrupt_is_empty_handler_entry(head);
     356  return bsp_interrupt_entry_load_first(vector) == NULL;
    363357}
    364358
  • bsps/include/bsp/irq-generic.h

    r70357f1 re518323  
    1313 * Copyright (C) 2016 Chris Johns <chrisj@rtems.org>
    1414 *
    15  * Copyright (C) 2008, 2017 embedded brains GmbH (http://www.embedded-brains.de)
     15 * Copyright (C) 2008, 2021 embedded brains GmbH (http://www.embedded-brains.de)
    1616 *
    1717 * Redistribution and use in source and binary forms, with or without
     
    7171#endif
    7272
    73 /* Internal macros for SMP support, do not use externally */
    74 #ifdef RTEMS_SMP
    75   #define bsp_interrupt_disable(level) do { (void) level; } while (0)
    76   #define bsp_interrupt_enable(level) do { } while (0)
    77   #define bsp_interrupt_fence(order) _Atomic_Fence(order)
    78 #else
    79   #define bsp_interrupt_disable(level) rtems_interrupt_disable(level)
    80   #define bsp_interrupt_enable(level) rtems_interrupt_enable(level)
    81   #define bsp_interrupt_fence(order) do { } while (0)
    82 #endif
    83 
    8473#define bsp_interrupt_assert(e) _Assert(e)
    8574
    86 extern rtems_interrupt_entry bsp_interrupt_handler_table [];
     75/**
     76 * @brief Each member of this table references the first installed entry at the
     77 *   corresponding interrupt vector or is NULL.
     78 */
     79extern rtems_interrupt_entry *bsp_interrupt_handler_table[];
    8780
    8881#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
     
    141134 * - bsp_interrupt_vector_disable()
    142135 * - bsp_interrupt_handler_default()
     136 *
     137 * Optionally, the BSP may define the following macros to customize the vector
     138 * installation after installing the first entry and the vector removal before
     139 * removing the last entry:
     140 * - bsp_interrupt_vector_install()
     141 * - bsp_interrupt_vector_remove()
    143142 *
    144143 * The following now deprecated functions are provided for backward
     
    363362rtems_status_code bsp_interrupt_clear( rtems_vector_number vector );
    364363
     364#if defined(RTEMS_SMP)
     365/**
     366 * @brief Handles a spurious interrupt.
     367 *
     368 * @param vector is the vector number.
     369 */
     370void bsp_interrupt_spurious( rtems_vector_number vector );
     371#endif
     372
     373/**
     374 * @brief Loads the interrupt entry with atomic acquire semantic.
     375 *
     376 * @param ptr is the pointer to an ::rtems_interrupt_entry pointer.
     377 *
     378 * @return Returns the pointer value.
     379 */
     380static inline rtems_interrupt_entry *bsp_interrupt_entry_load_acquire(
     381  rtems_interrupt_entry * const *ptr
     382)
     383{
     384#if defined(RTEMS_SMP)
     385  return (rtems_interrupt_entry *) _Atomic_Load_uintptr(
     386    (const Atomic_Uintptr *) ptr,
     387    ATOMIC_ORDER_ACQUIRE
     388  );
     389#else
     390  return *ptr;
     391#endif
     392}
     393
     394/**
     395 * @brief Stores the interrupt entry with atomic release semantic.
     396 *
     397 * @param[out] ptr is the pointer to an ::rtems_interrupt_entry pointer.
     398 *
     399 * @param value is the pointer value.
     400 */
     401static inline void bsp_interrupt_entry_store_release(
     402  rtems_interrupt_entry **ptr,
     403  rtems_interrupt_entry  *value
     404)
     405{
     406#if defined(RTEMS_SMP)
     407  _Atomic_Store_uintptr(
     408    (Atomic_Uintptr *) ptr,
     409    (Atomic_Uintptr) value,
     410    ATOMIC_ORDER_RELEASE
     411  );
     412#else
     413  rtems_interrupt_level level;
     414
     415  rtems_interrupt_local_disable( level );
     416  *ptr = value;
     417  rtems_interrupt_local_enable( level );
     418#endif
     419}
     420
     421/**
     422 * @brief Loads the first interrupt entry installed at the interrupt vector.
     423 *
     424 * @param vector is the vector number.
     425 *
     426 * @return Returns the first entry or NULL.
     427 */
     428static inline rtems_interrupt_entry *bsp_interrupt_entry_load_first(
     429  rtems_vector_number vector
     430)
     431{
     432  rtems_vector_number index;
     433
     434  index = bsp_interrupt_handler_index( vector );
     435
     436  return bsp_interrupt_entry_load_acquire(
     437    &bsp_interrupt_handler_table[ index ]
     438  );
     439}
     440
     441/**
     442 * @brief Sequentially calls all interrupt handlers of the entry its
     443 *   successors.
     444 *
     445 * In uniprocessor configurations, you can call this function within every
     446 * context which can be disabled via rtems_interrupt_local_disable().
     447 *
     448 * In SMP configurations, you can call this function in every context.
     449 *
     450 * @param entry is the first entry.
     451 */
     452static inline void bsp_interrupt_dispatch_entries(
     453  const rtems_interrupt_entry *entry
     454)
     455{
     456  do {
     457    ( *entry->handler )( entry->arg );
     458    entry = bsp_interrupt_entry_load_acquire( &entry->next );
     459  } while ( RTEMS_PREDICT_FALSE( entry != NULL ) );
     460}
     461
    365462/**
    366463 * @brief Sequentially calls all interrupt handlers installed at the vector.
     
    369466 * out of range, then the behaviour is undefined.
    370467 *
    371  * You can call this function within every context which can be disabled via
    372  * rtems_interrupt_local_disable().
     468 * In uniprocessor configurations, you can call this function within every
     469 * context which can be disabled via rtems_interrupt_local_disable().
     470 *
     471 * In SMP configurations, you can call this function in every context.
    373472 *
    374473 * @param vector is the vector number.
     
    378477)
    379478{
    380   const rtems_interrupt_entry *e;
    381 
    382   e = &bsp_interrupt_handler_table[ bsp_interrupt_handler_index( vector ) ];
    383 
    384   do {
    385     rtems_interrupt_handler handler;
    386     void *arg;
    387 
    388     arg = e->arg;
    389     bsp_interrupt_fence( ATOMIC_ORDER_ACQUIRE );
    390     handler = e->handler;
    391     ( *handler )( arg );
    392 
    393     e = e->next;
    394   } while ( e != NULL );
     479  const rtems_interrupt_entry *entry;
     480
     481  entry = bsp_interrupt_entry_load_first( vector );
     482
     483  if ( RTEMS_PREDICT_TRUE( entry != NULL ) ) {
     484    bsp_interrupt_dispatch_entries( entry );
     485  } else {
     486#if defined(RTEMS_SMP)
     487    bsp_interrupt_spurious( vector );
     488#else
     489    bsp_interrupt_handler_default( vector );
     490#endif
     491  }
    395492}
    396493
     
    402499 * argument.
    403500 *
    404  * You can call this function within every context which can be disabled via
    405  * rtems_interrupt_local_disable().
     501 * In uniprocessor configurations, you can call this function within every
     502 * context which can be disabled via rtems_interrupt_local_disable().
     503 *
     504 * In SMP configurations, you can call this function in every context.
    406505 *
    407506 * @param vector is the vector number.
     
    458557);
    459558
     559/* For internal use only */
     560rtems_interrupt_entry *bsp_interrupt_entry_find(
     561  rtems_vector_number      vector,
     562  rtems_interrupt_handler  routine,
     563  void                    *arg,
     564  rtems_interrupt_entry ***previous_next
     565);
     566
     567/* For internal use only */
     568void bsp_interrupt_entry_remove(
     569  rtems_vector_number     vector,
     570  rtems_interrupt_entry  *entry,
     571  rtems_interrupt_entry **previous_next
     572);
     573
    460574/**
    461575 * @brief This table contains a bit map which indicates if an entry is unique
     
    490604
    491605/**
     606 * @brief Sets the unique status of the handler entry.
     607 *
     608 * @param index is the handler index.
     609 *
     610 * @param unique is the unique status to set.
     611 */
     612static inline void bsp_interrupt_set_handler_unique(
     613  rtems_vector_number index,
     614  bool                unique
     615)
     616{
     617  rtems_vector_number table_index;
     618  uint8_t             bit;
     619
     620  table_index = index / 8;
     621  bit = (uint8_t) ( 1U << ( index % 8 ) );
     622
     623  if (unique) {
     624    bsp_interrupt_handler_unique_table[ table_index ] |= bit;
     625  } else {
     626    bsp_interrupt_handler_unique_table[ table_index ] &= ~bit;
     627  }
     628}
     629
     630/**
    492631 * @brief Checks if the interrupt support is initialized.
    493632 *
     
    500639}
    501640
    502 /**
    503  * @brief This handler routine is used for empty entries.
    504  */
    505 void bsp_interrupt_handler_empty( void *arg );
    506 
    507 /**
    508  * @brief Checks if a handler entry is empty.
    509  */
    510 static inline bool bsp_interrupt_is_empty_handler_entry(
    511   const rtems_interrupt_entry *entry
    512 )
    513 {
    514   return entry->handler == bsp_interrupt_handler_empty;
    515 }
    516 
    517641#ifdef __cplusplus
    518642}
  • bsps/m68k/genmcf548x/include/bsp/irq.h

    r70357f1 re518323  
    100100}
    101101
     102void mcf548x_interrupt_vector_install(rtems_vector_number vector);
     103
     104void mcf548x_interrupt_vector_remove(rtems_vector_number vector);
     105
     106#define bsp_interrupt_vector_install(v) mcf548x_interrupt_vector_install(v)
     107
     108#define bsp_interrupt_vector_remove(v) mcf548x_interrupt_vector_remove(v)
     109
    102110#endif /* LIBBSP_M68K_MCF548X_IRQ_H */
  • bsps/m68k/genmcf548x/irq/irq.c

    r70357f1 re518323  
    11/*
    2  * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
     2 * Copyright (c) 2013, 2021 embedded brains GmbH.  All rights reserved.
    33 *
    44 *  embedded brains GmbH
     
    2020
    2121typedef void (*void_func)(void);
    22 
    23 typedef struct {
    24   rtems_interrupt_handler handler;
    25   void *arg;
    26   const char *info;
    27 } interrupt_control;
    28 
    29 static interrupt_control interrupt_controls[BSP_INTERRUPT_VECTOR_COUNT];
    3022
    3123static uint32_t vector_to_reg(rtems_vector_number vector)
     
    132124}
    133125
    134 static void_func get_exception_handler(rtems_vector_number vector)
    135 {
    136   void **vbr;
    137   void_func *exception_table;
    138 
    139   m68k_get_vbr(vbr);
    140 
    141   exception_table = (void_func *)vbr;
    142 
    143   return exception_table[vector_to_exception_vector(vector)];
    144 }
    145 
    146126static void set_exception_handler(rtems_vector_number vector, void_func handler)
    147127{
     
    158138static void dispatch_handler(rtems_vector_number exception_vector)
    159139{
    160   const interrupt_control *ic =
    161     &interrupt_controls[exception_vector_to_vector(exception_vector)];
    162 
    163   (*ic->handler)(ic->arg);
     140  bsp_interrupt_handler_dispatch_unchecked(
     141    exception_vector_to_vector(exception_vector)
     142  );
    164143}
    165144
    166 static uint8_t get_intc_icr(rtems_vector_number vector)
     145void mcf548x_interrupt_vector_install(rtems_vector_number vector)
    167146{
    168   volatile uint8_t *icr = &MCF548X_INTC_ICR0;
    169 
    170   return icr[vector];
     147  _ISR_Vector_table[vector_to_exception_vector(vector)]
     148    = dispatch_handler;
     149  set_exception_handler(vector, _ISR_Handler);
    171150}
    172151
    173 rtems_status_code rtems_interrupt_handler_install(
    174   rtems_vector_number vector,
    175   const char *info,
    176   rtems_option options,
    177   rtems_interrupt_handler handler,
    178   void *arg
    179 )
     152void mcf548x_interrupt_vector_remove(rtems_vector_number vector)
    180153{
    181   rtems_status_code sc = RTEMS_SUCCESSFUL;
    182 
    183   if (bsp_interrupt_is_valid_vector(vector)) {
    184     rtems_interrupt_level level;
    185 
    186     rtems_interrupt_disable(level);
    187 
    188     if (
    189       get_exception_handler(vector) == asm_default_interrupt
    190         && get_intc_icr(vector) != 0
    191     ) {
    192       interrupt_control *ic = &interrupt_controls[vector];
    193 
    194       ic->handler = handler;
    195       ic->arg = arg;
    196       ic->info = info;
    197 
    198       _ISR_Vector_table[vector_to_exception_vector(vector)]
    199         = dispatch_handler;
    200       set_exception_handler(vector, _ISR_Handler);
    201       bsp_interrupt_vector_enable(vector);
    202     } else {
    203       sc = RTEMS_RESOURCE_IN_USE;
    204     }
    205 
    206     rtems_interrupt_enable(level);
    207   } else {
    208     sc = RTEMS_INVALID_ID;
    209   }
    210 
    211   return sc;
     154  set_exception_handler(vector, asm_default_interrupt);
    212155}
    213 
    214 static bool is_occupied_by_us(rtems_vector_number vector)
    215 {
    216   return get_exception_handler(vector) == _ISR_Handler
    217     && _ISR_Vector_table[vector_to_exception_vector(vector)]
    218       == dispatch_handler;
    219 }
    220 
    221 rtems_status_code rtems_interrupt_handler_remove(
    222   rtems_vector_number vector,
    223   rtems_interrupt_handler handler,
    224   void *arg
    225 )
    226 {
    227   rtems_status_code sc = RTEMS_SUCCESSFUL;
    228 
    229   if (bsp_interrupt_is_valid_vector(vector)) {
    230     rtems_interrupt_level level;
    231     interrupt_control *ic = &interrupt_controls[vector];
    232 
    233     rtems_interrupt_disable(level);
    234 
    235     if (
    236       is_occupied_by_us(vector)
    237         && ic->handler == handler
    238         && ic->arg == arg
    239     ) {
    240       bsp_interrupt_vector_disable(vector);
    241       set_exception_handler(vector, asm_default_interrupt);
    242 
    243       memset(ic, 0, sizeof(*ic));
    244     } else {
    245       sc = RTEMS_UNSATISFIED;
    246     }
    247 
    248     rtems_interrupt_enable(level);
    249   } else {
    250     sc = RTEMS_INVALID_ID;
    251   }
    252 
    253   return sc;
    254 }
    255 
    256 rtems_status_code rtems_interrupt_handler_iterate(
    257   rtems_vector_number vector,
    258   rtems_interrupt_per_handler_routine routine,
    259   void *arg
    260 )
    261 {
    262   rtems_status_code sc = RTEMS_SUCCESSFUL;
    263 
    264   if (bsp_interrupt_is_valid_vector(vector)) {
    265     if (is_occupied_by_us(vector)) {
    266       const interrupt_control *ic = &interrupt_controls[vector];
    267 
    268       (*routine)(arg, ic->info, RTEMS_INTERRUPT_UNIQUE, ic->handler, ic->arg);
    269     }
    270   } else {
    271     sc = RTEMS_INVALID_ID;
    272   }
    273 
    274   return sc;
    275 }
  • bsps/shared/irq-default-sources.am

    r70357f1 re518323  
    44librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
    55librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c
     6librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c
    67librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c
     8librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c
    79librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c
     10librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c
    811librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c
    912librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c
  • bsps/shared/irq-sources.am

    r70357f1 re518323  
    22librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-raise-clear.c
    33librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c
     4librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c
    45librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c
     6librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c
    57librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c
     8librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c
    69librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c
    710librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-legacy.c
  • bsps/shared/irq/irq-generic.c

    r70357f1 re518323  
    1111
    1212/*
    13  * Copyright (C) 2008, 2018 embedded brains GmbH (http://www.embedded-brains.de)
     13 * Copyright (C) 2008, 2021 embedded brains GmbH (http://www.embedded-brains.de)
    1414 *
    1515 * Redistribution and use in source and binary forms, with or without
     
    4747#endif
    4848
    49 rtems_interrupt_entry bsp_interrupt_handler_table
    50   [BSP_INTERRUPT_HANDLER_TABLE_SIZE];
     49rtems_interrupt_entry *
     50bsp_interrupt_handler_table[ BSP_INTERRUPT_HANDLER_TABLE_SIZE ];
    5151
    5252/* The last entry indicates if everything is initialized */
     
    5454  [ ( BSP_INTERRUPT_HANDLER_TABLE_SIZE + 7 + 1 ) / 8 ];
    5555
    56 void bsp_interrupt_handler_empty( void *arg )
    57 {
    58   rtems_vector_number vector = (rtems_vector_number) (uintptr_t) arg;
    59 
    60   bsp_interrupt_handler_default( vector );
    61 }
    62 
    63 #ifdef RTEMS_SMP
    64   static void bsp_interrupt_handler_do_nothing(void *arg)
    65   {
    66     (void) arg;
    67   }
    68 #endif
    69 
    70 static inline void bsp_interrupt_set_handler_unique(
    71   rtems_vector_number index,
    72   bool unique
    73 )
    74 {
    75   rtems_vector_number i = index / 8;
    76   rtems_vector_number s = index % 8;
    77   if (unique) {
    78     bsp_interrupt_handler_unique_table [i] |= (uint8_t) (0x1U << s);
     56static inline void bsp_interrupt_set_initialized(void)
     57{
     58  bsp_interrupt_set_handler_unique(BSP_INTERRUPT_HANDLER_TABLE_SIZE, true);
     59}
     60
     61#if defined(BSP_INTERRUPT_USE_INDEX_TABLE)
     62static inline rtems_vector_number bsp_interrupt_allocate_handler_index(
     63  rtems_vector_number vector
     64)
     65{
     66  rtems_vector_number i;
     67
     68  /* The first entry will remain empty */
     69  for ( i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i ) {
     70    if (  bsp_interrupt_handler_table[ i ] == NULL ) {
     71      break;
     72    }
     73  }
     74
     75  return i;
     76}
     77#endif
     78
     79#if defined(RTEMS_SMP)
     80RTEMS_STATIC_ASSERT(
     81  sizeof( Atomic_Uintptr ) == sizeof( rtems_interrupt_entry * ),
     82  rtems_interrupt_entry_pointer_size
     83);
     84
     85void bsp_interrupt_spurious( rtems_vector_number vector )
     86{
     87  Atomic_Uintptr        *ptr;
     88  rtems_interrupt_entry *first;
     89
     90  /*
     91   * In order to get the last written pointer value to the first entry, we have
     92   * to carry out an atomic read-modify-write operation.
     93   */
     94  ptr = (Atomic_Uintptr *) &bsp_interrupt_handler_table[
     95    bsp_interrupt_handler_index( vector )
     96  ];
     97  first = (rtems_interrupt_entry *)
     98    _Atomic_Fetch_add_uintptr( ptr, 0, ATOMIC_ORDER_ACQUIRE );
     99
     100  if ( first == NULL ) {
     101    bsp_interrupt_handler_default( vector );
    79102  } else {
    80     bsp_interrupt_handler_unique_table [i] &= (uint8_t) ~(0x1U << s);
    81   }
    82 }
    83 
    84 static inline void bsp_interrupt_set_initialized(void)
    85 {
    86   bsp_interrupt_set_handler_unique(BSP_INTERRUPT_HANDLER_TABLE_SIZE, true);
    87 }
    88 
    89 static inline void bsp_interrupt_clear_handler_entry(
    90   rtems_interrupt_entry *e,
    91   rtems_vector_number vector
    92 )
    93 {
    94   e->handler = bsp_interrupt_handler_empty;
    95   bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
    96   e->arg = (void *) (uintptr_t) vector;
    97   e->info = NULL;
    98   e->next = NULL;
    99 }
    100 
    101 static inline bool bsp_interrupt_allocate_handler_index(
    102   rtems_vector_number vector,
    103   rtems_vector_number *index
    104 )
    105 {
    106   #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
    107     rtems_vector_number i = 0;
    108 
    109     /* The first entry will remain empty */
    110     for (i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
    111       const rtems_interrupt_entry *e = &bsp_interrupt_handler_table [i];
    112       if (bsp_interrupt_is_empty_handler_entry(e)) {
    113         *index = i;
    114         return true;
    115       }
    116     }
    117 
    118     return false;
    119   #else
    120     *index = bsp_interrupt_handler_index(vector);
    121     return true;
    122   #endif
    123 }
     103    bsp_interrupt_dispatch_entries( first );
     104  }
     105}
     106#endif
    124107
    125108rtems_status_code bsp_interrupt_check_and_lock(
    126109  rtems_vector_number     vector,
    127   rtems_interrupt_handler handler
     110  rtems_interrupt_handler routine
    128111)
    129112{
     
    132115  }
    133116
    134   if ( handler == NULL ) {
     117  if ( routine == NULL ) {
    135118    return RTEMS_INVALID_ADDRESS;
    136119  }
     
    149132}
    150133
    151 void bsp_interrupt_initialize(void)
    152 {
    153   rtems_status_code sc = RTEMS_SUCCESSFUL;
    154   size_t i = 0;
    155 
    156   /* Initialize handler table */
    157   for (i = 0; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
    158     bsp_interrupt_handler_table [i].handler = bsp_interrupt_handler_empty;
    159     bsp_interrupt_handler_table [i].arg = (void *) i;
    160   }
     134rtems_interrupt_entry *bsp_interrupt_entry_find(
     135  rtems_vector_number      vector,
     136  rtems_interrupt_handler  routine,
     137  void                    *arg,
     138  rtems_interrupt_entry ***previous_next
     139)
     140{
     141  rtems_vector_number    index;
     142  rtems_interrupt_entry *entry;
     143
     144  bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
     145  index = bsp_interrupt_handler_index( vector );
     146  *previous_next = &bsp_interrupt_handler_table[ index ];
     147  entry = bsp_interrupt_handler_table[ index ];
     148
     149  while ( entry != NULL ) {
     150    if ( entry->handler == routine && entry->arg == arg ) {
     151      return entry;
     152    }
     153
     154    *previous_next = &entry->next;
     155    entry = entry->next;
     156  }
     157
     158  return NULL;
     159}
     160
     161void bsp_interrupt_initialize( void )
     162{
     163  rtems_status_code sc;
    161164
    162165  sc = bsp_interrupt_facility_initialize();
    163   if (sc != RTEMS_SUCCESSFUL) {
    164     bsp_fatal(BSP_FATAL_INTERRUPT_INITIALIZATION);
     166  if ( sc != RTEMS_SUCCESSFUL ) {
     167    bsp_fatal( BSP_FATAL_INTERRUPT_INITIALIZATION );
    165168  }
    166169
     
    168171}
    169172
    170 /**
    171  * @brief Installs an interrupt handler.
    172  *
    173  * @ingroup bsp_interrupt
    174  *
    175  * @return In addition to the standard status codes this function returns:
    176  * - If the BSP interrupt support is not initialized RTEMS_INTERNAL_ERROR will
    177  * be returned.
    178  * - If not enough memory for a new handler is available RTEMS_NO_MEMORY will
    179  * be returned
    180  *
    181  * @see rtems_interrupt_handler_install()
    182  */
    183 static rtems_status_code bsp_interrupt_handler_install(
    184   rtems_vector_number vector,
    185   const char *info,
    186   rtems_option options,
    187   rtems_interrupt_handler handler,
    188   void *arg
     173static rtems_status_code bsp_interrupt_entry_install_first(
     174  rtems_vector_number       vector,
     175  rtems_option              options,
     176  rtems_interrupt_entry    *entry
     177)
     178{
     179  rtems_vector_number index;
     180
     181#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
     182  index = bsp_interrupt_allocate_handler_index( vector );
     183
     184  if ( index == BSP_INTERRUPT_HANDLER_TABLE_SIZE ) {
     185    /* Handler table is full */
     186    return RTEMS_NO_MEMORY;
     187  }
     188#else
     189  index = vector;
     190#endif
     191
     192#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
     193  bsp_interrupt_handler_index_table[ vector ] = index;
     194#endif
     195  bsp_interrupt_entry_store_release(
     196    &bsp_interrupt_handler_table[ index ],
     197    entry
     198  );
     199
     200  bsp_interrupt_set_handler_unique(
     201    index,
     202    RTEMS_INTERRUPT_IS_UNIQUE( options )
     203  );
     204#if defined(bsp_interrupt_vector_install)
     205  bsp_interrupt_vector_install( vector );
     206#else
     207  bsp_interrupt_vector_enable( vector );
     208#endif
     209
     210  return RTEMS_SUCCESSFUL;
     211}
     212
     213static rtems_status_code bsp_interrupt_entry_install(
     214  rtems_vector_number    vector,
     215  rtems_option           options,
     216  rtems_interrupt_entry *entry
     217)
     218{
     219  rtems_vector_number     index;
     220  rtems_interrupt_entry  *first;
     221  rtems_interrupt_entry  *other;
     222  rtems_interrupt_entry **previous_next;
     223
     224  if ( RTEMS_INTERRUPT_IS_REPLACE( options ) ) {
     225    return RTEMS_INVALID_NUMBER;
     226  }
     227
     228  index = bsp_interrupt_handler_index( vector );
     229  first = bsp_interrupt_handler_table[ index ];
     230
     231  if ( first == NULL ) {
     232    return bsp_interrupt_entry_install_first( vector, options, entry );
     233  }
     234
     235  if ( RTEMS_INTERRUPT_IS_UNIQUE( options ) ) {
     236    /* Cannot install a unique entry if there is already an entry installed */
     237    return RTEMS_RESOURCE_IN_USE;
     238  }
     239
     240  if ( bsp_interrupt_is_handler_unique( index ) ) {
     241    /*
     242     * Cannot install another entry if there is already an unique entry
     243     * installed.
     244     */
     245    return RTEMS_RESOURCE_IN_USE;
     246  }
     247
     248  other = bsp_interrupt_entry_find(
     249    vector,
     250    entry->handler,
     251    entry->arg,
     252    &previous_next
     253  );
     254
     255  if ( other != NULL ) {
     256    /*
     257     * Cannot install an entry which has the same routine and argument as an
     258     * already installed entry.
     259     */
     260    return RTEMS_TOO_MANY;
     261  }
     262
     263  bsp_interrupt_entry_store_release( previous_next, entry );
     264
     265  return RTEMS_SUCCESSFUL;
     266}
     267
     268rtems_status_code rtems_interrupt_entry_install(
     269  rtems_vector_number    vector,
     270  rtems_option           options,
     271  rtems_interrupt_entry *entry
    189272)
    190273{
    191274  rtems_status_code sc;
    192   rtems_interrupt_level level;
    193   rtems_vector_number index = 0;
    194   rtems_interrupt_entry *head = NULL;
    195   bool enable_vector = false;
    196   bool replace = RTEMS_INTERRUPT_IS_REPLACE(options);
    197 
    198   sc = bsp_interrupt_check_and_lock( vector, handler );
     275
     276  if ( entry == NULL ) {
     277    return RTEMS_INVALID_ADDRESS;
     278  }
     279
     280  sc = bsp_interrupt_check_and_lock( vector, entry->handler );
    199281
    200282  if ( sc != RTEMS_SUCCESSFUL ) {
     
    202284  }
    203285
    204   /* Get handler table index */
    205   index = bsp_interrupt_handler_index(vector);
    206 
    207   /* Get head entry of the handler list for current vector */
    208   head = &bsp_interrupt_handler_table [index];
    209 
    210   if (bsp_interrupt_is_empty_handler_entry(head)) {
    211     if (replace) {
    212       /* No handler to replace exists */
    213       bsp_interrupt_unlock();
    214       return RTEMS_UNSATISFIED;
    215     }
    216 
    217     /*
    218      * No real handler installed yet.  So allocate a new index in
    219      * the handler table and fill the entry with life.
    220      */
    221     if (bsp_interrupt_allocate_handler_index(vector, &index)) {
    222       bsp_interrupt_disable(level);
    223       bsp_interrupt_handler_table [index].arg = arg;
    224       bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
    225       bsp_interrupt_handler_table [index].handler = handler;
    226       #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
    227         bsp_interrupt_handler_index_table [vector] = index;
    228       #endif
    229       bsp_interrupt_enable(level);
    230       bsp_interrupt_handler_table [index].info = info;
    231     } else {
    232       /* Handler table is full */
    233       bsp_interrupt_unlock();
    234       return RTEMS_NO_MEMORY;
    235     }
    236 
    237     /* This is the first handler so enable the vector later */
    238     enable_vector = true;
    239   } else {
    240     rtems_interrupt_entry *current = head;
    241     rtems_interrupt_entry *tail = NULL;
    242     rtems_interrupt_entry *match = NULL;
    243 
    244     /* Ensure that a unique handler remains unique */
    245     if (
    246       !replace
    247         && (RTEMS_INTERRUPT_IS_UNIQUE(options)
    248           || bsp_interrupt_is_handler_unique(index))
    249     ) {
    250       /*
    251        * Tried to install a unique handler on a not empty
    252        * list or there is already a unique handler installed.
    253        */
    254       bsp_interrupt_unlock();
    255       return RTEMS_RESOURCE_IN_USE;
    256     }
    257 
    258     /*
    259      * Search for the list tail and check if the handler is already
    260      * installed.
    261      */
    262     do {
    263       if (
    264         match == NULL
    265           && (current->handler == handler || replace)
    266           && current->arg == arg
    267       ) {
    268         match = current;
    269       }
    270       tail = current;
    271       current = current->next;
    272     } while (current != NULL);
    273 
    274     if (replace) {
    275       /* Ensure that a handler to replace exists */
    276       if (match == NULL) {
    277         bsp_interrupt_unlock();
    278         return RTEMS_UNSATISFIED;
    279       }
    280 
    281       /* Use existing entry */
    282       current = match;
    283     } else {
    284       /* Ensure the handler is not already installed */
    285       if (match != NULL) {
    286         /* The handler is already installed */
    287         bsp_interrupt_unlock();
    288         return RTEMS_TOO_MANY;
    289       }
    290 
    291       /* Allocate a new entry */
    292       current = rtems_malloc(sizeof(*current));
    293       if (current == NULL) {
    294         /* Not enough memory */
    295         bsp_interrupt_unlock();
    296         return RTEMS_NO_MEMORY;
    297       }
    298     }
    299 
    300     /* Update existing entry or set new entry */
    301     current->handler = handler;
    302     current->info = info;
    303 
    304     if (!replace) {
    305       /* Set new entry */
    306       current->arg = arg;
    307       current->next = NULL;
    308 
    309       /* Link to list tail */
    310       bsp_interrupt_disable(level);
    311       bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
    312       tail->next = current;
    313       bsp_interrupt_enable(level);
    314     }
    315   }
    316 
    317   /* Make the handler unique if necessary */
    318   bsp_interrupt_set_handler_unique(index, RTEMS_INTERRUPT_IS_UNIQUE(options));
    319 
    320   /* Enable the vector if necessary */
    321   if (enable_vector) {
    322     bsp_interrupt_vector_enable(vector);
    323   }
    324 
    325   /* Unlock */
     286  sc = bsp_interrupt_entry_install( vector, options, entry );
    326287  bsp_interrupt_unlock();
    327288
    328   return RTEMS_SUCCESSFUL;
    329 }
    330 
    331 /**
    332  * @brief Removes an interrupt handler.
    333  *
    334  * @ingroup bsp_interrupt
    335  *
    336  * @return In addition to the standard status codes this function returns
    337  * RTEMS_INTERNAL_ERROR if the BSP interrupt support is not initialized.
    338  *
    339  * @see rtems_interrupt_handler_remove().
    340  */
    341 static rtems_status_code bsp_interrupt_handler_remove(
    342   rtems_vector_number vector,
    343   rtems_interrupt_handler handler,
    344   void *arg
    345 )
    346 {
    347   rtems_status_code sc;
    348   rtems_interrupt_level level;
    349   rtems_vector_number index = 0;
    350   rtems_interrupt_entry *head = NULL;
    351   rtems_interrupt_entry *current = NULL;
    352   rtems_interrupt_entry *previous = NULL;
    353   rtems_interrupt_entry *match = NULL;
    354 
    355   sc = bsp_interrupt_check_and_lock( vector, handler );
    356 
    357   if ( sc != RTEMS_SUCCESSFUL ) {
    358     return sc;
    359   }
    360 
    361   /* Get handler table index */
    362   index = bsp_interrupt_handler_index(vector);
    363 
    364   /* Get head entry of the handler list for current vector */
    365   head = &bsp_interrupt_handler_table [index];
    366 
    367   /* Search for a matching entry */
    368   current = head;
    369   do {
    370     if (current->handler == handler && current->arg == arg) {
    371       match = current;
    372       break;
    373     }
    374     previous = current;
    375     current = current->next;
    376   } while (current != NULL);
    377 
    378   /* Remove the matching entry */
    379   if (match != NULL) {
    380     if (match->next != NULL) {
    381       /*
    382        * The match has a successor.  A successor is always
    383        * allocated.  So replace the match with its successor
    384        * and free the successor entry.
    385        */
    386       current = match->next;
    387 
    388       bsp_interrupt_disable(level);
    389       #ifdef RTEMS_SMP
    390         match->handler = bsp_interrupt_handler_do_nothing;
    391         bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
    392       #endif
    393       match->arg = current->arg;
    394       bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
    395       match->handler = current->handler;
    396       match->info = current->info;
    397       match->next = current->next;
    398       bsp_interrupt_enable(level);
    399 
    400       free(current);
    401     } else if (match == head) {
    402       /*
    403        * The match is the list head and has no successor.
    404        * The list head is stored in a static table so clear
    405        * this entry.  Since now the list is empty disable the
    406        * vector.
    407        */
    408 
    409       /* Disable the vector */
    410       bsp_interrupt_vector_disable(vector);
    411 
    412       /* Clear entry */
    413       bsp_interrupt_disable(level);
    414       bsp_interrupt_clear_handler_entry(head, vector);
    415       #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
    416         bsp_interrupt_handler_index_table [vector] = 0;
    417       #endif
    418       bsp_interrupt_enable(level);
    419 
    420       /* Allow shared handlers */
    421       bsp_interrupt_set_handler_unique(index, false);
    422     } else {
    423       /*
    424        * The match is the list tail and has a predecessor.
    425        * So terminate the predecessor and free the match.
    426        */
    427       bsp_interrupt_disable(level);
    428       previous->next = NULL;
    429       bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
    430       bsp_interrupt_enable(level);
    431 
    432       free(match);
    433     }
    434   } else {
    435     /* No matching entry found */
    436     bsp_interrupt_unlock();
    437     return RTEMS_UNSATISFIED;
    438   }
    439 
    440   /* Unlock */
    441   bsp_interrupt_unlock();
    442 
    443   return RTEMS_SUCCESSFUL;
    444 }
    445 
    446 rtems_status_code rtems_interrupt_handler_install(
    447   rtems_vector_number vector,
    448   const char *info,
    449   rtems_option options,
    450   rtems_interrupt_handler handler,
    451   void *arg
    452 )
    453 {
    454   return bsp_interrupt_handler_install(vector, info, options, handler, arg);
    455 }
    456 
    457 rtems_status_code rtems_interrupt_handler_remove(
    458   rtems_vector_number vector,
    459   rtems_interrupt_handler handler,
    460   void *arg
    461 )
    462 {
    463   return bsp_interrupt_handler_remove(vector, handler, arg);
    464 }
     289  return sc;
     290}
  • bsps/shared/irq/irq-handler-iterate.c

    r70357f1 re518323  
    1111
    1212/*
    13  * Copyright (C) 2017 embedded brains GmbH (http://www.embedded-brains.de)
     13 * Copyright (C) 2017, 2021 embedded brains GmbH (http://www.embedded-brains.de)
    1414 *
    1515 * Redistribution and use in source and binary forms, with or without
     
    4646  rtems_vector_number    index;
    4747  rtems_option           options;
    48   rtems_interrupt_entry *current;
     48  rtems_interrupt_entry *entry;
    4949
    5050  sc = bsp_interrupt_check_and_lock(
     
    5757  }
    5858
    59   index = bsp_interrupt_handler_index(vector);
    60   current = &bsp_interrupt_handler_table [index];
    61   if (!bsp_interrupt_is_empty_handler_entry(current)) {
    62     do {
    63       options = bsp_interrupt_is_handler_unique(index) ?
    64         RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED;
    65       routine(arg, current->info, options, current->handler, current->arg);
    66       current = current->next;
    67     } while (current != NULL);
     59  index = bsp_interrupt_handler_index( vector );
     60  options = bsp_interrupt_is_handler_unique( index ) ?
     61    RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED;
     62  entry = bsp_interrupt_handler_table[ index ];
     63
     64  while ( entry != NULL ) {
     65    ( *routine )( arg, entry->info, options, entry->handler, entry->arg );
     66    entry = entry->next;
    6867  }
    6968
  • c/src/lib/libbsp/m68k/genmcf548x/Makefile.am

    r70357f1 re518323  
    3939
    4040# IRQ
    41 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-affinity.c
    42 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-raise-clear.c
    4341librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
    44 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c
    45 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c
    46 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c
    47 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-legacy.c
    48 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c
    49 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-server.c
    50 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-shell.c
    5142librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/irq/irq.c
    5243librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/irq/intc-icr-init-values.c
     
    6051librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/start/cache.c
    6152
     53include $(srcdir)/../../../../../../bsps/shared/irq-sources.am
    6254include $(srcdir)/../../../../../../bsps/shared/shared-sources.am
    6355include $(srcdir)/../../../../../../bsps/m68k/genmcf548x/headers.am
  • c/src/lib/libbsp/powerpc/ss555/Makefile.am

    r70357f1 re518323  
    5252librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
    5353librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c
     54librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c
    5455librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c
     56librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c
    5557librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c
     58librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c
    5659librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c
    5760librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c
  • spec/build/bsps/m68k/genmcf548x/grp.yml

    r70357f1 re518323  
    2929  uid: ../../obj
    3030- role: build-dependency
     31  uid: ../../objirq
     32- role: build-dependency
    3133  uid: ../../optconsolebaud
    3234- role: build-dependency
  • spec/build/bsps/m68k/genmcf548x/obj.yml

    r70357f1 re518323  
    3939- bsps/m68k/shared/memProbe.c
    4040- bsps/shared/dev/getentropy/getentropy-cpucounter.c
    41 - bsps/shared/irq/irq-affinity.c
    42 - bsps/shared/irq/irq-raise-clear.c
    4341- bsps/shared/irq/irq-default-handler.c
    44 - bsps/shared/irq/irq-enable-disable.c
    45 - bsps/shared/irq/irq-handler-iterate.c
    46 - bsps/shared/irq/irq-info.c
    47 - bsps/shared/irq/irq-legacy.c
    48 - bsps/shared/irq/irq-lock.c
    49 - bsps/shared/irq/irq-server.c
    50 - bsps/shared/irq/irq-shell.c
    5142- bsps/shared/start/bspfatal-default.c
    5243- bsps/shared/start/bspgetworkarea-default.c
  • spec/build/bsps/objirq.yml

    r70357f1 re518323  
    1414- bsps/shared/irq/irq-raise-clear.c
    1515- bsps/shared/irq/irq-enable-disable.c
     16- bsps/shared/irq/irq-entry-remove.c
    1617- bsps/shared/irq/irq-generic.c
     18- bsps/shared/irq/irq-handler-install.c
    1719- bsps/shared/irq/irq-handler-iterate.c
     20- bsps/shared/irq/irq-handler-remove.c
    1821- bsps/shared/irq/irq-info.c
    1922- bsps/shared/irq/irq-legacy.c
  • spec/build/bsps/powerpc/ss555/bspss555.yml

    r70357f1 re518323  
    7373- bsps/shared/irq/irq-default.c
    7474- bsps/shared/irq/irq-enable-disable.c
     75- bsps/shared/irq/irq-entry-remove.c
    7576- bsps/shared/irq/irq-generic.c
     77- bsps/shared/irq/irq-handler-install.c
    7678- bsps/shared/irq/irq-handler-iterate.c
     79- bsps/shared/irq/irq-handler-remove.c
    7780- bsps/shared/irq/irq-info.c
    7881- bsps/shared/irq/irq-lock.c
Note: See TracChangeset for help on using the changeset viewer.