source: rtems/bsps/shared/irq/irq-generic.c

Last change on this file was 5b22003, checked in by Kinsey Moore <kinsey.moore@…>, on 10/12/23 at 18:14:59

bsps: Remove unused includes

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSImplClassicIntr
7 *
8 * @brief This source file contains the generic interrupt controller support
9 *   implementation.
10 */
11
12/*
13 * Copyright (C) 2008, 2021 embedded brains GmbH & Co. KG
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <bsp/irq-generic.h>
38
39#include <rtems/malloc.h>
40
41#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
42  bsp_interrupt_dispatch_index_type bsp_interrupt_dispatch_index_table
43    [BSP_INTERRUPT_VECTOR_COUNT];
44#endif
45
46rtems_interrupt_entry *
47bsp_interrupt_dispatch_table[ BSP_INTERRUPT_DISPATCH_TABLE_SIZE ];
48
49RTEMS_WEAK rtems_interrupt_entry **bsp_interrupt_get_dispatch_table_slot(
50  rtems_vector_number index
51)
52{
53  return &bsp_interrupt_dispatch_table[ index ];
54}
55
56/* The last entry indicates if everything is initialized */
57uint8_t bsp_interrupt_handler_unique_table
58  [ ( BSP_INTERRUPT_DISPATCH_TABLE_SIZE + 7 + 1 ) / 8 ];
59
60static inline void bsp_interrupt_set_initialized(void)
61{
62  bsp_interrupt_set_handler_unique(BSP_INTERRUPT_DISPATCH_TABLE_SIZE, true);
63}
64
65#if defined(BSP_INTERRUPT_USE_INDEX_TABLE)
66static inline rtems_vector_number bsp_interrupt_allocate_handler_index( void )
67{
68  rtems_vector_number i;
69
70  /* The first entry will remain empty */
71  for ( i = 1; i < BSP_INTERRUPT_DISPATCH_TABLE_SIZE; ++i ) {
72    if (  bsp_interrupt_dispatch_table[ i ] == NULL ) {
73      break;
74    }
75  }
76
77  return i;
78}
79#endif
80
81#if defined(RTEMS_SMP)
82RTEMS_STATIC_ASSERT(
83  sizeof( Atomic_Uintptr ) == sizeof( rtems_interrupt_entry * ),
84  rtems_interrupt_entry_pointer_size
85);
86
87void bsp_interrupt_spurious( rtems_vector_number vector )
88{
89  Atomic_Uintptr        *ptr;
90  rtems_interrupt_entry *first;
91
92  /*
93   * In order to get the last written pointer value to the first entry, we have
94   * to carry out an atomic read-modify-write operation.
95   */
96  ptr = (Atomic_Uintptr *) bsp_interrupt_get_dispatch_table_slot(
97    bsp_interrupt_dispatch_index( vector )
98  );
99  first = (rtems_interrupt_entry *)
100    _Atomic_Fetch_add_uintptr( ptr, 0, ATOMIC_ORDER_ACQUIRE );
101
102  if ( first == NULL ) {
103    bsp_interrupt_handler_default( vector );
104  } else {
105    bsp_interrupt_dispatch_entries( first );
106  }
107}
108#endif
109
110rtems_status_code bsp_interrupt_check_and_lock(
111  rtems_vector_number     vector,
112  rtems_interrupt_handler routine
113)
114{
115  if ( !bsp_interrupt_is_initialized() ) {
116    return RTEMS_INCORRECT_STATE;
117  }
118
119  if ( routine == NULL ) {
120    return RTEMS_INVALID_ADDRESS;
121  }
122
123  if ( !bsp_interrupt_is_valid_vector( vector ) ) {
124    return RTEMS_INVALID_ID;
125  }
126
127  if ( rtems_interrupt_is_in_progress() ) {
128    return RTEMS_CALLED_FROM_ISR;
129  }
130
131  bsp_interrupt_lock();
132
133  return RTEMS_SUCCESSFUL;
134}
135
136rtems_interrupt_entry *bsp_interrupt_entry_find(
137  rtems_vector_number      vector,
138  rtems_interrupt_handler  routine,
139  void                    *arg,
140  rtems_interrupt_entry ***previous_next
141)
142{
143  rtems_vector_number    index;
144  rtems_interrupt_entry *entry;
145
146  bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
147  index = bsp_interrupt_dispatch_index( vector );
148  *previous_next = bsp_interrupt_get_dispatch_table_slot( index );
149  entry = **previous_next;
150
151  while ( entry != NULL ) {
152    if ( entry->handler == routine && entry->arg == arg ) {
153      return entry;
154    }
155
156    *previous_next = &entry->next;
157    entry = entry->next;
158  }
159
160  return NULL;
161}
162
163void bsp_interrupt_initialize( void )
164{
165  bsp_interrupt_facility_initialize();
166  bsp_interrupt_set_initialized();
167}
168
169static rtems_status_code bsp_interrupt_entry_install_first(
170  rtems_vector_number       vector,
171  rtems_option              options,
172  rtems_interrupt_entry    *entry
173)
174{
175  rtems_vector_number index;
176
177#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
178  index = bsp_interrupt_allocate_handler_index();
179
180  if ( index == BSP_INTERRUPT_DISPATCH_TABLE_SIZE ) {
181    /* Handler table is full */
182    return RTEMS_NO_MEMORY;
183  }
184#else
185  index = vector;
186#endif
187
188#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
189  bsp_interrupt_dispatch_index_table[ vector ] = index;
190#endif
191  bsp_interrupt_entry_store_release(
192    bsp_interrupt_get_dispatch_table_slot( index ),
193    entry
194  );
195
196  bsp_interrupt_set_handler_unique(
197    index,
198    RTEMS_INTERRUPT_IS_UNIQUE( options )
199  );
200#if defined(bsp_interrupt_vector_install)
201  bsp_interrupt_vector_install( vector );
202#else
203  bsp_interrupt_vector_enable( vector );
204#endif
205
206  return RTEMS_SUCCESSFUL;
207}
208
209static rtems_status_code bsp_interrupt_entry_install(
210  rtems_vector_number    vector,
211  rtems_option           options,
212  rtems_interrupt_entry *entry
213)
214{
215  rtems_vector_number     index;
216  rtems_interrupt_entry  *first;
217  rtems_interrupt_entry  *other;
218  rtems_interrupt_entry **previous_next;
219
220  if ( RTEMS_INTERRUPT_IS_REPLACE( options ) ) {
221    return RTEMS_INVALID_NUMBER;
222  }
223
224  index = bsp_interrupt_dispatch_index( vector );
225  first = *bsp_interrupt_get_dispatch_table_slot( index );
226
227  if ( first == NULL ) {
228    return bsp_interrupt_entry_install_first( vector, options, entry );
229  }
230
231  if ( RTEMS_INTERRUPT_IS_UNIQUE( options ) ) {
232    /* Cannot install a unique entry if there is already an entry installed */
233    return RTEMS_RESOURCE_IN_USE;
234  }
235
236  if ( bsp_interrupt_is_handler_unique( index ) ) {
237    /*
238     * Cannot install another entry if there is already an unique entry
239     * installed.
240     */
241    return RTEMS_RESOURCE_IN_USE;
242  }
243
244  other = bsp_interrupt_entry_find(
245    vector,
246    entry->handler,
247    entry->arg,
248    &previous_next
249  );
250
251  if ( other != NULL ) {
252    /*
253     * Cannot install an entry which has the same routine and argument as an
254     * already installed entry.
255     */
256    return RTEMS_TOO_MANY;
257  }
258
259  bsp_interrupt_entry_store_release( previous_next, entry );
260
261  return RTEMS_SUCCESSFUL;
262}
263
264rtems_status_code rtems_interrupt_entry_install(
265  rtems_vector_number    vector,
266  rtems_option           options,
267  rtems_interrupt_entry *entry
268)
269{
270  rtems_status_code sc;
271
272  if ( entry == NULL ) {
273    return RTEMS_INVALID_ADDRESS;
274  }
275
276  sc = bsp_interrupt_check_and_lock( vector, entry->handler );
277
278  if ( sc != RTEMS_SUCCESSFUL ) {
279    return sc;
280  }
281
282  sc = bsp_interrupt_entry_install( vector, options, entry );
283  bsp_interrupt_unlock();
284
285  return sc;
286}
Note: See TracBrowser for help on using the repository browser.