make vfs & filesystems use failable copying
[minix3.git] / lib / libddekit / src / irq.c
blobed30d71633208db5d9d952d5eeb9c61081701291
1 #include "common.h"
2 #include <ddekit/interrupt.h>
3 #include <ddekit/memory.h>
4 #include <ddekit/semaphore.h>
5 #include <ddekit/thread.h>
7 #ifdef DDEBUG_LEVEL_IRQ
8 #undef DDEBUG
9 #define DDEBUG DDEBUG_LEVEL_IRQ
10 #endif
12 #include "debug.h"
14 struct ddekit_irq_s {
15 int irq;
16 int irq_hook;
17 int shared;
18 void(*thread_init)(void *);
19 void(*handler)(void *);
20 void *priv;
21 int enabled;
22 ddekit_thread_t *th;
23 ddekit_sem_t *sem;
24 struct ddekit_irq_s *next;
27 static struct ddekit_irq_s *irqs = 0;
28 static ddekit_lock_t lock;
30 /******************************************************************************
31 * Local helpers *
32 *****************************************************************************/
35 static void ddekit_irq_lock(void);
36 static void ddekit_irq_unlock(void);
37 static struct ddekit_irq_s* find_by_irq(int irq);
38 static void ddekit_irq_remove(struct ddekit_irq_s *irq_s);
39 static void ddekit_irq_thread(void *data);
41 /******************************************************************************
42 * ddekit_irq_lock *
43 *****************************************************************************/
44 static void ddekit_irq_lock(void)
46 ddekit_lock_lock(&lock);
49 /******************************************************************************
50 * ddekit_irq_unlock *
51 *****************************************************************************/
52 static void ddekit_irq_unlock(void)
54 ddekit_lock_unlock(&lock);
57 /******************************************************************************
58 * find_by_irq *
59 *****************************************************************************/
60 static struct ddekit_irq_s * find_by_irq(int irq)
62 struct ddekit_irq_s * irq_s;
63 ddekit_irq_lock();
64 if (!irqs) {
65 return 0;
68 irq_s = irqs;
70 while(irq_s) {
71 if(irq_s->irq==irq)
72 break;
73 irq_s = irq_s->next;
76 ddekit_irq_unlock();
77 return irq_s;
80 /******************************************************************************
81 * ddekit_irq_remove *
82 *****************************************************************************/
83 static void ddekit_irq_remove(struct ddekit_irq_s *irq_s)
85 struct ddekit_irq_s *i;
87 ddekit_irq_lock();
89 if(!irqs) {
90 ddekit_irq_unlock();
91 return;
94 if(irqs==irq_s) {
95 irqs=irq_s->next;
96 ddekit_irq_unlock();
97 return;
100 i = irqs;
102 while(i) {
103 if (i->next == irq_s) {
104 i->next = irq_s->next;
105 ddekit_irq_unlock();
106 return;
108 i = i->next;
111 ddekit_irq_unlock();
114 /******************************************************************************
115 * ddekit_irq_thread *
116 *****************************************************************************/
117 static void ddekit_irq_thread(void *data)
119 /* For each IRQ line an own thread is started */
121 struct ddekit_irq_s *irq_s = (struct ddekit_irq_s *) data;
123 /* call IRQ thread init function */
124 irq_s->thread_init(irq_s->priv);
126 while(1) {
128 /* Wait for IRQs */
129 DDEBUG_MSG_VERBOSE("wating for IRQ %d to occur", irq_s->irq);
130 ddekit_sem_down(irq_s->sem);
131 DDEBUG_MSG_VERBOSE("executing handler for IRQ %d", irq_s->irq);
132 irq_s->handler(irq_s->priv);
138 /******************************************************************************
139 * DDEKIT public API (include/dde/ddekit) *
140 *****************************************************************************/
142 /******************************************************************************
143 * ddekit_interrupt_attach *
144 *****************************************************************************/
145 ddekit_thread_t *ddekit_interrupt_attach(int irq,
146 int shared,
147 void(*thread_init)(void *),
148 void(*handler)(void *),
149 void *priv)
151 struct ddekit_irq_s *irq_s;
152 char name[32];
153 irq_s = (struct ddekit_irq_s *)
154 ddekit_simple_malloc(sizeof(struct ddekit_irq_s));
156 irq_s->sem = ddekit_sem_init(0);
157 irq_s->irq = irq;
158 irq_s->irq_hook = irq;
159 irq_s->shared = shared;
160 irq_s->thread_init = thread_init;
161 irq_s->handler = handler;
162 irq_s->priv = priv;
163 irq_s->next = 0;
164 irq_s->enabled = 1;
166 /* create interrupt thread */
167 snprintf(name, 32, "ddekit_irq_%d",irq);
168 irq_s->th = ddekit_thread_create(ddekit_irq_thread, irq_s, name);
170 /* attach to IRQ */
171 sys_irqsetpolicy(irq,
172 0, /* not automatically re-enable interupts */
173 &irq_s->irq_hook);
175 /* add to IRQ list */
176 ddekit_irq_lock();
177 irq_s->next = irqs;
178 irqs=irq_s;
179 ddekit_irq_unlock();
181 DDEBUG_MSG_INFO("Attached to irq %d (hook: %d)", irq, irq_s->irq_hook);
183 return irq_s->th;
186 /******************************************************************************
187 * ddekit_interrupt_detach *
188 *****************************************************************************/
189 void ddekit_interrupt_detach(int irq)
191 struct ddekit_irq_s *irq_s;
193 irq_s = find_by_irq(irq);
195 sys_irqrmpolicy(&irq_s->irq_hook);
197 ddekit_thread_terminate(irq_s->th);
198 ddekit_irq_remove(irq_s);
199 ddekit_simple_free(irq_s);
200 DDEBUG_MSG_VERBOSE(" IRQ %d", irq);
203 /******************************************************************************
204 * ddekit_interrupt_disable *
205 *****************************************************************************/
206 void ddekit_interrupt_disable(int irq)
208 struct ddekit_irq_s *irq_s;
209 irq_s = find_by_irq(irq);
210 irq_s->enabled=0;
211 //sys_irqdisable(&irq_s->irq_hook);
212 DDEBUG_MSG_VERBOSE(" IRQ %d", irq);
215 /******************************************************************************
216 * ddekit_interrupt_enable *
217 *****************************************************************************/
218 void ddekit_interrupt_enable(int irq)
220 struct ddekit_irq_s *irq_s;
221 irq_s = find_by_irq(irq);
222 irq_s->enabled=1;
223 //sys_irqenable(&irq_s->irq_hook);
224 DDEBUG_MSG_VERBOSE(" IRQ %d", irq);
227 /******************************************************************************
228 * ddekit_init_irqs *
229 *****************************************************************************/
230 void ddekit_init_irqs()
232 ddekit_lock_init(&lock);
235 /******************************************************************************
236 * DDEKIT internals (src/irq.h) *
237 *****************************************************************************/
239 /******************************************************************************
240 * _ddekit_interrupt_trigger *
241 *****************************************************************************/
242 void _ddekit_interrupt_trigger(int irq)
244 struct ddekit_irq_s *irq_s;
246 irq_s = find_by_irq(irq);
248 if (irq_s) {
249 DDEBUG_MSG_VERBOSE("Triggering IRQ %d", irq);
250 ddekit_sem_up(irq_s->sem);
251 sys_irqenable(&irq_s->irq_hook);
252 } else {
253 DDEBUG_MSG_WARN("no handler for IRQ %d", irq);