/*************************************************************************** rt_test_module.c ------------------- begin : Thr Dec 04 2003 copyright : (C) 2003 by Jan Kiszka email : Jan.Kiszka@domain.hid ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include #include #include #include #include static int irq_no = -1; MODULE_PARM(irq_no, "i"); SEM sem; RT_TASK delay_task; /* begin shared RT-IRQ stuff */ struct suspend_handler { struct list_head chain; void (*suspend_handler)(int, void*); void *dev_id; }; static struct list_head susp_handler[NR_IRQS]; static spinlock_t susp_handler_lock = SPIN_LOCK_UNLOCKED; int request_shared_rtirq(unsigned int irq, void (*irq_handler)(int, void *, struct pt_regs *), void (*suspend_handler)(int, void *), unsigned long flags, char *dev_name, void *dev_id) { struct suspend_handler *new_handler; unsigned long cpu_flags; int result; new_handler = kmalloc(sizeof(struct suspend_handler), GFP_KERNEL); if (!new_handler) return -ENOMEM; new_handler->suspend_handler = suspend_handler; new_handler->dev_id = dev_id; result = request_irq(irq, irq_handler, flags, dev_name, dev_id); if (result < 0) { kfree(new_handler); return result; } cpu_flags = rt_spin_lock_irqsave(&susp_handler_lock); list_add_tail(&new_handler->chain, &susp_handler[irq]); rt_spin_unlock_irqrestore(cpu_flags, &susp_handler_lock); return 0; } void free_shared_rtirq(unsigned int irq, void *dev_id) { struct list_head *entry; struct suspend_handler *handler; unsigned long flags; flags = rt_spin_lock_irqsave(&susp_handler_lock); list_for_each(entry, &susp_handler[irq]) { handler = list_entry(entry, struct suspend_handler, chain); if (handler->dev_id == dev_id) { list_del(entry); rt_spin_unlock_irqrestore(flags, &susp_handler_lock); kfree(handler); goto out; } } rt_spin_unlock_irqrestore(flags, &susp_handler_lock); out: free_irq(irq, dev_id); } EXPORT_SYMBOL(request_shared_rtirq); EXPORT_SYMBOL(free_shared_rtirq); /* end shared RT-IRQ stuff */ /* REPLACE: */ static void rt_irq_handler(int irq, unsigned long data) /* WITH: static void arti_irq_trampoline (unsigned irq) */ { struct list_head *entry; struct suspend_handler *cur_handler; int shared; /* ADD: TRACE_RTAI_GLOBAL_IRQ_ENTRY(irq,0); if (arti_realtime_irq[irq].handler) { */ shared = 0; spin_lock(&susp_handler_lock); list_for_each(entry, &susp_handler[irq]) { cur_handler = list_entry(entry, struct suspend_handler, chain); cur_handler->suspend_handler(irq, cur_handler->dev_id); shared = 1; } spin_unlock(&susp_handler_lock); /* REPLACE: */ rt_enable_irq(irq); rt_sem_signal(&sem); /* WITH: arti_realtime_irq[irq].handler(irq,arti_realtime_irq[irq].cookie); */ if (shared) adeos_propagate_irq(irq); /* ADD: } else adeos_propagate_irq(irq); TRACE_RTAI_GLOBAL_IRQ_EXIT(); */ } void rt_delay_task(int arg) { while (1) { rt_sem_wait(&sem); rt_busy_sleep(50000000ll); /* freeze system for 50 ms */ } } int init_module() { int i; printk("Shared RT-IRQ test loaded\n"); for (i = 0; i < NR_IRQS; i++) INIT_LIST_HEAD(&susp_handler[i]); if (rt_request_global_irq_ext(irq_no, (void(*)(void))rt_irq_handler, 0) < 0) { printk("Failed to alloc irq %d.\n", irq_no); return 1; } rt_sem_init(&sem, 0); rt_task_init(&delay_task, rt_delay_task, 0, 4096, 10, 0, 0); rt_task_resume(&delay_task); return 0; } void cleanup_module() { rt_free_global_irq(irq_no); rt_task_delete(&delay_task); rt_sem_delete(&sem); }