From: Pavel Pisa <p...@cmp.felk.cvut.cz> The global state of enabled and disabled interrupts has to hold interrupts really disabled by drivers and system. If the state is combined with interrupts temporarily disabled because they are processed at given time then it is impossible to maintain state by interrupt handlers in drivers. --- c/src/lib/libbsp/i386/shared/irq/irq.c | 51 +++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 19 deletions(-)
diff --git a/c/src/lib/libbsp/i386/shared/irq/irq.c b/c/src/lib/libbsp/i386/shared/irq/irq.c index 0511257..8316fe6 100644 --- a/c/src/lib/libbsp/i386/shared/irq/irq.c +++ b/c/src/lib/libbsp/i386/shared/irq/irq.c @@ -51,7 +51,22 @@ static enum intr_trigger irq_trigger[BSP_IRQ_LINES_NUMBER]; * while upper bits are interrupt on the slave PIC. * This cache is initialized in ldseg.s */ -static rtems_i8259_masks i8259a_cache = 0xFFFB; +static rtems_i8259_masks i8259a_imr_cache = 0xFFFB; +static rtems_i8259_masks i8259a_in_progress = 0; + +static inline +void BSP_i8259a_irq_update_master_imr( void ) +{ + rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache; + outport_byte( PIC_MASTER_IMR_IO_PORT, mask & 0xff ); +} + +static inline +void BSP_i8259a_irq_update_slave_imr( void ) +{ + rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache; + outport_byte( PIC_SLAVE_IMR_IO_PORT, ( mask >> 8 ) & 0xff ); +} /* * Print the stats. @@ -107,7 +122,7 @@ static inline uint8_t BSP_i8259a_irq_in_service_reg(uint32_t ioport) /*-------------------------------------------------------------------------+ | Function: BSP_irq_disable_at_i8259a | Description: Mask IRQ line in appropriate PIC chip. -| Global Variables: i8259a_cache +| Global Variables: i8259a_imr_cache, i8259a_in_progress | Arguments: vector_offset - number of IRQ line to mask. | Returns: 0 is OK. +--------------------------------------------------------------------------*/ @@ -119,15 +134,15 @@ static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine) rtems_interrupt_disable(level); mask = 1 << irqLine; - i8259a_cache |= mask; + i8259a_imr_cache |= mask; if (irqLine < 8) { - outport_byte(PIC_MASTER_IMR_IO_PORT, i8259a_cache & 0xff); + BSP_i8259a_irq_update_master_imr(); } else { - outport_byte(PIC_SLAVE_IMR_IO_PORT, (i8259a_cache >> 8) & 0xff); + BSP_i8259a_irq_update_slave_imr(); } rtems_interrupt_enable(level); @@ -138,7 +153,7 @@ static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine) /*-------------------------------------------------------------------------+ | Function: BSP_irq_enable_at_i8259a | Description: Unmask IRQ line in appropriate PIC chip. -| Global Variables: i8259a_cache +| Global Variables: i8259a_imr_cache, i8259a_in_progress | Arguments: irqLine - number of IRQ line to mask. | Returns: Nothing. +--------------------------------------------------------------------------*/ @@ -152,19 +167,19 @@ static int BSP_irq_enable_at_i8259a(const rtems_irq_number irqLine) rtems_interrupt_disable(level); mask = 1 << irqLine; - i8259a_cache &= ~mask; + i8259a_imr_cache &= ~mask; if (irqLine < 8) { isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT); irr = BSP_i8259a_irq_int_request_reg(PIC_MASTER_COMMAND_IO_PORT); - outport_byte(PIC_MASTER_IMR_IO_PORT, i8259a_cache & 0xff); + BSP_i8259a_irq_update_master_imr(); } else { isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT); irr = BSP_i8259a_irq_int_request_reg(PIC_SLAVE_COMMAND_IO_PORT); - outport_byte(PIC_SLAVE_IMR_IO_PORT, (i8259a_cache >> 8) & 0xff); + BSP_i8259a_irq_update_slave_imr(); } if (((isr ^ irr) & mask) != 0) @@ -298,7 +313,7 @@ void BSP_dispatch_isr(int vector); void BSP_dispatch_isr(int vector) { - uint16_t old_imr = 0; + rtems_i8259_masks in_progress_save = 0; if (vector < BSP_IRQ_VECTOR_NUMBER) { /* @@ -329,10 +344,10 @@ void BSP_dispatch_isr(int vector) * vector clear. */ if (vector <= BSP_IRQ_MAX_ON_i8259A) { - old_imr = i8259a_cache; - i8259a_cache |= irq_mask_or_tbl[vector]; - outport_byte(PIC_MASTER_IMR_IO_PORT, i8259a_cache & 0xff); - outport_byte(PIC_SLAVE_IMR_IO_PORT, (i8259a_cache >> 8) & 0xff); + in_progress_save = i8259a_in_progress; + i8259a_in_progress |= irq_mask_or_tbl[vector]; + BSP_i8259a_irq_update_master_imr(); + BSP_i8259a_irq_update_slave_imr(); } /* @@ -365,11 +380,9 @@ void BSP_dispatch_isr(int vector) * again. */ if (vector <= BSP_IRQ_MAX_ON_i8259A) { - if (irq_trigger[vector] == INTR_TRIGGER_LEVEL) - old_imr |= 1 << vector; - i8259a_cache = old_imr; - outport_byte(PIC_MASTER_IMR_IO_PORT, i8259a_cache & 0xff); - outport_byte(PIC_SLAVE_IMR_IO_PORT, (i8259a_cache >> 8) & 0xff); + i8259a_in_progress = in_progress_save; + BSP_i8259a_irq_update_master_imr(); + BSP_i8259a_irq_update_slave_imr(); } } } -- 1.9.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel