00001
00002
00011
00012
00013
00014
00015
00040
00041
00042
00043 #include <l4/env/errno.h>
00044 #include <l4/omega0/client.h>
00045 #include <l4/rmgr/librmgr.h>
00046 #include <l4/util/irq.h>
00047 #include <l4/util/thread.h>
00048 #include <l4/thread/thread.h>
00049 #include <l4/lock/lock.h>
00050
00051 #include <l4/dde_linux/dde.h>
00052
00053
00054 #include <linux/sched.h>
00055 #include <asm/hardirq.h>
00056 #include <asm/irq.h>
00057
00058
00059 #include "__config.h"
00060 #include "internal.h"
00061
00067 static struct irq_desc
00068 {
00069 int active;
00070 int num;
00071 l4thread_t t;
00072 void (*handler) (int, void *, struct pt_regs *);
00074 unsigned long flags;
00075 const char *dev_name;
00076 void *dev_id;
00077 } handlers[NR_IRQS];
00078
00081 static int use_omega0 = 0;
00082
00083 static int _initialized = 0;
00085 int l4dde_irq_set_prio(unsigned int irq, unsigned prio){
00086 struct irq_desc *handler;
00087
00088
00089 handler = &handlers[irq];
00090 if(!handler) return -L4_EINVAL;
00091 return l4thread_set_prio(handler->t, prio);
00092 }
00093
00094
00099 #define OM_MASK 0x00000001
00100 #define OM_UNMASK 0x00000002
00101 #define OM_CONSUME 0x00000004
00102
00110 static inline int __omega0_attach(unsigned int irq, int *handle)
00111 {
00112 omega0_irqdesc_t irqdesc;
00113
00114
00115 irqdesc.s.num = irq + 1;
00116 irqdesc.s.shared = 0;
00117
00118
00119 *handle = omega0_attach(irqdesc);
00120 if (*handle < 0)
00121 return -1;
00122 else
00123 return 0;
00124 }
00125
00135 static inline int __omega0_wait(unsigned int irq, int handle, unsigned int flags)
00136 {
00137 omega0_request_t request;
00138 int ret;
00139
00140
00141 request.s.param = irq + 1;
00142 request.s.wait = 1;
00143 request.s.consume = (flags & OM_CONSUME) ? 1 : 0;
00144 request.s.mask = (flags & OM_MASK) ? 1 : 0;
00145 request.s.unmask = (flags & OM_UNMASK) ? 1 : 0;
00146
00147
00148 ret = omega0_request(handle, request);
00149 if (ret != (irq + 1))
00150 Panic("error waiting for interrupt\n");
00151
00152 return 0;
00153 }
00154
00163 static inline void __enable_irq(unsigned int irq)
00164 {
00165 int port;
00166 l4util_cli();
00167 port = (((irq & 0x08) << 4) + 0x21);
00168 l4util_out8(l4util_in8(port) & ~(1 << (irq & 7)), port);
00169 l4util_sti();
00170 }
00171
00176 static inline void __disable_irq(unsigned int irq)
00177 {
00178 unsigned short port;
00179 l4util_cli();
00180 port = (((irq & 0x08) << 4) + 0x21);
00181 l4util_out8(l4util_in8(port) | (1 << (irq & 7)), port);
00182 l4util_sti();
00183 }
00184
00189 static inline void __ack_irq(unsigned int irq)
00190 {
00191 l4util_irq_acknowledge(irq);
00192 }
00193
00199 static void dde_irq_thread(struct irq_desc *irq_desc)
00200 {
00201 unsigned int irq = irq_desc->num;
00202 int retval = 0;
00203
00204 int ret, error = L4_IPC_RETIMEOUT, irq_handle;
00205 l4_threadid_t irq_id;
00206 l4_umword_t dw0, dw1;
00207 l4_msgdope_t result;
00208 unsigned int om_flags;
00209
00210
00211 if (use_omega0)
00212 {
00213 ret = __omega0_attach(irq, &irq_handle);
00214 if (ret < 0)
00215 Panic("failed to attach IRQ %d at omega0!\n", irq);
00216 else
00217 error = L4_IPC_RETIMEOUT;
00218 }
00219 else
00220 {
00221 if (rmgr_get_irq(irq))
00222
00223 Panic("%s: can't get permission for irq 0x%02x, giving up...\n",
00224 __FUNCTION__, irq);
00225
00226
00227 if (l4_is_invalid_id(irq_id = l4util_attach_interrupt(irq)))
00228 Panic("%s: can't attach to irq 0x%02x, giving up...\n",
00229 __FUNCTION__, irq);
00230
00231
00232 for (;;)
00233 {
00234 error = l4_ipc_receive(irq_id,
00235 L4_IPC_SHORT_MSG, &dw0, &dw1,
00236 L4_IPC_TIMEOUT(0, 0, 1, 15, 0, 0), &result);
00237 if (error == L4_IPC_RETIMEOUT)
00238 break;
00239 }
00240 }
00241
00242 if (l4dde_process_add_worker())
00243 Panic("l4dde_process_add_worker() failed");
00244 ++local_irq_count(smp_processor_id());
00245
00246
00247 retval = (error != L4_IPC_RETIMEOUT) ? 1 : 0;
00248 ret = l4thread_started(&retval);
00249
00250 if ((ret < 0)|| retval)
00251 Panic("IRQ thread startup failed!");
00252
00253 LOGd(DEBUG_MSG, "dde_irq_thread[%d] "l4util_idfmt" running.",
00254 irq_desc->num, l4util_idstr(l4thread_l4_id(l4thread_myself())));
00255
00256 if (!use_omega0)
00257 __enable_irq(irq);
00258 om_flags = OM_UNMASK;
00259 for (;;)
00260 {
00261 if (use_omega0)
00262 error = __omega0_wait(irq, irq_handle, om_flags);
00263 else
00264 {
00265
00266 error = l4_ipc_receive(irq_id,
00267 L4_IPC_SHORT_MSG, &dw0, &dw1,
00268 L4_IPC_NEVER, &result);
00269 __disable_irq(irq);
00270 __ack_irq(irq);
00271 }
00272
00273 switch (error)
00274 {
00275 case 0:
00276 LOGd(DEBUG_IRQ, "got IRQ %d\n", irq);
00277 if (irq_desc->active)
00278 irq_desc->handler(irq, irq_desc->dev_id, 0);
00279 if (use_omega0)
00280 om_flags = 0;
00281 else
00282 __enable_irq(irq);
00283 break;
00284 case L4_IPC_RETIMEOUT:
00285 LOGdL(DEBUG_ERRORS, "Error: timeout while receiving irq");
00286 break;
00287 default:
00288 LOGdL(DEBUG_ERRORS, "Error: receiving irq (%d)", error);
00289 break;
00290 }
00291 }
00292 }
00293
00307 int request_irq(unsigned int irq,
00308 void (*handler) (int, void *, struct pt_regs *),
00309 unsigned long flags, const char *dev_name, void *dev_id)
00310 {
00311 l4thread_t irq_tid;
00312 char name[16];
00313
00314 if (irq >= NR_IRQS)
00315 return -EINVAL;
00316 if (!handler)
00317 return -EINVAL;
00318
00319 if(handlers[irq].t)
00320 {
00321 if (handlers[irq].active)
00322 {
00323 LOGd(DEBUG_IRQ, "XXX attempt to reattach to active irq %d", irq);
00324 return -EBUSY;
00325 }
00326 handlers[irq].active = 1;
00327
00328
00329
00330 LOGd(DEBUG_IRQ, "reattached to irq %d", irq);
00331 return 0;
00332 }
00333
00334 handlers[irq].handler = handler;
00335
00336
00337 snprintf(name, 16, ".irq%.2X", irq);
00338 irq_tid = l4thread_create_long(L4THREAD_INVALID_ID,
00339 (l4thread_fn_t) dde_irq_thread,
00340 name,
00341 L4THREAD_INVALID_SP,
00342 L4THREAD_DEFAULT_SIZE,
00343 L4THREAD_DEFAULT_PRIO,
00344 (void *) &handlers[irq],
00345 L4THREAD_CREATE_SYNC);
00346
00347 if (irq_tid<0)
00348 {
00349 LOGdL(DEBUG_ERRORS, "Error: thread creation failed");
00350 return -EAGAIN;
00351 }
00352 if (*(int*)l4thread_startup_return(irq_tid))
00353 {
00354 LOGdL(DEBUG_ERRORS, "Error: irq not free");
00355 return -EBUSY;
00356 }
00357
00358 handlers[irq].active = 1;
00359 handlers[irq].t = irq_tid;
00360
00361 handlers[irq].flags = flags;
00362 handlers[irq].dev_name = dev_name;
00363 handlers[irq].dev_id = dev_id;
00364
00365 LOGd(DEBUG_IRQ, "attached to irq %d", irq);
00366
00367 return 0;
00368 }
00369
00380 void free_irq(unsigned int irq, void *dev_id)
00381 {
00382 handlers[irq].active = 0;
00383
00384 LOGd(DEBUG_IRQ, "XXX attempt to free irq %d ("l4util_idfmt")", irq,
00385 l4util_idstr(l4thread_l4_id(handlers[irq].t)));
00386 }
00387
00388
00392 void disable_irq(unsigned int irq_num)
00393 {
00394 LOG("%s not implemented", __FUNCTION__);
00395 }
00396
00397 void disable_irq_nosync(unsigned int irq_num)
00398 {
00399 LOG("%s not implemented", __FUNCTION__);
00400 }
00401
00402 void enable_irq(unsigned int irq_num)
00403 {
00404 LOG("%s not implemented", __FUNCTION__);
00405 }
00406
00412 int probe_irq_on(unsigned long val)
00413 {
00414 LOG_Error("%s not implemented", __FUNCTION__);
00415 return 0;
00416 }
00422 int probe_irq_off(unsigned long val)
00423 {
00424 LOG_Error("%s not implemented", __FUNCTION__);
00425 return 0;
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 #ifdef CONFIG_SMP
00438 void synchronize_irq(void){
00439 #warning synchronize_irq() is not implemented.
00440
00441
00442
00443
00444
00445
00446 }
00447 #endif
00448
00458 int l4dde_irq_init(int omega0)
00459 {
00460 int i;
00461
00462 if (_initialized)
00463 return -L4_ESKIPPED;
00464
00465 use_omega0 = omega0;
00466
00467 memset(&handlers, 0, sizeof(handlers));
00468 for (i=0; i<NR_IRQS;i++)
00469 handlers[i].num = i;
00470
00471 ++_initialized;
00472 return 0;
00473 }
00474
00482 l4_threadid_t l4dde_irq_l4_id(int irq){
00483 if(irq >= NR_IRQS) return L4_INVALID_ID;
00484 if(!handlers[irq].active) return L4_INVALID_ID;
00485 return l4thread_l4_id(handlers[irq].t);
00486 }