00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <l4/dde/ddekit/interrupt.h>
00012 #include <l4/dde/ddekit/semaphore.h>
00013 #include <l4/dde/ddekit/thread.h>
00014 #include <l4/dde/ddekit/memory.h>
00015 #include <l4/dde/ddekit/panic.h>
00016
00017 #include <l4/omega0/client.h>
00018 #include <l4/log/l4log.h>
00019 #include <l4/thread/thread.h>
00020
00021 #include <stdio.h>
00022
00023 #define DEBUG_INTERRUPTS 0
00024
00025 #define MAX_INTERRUPTS 32
00026
00027 #define BLOCK_IRQ 0
00028
00029
00030
00031
00032 struct intloop_params
00033 {
00034 unsigned irq;
00035 int shared;
00036 void(*thread_init)(void *);
00037 void(*handler)(void *);
00038 void *priv;
00039 ddekit_sem_t *started;
00040
00041 int start_err;
00042 };
00043
00044 static struct
00045 {
00046 int handle_irq;
00047 ddekit_sem_t *irqsem;
00048 ddekit_thread_t *irq_thread;
00049 omega0_irqdesc_t irq_desc;
00050 } ddekit_irq_ctrl[MAX_INTERRUPTS];
00051
00052
00053 static void ddekit_irq_exit_fn(l4thread_t thread, void *data)
00054 {
00055 int idx = (int)data;
00056
00057
00058 omega0_detach(ddekit_irq_ctrl[idx].irq_desc);
00059 }
00060
00061 L4THREAD_EXIT_FN_STATIC(exit_fn, ddekit_irq_exit_fn);
00062
00063
00064
00065
00066
00067
00068 static void intloop(void *arg)
00069 {
00070 struct intloop_params *params = arg;
00071
00072 l4thread_set_prio(l4thread_myself(), DDEKIT_IRQ_PRIO);
00073
00074 omega0_request_t req = { .i = 0 };
00075 int o0handle;
00076 int my_index = params->irq;
00077 omega0_irqdesc_t *desc = &ddekit_irq_ctrl[my_index].irq_desc;
00078
00079
00080 desc->s.num = params->irq + 1;
00081 desc->s.shared = params->shared;
00082
00083
00084 o0handle = omega0_attach(*desc);
00085 if (o0handle < 0) {
00086
00087
00088 params->start_err = o0handle;
00089 ddekit_sem_up(params->started);
00090 return;
00091 }
00092
00093
00094
00095
00096
00097 if (l4thread_on_exit(&exit_fn, (void *)my_index) < 0)
00098 ddekit_panic("Could not set exit handler for IRQ fn.");
00099
00100
00101
00102 if (params->thread_init) params->thread_init(params->priv);
00103
00104
00105 params->start_err = 0;
00106 ddekit_sem_up(params->started);
00107
00108
00109 req.s.param = params->irq + 1;
00110 req.s.wait = 1;
00111 req.s.consume = 0;
00112 req.s.unmask = 1;
00113
00114 while (1) {
00115 int err;
00116
00117
00118 err = omega0_request(o0handle, req);
00119 if (err != params->irq + 1)
00120 LOG("omega0_request returned %d, %d (irq+1) expected", err, params->irq + 1);
00121
00122 LOGd(DEBUG_INTERRUPTS, "received irq 0x%X", err - 1);
00123
00124
00125 req.s.unmask = 0;
00126
00127
00128 ddekit_sem_down(ddekit_irq_ctrl[my_index].irqsem);
00129 if (ddekit_irq_ctrl[my_index].handle_irq > 0) {
00130 LOGd(DEBUG_INTERRUPTS, "IRQ %x, handler %p", my_index,params->handler);
00131 params->handler(params->priv);
00132 }
00133 else
00134 LOGd(DEBUG_INTERRUPTS, "not handling IRQ %x, because it is disabled.", my_index);
00135
00136 ddekit_sem_up(ddekit_irq_ctrl[my_index].irqsem);
00137 LOGd(DEBUG_INTERRUPTS, "after irq handler");
00138 }
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 ddekit_thread_t *ddekit_interrupt_attach(int irq, int shared,
00156 void(*thread_init)(void *),
00157 void(*handler)(void *), void *priv)
00158 {
00159 struct intloop_params *params;
00160 ddekit_thread_t *thread;
00161 char thread_name[10];
00162
00163
00164 params = ddekit_simple_malloc(sizeof(*params));
00165 if (!params) return NULL;
00166
00167 params->irq = irq;
00168 params->thread_init = thread_init;
00169 params->handler = handler;
00170 params->priv = priv;
00171 params->started = ddekit_sem_init(0);
00172 params->start_err = 0;
00173 params->shared = shared;
00174
00175
00176 snprintf(thread_name, 10, "irq%02X", irq);
00177
00178
00179 thread = ddekit_thread_create(intloop, params, thread_name);
00180 if (!thread) {
00181 ddekit_simple_free(params);
00182 return NULL;
00183 }
00184
00185 ddekit_irq_ctrl[irq].handle_irq = 1;
00186 ddekit_irq_ctrl[irq].irq_thread = thread;
00187 ddekit_irq_ctrl[irq].irqsem = ddekit_sem_init(1);
00188
00189
00190
00191 ddekit_sem_down(params->started);
00192 ddekit_sem_deinit(params->started);
00193 if (params->start_err) {
00194 ddekit_simple_free(params);
00195 return NULL;
00196 }
00197
00198 return thread;
00199 }
00200
00201
00202
00203
00204
00205 void ddekit_interrupt_detach(int irq)
00206 {
00207 ddekit_interrupt_disable(irq);
00208 ddekit_thread_terminate(ddekit_irq_ctrl[irq].irq_thread);
00209 }
00210
00211
00212 void ddekit_interrupt_disable(int irq)
00213 {
00214 if (ddekit_irq_ctrl[irq].irqsem) {
00215 ddekit_sem_down(ddekit_irq_ctrl[irq].irqsem);
00216 --ddekit_irq_ctrl[irq].handle_irq;
00217 ddekit_sem_up(ddekit_irq_ctrl[irq].irqsem);
00218 }
00219 }
00220
00221
00222 void ddekit_interrupt_enable(int irq)
00223 {
00224 if (ddekit_irq_ctrl[irq].irqsem) {
00225 ddekit_sem_down(ddekit_irq_ctrl[irq].irqsem);
00226 ++ddekit_irq_ctrl[irq].handle_irq;
00227 ddekit_sem_up(ddekit_irq_ctrl[irq].irqsem);
00228 }
00229 }