File indexing completed on 2025-05-11 08:23:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <stdlib.h>
0014
0015 #include <rtems.h>
0016 #include <rtems/malloc.h>
0017 #include <rtems/bspIo.h> /* for printk */
0018 #include <libcpu/spr.h>
0019 #include <bsp/irq_supp.h>
0020 #include <bsp/vectors.h>
0021
0022
0023
0024
0025 static rtems_irq_connect_data default_rtems_entry;
0026
0027
0028
0029
0030
0031 static rtems_irq_global_settings* internal_config;
0032 static rtems_irq_connect_data* rtems_hdl_tbl;
0033
0034
0035 SPR_RW(BOOKE_TSR)
0036 SPR_RW(PPC405_TSR)
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 static int C_dispatch_dec_handler_bookE (BSP_Exception_frame *frame, unsigned int excNum)
0047 {
0048
0049
0050
0051
0052
0053 if ( ppc_cpu_is_bookE()==PPC_BOOKE_405)
0054 _write_PPC405_TSR( BOOKE_TSR_DIS );
0055 else
0056 _write_BOOKE_TSR( BOOKE_TSR_DIS );
0057 return C_dispatch_irq_handler(frame, ASM_DEC_VECTOR);
0058 }
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 static int isValidInterrupt(int irq)
0070 {
0071 if ( (irq < internal_config->irqBase) || (irq >= internal_config->irqBase + internal_config->irqNb))
0072 return 0;
0073 return 1;
0074 }
0075
0076
0077
0078
0079 int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data* irq)
0080 {
0081 rtems_interrupt_level level;
0082 rtems_irq_connect_data* vchain;
0083
0084 if (!isValidInterrupt(irq->name)) {
0085 printk("Invalid interrupt vector %d\n",irq->name);
0086 return 0;
0087 }
0088
0089
0090 vchain = (rtems_irq_connect_data*) rtems_malloc(sizeof(rtems_irq_connect_data));
0091
0092 rtems_interrupt_disable(level);
0093
0094 if ( (intptr_t)rtems_hdl_tbl[irq->name].next_handler == -1 ) {
0095 rtems_interrupt_enable(level);
0096 printk("IRQ vector %d already connected to an unshared handler\n",irq->name);
0097 free(vchain);
0098 return 0;
0099 }
0100
0101
0102 vchain[0]= rtems_hdl_tbl[irq->name];
0103
0104
0105
0106
0107 rtems_hdl_tbl[irq->name] = *irq;
0108
0109
0110 rtems_hdl_tbl[irq->name].next_handler = (void *)vchain;
0111
0112
0113
0114
0115
0116
0117 BSP_enable_irq_at_pic(irq->name);
0118
0119
0120
0121
0122 if (irq->on)
0123 irq->on(irq);
0124
0125 rtems_interrupt_enable(level);
0126
0127 return 1;
0128 }
0129
0130
0131
0132
0133
0134 int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
0135 {
0136 rtems_interrupt_level level;
0137
0138 if (!isValidInterrupt(irq->name)) {
0139 printk("Invalid interrupt vector %d\n",irq->name);
0140 return 0;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149 rtems_interrupt_disable(level);
0150 if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
0151 rtems_interrupt_enable(level);
0152 printk("IRQ vector %d already connected\n",irq->name);
0153 return 0;
0154 }
0155
0156
0157
0158
0159 rtems_hdl_tbl[irq->name] = *irq;
0160 rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
0161
0162
0163
0164
0165
0166
0167 BSP_enable_irq_at_pic(irq->name);
0168
0169
0170
0171
0172 if (irq->on)
0173 irq->on(irq);
0174
0175 rtems_interrupt_enable(level);
0176
0177 return 1;
0178 }
0179
0180 int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
0181 {
0182 rtems_interrupt_level level;
0183
0184 if (!isValidInterrupt(irq->name)) {
0185 return 0;
0186 }
0187 rtems_interrupt_disable(level);
0188 *irq = rtems_hdl_tbl[irq->name];
0189 rtems_interrupt_enable(level);
0190 return 1;
0191 }
0192
0193 int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
0194 {
0195 rtems_irq_connect_data *pchain= NULL, *vchain = NULL;
0196 rtems_interrupt_level level;
0197
0198 if (!isValidInterrupt(irq->name)) {
0199 return 0;
0200 }
0201
0202
0203
0204
0205
0206
0207
0208 rtems_interrupt_disable(level);
0209 if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
0210 rtems_interrupt_enable(level);
0211 return 0;
0212 }
0213
0214 if( (intptr_t)rtems_hdl_tbl[irq->name].next_handler != -1 )
0215 {
0216 int found = 0;
0217
0218 for( (pchain= NULL, vchain = &rtems_hdl_tbl[irq->name]);
0219 (vchain->hdl != default_rtems_entry.hdl);
0220 (pchain= vchain, vchain = (rtems_irq_connect_data*)vchain->next_handler) )
0221 {
0222 if( vchain->hdl == irq->hdl )
0223 {
0224 found= -1; break;
0225 }
0226 }
0227
0228 if( !found )
0229 {
0230 rtems_interrupt_enable(level);
0231 return 0;
0232 }
0233 }
0234 else
0235 {
0236 if (rtems_hdl_tbl[irq->name].hdl != irq->hdl)
0237 {
0238 rtems_interrupt_enable(level);
0239 return 0;
0240 }
0241 }
0242
0243
0244
0245
0246 if (irq->off)
0247 irq->off(irq);
0248
0249
0250
0251
0252 if( !vchain )
0253 {
0254
0255 rtems_hdl_tbl[irq->name] = default_rtems_entry;
0256 }
0257 else
0258 {
0259 if( pchain )
0260 {
0261
0262 pchain->next_handler = vchain->next_handler;
0263 }
0264 else
0265 {
0266
0267
0268
0269 vchain = vchain->next_handler;
0270 rtems_hdl_tbl[irq->name]= *vchain;
0271 }
0272 }
0273
0274
0275 if ( rtems_hdl_tbl[irq->name].hdl == default_rtems_entry.hdl ) {
0276
0277
0278
0279
0280
0281 BSP_disable_irq_at_pic(irq->name);
0282 }
0283
0284 rtems_interrupt_enable(level);
0285
0286 free(vchain);
0287
0288 return 1;
0289 }
0290
0291
0292
0293
0294
0295
0296 static int doit(
0297 int (*p)(const rtems_irq_connect_data*),
0298 rtems_irq_number n,
0299 rtems_irq_hdl hdl,
0300 rtems_irq_hdl_param prm)
0301 {
0302 rtems_irq_connect_data xx;
0303 xx.name = n;
0304 xx.hdl = hdl;
0305 xx.handle = prm;
0306 xx.on = 0;
0307 xx.off = 0;
0308 xx.isOn = 0;
0309 return ! p(&xx);
0310 }
0311
0312 int BSP_rtems_int_connect(rtems_irq_number n, rtems_irq_hdl hdl, rtems_irq_hdl_param p)
0313 {
0314 return doit(BSP_install_rtems_shared_irq_handler, n, hdl, p);
0315 }
0316
0317 int BSP_rtems_int_disconnect(rtems_irq_number n, rtems_irq_hdl hdl, rtems_irq_hdl_param p)
0318 {
0319 return doit(BSP_remove_rtems_irq_handler, n, hdl, p);
0320 }
0321
0322
0323
0324
0325
0326
0327 int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
0328 {
0329 int i;
0330 rtems_interrupt_level level;
0331 rtems_irq_connect_data* vchain;
0332
0333
0334
0335
0336 internal_config = config;
0337 default_rtems_entry = config->defaultEntry;
0338 rtems_hdl_tbl = config->irqHdlTbl;
0339
0340 rtems_interrupt_disable(level);
0341
0342 if ( !BSP_setup_the_pic(config) ) {
0343 printk("PIC setup failed; leaving IRQs OFF\n");
0344 return 0;
0345 }
0346
0347 for ( i = config->irqBase; i < config->irqBase + config->irqNb; i++ ) {
0348 for( vchain = &rtems_hdl_tbl[i];
0349 ((intptr_t)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
0350 vchain = (rtems_irq_connect_data*)vchain->next_handler )
0351 {
0352 if (vchain->on)
0353 vchain->on(vchain);
0354 }
0355 if ( vchain != &rtems_hdl_tbl[i] ) {
0356
0357 BSP_enable_irq_at_pic(i);
0358 } else {
0359
0360
0361
0362
0363
0364
0365
0366
0367 }
0368 }
0369
0370 rtems_interrupt_enable(level);
0371
0372 {
0373 ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler);
0374
0375 if ( ppc_cpu_is_bookE() ) {
0376
0377
0378
0379
0380
0381
0382 ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_dec_handler_bookE);
0383 } else {
0384 ppc_exc_set_handler(ASM_DEC_VECTOR, C_dispatch_irq_handler);
0385 }
0386 }
0387 return 1;
0388 }
0389
0390 int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
0391 {
0392 *config = internal_config;
0393 return 0;
0394 }