2 #include <ddekit/interrupt.h>
3 #include <ddekit/memory.h>
4 #include <ddekit/panic.h>
5 #include <ddekit/semaphore.h>
6 #include <ddekit/thread.h>
8 #ifdef DDEBUG_LEVEL_IRQ
10 #define DDEBUG DDEBUG_LEVEL_IRQ
20 void(*thread_init
)(void *);
21 void(*handler
)(void *);
26 struct ddekit_irq_s
*next
;
29 static struct ddekit_irq_s
*irqs
= 0;
30 static ddekit_lock_t lock
;
31 static int next_notify_id
= 0; /* TODO: This is only incremented and after
32 * enough interrupt attachments/detachments
33 * we can run out of legal IDs (this is however
34 * very atypical use case) */
36 /******************************************************************************
38 *****************************************************************************/
41 static void ddekit_irq_lock(void);
42 static void ddekit_irq_unlock(void);
43 static struct ddekit_irq_s
* find_by_irq(int irq
);
44 static struct ddekit_irq_s
* find_by_irq_id(int irq_id
);
45 static void ddekit_irq_remove(struct ddekit_irq_s
*irq_s
);
46 static void ddekit_irq_thread(void *data
);
48 /******************************************************************************
50 *****************************************************************************/
51 static void ddekit_irq_lock(void)
53 ddekit_lock_lock(&lock
);
56 /******************************************************************************
58 *****************************************************************************/
59 static void ddekit_irq_unlock(void)
61 ddekit_lock_unlock(&lock
);
64 /******************************************************************************
66 *****************************************************************************/
67 static struct ddekit_irq_s
* find_by_irq(int irq
)
69 struct ddekit_irq_s
* irq_s
;
87 /******************************************************************************
89 *****************************************************************************/
90 static struct ddekit_irq_s
* find_by_irq_id(int irq_id
)
92 struct ddekit_irq_s
* irq_s
;
101 if(irq_s
->notify_id
==irq_id
)
110 /******************************************************************************
111 * ddekit_irq_remove *
112 *****************************************************************************/
113 static void ddekit_irq_remove(struct ddekit_irq_s
*irq_s
)
115 struct ddekit_irq_s
*i
;
133 if (i
->next
== irq_s
) {
134 i
->next
= irq_s
->next
;
144 /******************************************************************************
145 * ddekit_irq_thread *
146 *****************************************************************************/
147 static void ddekit_irq_thread(void *data
)
149 /* For each IRQ line an own thread is started */
151 struct ddekit_irq_s
*irq_s
= (struct ddekit_irq_s
*) data
;
153 /* call IRQ thread init function */
154 irq_s
->thread_init(irq_s
->priv
);
159 DDEBUG_MSG_VERBOSE("wating for IRQ %d to occur", irq_s
->irq
);
160 ddekit_sem_down(irq_s
->sem
);
161 DDEBUG_MSG_VERBOSE("executing handler for IRQ %d", irq_s
->irq
);
162 irq_s
->handler(irq_s
->priv
);
168 /******************************************************************************
169 * DDEKIT public API (include/dde/ddekit) *
170 *****************************************************************************/
172 /******************************************************************************
173 * ddekit_interrupt_attach *
174 *****************************************************************************/
175 ddekit_thread_t
*ddekit_interrupt_attach(int irq
,
177 void(*thread_init
)(void *),
178 void(*handler
)(void *),
181 struct ddekit_irq_s
*irq_s
;
184 irq_s
= (struct ddekit_irq_s
*)
185 ddekit_simple_malloc(sizeof(struct ddekit_irq_s
));
187 irq_s
->sem
= ddekit_sem_init(0);
188 irq_s
->irq
= irq
; /* represents real IRQ number */
190 irq_s
->notify_id
= next_notify_id
; /* represents kernel's IRQ ID */
191 irq_s
->irq_hook
= next_notify_id
; /* after given ID is passed to
192 * kernel, this field will be
193 * set to real irq_hook */
194 next_notify_id
++; /* next time, assign different
195 * ID so we can distinguish
198 irq_s
->shared
= shared
;
199 irq_s
->thread_init
= thread_init
;
200 irq_s
->handler
= handler
;
205 /* create interrupt thread */
206 snprintf(name
, 32, "ddekit_irq_%d",irq
);
207 irq_s
->th
= ddekit_thread_create(ddekit_irq_thread
, irq_s
, name
);
209 /* try attaching to IRQ */
210 /* do not automatically re-enable interupts */
211 if (0 != (err_code
= sys_irqsetpolicy(irq
, 0, &irq_s
->irq_hook
)))
212 ddekit_panic("Failed to attach interrupt (ERROR %d)", err_code
);
214 /* add to IRQ list */
220 DDEBUG_MSG_INFO("Attached to irq %d (hook: %d)", irq
, irq_s
->irq_hook
);
225 /******************************************************************************
226 * ddekit_interrupt_detach *
227 *****************************************************************************/
228 void ddekit_interrupt_detach(int irq
)
230 struct ddekit_irq_s
*irq_s
;
233 irq_s
= find_by_irq(irq
);
235 if (0 != (err_code
= sys_irqrmpolicy(&irq_s
->irq_hook
)))
236 ddekit_panic("Failed to detach interrupt (ERROR %d)", err_code
);
238 ddekit_thread_terminate(irq_s
->th
);
239 ddekit_irq_remove(irq_s
);
240 ddekit_simple_free(irq_s
);
241 DDEBUG_MSG_VERBOSE(" IRQ %d", irq
);
244 /******************************************************************************
245 * ddekit_interrupt_disable *
246 *****************************************************************************/
247 void ddekit_interrupt_disable(int irq
)
249 struct ddekit_irq_s
*irq_s
;
250 irq_s
= find_by_irq(irq
);
252 //sys_irqdisable(&irq_s->irq_hook);
253 DDEBUG_MSG_VERBOSE(" IRQ %d", irq
);
256 /******************************************************************************
257 * ddekit_interrupt_enable *
258 *****************************************************************************/
259 void ddekit_interrupt_enable(int irq
)
261 struct ddekit_irq_s
*irq_s
;
262 irq_s
= find_by_irq(irq
);
264 //sys_irqenable(&irq_s->irq_hook);
265 DDEBUG_MSG_VERBOSE(" IRQ %d", irq
);
268 /******************************************************************************
270 *****************************************************************************/
271 void ddekit_init_irqs()
273 ddekit_lock_init(&lock
);
276 /******************************************************************************
277 * DDEKIT internals (src/irq.h) *
278 *****************************************************************************/
280 /******************************************************************************
281 * _ddekit_interrupt_trigger *
282 *****************************************************************************/
283 void _ddekit_interrupt_trigger(int irq_id
)
285 struct ddekit_irq_s
*irq_s
;
288 irq_s
= find_by_irq_id(irq_id
);
291 DDEBUG_MSG_VERBOSE("Triggering IRQ %d", irq_s
->irq
);
292 ddekit_sem_up(irq_s
->sem
);
293 if (0 != (err_code
= sys_irqenable(&irq_s
->irq_hook
)))
294 ddekit_panic("Failed to enable interrupt "
295 "(ERROR %d)", err_code
);
297 DDEBUG_MSG_WARN("no handler for IRQ %d", irq_s
->irq
);