summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefrag.am4
-rw-r--r--device/ds_routines.c56
-rw-r--r--device/ds_routines.h3
-rw-r--r--device/intr.c309
-rw-r--r--device/intr.h50
-rw-r--r--include/device/device.defs20
-rw-r--r--include/device/notify.defs36
-rw-r--r--include/device/notify.h34
-rw-r--r--kern/startup.c4
-rw-r--r--linux/dev/arch/i386/kernel/irq.c130
-rw-r--r--linux/dev/drivers/block/genhd.c4
-rw-r--r--linux/src/include/asm-i386/irq.h2
12 files changed, 620 insertions, 32 deletions
diff --git a/Makefrag.am b/Makefrag.am
index 9cf976a5..ea612275 100644
--- a/Makefrag.am
+++ b/Makefrag.am
@@ -314,6 +314,8 @@ libkernel_a_SOURCES += \
device/ds_routines.h \
device/if_ether.h \
device/if_hdr.h \
+ device/intr.c \
+ device/intr.h \
device/io_req.h \
device/net_io.c \
device/net_io.h \
@@ -361,6 +363,8 @@ include_device_HEADERS = \
include/device/device_types.h \
include/device/disk_status.h \
include/device/net_status.h \
+ include/device/notify.defs \
+ include/device/notify.h \
include/device/tape_status.h \
include/device/tty_status.h
diff --git a/device/ds_routines.c b/device/ds_routines.c
index fc051e8f..1cc38f98 100644
--- a/device/ds_routines.c
+++ b/device/ds_routines.c
@@ -92,6 +92,7 @@
#include <device/device_port.h>
#include <device/device_reply.user.h>
#include <device/device_emul.h>
+#include <device/intr.h>
#include <machine/machspl.h>
@@ -319,6 +320,48 @@ ds_device_map (device_t dev, vm_prot_t prot, vm_offset_t offset,
offset, size, pager, unmap);
}
+/* TODO: missing deregister support */
+io_return_t
+ds_device_intr_register (ipc_port_t master_port, int line,
+ int id, int flags, ipc_port_t receive_port)
+{
+#ifdef MACH_XEN
+ return D_INVALID_OPERATION;
+#else /* MACH_XEN */
+ io_return_t ret;
+
+ /* Open must be called on the master device port. */
+ if (master_port != master_device_port)
+ return D_INVALID_OPERATION;
+
+ /* XXX: move to arch-specific */
+ if (line < 0 || line >= 16)
+ return D_INVALID_OPERATION;
+
+ user_intr_t *user_intr = insert_intr_entry (line, receive_port);
+ if (!user_intr)
+ return D_NO_MEMORY;
+ // TODO The original port should be replaced
+ // when the same device driver calls it again,
+ // in order to handle the case that the device driver crashes and restarts.
+ ret = install_user_intr_handler (line, flags, user_intr);
+
+ if (ret == 0)
+ {
+ /* If the port is installed successfully, increase its reference by 1.
+ * Thus, the port won't be destroyed after its task is terminated. */
+ ip_reference (receive_port);
+
+ /* For now netdde calls device_intr_enable once after registration. Assume
+ * it does so for now. When we move to IRQ acknowledgment convention we will
+ * change this. */
+ __disable_irq (line);
+ }
+
+ return ret;
+#endif /* MACH_XEN */
+}
+
boolean_t
ds_notify (mach_msg_header_t *msg)
{
@@ -1799,6 +1842,19 @@ device_writev_trap (mach_device_t device, dev_mode_t mode,
return (result);
}
+kern_return_t
+ds_device_intr_enable(ipc_port_t master_port, int line, char status)
+{
+#ifdef MACH_XEN
+ return D_INVALID_OPERATION;
+#else /* MACH_XEN */
+ if (master_port != master_device_port)
+ return D_INVALID_OPERATION;
+
+ return user_intr_enable(line, status);
+#endif /* MACH_XEN */
+}
+
struct device_emulation_ops mach_device_emulation_ops =
{
(void*) mach_device_reference,
diff --git a/device/ds_routines.h b/device/ds_routines.h
index c0543cbc..e9f115fc 100644
--- a/device/ds_routines.h
+++ b/device/ds_routines.h
@@ -83,4 +83,7 @@ io_return_t ds_device_writev_trap(
io_buf_vec_t *iovec,
vm_size_t count);
+/* XXX arch-specific */
+extern ipc_port_t intr_rcv_ports[16];
+
#endif /* DS_ROUTINES_H */
diff --git a/device/intr.c b/device/intr.c
new file mode 100644
index 00000000..bbbdc92d
--- /dev/null
+++ b/device/intr.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2010, 2011, 2016, 2019 Free Software Foundation, Inc.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE FREE SOFTWARE FOUNDATIONALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ */
+
+#include <device/intr.h>
+#include <device/ds_routines.h>
+#include <kern/queue.h>
+#include <kern/printf.h>
+#include <machine/spl.h>
+
+#ifndef MACH_XEN
+
+static boolean_t deliver_intr (int line, ipc_port_t dest_port);
+
+static queue_head_t intr_queue;
+/* The total number of unprocessed interrupts. */
+static int tot_num_intr;
+
+static struct intr_entry *
+search_intr (int line, ipc_port_t dest)
+{
+ struct intr_entry *e;
+ queue_iterate (&intr_queue, e, struct intr_entry *, chain)
+ {
+ if (e->dest == dest && e->line == line)
+ return e;
+ }
+ return NULL;
+}
+
+static struct intr_entry *
+search_intr_line (int line)
+{
+ struct intr_entry *e;
+ queue_iterate (&intr_queue, e, struct intr_entry *, chain)
+ {
+ if (e->line == line &&
+ (e->dest != MACH_PORT_NULL
+ && e->dest->ip_references != 1
+ && e->unacked_interrupts))
+ return e;
+ }
+ return NULL;
+}
+
+kern_return_t user_intr_enable (int line, char status)
+{
+ struct intr_entry *e;
+ kern_return_t ret = D_SUCCESS;
+
+ spl_t s = splhigh ();
+ /* FIXME: Use search_intr instead once we get the delivery port from ds_device_intr_enable, and get rid of search_intr_line */
+ e = search_intr_line (line);
+
+ if (!e)
+ printf("didn't find user intr for interrupt %d!?\n", line);
+ else if (status)
+ {
+ if (!e->unacked_interrupts)
+ ret = D_INVALID_OPERATION;
+ else
+ e->unacked_interrupts--;
+ }
+ else
+ {
+ e->unacked_interrupts++;
+ if (!e->unacked_interrupts)
+ {
+ ret = D_INVALID_OPERATION;
+ e->unacked_interrupts--;
+ }
+ }
+ splx (s);
+
+ if (ret)
+ return ret;
+
+ if (status)
+ /* TODO: better name for generic-to-arch-specific call */
+ __enable_irq (line);
+ else
+ __disable_irq (line);
+ return D_SUCCESS;
+}
+
+/* This function can only be used in the interrupt handler. */
+static void
+queue_intr (int line, user_intr_t *e)
+{
+ /* Until userland has handled the IRQ in the driver, we have to keep it
+ * disabled. Level-triggered interrupts would keep raising otherwise. */
+ __disable_irq (line);
+
+ spl_t s = splhigh ();
+ e->unacked_interrupts++;
+ e->interrupts++;
+ tot_num_intr++;
+ splx (s);
+
+ thread_wakeup ((event_t) &intr_thread);
+}
+
+int deliver_user_intr (int line, user_intr_t *intr)
+{
+ /* 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 (intr->dest
+ && intr->dest->ip_references == 1)
+ {
+ printf ("irq handler %d: release a dead delivery port %p entry %p\n", line, intr->dest, intr);
+ ipc_port_release (intr->dest);
+ intr->dest = MACH_PORT_NULL;
+ thread_wakeup ((event_t) &intr_thread);
+ return 0;
+ }
+ else
+ {
+ queue_intr (line, intr);
+ return 1;
+ }
+}
+
+/* insert an interrupt entry in the queue.
+ * This entry exists in the queue until
+ * the corresponding interrupt port is removed.*/
+user_intr_t *
+insert_intr_entry (int line, ipc_port_t dest)
+{
+ struct intr_entry *e, *new, *ret;
+ int free = 0;
+
+ new = (struct intr_entry *) kalloc (sizeof (*new));
+ if (new == NULL)
+ return NULL;
+
+ /* check whether the intr entry has been in the queue. */
+ spl_t s = splhigh ();
+ e = search_intr (line, dest);
+ if (e)
+ {
+ printf ("the interrupt entry for line %d and port %p has already been inserted\n", line, dest);
+ free = 1;
+ ret = NULL;
+ goto out;
+ }
+ printf("irq handler %d: new delivery port %p entry %p\n", line, dest, new);
+ ret = new;
+ new->line = line;
+ new->dest = dest;
+ new->interrupts = 0;
+
+ /* For now netdde calls device_intr_enable once after registration. Assume
+ * it does so for now. When we move to IRQ acknowledgment convention we will
+ * change this. */
+ new->unacked_interrupts = 1;
+
+ queue_enter (&intr_queue, new, struct intr_entry *, chain);
+out:
+ splx (s);
+ if (free)
+ kfree ((vm_offset_t) new, sizeof (*new));
+ return ret;
+}
+
+void
+intr_thread (void)
+{
+ struct intr_entry *e;
+ int line;
+ ipc_port_t dest;
+ queue_init (&intr_queue);
+
+ for (;;)
+ {
+ assert_wait ((event_t) &intr_thread, FALSE);
+ /* Make sure we wake up from times to times to check for aborted processes */
+ thread_set_timeout (hz);
+ spl_t s = splhigh ();
+
+ /* Check for aborted processes */
+ queue_iterate (&intr_queue, e, struct intr_entry *, chain)
+ {
+ if ((!e->dest || e->dest->ip_references == 1) && e->unacked_interrupts)
+ {
+ printf ("irq handler %d: release dead delivery %d unacked irqs port %p entry %p\n", e->line, e->unacked_interrupts, e->dest, e);
+ /* 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 clear unacked irqs now, so the Linux
+ * handling can trigger, and we will cleanup later after the Linux
+ * handler is cleared. */
+ /* TODO: rather immediately remove from Linux handler */
+ while (e->unacked_interrupts)
+ {
+ __enable_irq(e->line);
+ e->unacked_interrupts--;
+ }
+ }
+ }
+
+ /* Now check for interrupts */
+ while (tot_num_intr)
+ {
+ int del = 0;
+
+ queue_iterate (&intr_queue, e, struct intr_entry *, chain)
+ {
+ /* if an entry doesn't have dest port,
+ * we should remove it. */
+ if (e->dest == MACH_PORT_NULL)
+ {
+ clear_wait (current_thread (), 0, 0);
+ del = 1;
+ break;
+ }
+
+ if (e->interrupts)
+ {
+ clear_wait (current_thread (), 0, 0);
+ line = e->line;
+ dest = e->dest;
+ e->interrupts--;
+ tot_num_intr--;
+
+ splx (s);
+ deliver_intr (line, dest);
+ s = splhigh ();
+ }
+ }
+
+ /* remove the entry without dest port from the queue and free it. */
+ if (del)
+ {
+ assert (!queue_empty (&intr_queue));
+ queue_remove (&intr_queue, e, struct intr_entry *, chain);
+ if (e->unacked_interrupts)
+ printf("irq handler %d: still %d unacked irqs in entry %p\n", e->line, e->unacked_interrupts, e);
+ while (e->unacked_interrupts)
+ {
+ __enable_irq(e->line);
+ e->unacked_interrupts--;
+ }
+ printf("irq handler %d: removed entry %p\n", e->line, e);
+ splx (s);
+ kfree ((vm_offset_t) e, sizeof (*e));
+ s = splhigh ();
+ }
+ }
+ splx (s);
+ thread_block (NULL);
+ }
+}
+
+static boolean_t
+deliver_intr (int line, ipc_port_t dest_port)
+{
+ ipc_kmsg_t kmsg;
+ device_intr_notification_t *n;
+ mach_port_t dest = (mach_port_t) dest_port;
+
+ if (dest == MACH_PORT_NULL)
+ return FALSE;
+
+ kmsg = ikm_alloc(sizeof *n);
+ if (kmsg == IKM_NULL)
+ return FALSE;
+
+ ikm_init(kmsg, sizeof *n);
+ n = (device_intr_notification_t *) &kmsg->ikm_header;
+
+ mach_msg_header_t *m = &n->intr_header;
+ mach_msg_type_t *t = &n->intr_type;
+
+ m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0);
+ m->msgh_size = sizeof *n;
+ m->msgh_seqno = DEVICE_NOTIFY_MSGH_SEQNO;
+ m->msgh_local_port = MACH_PORT_NULL;
+ m->msgh_remote_port = MACH_PORT_NULL;
+ m->msgh_id = DEVICE_INTR_NOTIFY;
+
+ t->msgt_name = MACH_MSG_TYPE_INTEGER_32;
+ t->msgt_size = 32;
+ t->msgt_number = 1;
+ t->msgt_inline = TRUE;
+ t->msgt_longform = FALSE;
+ t->msgt_deallocate = FALSE;
+ t->msgt_unused = 0;
+
+ n->intr_header.msgh_remote_port = dest;
+ n->line = line;
+
+ ipc_port_copy_send (dest_port);
+ ipc_mqueue_send_always(kmsg);
+
+ return TRUE;
+}
+#endif /* MACH_XEN */
diff --git a/device/intr.h b/device/intr.h
new file mode 100644
index 00000000..df282c05
--- /dev/null
+++ b/device/intr.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010, 2011, 2019 Free Software Foundation, Inc.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE FREE SOFTWARE FOUNDATIONALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ */
+
+#ifndef __INTR_H__
+#define __INTR_H__
+
+#include <device/device_types.h>
+#include <kern/queue.h>
+#include <device/notify.h>
+
+typedef struct intr_entry
+{
+ queue_chain_t chain;
+ ipc_port_t dest;
+ int line;
+ int interrupts; /* The number of interrupts occur since last run of intr_thread. */
+ int unacked_interrupts; /* Number of times irqs were disabled for this */
+} user_intr_t;
+
+#define DEVICE_NOTIFY_MSGH_SEQNO 0
+
+int install_user_intr_handler (unsigned int line,
+ unsigned long flags,
+ user_intr_t *user_intr);
+
+/* Returns 0 if action should be removed */
+int deliver_user_intr (int line, user_intr_t *intr);
+
+user_intr_t *insert_intr_entry (int line, ipc_port_t dest);
+
+/* TODO: should rather take delivery port */
+kern_return_t user_intr_enable (int line, char status);
+
+void intr_thread (void);
+
+void __disable_irq(unsigned int);
+void __enable_irq(unsigned int);
+
+#endif
diff --git a/include/device/device.defs b/include/device/device.defs
index 409146f5..dca1be4e 100644
--- a/include/device/device.defs
+++ b/include/device/device.defs
@@ -142,3 +142,23 @@ routine device_set_filter(
in filter : filter_array_t
);
+routine device_intr_register(
+ master_port : mach_port_t;
+ in line : int;
+ in id : int;
+ in flags : int;
+ in receive_port : mach_port_send_t
+ );
+
+/*
+ * enable/disable the specified line.
+ */
+/* XXX: Naming a function taht can disable something "xxx_enable" is confusing. */
+/* Is the disable part actually used at all? AIUI, the kernel IRQ handler
+should always disable the line; and the userspace driver only has to
+reenable it, after acknowledging and handling the interrupt...
+*/
+routine device_intr_enable(
+ master_port : mach_port_t;
+ line : int;
+ status : char);
diff --git a/include/device/notify.defs b/include/device/notify.defs
new file mode 100644
index 00000000..ea374d26
--- /dev/null
+++ b/include/device/notify.defs
@@ -0,0 +1,36 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+subsystem notify 100;
+
+#include <mach/std_types.defs>
+
+serverprefix do_;
+serverdemux device_intr_notify_server;
+
+simpleroutine device_intr_notify(
+ notify : notify_port_t;
+ name : int);
diff --git a/include/device/notify.h b/include/device/notify.h
new file mode 100644
index 00000000..b6907b03
--- /dev/null
+++ b/include/device/notify.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010 Free Software Foundation, Inc.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE FREE SOFTWARE FOUNDATIONALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ */
+
+/*
+ * Device notification definitions.
+ */
+
+#ifndef _MACH_DEVICE_NOTIFY_H_
+#define _MACH_DEVICE_NOTIFY_H_
+
+#include <mach/port.h>
+#include <mach/message.h>
+
+typedef struct
+{
+ mach_msg_header_t intr_header;
+ mach_msg_type_t intr_type;
+ int line;
+} device_intr_notification_t;
+
+#define DEVICE_INTR_NOTIFY 100
+
+#endif /* _MACH_DEVICE_NOTIFY_H_ */
diff --git a/kern/startup.c b/kern/startup.c
index 56e05b3f..1f873192 100644
--- a/kern/startup.c
+++ b/kern/startup.c
@@ -63,6 +63,7 @@
#include <machine/model_dep.h>
#include <mach/version.h>
#include <device/device_init.h>
+#include <device/intr.h>
#if MACH_KDB
#include <device/cons.h>
@@ -228,6 +229,9 @@ void start_kernel_threads(void)
(void) kernel_thread(kernel_task, reaper_thread, (char *) 0);
(void) kernel_thread(kernel_task, swapin_thread, (char *) 0);
(void) kernel_thread(kernel_task, sched_thread, (char *) 0);
+#ifndef MACH_XEN
+ (void) kernel_thread(kernel_task, intr_thread, (char *)0);
+#endif /* MACH_XEN */
#if NCPUS > 1
/*
diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c
index 18448638..bc752013 100644
--- a/linux/dev/arch/i386/kernel/irq.c
+++ b/linux/dev/arch/i386/kernel/irq.c
@@ -50,6 +50,8 @@
#include <linux/dev/glue/glue.h>
#include <machine/machspl.h>
+#include <device/intr.h>
+
#if 0
/* XXX: This is the way it's done in linux 2.2. GNU Mach currently uses intr_count. It should be made using local_{bh/irq}_count instead (through hardirq_enter/exit) for SMP support. */
unsigned int local_bh_count[NR_CPUS];
@@ -76,6 +78,7 @@ struct linux_action
void *dev_id;
struct linux_action *next;
unsigned long flags;
+ user_intr_t *user_intr;
};
static struct linux_action *irq_action[16] =
@@ -87,35 +90,6 @@ static struct linux_action *irq_action[16] =
};
/*
- * Generic interrupt handler for Linux devices.
- * Set up a fake `struct pt_regs' then call the real handler.
- */
-static void
-linux_intr (int irq)
-{
- struct pt_regs regs;
- struct linux_action *action = *(irq_action + irq);
- unsigned long flags;
-
- kstat.interrupts[irq]++;
- intr_count++;
-
- save_flags (flags);
- if (action && (action->flags & SA_INTERRUPT))
- cli ();
-
- while (action)
- {
- action->handler (irq, action->dev_id, &regs);
- action = action->next;
- }
-
- restore_flags (flags);
-
- intr_count--;
-}
-
-/*
* Mask an IRQ.
*/
static inline void
@@ -158,6 +132,58 @@ unmask_irq (unsigned int irq_nr)
}
}
+/*
+ * Generic interrupt handler for Linux devices.
+ * Set up a fake `struct pt_regs' then call the real handler.
+ */
+static void
+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]++;
+ intr_count++;
+
+ save_flags (flags);
+ if (action && (action->flags & SA_INTERRUPT))
+ cli ();
+
+ while (action)
+ {
+ // 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)
+ {
+ if (!deliver_user_intr(irq, action->user_intr))
+ {
+ *prev = action->next;
+ linux_kfree(action);
+ action = *prev;
+ continue;
+ }
+ }
+ else if (action->handler)
+ action->handler (irq, action->dev_id, &regs);
+ prev = &action->next;
+ action = action->next;
+ }
+
+ if (!irq_action[irq])
+ {
+ /* No handler any more, disable interrupt */
+ mask_irq (irq);
+ ivect[irq] = intnull;
+ iunit[irq] = irq;
+ }
+
+ restore_flags (flags);
+
+ intr_count--;
+}
+
/* Count how many subsystems requested to disable each IRQ */
static unsigned ndisabled_irq[NR_IRQS];
@@ -273,6 +299,51 @@ setup_x86_irq (int irq, struct linux_action *new)
return 0;
}
+int
+install_user_intr_handler (unsigned int irq, unsigned long flags,
+ user_intr_t *user_intr)
+{
+ 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->user_intr && old->user_intr->dest == user_intr->dest)
+ {
+ 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 = NULL;
+ action->flags = flags;
+ 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.
*/
@@ -301,6 +372,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->user_intr = 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 23c1e120..44ba6533 100644
--- a/linux/dev/drivers/block/genhd.c
+++ b/linux/dev/drivers/block/genhd.c
@@ -1057,7 +1057,9 @@ void device_setup(void)
scsi_dev_init();
#endif
#ifdef CONFIG_INET
- net_dev_init();
+ extern char *kernel_cmdline;
+ if (!strstr(kernel_cmdline, " nonetdev"))
+ net_dev_init();
#endif
#ifndef MACH
console_map_init();
diff --git a/linux/src/include/asm-i386/irq.h b/linux/src/include/asm-i386/irq.h
index d7d1e3c5..c75744a5 100644
--- a/linux/src/include/asm-i386/irq.h
+++ b/linux/src/include/asm-i386/irq.h
@@ -16,8 +16,6 @@
#define TIMER_IRQ 0
-extern void __disable_irq(unsigned int);
-extern void __enable_irq(unsigned int);
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);