2 ** Copyright 2001-2004, Travis Geiselbrecht. All rights reserved.
3 ** Distributed under the terms of the NewOS License.
5 #include <kernel/kernel.h>
6 #include <kernel/int.h>
7 #include <kernel/debug.h>
8 #include <kernel/heap.h>
9 #include <kernel/smp.h>
10 #include <kernel/thread.h>
11 #include <kernel/arch/int.h>
12 #include <newos/errors.h>
13 #include <boot/stage2.h>
18 struct io_handler
*next
;
25 struct io_handler
*handler_list
;
26 spinlock_t vector_lock
;
32 static struct io_vector io_vectors
[ARCH_NUM_INT_VECTORS
];
34 int int_init(kernel_args
*ka
)
36 dprintf("init_int_handlers: entry\n");
38 return arch_int_init(ka
);
41 int int_init2(kernel_args
*ka
)
43 // clear out all of the vectors
44 memset(io_vectors
, 0, sizeof(struct io_vector
) * ARCH_NUM_INT_VECTORS
);
46 return arch_int_init2(ka
);
49 int int_set_io_interrupt_handler(int vector
, int (*func
)(void*), void* data
, const char *name
)
51 struct io_handler
*io
;
53 if(vector
< 0 || vector
>= ARCH_NUM_INT_VECTORS
)
54 return ERR_INVALID_ARGS
;
56 // insert this io handler in the chain of interrupt
57 // handlers registered for this io interrupt
59 io
= (struct io_handler
*)kmalloc(sizeof(struct io_handler
));
63 io
->name
= kstrdup(name
);
64 if(io
->name
== NULL
) {
71 int_disable_interrupts();
72 acquire_spinlock(&io_vectors
[vector
].vector_lock
);
73 io
->next
= io_vectors
[vector
].handler_list
;
74 io_vectors
[vector
].handler_list
= io
;
75 release_spinlock(&io_vectors
[vector
].vector_lock
);
76 int_restore_interrupts();
78 arch_int_enable_io_interrupt(vector
);
83 int int_remove_io_interrupt_handler(int vector
, int (*func
)(void*), void* data
)
85 struct io_handler
*io
, *prev
= NULL
;
87 if(vector
< 0 || vector
>= ARCH_NUM_INT_VECTORS
)
88 return ERR_INVALID_ARGS
;
90 // lock the structures down so it is not modified while we search
91 int_disable_interrupts();
92 acquire_spinlock(&io_vectors
[vector
].vector_lock
);
94 // start at the beginning
95 io
= io_vectors
[vector
].handler_list
;
99 // see if we match both the function & data
100 if (io
->func
== func
&& io
->data
== data
)
103 // Store our backlink and move to next
110 // unlink it, taking care of the change it was the first in line
112 prev
->next
= io
->next
;
114 io_vectors
[vector
].handler_list
= io
->next
;
117 // release our lock as we're done with the vector
118 release_spinlock(&io_vectors
[vector
].vector_lock
);
119 int_restore_interrupts();
121 // and disable the IRQ if nothing left
123 if (prev
== NULL
&& io
->next
== NULL
)
124 arch_int_disable_io_interrupt(vector
);
126 kfree((char *)io
->name
);
130 return (io
!= NULL
) ? NO_ERROR
: ERR_INVALID_ARGS
;
133 int int_io_interrupt_handler(int vector
)
135 int ret
= INT_NO_RESCHEDULE
;
137 acquire_spinlock(&io_vectors
[vector
].vector_lock
);
139 io_vectors
[vector
].call_count
++;
141 if(io_vectors
[vector
].handler_list
== NULL
) {
142 dprintf("unhandled io interrupt 0x%x\n", vector
);
144 struct io_handler
*io
;
147 io
= io_vectors
[vector
].handler_list
;
149 temp_ret
= io
->func(io
->data
);
150 if(temp_ret
== INT_RESCHEDULE
)
151 ret
= INT_RESCHEDULE
;
156 release_spinlock(&io_vectors
[vector
].vector_lock
);
161 void int_enable_interrupts(void)
163 arch_int_enable_interrupts();
166 // increase the interrupt disable count in the current thread structure.
167 // if we go from 0 to 1, disable interrupts
168 void int_disable_interrupts(void)
170 struct thread
*t
= thread_get_current_thread();
174 ASSERT(t
->int_disable_level
>= 0);
176 t
->int_disable_level
++;
177 if(t
->int_disable_level
== 1) {
178 // we just crossed from 0 -> 1
179 arch_int_disable_interrupts();
183 // decrement the interrupt disable count. If we hit zero, re-enable interrupts
184 void int_restore_interrupts(void)
186 struct thread
*t
= thread_get_current_thread();
190 t
->int_disable_level
--;
192 ASSERT(t
->int_disable_level
>= 0);
193 if(t
->int_disable_level
== 0) {
195 arch_int_enable_interrupts();
199 bool int_are_interrupts_enabled(void)
201 return arch_int_are_interrupts_enabled();