. use library function to parse memory string
[minix3.git] / kernel / interrupt.c
blob6d54fab22df188981f5891ec7ab18dadda006bb4
1 /*
2 * The Minix hardware interrupt system.
3 *
4 * This file contains routines for managing the interrupt
5 * controller.
6 *
7 * put_irq_handler: register an interrupt handler.
8 * rm_irq_handler: deregister an interrupt handler.
9 * intr_handle: handle a hardware interrupt.
10 * called by the system dependent part when an
11 * external interrupt occures.
12 * enable_irq: enable hook for IRQ.
13 * disable_irq: disable hook for IRQ.
16 #include "kernel.h"
17 #include "proc.h"
18 #include <minix/com.h>
19 #include <archconst.h>
21 /* number of lists of IRQ hooks, one list per supported line. */
22 PUBLIC irq_hook_t* irq_handlers[NR_IRQ_VECTORS] = {0};
23 /*===========================================================================*
24 * put_irq_handler *
25 *===========================================================================*/
26 /* Register an interrupt handler. */
27 PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
29 int id;
30 irq_hook_t **line;
32 if( irq < 0 || irq >= NR_IRQ_VECTORS )
33 panic("invalid call to put_irq_handler", irq);
35 line = &irq_handlers[irq];
36 id = 1;
38 while ( *line != NULL ) {
39 if(hook == *line) return; /* extra initialization */
40 line = &(*line)->next;
41 id <<= 1; /* max 32 hooks for one line. */
44 if(id == 0)
45 panic("Too many handlers for irq", irq);
47 hook->next = NULL;
48 hook->handler = handler;
49 hook->irq = irq;
50 hook->id = id;
51 *line = hook;
52 irq_use |= 1 << irq; /* this does not work for irq >= 32 */
54 /* And as last enable the irq at the hardware.
56 * Internal this activates the line or source of the given interrupt.
58 intr_unmask(hook);
61 /*===========================================================================*
62 * rm_irq_handler *
63 *===========================================================================*/
64 /* Unregister an interrupt handler. */
65 PUBLIC void rm_irq_handler( irq_hook_t* hook ) {
66 int irq = hook->irq;
67 int id = hook->id;
68 irq_hook_t **line;
70 if( irq < 0 || irq >= NR_IRQ_VECTORS )
71 panic("invalid call to rm_irq_handler", irq);
73 /* disable the irq. */
74 intr_mask(hook);
76 /* remove the hook. */
77 line = &irq_handlers[irq];
79 while( (*line) != NULL ) {
80 if((*line)->id == id) {
81 (*line) = (*line)->next;
82 if(!irq_handlers[irq])
83 irq_use &= ~(1 << irq);
84 return;
86 line = &(*line)->next;
88 /* When the handler is not found, normally return here. */
91 /*===========================================================================*
92 * intr_handle *
93 *===========================================================================*/
94 PUBLIC void intr_handle(irq_hook_t *hook)
96 /* Call the interrupt handlers for an interrupt with the given hook list.
97 * The assembly part of the handler has already masked the IRQ, reenabled the
98 * controller(s) and enabled interrupts.
101 /* Call list of handlers for an IRQ. */
102 while( hook != NULL ) {
103 /* For each handler in the list, mark it active by setting its ID bit,
104 * call the function, and unmark it if the function returns true.
106 irq_actids[hook->irq] |= hook->id;
108 /* Call the hooked function. */
109 if( (*hook->handler)(hook) )
110 irq_actids[hook->irq] &= ~hook->id;
112 /* Next hooked function. */
113 hook = hook->next;
116 /* The assembly code will now disable interrupts, unmask the IRQ if and only
117 * if all active ID bits are cleared, and restart a process.
121 /* Enable/Disable a interrupt line. */
122 PUBLIC void enable_irq(hook)
123 irq_hook_t* hook;
125 if((irq_actids[hook->irq] &= ~hook->id) == 0) {
126 intr_unmask(hook);
127 return;
131 /* Return true if the interrupt was enabled before call. */
132 PUBLIC int disable_irq(hook)
133 irq_hook_t* hook;
135 if(irq_actids[hook->irq] & hook->id) /* already disabled */
136 return 0;
137 irq_actids[hook->irq] |= hook->id;
138 intr_mask(hook);
139 return TRUE;