Remove building with NOCRYPTO option
[minix.git] / minix / lib / libddekit / src / irq.c
blobda0a949ea4c519aa89f14c89d9344d3999fc53b8
1 #include "common.h"
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
9 #undef DDEBUG
10 #define DDEBUG DDEBUG_LEVEL_IRQ
11 #endif
13 #include "debug.h"
15 struct ddekit_irq_s {
16 int irq;
17 int notify_id;
18 int irq_hook;
19 int shared;
20 void(*thread_init)(void *);
21 void(*handler)(void *);
22 void *priv;
23 int enabled;
24 ddekit_thread_t *th;
25 ddekit_sem_t *sem;
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 /******************************************************************************
37 * Local helpers *
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 /******************************************************************************
49 * ddekit_irq_lock *
50 *****************************************************************************/
51 static void ddekit_irq_lock(void)
53 ddekit_lock_lock(&lock);
56 /******************************************************************************
57 * ddekit_irq_unlock *
58 *****************************************************************************/
59 static void ddekit_irq_unlock(void)
61 ddekit_lock_unlock(&lock);
64 /******************************************************************************
65 * find_by_irq *
66 *****************************************************************************/
67 static struct ddekit_irq_s * find_by_irq(int irq)
69 struct ddekit_irq_s * irq_s;
70 ddekit_irq_lock();
71 if (!irqs) {
72 return 0;
75 irq_s = irqs;
77 while(irq_s) {
78 if(irq_s->irq==irq)
79 break;
80 irq_s = irq_s->next;
83 ddekit_irq_unlock();
84 return irq_s;
87 /******************************************************************************
88 * find_by_irq_id *
89 *****************************************************************************/
90 static struct ddekit_irq_s * find_by_irq_id(int irq_id)
92 struct ddekit_irq_s * irq_s;
93 ddekit_irq_lock();
94 if (!irqs) {
95 return 0;
98 irq_s = irqs;
100 while(irq_s) {
101 if(irq_s->notify_id==irq_id)
102 break;
103 irq_s = irq_s->next;
106 ddekit_irq_unlock();
107 return irq_s;
110 /******************************************************************************
111 * ddekit_irq_remove *
112 *****************************************************************************/
113 static void ddekit_irq_remove(struct ddekit_irq_s *irq_s)
115 struct ddekit_irq_s *i;
117 ddekit_irq_lock();
119 if(!irqs) {
120 ddekit_irq_unlock();
121 return;
124 if(irqs==irq_s) {
125 irqs=irq_s->next;
126 ddekit_irq_unlock();
127 return;
130 i = irqs;
132 while(i) {
133 if (i->next == irq_s) {
134 i->next = irq_s->next;
135 ddekit_irq_unlock();
136 return;
138 i = i->next;
141 ddekit_irq_unlock();
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);
156 while(1) {
158 /* Wait for IRQs */
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,
176 int shared,
177 void(*thread_init)(void *),
178 void(*handler)(void *),
179 void *priv)
181 struct ddekit_irq_s *irq_s;
182 int err_code;
183 char name[32];
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 */
189 ddekit_irq_lock();
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
196 * interrupts */
197 ddekit_irq_unlock();
198 irq_s->shared = shared;
199 irq_s->thread_init = thread_init;
200 irq_s->handler = handler;
201 irq_s->priv = priv;
202 irq_s->next = 0;
203 irq_s->enabled = 1;
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 */
215 ddekit_irq_lock();
216 irq_s->next = irqs;
217 irqs=irq_s;
218 ddekit_irq_unlock();
220 DDEBUG_MSG_INFO("Attached to irq %d (hook: %d)", irq, irq_s->irq_hook);
222 return irq_s->th;
225 /******************************************************************************
226 * ddekit_interrupt_detach *
227 *****************************************************************************/
228 void ddekit_interrupt_detach(int irq)
230 struct ddekit_irq_s *irq_s;
231 int err_code;
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);
251 irq_s->enabled=0;
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);
263 irq_s->enabled=1;
264 //sys_irqenable(&irq_s->irq_hook);
265 DDEBUG_MSG_VERBOSE(" IRQ %d", irq);
268 /******************************************************************************
269 * ddekit_init_irqs *
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;
286 int err_code;
288 irq_s = find_by_irq_id(irq_id);
290 if (irq_s) {
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);
296 } else {
297 DDEBUG_MSG_WARN("no handler for IRQ %d", irq_s->irq);