the ULIBS make variable doesn't appear to be in use anymore
[newos.git] / kernel / int.c
blob1894cb9e6816337de77ad857268e0c56ab637a43
1 /*
2 ** Copyright 2001-2004, Travis Geiselbrecht. All rights reserved.
3 ** Distributed under the terms of the NewOS License.
4 */
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>
14 #include <string.h>
15 #include <stdio.h>
17 struct io_handler {
18 struct io_handler *next;
19 int (*func)(void*);
20 void* data;
21 const char *name;
24 struct io_vector {
25 struct io_handler *handler_list;
26 spinlock_t vector_lock;
28 // statistics
29 int call_count;
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));
60 if(io == NULL)
61 return ERR_NO_MEMORY;
63 io->name = kstrdup(name);
64 if(io->name == NULL) {
65 kfree(io);
66 return ERR_NO_MEMORY;
68 io->func = func;
69 io->data = data;
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);
80 return NO_ERROR;
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;
97 // while not at end
98 while(io != NULL) {
99 // see if we match both the function & data
100 if (io->func == func && io->data == data)
101 break;
103 // Store our backlink and move to next
104 prev = io;
105 io = io->next;
108 // If we found it
109 if (io != NULL) {
110 // unlink it, taking care of the change it was the first in line
111 if (prev != NULL)
112 prev->next = io->next;
113 else
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
122 if (io != NULL) {
123 if (prev == NULL && io->next == NULL)
124 arch_int_disable_io_interrupt(vector);
126 kfree((char *)io->name);
127 kfree(io);
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);
143 } else {
144 struct io_handler *io;
145 int temp_ret;
147 io = io_vectors[vector].handler_list;
148 while(io != NULL) {
149 temp_ret = io->func(io->data);
150 if(temp_ret == INT_RESCHEDULE)
151 ret = INT_RESCHEDULE;
152 io = io->next;
156 release_spinlock(&io_vectors[vector].vector_lock);
158 return ret;
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();
171 if(!t)
172 return;
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();
187 if(!t)
188 return;
190 t->int_disable_level--;
192 ASSERT(t->int_disable_level >= 0);
193 if(t->int_disable_level == 0) {
194 // we just hit 0
195 arch_int_enable_interrupts();
199 bool int_are_interrupts_enabled(void)
201 return arch_int_are_interrupts_enabled();