00001
00009
00010
00011
00012
00013
00027
00028 #include <l4/env/errno.h>
00029 #include <l4/omega0/client.h>
00030 #include <l4/thread/thread.h>
00031 #include <l4/lock/lock.h>
00032
00033 #include <l4/dde_linux/dde.h>
00034
00035
00036 #include <linux/sched.h>
00037 #include <asm/hardirq.h>
00038 #include <asm/irq.h>
00039
00040
00041 #include "__config.h"
00042 #include "internal.h"
00043
00049 static struct irq_desc
00050 {
00051 int active;
00052 int num;
00053 l4thread_t t;
00054 struct {
00055 void (*isr) (int, void *, struct pt_regs *);
00057 unsigned long flags;
00058 const char *dev_name;
00059 void *dev_id;
00060 } h[MAX_IRQ_HANDLERS];
00061 void (*def_handler) (int, void *);
00063 void *dev_def_id;
00064 } handlers[NR_IRQS];
00065
00066 static int _initialized = 0;
00068 int l4dde_irq_set_prio(unsigned int irq, unsigned prio)
00069 {
00070 struct irq_desc *handler = &handlers[irq];
00071
00072 if ( !(irq < NR_IRQS) || !handler->active )
00073 return -L4_EINVAL;
00074
00075 return l4thread_set_prio(handler->t, prio);
00076 }
00077
00078
00083 #define OM_MASK 0x00000001
00084 #define OM_UNMASK 0x00000002
00085 #define OM_CONSUME 0x00000004
00086
00094 static inline int __omega0_attach(unsigned int irq, int *handle)
00095 {
00096 omega0_irqdesc_t irqdesc;
00097
00098
00099 irqdesc.s.num = irq + 1;
00100 irqdesc.s.shared = 1;
00101
00102
00103 *handle = omega0_attach(irqdesc);
00104 if (*handle < 0)
00105 return -1;
00106 else
00107 return 0;
00108 }
00109
00119 static inline int __omega0_wait(unsigned int irq, int handle, unsigned int flags)
00120 {
00121 omega0_request_t request = { .i=0 };
00122 int ret;
00123
00124
00125 request.s.param = irq + 1;
00126 request.s.wait = 1;
00127 request.s.consume = (flags & OM_CONSUME) ? 1 : 0;
00128 request.s.mask = (flags & OM_MASK) ? 1 : 0;
00129 request.s.unmask = (flags & OM_UNMASK) ? 1 : 0;
00130
00131
00132 ret = omega0_request(handle, request);
00133 if (ret != (irq + 1))
00134 Panic("error waiting for interrupt\n");
00135
00136 return 0;
00137 }
00138
00144 static void dde_irq_thread(struct irq_desc *irq_desc)
00145 {
00146 unsigned int irq = irq_desc->num;
00147 int retval = 0;
00148
00149 int err, irq_handle;
00150 unsigned int om_flags;
00151
00152
00153 err = __omega0_attach(irq, &irq_handle);
00154 if (err < 0)
00155 Panic("failed to attach IRQ %d at omega0!\n", irq);
00156
00157 if (l4dde_process_add_worker())
00158 Panic("l4dde_process_add_worker() failed");
00159 ++local_irq_count(smp_processor_id());
00160
00161
00162 retval = err;
00163 err = l4thread_started(&retval);
00164
00165 if ((err < 0) || retval)
00166 Panic("IRQ thread startup failed!");
00167
00168 LOGd(DEBUG_MSG, "dde_irq_thread[%d] "l4util_idfmt" running.",
00169 irq_desc->num, l4util_idstr(l4thread_l4_id(l4thread_myself())));
00170
00171 om_flags = OM_UNMASK;
00172 for (;;)
00173 {
00174 err = __omega0_wait(irq, irq_handle, om_flags);
00175
00176 switch (err)
00177 {
00178 case 0:
00179 LOGd(DEBUG_IRQ, "got IRQ %d\n", irq);
00180 if (irq_desc->active)
00181 {
00182 int i;
00183 for (i = 0; i < MAX_IRQ_HANDLERS; i++)
00184 if (irq_desc->h[i].isr)
00185 irq_desc->h[i].isr(irq, irq_desc->h[i].dev_id, 0);
00186 if (irq_desc->def_handler)
00187 irq_desc->def_handler(irq, irq_desc->dev_def_id);
00188 }
00189 om_flags = 0;
00190 break;
00191
00192 case L4_IPC_RETIMEOUT:
00193 LOGdL(DEBUG_ERRORS, "Error: timeout while receiving irq");
00194 break;
00195
00196 default:
00197 LOGdL(DEBUG_ERRORS, "Error: receiving irq (%d)", err);
00198 }
00199 }
00200 }
00201
00215 int request_irq(unsigned int irq,
00216 void (*handler) (int, void *, struct pt_regs *),
00217 unsigned long flags, const char *dev_name, void *dev_id)
00218 {
00219 l4thread_t irq_tid;
00220 char name[16];
00221
00222 if ( !(irq < NR_IRQS) )
00223 return -EINVAL;
00224 if (!handler)
00225 return -EINVAL;
00226
00227
00228 if (!handlers[irq].t)
00229 {
00230
00231 LOG_snprintf(name, 16, ".irq%.2X", irq);
00232 irq_tid = l4thread_create_long(L4THREAD_INVALID_ID,
00233 (l4thread_fn_t) dde_irq_thread,
00234 name,
00235 L4THREAD_INVALID_SP,
00236 L4THREAD_DEFAULT_SIZE,
00237 L4THREAD_DEFAULT_PRIO,
00238 (void *) &handlers[irq],
00239 L4THREAD_CREATE_SYNC);
00240
00241 if (irq_tid < 0)
00242 {
00243 LOGdL(DEBUG_ERRORS, "Error: thread creation failed");
00244 return -EAGAIN;
00245 }
00246 if (*(int*)l4thread_startup_return(irq_tid))
00247 {
00248 LOGdL(DEBUG_ERRORS, "Error: irq not free");
00249 return -EBUSY;
00250 }
00251 handlers[irq].t = irq_tid;
00252 }
00253
00254 int i;
00255 for (i = 0; i < MAX_IRQ_HANDLERS; i++)
00256 if (!handlers[irq].h[i].isr)
00257 break;
00258
00259 if (i == MAX_IRQ_HANDLERS)
00260 {
00261 LOGd(DEBUG_ERRORS, "Error: maximum number of irq handlers exceeded");
00262 return -EBUSY;
00263 }
00264
00265 handlers[irq].h[i].isr = handler;
00266
00267 LOGd(DEBUG_IRQ, "new handler for irq %d is %p", irq, handler);
00268
00269 handlers[irq].h[i].flags = flags;
00270 handlers[irq].h[i].dev_name = dev_name;
00271 handlers[irq].h[i].dev_id = dev_id;
00272
00273 handlers[irq].active = 1;
00274
00275 LOGd(DEBUG_IRQ, "attached to irq %d", irq);
00276
00277 return 0;
00278 }
00279
00290 void free_irq(unsigned int irq, void *dev_id)
00291 {
00292 int i;
00293 int active = 0;
00294
00295 for (i = 0; i < MAX_IRQ_HANDLERS; i++)
00296 {
00297 if (handlers[irq].h[i].dev_id == dev_id)
00298 handlers[irq].h[i].isr = NULL;
00299 if (handlers[irq].h[i].isr)
00300 active = 1;
00301 }
00302
00303 handlers[irq].active = active;
00304
00305 LOGd(DEBUG_IRQ, "XXX attempt to free irq %d ("l4util_idfmt")", irq,
00306 l4util_idstr(l4thread_l4_id(handlers[irq].t)));
00307 }
00308
00309 int l4dde_set_deferred_irq_handler(unsigned int irq,
00310 void (*def_handler) (int, void *),
00311 void *dev_def_id)
00312 {
00313 if (handlers[irq].active==0)
00314 {
00315 LOGd(DEBUG_IRQ, "attempt to set deferred handler for free irq %d",
00316 irq);
00317 return -L4_EINVAL;
00318 }
00319 handlers[irq].dev_def_id = dev_def_id;
00320 handlers[irq].def_handler = def_handler;
00321 return 0;
00322 }
00323
00327 void disable_irq(unsigned int irq_num)
00328 {
00329 LOG("%s not implemented", __FUNCTION__);
00330 }
00331
00332 void disable_irq_nosync(unsigned int irq_num)
00333 {
00334 LOG("%s not implemented", __FUNCTION__);
00335 }
00336
00337 void enable_irq(unsigned int irq_num)
00338 {
00339 LOG("%s not implemented", __FUNCTION__);
00340 }
00341
00347 int probe_irq_on(unsigned long val)
00348 {
00349 LOG_Error("%s not implemented", __FUNCTION__);
00350 return 0;
00351 }
00357 int probe_irq_off(unsigned long val)
00358 {
00359 LOG_Error("%s not implemented", __FUNCTION__);
00360 return 0;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 #ifdef CONFIG_SMP
00373 void synchronize_irq(void)
00374 {
00375
00376
00377
00378
00379
00380 }
00381 #endif
00382
00392 int l4dde_irq_init()
00393 {
00394 int i;
00395
00396 if (_initialized)
00397 return -L4_ESKIPPED;
00398
00399 memset(&handlers, 0, sizeof(handlers));
00400 for (i = 0; i < NR_IRQS; i++)
00401 handlers[i].num = i;
00402
00403 ++_initialized;
00404 return 0;
00405 }
00406
00414 l4_threadid_t l4dde_irq_l4_id(int irq)
00415 {
00416 if (irq >= NR_IRQS) return L4_INVALID_ID;
00417 if (!handlers[irq].active) return L4_INVALID_ID;
00418 return l4thread_l4_id(handlers[irq].t);
00419 }
00420
00421 omega0_alien_handler_t l4dde_set_alien_handler(omega0_alien_handler_t handler)
00422 {
00423 if (!_initialized) return (omega0_alien_handler_t)-1;
00424 return omega0_set_alien_handler(handler);
00425 }
00426