irqdev: make deliver_user_intr a linux irq handler --- device/intr.c | 30 ++++++++++++++----- device/intr.h | 1 - linux/dev/arch/i386/kernel/irq.c | 51 +------------------------------- 3 files changed, 24 insertions(+), 58 deletions(-)
diff --git a/device/intr.c b/device/intr.c index c98e5c39..b60a6a28 100644 --- a/device/intr.c +++ b/device/intr.c @@ -27,6 +27,10 @@ extern struct irqdev irqtab; #define main_intr_queue irqtab.intr_queue static boolean_t deliver_intr (int id, ipc_port_t dst_port); +#define SA_SHIRQ 0x04000000 +struct pt_regs; +extern int request_irq (unsigned int irq, void (*handler) (int, void *, struct pt_regs *), + unsigned long flags, const char *device, void *dev_id); extern void free_irq (unsigned int irq, void *dev_id); #define PROTECT(lock, critical_section) \ @@ -84,18 +88,18 @@ irq_acknowledge (ipc_port_t receive_port) return D_SUCCESS; } -void -deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e) +static void +deliver_user_intr (int id, void *dev_id, struct pt_regs *regs) { + spl_t s = splhigh(); + user_intr_t *e = dev_id; /* Until userland has handled the IRQ in the driver, we have to keep it * disabled. Level-triggered interrupts would keep raising otherwise. */ - __disable_irq (dev->irq[id]); - - spl_t s = splhigh (); + __disable_irq (irqtab.irq[id]); e->n_unacked++; e->interrupts++; - dev->tot_num_intr++; - splx (s); + irqtab.tot_num_intr++; + splx(s); thread_wakeup ((event_t) &intr_thread); } @@ -283,4 +287,16 @@ deliver_intr (int id, ipc_port_t dst_port) return TRUE; } +int +install_user_intr_handler (struct irqdev *dev, int id, unsigned long flags, + user_intr_t *user_intr) +{ + if (id >= NINTR) + return D_INVALID_OPERATION; + unsigned int irq = dev->irq[id]; + if (irq >= NINTR) + return D_INVALID_OPERATION; + return request_irq (id, deliver_user_intr, SA_SHIRQ, NULL, user_intr); +} + #endif /* MACH_XEN */ diff --git a/device/intr.h b/device/intr.h index 55fc60dc..b1c09e6c 100644 --- a/device/intr.h +++ b/device/intr.h @@ -51,7 +51,6 @@ struct irqdev { }; extern int install_user_intr_handler (struct irqdev *dev, int id, unsigned long flags, user_intr_t *e); -extern void deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e); extern user_intr_t *insert_intr_entry (struct irqdev *dev, int id, ipc_port_t receive_port); void intr_thread (void); diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c index a01f7ab6..aee10462 100644 --- a/linux/dev/arch/i386/kernel/irq.c +++ b/linux/dev/arch/i386/kernel/irq.c @@ -111,9 +111,7 @@ linux_intr (int irq) { // TODO I might need to check whether the interrupt belongs to // the current device. But I don't do it for now. - if (action->user_intr) - deliver_user_intr(&irqtab, irq, action->user_intr); - else if (action->handler) + if (action->handler) action->handler (irq, action->dev_id, ®s); action = action->next; } @@ -209,53 +207,6 @@ setup_x86_irq (int irq, struct linux_action *new) return 0; } -int -install_user_intr_handler (struct irqdev *dev, int id, unsigned long flags, - user_intr_t *user_intr) -{ - struct linux_action *action; - struct linux_action *old; - int retval; - - unsigned int irq = dev->irq[id]; - - assert (irq < 16); - - /* Test whether the irq handler has been set */ - // TODO I need to protect the array when iterating it. - old = irq_action[irq]; - while (old) - { - if (old->user_intr && old->user_intr->dst_port == user_intr->dst_port) - { - printk ("The interrupt handler has already been installed on line %d", irq); - return linux_to_mach_error (-EAGAIN); - } - old = old->next; - } - - /* - * Hmm... Should I use `kalloc()' ? - * By OKUJI Yoshinori. - */ - action = (struct linux_action *) - linux_kmalloc (sizeof (struct linux_action), GFP_KERNEL); - if (action == NULL) - return linux_to_mach_error (-ENOMEM); - - action->handler = NULL; - action->next = NULL; - action->dev_id = user_intr; - action->flags = SA_SHIRQ; - action->user_intr = user_intr; - - retval = setup_x86_irq (irq, action); - if (retval) - linux_kfree (action); - - return linux_to_mach_error (retval); -} - /* * Attach a handler to an IRQ. */ -- 2.28.0.rc1