00001 /* 00002 * 00003 * This include file describe the data structure and the functions implemented 00004 * by rtems to write interrupt handlers. 00005 * 00006 * CopyRight (C) 1998 valette@crf.canon.fr 00007 * 00008 * This code is heavilly inspired by the public specification of STREAM V2 00009 * that can be found at : 00010 * 00011 * <http://www.chorus.com/Documentation/index.html> by following 00012 * the STREAM API Specification Document link. 00013 * 00014 * The license and distribution terms for this file may be 00015 * found in found in the file LICENSE in this distribution or at 00016 * http://www.rtems.com/license/LICENSE. 00017 * 00018 * $Id: irq.h,v 1.2 2005/10/31 14:14:32 ralf Exp $ 00019 */ 00020 00021 #ifndef _RTEMS_IRQ_H 00022 #define _RTEMS_IRQ_H 00023 00024 #ifndef ASM 00025 00026 #ifdef __cplusplus 00027 extern "C" { 00028 #endif 00029 00030 00031 /* 00032 * Type definition for RTEMS managed interrupts 00033 */ 00034 typedef unsigned char rtems_irq_prio; 00035 struct __rtems_irq_connect_data__; /* forward declaratiuon */ 00036 00037 typedef unsigned int rtems_irq_number; 00038 typedef void *rtems_irq_hdl_param; 00039 typedef void (*rtems_irq_hdl) (rtems_irq_hdl_param); 00040 typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*); 00041 typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*); 00042 typedef int (*rtems_irq_is_enabled) (const struct __rtems_irq_connect_data__*); 00043 00044 typedef struct __rtems_irq_connect_data__ { 00045 /* 00046 * IRQ line 00047 */ 00048 rtems_irq_number name; 00049 /* 00050 * handler. See comment on handler properties below in function prototype. 00051 */ 00052 rtems_irq_hdl hdl; 00053 /* 00054 * Handler handle to store private data 00055 */ 00056 rtems_irq_hdl_param handle; 00057 /* 00058 * function for enabling interrupts at device level (ONLY!). 00059 * The BSP code will automatically enable it at i8259s level. 00060 * RATIONALE : anyway such code has to exist in current driver code. 00061 * It is usually called immediately AFTER connecting the interrupt handler. 00062 * RTEMS may well need such a function when restoring normal interrupt 00063 * processing after a debug session. 00064 * 00065 */ 00066 rtems_irq_enable on; 00067 /* 00068 * function for disabling interrupts at device level (ONLY!). 00069 * The code will disable it at i8259s level. RATIONALE : anyway 00070 * such code has to exist for clean shutdown. It is usually called 00071 * BEFORE disconnecting the interrupt. RTEMS may well need such 00072 * a function when disabling normal interrupt processing for 00073 * a debug session. May well be a NOP function. 00074 */ 00075 rtems_irq_disable off; 00076 /* 00077 * function enabling to know what interrupt may currently occur 00078 * if someone manipulates the i8259s interrupt mask without care... 00079 */ 00080 rtems_irq_is_enabled isOn; 00081 00082 #ifdef BSP_SHARED_HANDLER_SUPPORT 00083 /* 00084 * Set to -1 for vectors forced to have only 1 handler 00085 */ 00086 void *next_handler; 00087 #endif 00088 00089 } rtems_irq_connect_data; 00090 00091 #define RTEMS_IRQ_SINGLE_HANDLER ((void *) -1) 00092 00093 #ifdef BSP_SHARED_HANDLER_SUPPORT 00094 #define RTEMS_IRQ_CONNECT_DATA_DEFAULT { \ 00095 .name = -1, \ 00096 .hdl = NULL, \ 00097 .handle = NULL, \ 00098 .on = NULL, \ 00099 .off = NULL, \ 00100 .isOn = NULL, \ 00101 .next_handler = RTEMS_IRQ_SINGLE_HANDLER \ 00102 }; 00103 #define RTEMS_IRQ_SET_NEXT_HANDLER( cd, next) (cd)->next_handler = next 00104 #define RTEMS_IRQ_GET_NEXT_HANDLER( cd) (cd)->next_handler 00105 #else /* BSP_SHARED_HANDLER_SUPPORT */ 00106 #define RTEMS_IRQ_CONNECT_DATA_DEFAULT { \ 00107 .name = -1, \ 00108 .hdl = NULL, \ 00109 .handle = NULL, \ 00110 .on = NULL, \ 00111 .off = NULL, \ 00112 .isOn = NULL \ 00113 }; 00114 #define RTEMS_IRQ_SET_NEXT_HANDLER( cd, next) 00115 #define RTEMS_IRQ_GET_NEXT_HANDLER( cd) RTEMS_IRQ_SINGLE_HANDLER 00116 #endif /* BSP_SHARED_HANDLER_SUPPORT */ 00117 #define RTEMS_IRQ_IS_SINGLE_HANDLER( cd) (RTEMS_IRQ_GET_NEXT_HANDLER( cd) == RTEMS_IRQ_SINGLE_HANDLER) 00118 #define RTEMS_IRQ_MAKE_SINGLE_HANDLER( cd) RTEMS_IRQ_SET_NEXT_HANDLER( cd, RTEMS_IRQ_SINGLE_HANDLER) 00119 00120 typedef struct { 00121 /* 00122 * size of all the table fields (*Tbl) described below. 00123 */ 00124 unsigned int irqNb; 00125 /* 00126 * Default handler used when disconnecting interrupts. 00127 */ 00128 rtems_irq_connect_data defaultEntry; 00129 /* 00130 * Table containing initials/current value. 00131 */ 00132 rtems_irq_connect_data* irqHdlTbl; 00133 /* 00134 * actual value of BSP_ISA_IRQ_VECTOR_BASE... 00135 */ 00136 rtems_irq_number irqBase; 00137 /* 00138 * software priorities associated with interrupts. 00139 * if (*irqPrio [i] > intrPrio [j] it means that 00140 * interrupt handler hdl connected for interrupt name i 00141 * will not be interrupted by the handler connected for interrupt j 00142 * The interrupt source will be physically masked at i8259 level. 00143 */ 00144 rtems_irq_prio* irqPrioTbl; 00145 } rtems_irq_global_settings; 00146 00147 /*-------------------------------------------------------------------------+ 00148 | Function Prototypes. 00149 +--------------------------------------------------------------------------*/ 00150 /* 00151 * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- 00152 */ 00153 /* 00154 * function to connect a particular irq handler. This hanlder will NOT be called 00155 * directly as the result of the corresponding interrupt. Instead, a RTEMS 00156 * irq prologue will be called that will : 00157 * 00158 * 1) save the C scratch registers, 00159 * 2) switch to a interrupt stack if the interrupt is not nested, 00160 * 3) store the current i8259s' interrupt masks 00161 * 4) modify them to disable the current interrupt at 8259 level (and may 00162 * be others depending on software priorities) 00163 * 5) aknowledge the i8259s', 00164 * 6) demask the processor, 00165 * 7) call the application handler 00166 * 00167 * As a result the hdl function provided 00168 * 00169 * a) can perfectly be written is C, 00170 * b) may also well directly call the part of the RTEMS API that can be used 00171 * from interrupt level, 00172 * c) It only responsible for handling the jobs that need to be done at 00173 * the device level including (aknowledging/re-enabling the interrupt at device, 00174 * level, getting the data,...) 00175 * 00176 * When returning from the function, the following will be performed by 00177 * the RTEMS irq epilogue : 00178 * 00179 * 1) masks the interrupts again, 00180 * 2) restore the original i8259s' interrupt masks 00181 * 3) switch back on the orinal stack if needed, 00182 * 4) perform rescheduling when necessary, 00183 * 5) restore the C scratch registers... 00184 * 6) restore initial execution flow 00185 * 00186 */ 00187 int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*); 00188 /* 00189 * function to get the current RTEMS irq handler for ptr->name. It enables to 00190 * define hanlder chain... 00191 */ 00192 int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr); 00193 /* 00194 * function to get disconnect the RTEMS irq handler for ptr->name. 00195 * This function checks that the value given is the current one for safety reason. 00196 * The user can use the previous function to get it. 00197 */ 00198 int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data*); 00199 00200 00201 /* 00202 * ------------------------ RTEMS Shared Irq Handler Mngt Routines ---------------- 00203 */ 00204 #ifdef BSP_SHARED_HANDLER_SUPPORT 00205 int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data*); 00206 #endif 00207 00208 00209 /* 00210 * ------------------------ RTEMS Global Irq Handler Mngt Routines ---------------- 00211 */ 00212 /* 00213 * (Re) Initialize the RTEMS interrupt management. 00214 * 00215 * The result of calling this function will be the same as if each individual 00216 * handler (config->irqHdlTbl[i].hdl) different from "config->defaultEntry.hdl" 00217 * has been individualy connected via 00218 * BSP_install_rtems_irq_handler(&config->irqHdlTbl[i]) 00219 * And each handler currently equal to config->defaultEntry.hdl 00220 * has been previously disconnected via 00221 * BSP_remove_rtems_irq_handler (&config->irqHdlTbl[i]) 00222 * 00223 * This is to say that all information given will be used and not just 00224 * only the space. 00225 * 00226 * CAUTION : the various table address contained in config will be used 00227 * directly by the interrupt mangement code in order to save 00228 * data size so they must stay valid after the call => they should 00229 * not be modified or declared on a stack. 00230 */ 00231 00232 int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config); 00233 /* 00234 * (Re) get info on current RTEMS interrupt management. 00235 */ 00236 int BSP_rtems_irq_mngt_get(rtems_irq_global_settings**); 00237 00238 #include <rtems.h> 00239 00249 typedef void (*rtems_interrupt_handler)( void *); 00250 00261 rtems_status_code bsp_interrupt_handler_install( rtems_vector_number vector, rtems_interrupt_handler handler, void *arg, rtems_boolean shared); 00262 00263 rtems_status_code bsp_interrupt_handler_remove( rtems_vector_number vector, rtems_interrupt_handler handler); 00264 00295 static inline rtems_status_code rtems_interrupt_handler_install( rtems_vector_number vector, rtems_interrupt_handler handler, void *arg) 00296 { 00297 return bsp_interrupt_handler_install( vector, handler, arg, TRUE); 00298 } 00299 00321 static inline rtems_status_code rtems_interrupt_handler_unique_install( rtems_vector_number vector, rtems_interrupt_handler handler, void *arg) 00322 { 00323 return bsp_interrupt_handler_install( vector, handler, arg, FALSE); 00324 } 00325 00342 static inline rtems_status_code rtems_interrupt_handler_remove( rtems_vector_number vector, rtems_interrupt_handler handler) 00343 { 00344 return bsp_interrupt_handler_remove( vector, handler); 00345 } 00346 00349 #ifdef __cplusplus 00350 } 00351 #endif 00352 00353 #endif /* ASM */ 00354 #endif /* _RTEMS_IRQ_H */