2 * The Minix hardware interrupt system.
4 * This file contains routines for managing the interrupt
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.
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 /*===========================================================================*
25 *===========================================================================*/
26 /* Register an interrupt handler. */
27 PUBLIC
void put_irq_handler( irq_hook_t
* hook
, int irq
, irq_handler_t handler
)
32 if( irq
< 0 || irq
>= NR_IRQ_VECTORS
)
33 panic("invalid call to put_irq_handler", irq
);
35 line
= &irq_handlers
[irq
];
38 while ( *line
!= NULL
) {
39 if(hook
== *line
) return; /* extra initialization */
40 line
= &(*line
)->next
;
41 id
<<= 1; /* max 32 hooks for one line. */
45 panic("Too many handlers for irq", irq
);
48 hook
->handler
= handler
;
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.
61 /*===========================================================================*
63 *===========================================================================*/
64 /* Unregister an interrupt handler. */
65 PUBLIC
void rm_irq_handler( irq_hook_t
* hook
) {
70 if( irq
< 0 || irq
>= NR_IRQ_VECTORS
)
71 panic("invalid call to rm_irq_handler", irq
);
73 /* disable the irq. */
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
);
86 line
= &(*line
)->next
;
88 /* When the handler is not found, normally return here. */
91 /*===========================================================================*
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. */
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
)
125 if((irq_actids
[hook
->irq
] &= ~hook
->id
) == 0) {
131 /* Return true if the interrupt was enabled before call. */
132 PUBLIC
int disable_irq(hook
)
135 if(irq_actids
[hook
->irq
] & hook
->id
) /* already disabled */
137 irq_actids
[hook
->irq
] |= hook
->id
;