summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorJustus Winter <justus@gnupg.org>2016-02-25 18:46:32 +0100
committerJustus Winter <justus@gnupg.org>2016-02-25 18:46:32 +0100
commit9ad7eb46b65b7324dd5f2c6f5568b6a0e033a5f4 (patch)
treeaab92d03e843bcc7423124b2ec069ccb6be8e7e4 /linux
parente7e91cc329b6a064d9703829911e940d7395d0a3 (diff)
70_dde.patch
Diffstat (limited to 'linux')
-rw-r--r--linux/dev/arch/i386/kernel/irq.c81
-rw-r--r--linux/dev/drivers/block/genhd.c4
2 files changed, 83 insertions, 2 deletions
diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c
index 7753814..b7dfa1a 100644
--- a/linux/dev/arch/i386/kernel/irq.c
+++ b/linux/dev/arch/i386/kernel/irq.c
@@ -83,6 +83,7 @@ struct linux_action
void *dev_id;
struct linux_action *next;
unsigned long flags;
+ volatile ipc_port_t delivery_port;
};
static struct linux_action *irq_action[16] =
@@ -102,6 +103,7 @@ linux_intr (int irq)
{
struct pt_regs regs;
struct linux_action *action = *(irq_action + irq);
+ struct linux_action **prev = &irq_action[irq];
unsigned long flags;
kstat.interrupts[irq]++;
@@ -113,7 +115,37 @@ linux_intr (int irq)
while (action)
{
- action->handler (irq, action->dev_id, &regs);
+ // TODO I might need to check whether the interrupt belongs to
+ // the current device. But I don't do it for now.
+ if (action->delivery_port)
+ {
+ /* The reference of the port was increased
+ * when the port was installed.
+ * If the reference is 1, it means the port should
+ * have been destroyed and I destroy it now. */
+ if (action->delivery_port
+ && action->delivery_port->ip_references == 1)
+ {
+ mark_intr_removed (irq, action->delivery_port);
+ ipc_port_release (action->delivery_port);
+ *prev = action->next;
+ printk ("irq handler %d: release an dead delivery port\n", irq);
+ linux_kfree(action);
+ action = *prev;
+ continue;
+ }
+ else
+ {
+ /* We disable the irq here and it will be enabled
+ * after the interrupt is handled by the user space driver. */
+ disable_irq (irq);
+ queue_intr (irq, action->delivery_port);
+ }
+
+ }
+ else if (action->handler)
+ action->handler (irq, action->dev_id, &regs);
+ prev = &action->next;
action = action->next;
}
@@ -233,6 +265,7 @@ setup_x86_irq (int irq, struct linux_action *new)
}
while (old);
shared = 1;
+ printk("store a new irq %d\n", irq);
}
save_flags (flags);
@@ -250,6 +283,51 @@ setup_x86_irq (int irq, struct linux_action *new)
return 0;
}
+int
+install_user_intr_handler (unsigned int irq, unsigned long flags,
+ ipc_port_t dest)
+{
+ struct linux_action *action;
+ struct linux_action *old;
+ int retval;
+
+ 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->delivery_port == dest)
+ {
+ printk ("The interrupt handler has 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 = NULL;
+ action->flags = flags;
+ action->delivery_port = dest;
+
+ retval = setup_x86_irq (irq, action);
+ if (retval)
+ linux_kfree (action);
+
+ return linux_to_mach_error (retval);
+}
+
/*
* Attach a handler to an IRQ.
*/
@@ -278,6 +356,7 @@ request_irq (unsigned int irq, void (*handler) (int, void *, struct pt_regs *),
action->next = NULL;
action->dev_id = dev_id;
action->flags = flags;
+ action->delivery_port = NULL;
retval = setup_x86_irq (irq, action);
if (retval)
diff --git a/linux/dev/drivers/block/genhd.c b/linux/dev/drivers/block/genhd.c
index 3a86138..4a36f7f 100644
--- a/linux/dev/drivers/block/genhd.c
+++ b/linux/dev/drivers/block/genhd.c
@@ -812,7 +812,9 @@ void device_setup(void)
#ifdef MACH
linux_intr_pri = SPL6;
#endif
- net_dev_init();
+ extern char *kernel_cmdline;
+ if (!strstr(kernel_cmdline, " nonetdev"))
+ net_dev_init();
#endif
#ifndef MACH
console_map_init();