File indexing completed on 2025-05-11 08:23:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <bsp.h>
0015 #include <bsp/irq.h>
0016 #include <bsp/irq-generic.h>
0017 #include <rtems/score/cpu.h>
0018 #include <rtems/score/processormaskimpl.h>
0019
0020 #include <stdlib.h>
0021 #include <stdio.h>
0022 #include <inttypes.h>
0023
0024
0025 #include "elcr.h"
0026
0027 RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_i8259_access_lock, "rtems_i8259_access_lock" );
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 static rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_LINES_NUMBER];
0038
0039
0040
0041
0042 static uint32_t irq_count[BSP_IRQ_VECTOR_NUMBER] = {0};
0043 static uint32_t spurious_count;
0044
0045
0046
0047
0048 static enum intr_trigger irq_trigger[BSP_IRQ_LINES_NUMBER];
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 static rtems_i8259_masks i8259a_imr_cache = 0xFFFB;
0059 static rtems_i8259_masks i8259a_in_progress = 0;
0060
0061 static inline
0062 void BSP_i8259a_irq_update_master_imr( void )
0063 {
0064 rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache;
0065 outport_byte( PIC_MASTER_IMR_IO_PORT, mask & 0xff );
0066 }
0067
0068 static inline
0069 void BSP_i8259a_irq_update_slave_imr( void )
0070 {
0071 rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache;
0072 outport_byte( PIC_SLAVE_IMR_IO_PORT, ( mask >> 8 ) & 0xff );
0073 }
0074
0075
0076
0077
0078 uint32_t BSP_irq_count_dump(FILE *f)
0079 {
0080 uint32_t tot = 0;
0081 int i;
0082 if ( !f )
0083 f = stdout;
0084 fprintf(f,"SPURIOUS: %9"PRIu32"\n", spurious_count);
0085 for ( i = 0; i < BSP_IRQ_VECTOR_NUMBER; i++ ) {
0086 char type = '-';
0087 if (i < BSP_IRQ_LINES_NUMBER)
0088 type = irq_trigger[i] == INTR_TRIGGER_EDGE ? 'E' : 'L';
0089 tot += irq_count[i];
0090 fprintf(f,"IRQ %2u: %c %9"PRIu32"\n", i, type, irq_count[i]);
0091 }
0092 return tot;
0093 }
0094
0095
0096
0097
0098 static inline bool BSP_i8259a_irq_valid(const rtems_irq_number irqLine)
0099 {
0100 return ((int)irqLine >= BSP_IRQ_VECTOR_LOWEST_OFFSET) &&
0101 ((int)irqLine <= BSP_IRQ_MAX_ON_i8259A);
0102 }
0103
0104
0105
0106
0107 static inline uint8_t BSP_i8259a_irq_int_request_reg(uint32_t ioport)
0108 {
0109 uint8_t isr;
0110 inport_byte(ioport, isr);
0111 return isr;
0112 }
0113
0114
0115
0116
0117 static inline uint8_t BSP_i8259a_irq_in_service_reg(uint32_t ioport)
0118 {
0119 uint8_t isr;
0120 outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR | PIC_OCW3_RIS);
0121 inport_byte(ioport, isr);
0122 outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR);
0123 return isr;
0124 }
0125
0126
0127
0128
0129
0130
0131
0132
0133 static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine)
0134 {
0135 unsigned short mask;
0136 rtems_interrupt_lock_context lock_context;
0137
0138 rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
0139
0140 mask = 1 << irqLine;
0141 i8259a_imr_cache |= mask;
0142
0143 if (irqLine < 8)
0144 {
0145 BSP_i8259a_irq_update_master_imr();
0146 }
0147 else
0148 {
0149 BSP_i8259a_irq_update_slave_imr();
0150 }
0151
0152 rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
0153
0154 return 0;
0155 }
0156
0157
0158
0159
0160
0161
0162
0163
0164 static int BSP_irq_enable_at_i8259a(const rtems_irq_number irqLine)
0165 {
0166 unsigned short mask;
0167 rtems_interrupt_lock_context lock_context;
0168 uint8_t isr;
0169 uint8_t irr;
0170
0171 rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
0172
0173 mask = 1 << irqLine;
0174 i8259a_imr_cache &= ~mask;
0175
0176 if (irqLine < 8)
0177 {
0178 isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT);
0179 irr = BSP_i8259a_irq_int_request_reg(PIC_MASTER_COMMAND_IO_PORT);
0180 BSP_i8259a_irq_update_master_imr();
0181 }
0182 else
0183 {
0184 isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT);
0185 irr = BSP_i8259a_irq_int_request_reg(PIC_SLAVE_COMMAND_IO_PORT);
0186 BSP_i8259a_irq_update_slave_imr();
0187 }
0188
0189 if (((isr ^ irr) & mask) != 0)
0190 printk("i386: isr=%x irr=%x\n", isr, irr);
0191
0192 rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
0193
0194 return 0;
0195 }
0196
0197
0198
0199
0200
0201
0202
0203
0204 static int BSP_irq_ack_at_i8259a(const rtems_irq_number irqLine)
0205 {
0206 uint8_t slave_isr = 0;
0207
0208 if (irqLine >= 8) {
0209 outport_byte(PIC_SLAVE_COMMAND_IO_PORT, PIC_EOI);
0210 slave_isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT);
0211 }
0212
0213
0214
0215
0216
0217
0218 if (slave_isr == 0)
0219 outport_byte(PIC_MASTER_COMMAND_IO_PORT, PIC_EOI);
0220
0221 return 0;
0222
0223 }
0224
0225
0226
0227
0228
0229 static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={
0230
0231
0232
0233
0234
0235
0236
0237
0238 0,0,
0239 255,
0240 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0241 };
0242
0243 static void compute_i8259_masks_from_prio (void)
0244 {
0245 rtems_interrupt_lock_context lock_context;
0246 unsigned int i;
0247 unsigned int j;
0248
0249 rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
0250
0251
0252
0253
0254 for (i=0; i < BSP_IRQ_LINES_NUMBER; i++) {
0255 * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
0256 for (j = 0; j < BSP_IRQ_LINES_NUMBER; j++) {
0257
0258
0259
0260 if (irqPrioTable [i] > irqPrioTable [j]) {
0261 * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
0262 }
0263 }
0264 }
0265
0266 rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
0267 }
0268
0269 static inline bool bsp_interrupt_vector_is_valid(rtems_vector_number vector)
0270 {
0271 return BSP_i8259a_irq_valid((const rtems_irq_number) vector);
0272 }
0273
0274 rtems_status_code bsp_interrupt_get_attributes(
0275 rtems_vector_number vector,
0276 rtems_interrupt_attributes *attributes
0277 )
0278 {
0279 return RTEMS_SUCCESSFUL;
0280 }
0281
0282 rtems_status_code bsp_interrupt_is_pending(
0283 rtems_vector_number vector,
0284 bool *pending
0285 )
0286 {
0287 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0288 bsp_interrupt_assert(pending != NULL);
0289 *pending = false;
0290 return RTEMS_UNSATISFIED;
0291 }
0292
0293 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0294 {
0295 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0296 return RTEMS_UNSATISFIED;
0297 }
0298
0299 #if defined(RTEMS_SMP)
0300 rtems_status_code bsp_interrupt_raise_on(
0301 rtems_vector_number vector,
0302 uint32_t cpu_index
0303 )
0304 {
0305 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0306 return RTEMS_UNSATISFIED;
0307 }
0308 #endif
0309
0310 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0311 {
0312 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0313 return RTEMS_UNSATISFIED;
0314 }
0315
0316 rtems_status_code bsp_interrupt_vector_is_enabled(
0317 rtems_vector_number vector,
0318 bool *enabled
0319 )
0320 {
0321 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0322 bsp_interrupt_assert(enabled != NULL);
0323 *enabled = false;
0324 return RTEMS_UNSATISFIED;
0325 }
0326
0327 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0328 {
0329 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0330 BSP_irq_enable_at_i8259a(vector);
0331 return RTEMS_SUCCESSFUL;
0332 }
0333
0334 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0335 {
0336 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0337 BSP_irq_disable_at_i8259a(vector);
0338 return RTEMS_SUCCESSFUL;
0339 }
0340
0341 rtems_status_code bsp_interrupt_set_priority(
0342 rtems_vector_number vector,
0343 uint32_t priority
0344 )
0345 {
0346 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0347 return RTEMS_UNSATISFIED;
0348 }
0349
0350 rtems_status_code bsp_interrupt_get_priority(
0351 rtems_vector_number vector,
0352 uint32_t *priority
0353 )
0354 {
0355 bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0356 bsp_interrupt_assert(priority != NULL);
0357 return RTEMS_UNSATISFIED;
0358 }
0359
0360 #if defined(RTEMS_SMP)
0361 rtems_status_code bsp_interrupt_get_affinity(
0362 rtems_vector_number vector,
0363 Processor_mask *affinity
0364 )
0365 {
0366 (void) vector;
0367 _Processor_mask_From_index( affinity, 0 );
0368 return RTEMS_UNSATISFIED;
0369 }
0370
0371 rtems_status_code bsp_interrupt_set_affinity(
0372 rtems_vector_number vector,
0373 const Processor_mask *affinity
0374 )
0375 {
0376 (void) vector;
0377 (void) affinity;
0378 return RTEMS_UNSATISFIED;
0379 }
0380 #endif
0381
0382 void bsp_interrupt_facility_initialize(void)
0383 {
0384 int i;
0385
0386
0387
0388
0389 compute_i8259_masks_from_prio();
0390
0391
0392
0393
0394 BSP_irq_enable_at_i8259a(2);
0395
0396
0397
0398
0399 elcr_probe();
0400
0401 for (i = 0; i < BSP_IRQ_LINES_NUMBER; i++)
0402 irq_trigger[i] = elcr_read_trigger(i);
0403 }
0404
0405 static bool bsp_interrupt_handler_is_empty(rtems_vector_number vector)
0406 {
0407 return bsp_interrupt_entry_load_first(vector) == NULL;
0408 }
0409
0410
0411
0412
0413 void BSP_dispatch_isr(int vector);
0414
0415 void BSP_dispatch_isr(int vector)
0416 {
0417 rtems_interrupt_lock_context lock_context;
0418 rtems_i8259_masks in_progress_save = 0;
0419
0420 if (vector < BSP_IRQ_VECTOR_NUMBER) {
0421
0422
0423
0424 if (vector <= BSP_IRQ_MAX_ON_i8259A) {
0425
0426 rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context);
0427
0428
0429
0430
0431 if ((vector == 7 || vector == 15)) {
0432
0433
0434
0435 if (bsp_interrupt_handler_is_empty(vector)) {
0436
0437
0438
0439 uint8_t isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT);
0440 if ((isr & (1 << 7)) == 0) {
0441 ++spurious_count;
0442 rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
0443 return;
0444 }
0445 }
0446 }
0447
0448
0449
0450
0451
0452 if (vector <= BSP_IRQ_MAX_ON_i8259A) {
0453 in_progress_save = i8259a_in_progress;
0454 i8259a_in_progress |= irq_mask_or_tbl[vector];
0455 BSP_i8259a_irq_update_master_imr();
0456 BSP_i8259a_irq_update_slave_imr();
0457 }
0458
0459
0460
0461
0462 BSP_irq_ack_at_i8259a(vector);
0463
0464 rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
0465 }
0466
0467
0468
0469
0470 irq_count[vector]++;
0471
0472 RTEMS_COMPILER_MEMORY_BARRIER();
0473
0474
0475
0476 __asm__ __volatile__("sti");
0477
0478 bsp_interrupt_handler_dispatch(vector);
0479
0480
0481
0482
0483 __asm__ __volatile__("cli");
0484
0485 RTEMS_COMPILER_MEMORY_BARRIER();
0486
0487 if (vector <= BSP_IRQ_MAX_ON_i8259A) {
0488
0489 rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context);
0490
0491
0492
0493
0494
0495
0496 if (vector <= BSP_IRQ_MAX_ON_i8259A) {
0497 i8259a_in_progress = in_progress_save;
0498 BSP_i8259a_irq_update_master_imr();
0499 BSP_i8259a_irq_update_slave_imr();
0500 }
0501
0502 rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
0503 }
0504 }
0505 }