Split of architecture-dependent and -independent functions for i386,
mainly in the kernel and headers. This split based on work by Ingmar Alting <iaalting@cs.vu.nl> done for his Minix PowerPC architecture port. . kernel does not program the interrupt controller directly, do any other architecture-dependent operations, or contain assembly any more, but uses architecture-dependent functions in arch/$(ARCH)/. . architecture-dependent constants and types defined in arch/$(ARCH)/include. . <ibm/portio.h> moved to <minix/portio.h>, as they have become, for now, architecture-independent functions. . int86, sdevio, readbios, and iopenable are now i386-specific kernel calls and live in arch/i386/do_* now. . i386 arch now supports even less 86 code; e.g. mpx86.s and klib86.s have gone, and 'machine.protected' is gone (and always taken to be 1 in i386). If 86 support is to return, it should be a new architecture. . prototypes for the architecture-dependent functions defined in kernel/arch/$(ARCH)/*.c but used in kernel/ are in kernel/proto.h . /etc/make.conf included in makefiles and shell scripts that need to know the building architecture; it defines ARCH=<arch>, currently only i386. . some basic per-architecture build support outside of the kernel (lib) . in clock.c, only dequeue a process if it was ready . fixes for new include files files deleted: . mpx/klib.s - only for choosing between mpx/klib86 and -386 . klib86.s - only for 86 i386-specific files files moved (or arch-dependent stuff moved) to arch/i386/: . mpx386.s (entry point) . klib386.s . sconst.h . exception.c . protect.c . protect.h . i8269.c
This commit is contained in:
141
kernel/interrupt.c
Normal file
141
kernel/interrupt.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* The Minix hardware interrupt system.
|
||||
*
|
||||
* This file contains routines for managing the interrupt
|
||||
* controller.
|
||||
*
|
||||
* put_irq_handler: register an interrupt handler.
|
||||
* rm_irq_handler: deregister an interrupt handler.
|
||||
* intr_handle: handle a hardware interrupt.
|
||||
* called by the system dependent part when an
|
||||
* external interrupt occures.
|
||||
* enable_irq: enable hook for IRQ.
|
||||
* disable_irq: disable hook for IRQ.
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
#include "proc.h"
|
||||
#include <minix/com.h>
|
||||
#include <archconst.h>
|
||||
|
||||
/* number of lists of IRQ hooks, one list per supported line. */
|
||||
PUBLIC irq_hook_t* irq_handlers[NR_IRQ_VECTORS] = {0};
|
||||
/*===========================================================================*
|
||||
* put_irq_handler *
|
||||
*===========================================================================*/
|
||||
/* Register an interrupt handler. */
|
||||
PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
|
||||
{
|
||||
int id;
|
||||
irq_hook_t **line;
|
||||
|
||||
if( irq < 0 || irq >= NR_IRQ_VECTORS )
|
||||
panic("invalid call to put_irq_handler", irq);
|
||||
|
||||
line = &irq_handlers[irq];
|
||||
id = 1;
|
||||
|
||||
while ( *line != NULL ) {
|
||||
if(hook == *line) return; /* extra initialization */
|
||||
line = &(*line)->next;
|
||||
id <<= 1; /* max 32 hooks for one line. */
|
||||
}
|
||||
|
||||
if(id == 0)
|
||||
panic("Too many handlers for irq", irq);
|
||||
|
||||
hook->next = NULL;
|
||||
hook->handler = handler;
|
||||
hook->irq = irq;
|
||||
hook->id = id;
|
||||
*line = hook;
|
||||
irq_use |= 1 << irq; /* this does not work for irq >= 32 */
|
||||
|
||||
/* And as last enable the irq at the hardware.
|
||||
*
|
||||
* Internal this activates the line or source of the given interrupt.
|
||||
*/
|
||||
intr_unmask(hook);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* rm_irq_handler *
|
||||
*===========================================================================*/
|
||||
/* Unregister an interrupt handler. */
|
||||
PUBLIC void rm_irq_handler( irq_hook_t* hook ) {
|
||||
int irq = hook->irq;
|
||||
int id = hook->id;
|
||||
irq_hook_t **line;
|
||||
|
||||
if( irq < 0 || irq >= NR_IRQ_VECTORS )
|
||||
panic("invalid call to rm_irq_handler", irq);
|
||||
|
||||
/* disable the irq. */
|
||||
intr_mask(hook);
|
||||
|
||||
/* remove the hook. */
|
||||
line = &irq_handlers[irq];
|
||||
|
||||
while( (*line) != NULL ) {
|
||||
if((*line)->id == id) {
|
||||
(*line) = (*line)->next;
|
||||
if(!irq_handlers[irq])
|
||||
irq_use &= ~(1 << irq);
|
||||
return;
|
||||
}
|
||||
line = &(*line)->next;
|
||||
}
|
||||
/* When the handler is not found, normally return here. */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* intr_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.
|
||||
*/
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Call the hooked function. */
|
||||
if( (*hook->handler)(hook) )
|
||||
irq_actids[hook->irq] &= ~hook->id;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Enable/Disable a interrupt line. */
|
||||
PUBLIC void enable_irq(hook)
|
||||
irq_hook_t* hook;
|
||||
{
|
||||
if((irq_actids[hook->irq] &= ~hook->id) == 0) {
|
||||
intr_unmask(hook);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if the interrupt was enabled before call. */
|
||||
PUBLIC int disable_irq(hook)
|
||||
irq_hook_t* hook;
|
||||
{
|
||||
if(irq_actids[hook->irq] & hook->id) /* already disabled */
|
||||
return 0;
|
||||
irq_actids[hook->irq] |= hook->id;
|
||||
intr_mask(hook);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user