Hardware interrupts code path cleanup

- the PIC master and slave irq handlers don't pass the irq hook pointer but just
  the irq number. It gives a little bit more information to the C handler as the
  irq number is not lost

- the irq code path is more achitecture independent. i386 hw interrupts are
  called irq and whereever the code is arch independent enough hw_intr_
  functions are called to mask/unmask interrupts

- the legacy PIC is not the only possible interrupt controller in the x86 world,
  therefore the intr_(un)mask functions were renamed to signal their
  functionality explicitly. APIC will add their own.

- masking and unmasking PIC interrupt lines is removed from assembler and all
  the functionality is rewriten in C and moved to i8259.c

- interrupt handlers have to unmask the interrupt line if all irq handlers are
  done. Assembler does not do it anymore
This commit is contained in:
Tomas Hruby
2009-11-04 13:24:56 +00:00
parent 7e73260cf5
commit cf854041ce
6 changed files with 62 additions and 123 deletions

View File

@@ -6,7 +6,7 @@
*
* put_irq_handler: register an interrupt handler.
* rm_irq_handler: deregister an interrupt handler.
* intr_handle: handle a hardware interrupt.
* irq_handle: handle a hardware interrupt.
* called by the system dependent part when an
* external interrupt occures.
* enable_irq: enable hook for IRQ.
@@ -18,6 +18,8 @@
#include <minix/com.h>
#include <archconst.h>
#include "arch/i386/hw_intr.h"
/* number of lists of IRQ hooks, one list per supported line. */
PUBLIC irq_hook_t* irq_handlers[NR_IRQ_VECTORS] = {0};
/*===========================================================================*
@@ -29,7 +31,7 @@ PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
int id;
irq_hook_t **line;
unsigned long bitmap;
if( irq < 0 || irq >= NR_IRQ_VECTORS )
minix_panic("invalid call to put_irq_handler", irq);
@@ -60,7 +62,9 @@ PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
*
* Internal this activates the line or source of the given interrupt.
*/
intr_unmask(hook);
if((irq_actids[hook->irq] &= ~hook->id) == 0) {
hw_intr_unmask(hook->irq);
}
}
/*===========================================================================*
@@ -76,7 +80,8 @@ PUBLIC void rm_irq_handler( irq_hook_t* hook ) {
minix_panic("invalid call to rm_irq_handler", irq);
/* disable the irq. */
intr_mask(hook);
irq_actids[hook->irq] |= hook->id;
hw_intr_mask(hook->irq);
/* remove the hook. */
line = &irq_handlers[irq];
@@ -96,21 +101,27 @@ PUBLIC void rm_irq_handler( irq_hook_t* hook ) {
}
/*===========================================================================*
* intr_handle *
* irq_handle *
*===========================================================================*/
PUBLIC void intr_handle(irq_hook_t *hook)
{
/* Call the interrupt handlers for an interrupt with the given hook list.
* The assembly part of the handler has already masked the IRQ, reenabled the
* controller(s) and enabled interrupts.
/*
* The function first disables interrupt is need be and restores the state at
* the end. Before returning, it unmasks the IRQ if and only if all active ID
* bits are cleared, and restart a process.
*/
PUBLIC void irq_handle(int irq)
{
irq_hook_t * hook;
/* here we need not to get this IRQ until all the handlers had a say */
hw_intr_mask(irq);
hook = irq_handlers[irq];
/* Call list of handlers for an IRQ. */
while( hook != NULL ) {
/* For each handler in the list, mark it active by setting its ID bit,
* call the function, and unmark it if the function returns true.
*/
irq_actids[hook->irq] |= hook->id;
irq_actids[irq] |= hook->id;
/* Call the hooked function. */
if( (*hook->handler)(hook) )
@@ -119,10 +130,10 @@ PUBLIC void intr_handle(irq_hook_t *hook)
/* Next hooked function. */
hook = hook->next;
}
/* The assembly code will now disable interrupts, unmask the IRQ if and only
* if all active ID bits are cleared, and restart a process.
*/
/* reenable the IRQ only if there is no active handler */
if (irq_actids[irq] == 0)
hw_intr_unmask(irq);
}
/* Enable/Disable a interrupt line. */
@@ -130,8 +141,7 @@ PUBLIC void enable_irq(hook)
irq_hook_t* hook;
{
if((irq_actids[hook->irq] &= ~hook->id) == 0) {
intr_unmask(hook);
return;
hw_intr_unmask(hook->irq);
}
}
@@ -142,7 +152,7 @@ irq_hook_t* hook;
if(irq_actids[hook->irq] & hook->id) /* already disabled */
return 0;
irq_actids[hook->irq] |= hook->id;
intr_mask(hook);
hw_intr_mask(hook->irq);
return TRUE;
}