diff -Naur linux-std/arch/i386/config.in linux-adeos/arch/i386/config.in
--- linux-std/arch/i386/config.in	Mon Feb 25 20:37:52 2002
+++ linux-adeos/arch/i386/config.in	Fri May 31 20:21:53 2002
@@ -206,6 +206,7 @@
 mainmenu_option next_comment
 comment 'General setup'
 
+bool 'Adaptive Domain Environment support' CONFIG_ADEOS
 bool 'Networking support' CONFIG_NET
 
 # Visual Workstation support is utterly broken.
diff -Naur linux-std/arch/i386/kernel/Makefile linux-adeos/arch/i386/kernel/Makefile
--- linux-std/arch/i386/kernel/Makefile	Fri Nov  9 23:21:21 2001
+++ linux-adeos/arch/i386/kernel/Makefile	Fri May 31 20:21:53 2002
@@ -14,7 +14,7 @@
 
 O_TARGET := kernel.o
 
-export-objs     := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o
+export-objs     := mca.o mtrr.o msr.o cpuid.o microcode.o ipipe.o i386_ksyms.o adeos.o
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
@@ -40,5 +40,6 @@
 obj-$(CONFIG_X86_LOCAL_APIC)	+= mpparse.o apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o acpitable.o
 obj-$(CONFIG_X86_VISWS_APIC)	+= visws_apic.o
+obj-$(CONFIG_ADEOS)		+= ipipe.o adeos.o
 
 include $(TOPDIR)/Rules.make
diff -Naur linux-std/arch/i386/kernel/adeos.c linux-adeos/arch/i386/kernel/adeos.c
--- linux-std/arch/i386/kernel/adeos.c	Thu Jan  1 01:00:00 1970
+++ linux-adeos/arch/i386/kernel/adeos.c	Fri May 31 20:21:53 2002
@@ -0,0 +1,73 @@
+/*
+ *   linux/arch/i386/kernel/adeos.c
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   This code implements the architecture-dependent ADEOS support.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <asm/system.h>
+
+void __adeos_init_domain (adomain_t *adp, adattr_t *attr)
+
+{
+    int estacksz = attr->estacksz > 0 ? attr->estacksz : 4096;
+    int **psp = &adp->sp;
+
+    adp->estackbase = (int *)kmalloc(estacksz,GFP_KERNEL);
+
+    if (adp->estackbase == NULL)
+	panic("no memory for domain entry stack");
+
+    adp->sp = adp->estackbase;
+    **psp = 0;
+    *psp = (int *)(((unsigned long)*psp + estacksz - 0x10) & ~0xf);
+    *--(*psp) = 0;
+    *--(*psp) = (int)attr->entry;
+}
+
+void __adeos_switch_domain (adomain_t *adp)
+
+{
+    __asm__ __volatile__( \
+	"pushl %%eax\n\t" \
+	"pushl %%edx\n\t" \
+	"pushl %%ecx\n\t" \
+	"pushl %%ebx\n\t" \
+	"pushl %%ebp\n\t" \
+	"pushl %%edi\n\t" \
+	"pushl %%esi\n\t" \
+	"movl "SYMBOL_NAME_STR(adp_current)", %%edx\n\t" \
+	"pushl $1f\n\t" \
+	"movl %%esp, (%%edx)\n\t" \
+	"movl (%%ecx), %%esp\n\t" \
+	"movl %%ecx, "SYMBOL_NAME_STR(adp_current)"\n\t" \
+	"ret\n\t" \
+"1:	 popl %%esi\n\t" \
+	"popl %%edi\n\t" \
+	"popl %%ebp\n\t" \
+	"popl %%ebx\n\t" \
+	"popl %%ecx\n\t" \
+	"popl %%edx\n\t" \
+	"popl %%eax\n\t" \
+	: \
+	: "c" (adp));
+}
diff -Naur linux-std/arch/i386/kernel/apic.c linux-adeos/arch/i386/kernel/apic.c
--- linux-std/arch/i386/kernel/apic.c	Mon Feb 25 20:37:52 2002
+++ linux-adeos/arch/i386/kernel/apic.c	Fri May 31 20:21:53 2002
@@ -1033,7 +1033,10 @@
 	 * NOTE! We'd better ACK the irq immediately,
 	 * because timer handling can be slow.
 	 */
+#ifndef CONFIG_ADEOS
+	/* IRQ acknowledging is in the hands of the IPIPE exclusively. */
 	ack_APIC_irq();
+#endif
 	/*
 	 * update_process_times() expects us to have done irq_enter().
 	 * Besides, if we don't timer interrupts ignore the global
@@ -1060,8 +1063,11 @@
 	 * Spurious interrupts should not be ACKed.
 	 */
 	v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
+#ifndef CONFIG_ADEOS
+	/* IRQ acknowledging is in the hands of the IPIPE exclusively. */
 	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
 		ack_APIC_irq();
+#endif
 
 	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
 	printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n",
@@ -1080,7 +1086,10 @@
 	v = apic_read(APIC_ESR);
 	apic_write(APIC_ESR, 0);
 	v1 = apic_read(APIC_ESR);
+#ifndef CONFIG_ADEOS
+	/* IRQ acknowledging is in the hands of the IPIPE exclusively. */
 	ack_APIC_irq();
+#endif
 	atomic_inc(&irq_err_count);
 
 	/* Here is what the APIC error bits mean:
diff -Naur linux-std/arch/i386/kernel/entry.S linux-adeos/arch/i386/kernel/entry.S
--- linux-std/arch/i386/kernel/entry.S	Mon Feb 25 20:37:53 2002
+++ linux-adeos/arch/i386/kernel/entry.S	Fri May 31 20:21:53 2002
@@ -176,6 +176,9 @@
 
 
 ENTRY(ret_from_fork)
+#ifdef CONFIG_ADEOS
+	sti
+#endif /* CONFIG_ADEOS */	
 	pushl %ebx
 	call SYMBOL_NAME(schedule_tail)
 	addl $4, %esp
@@ -202,17 +205,28 @@
 	call *SYMBOL_NAME(sys_call_table)(,%eax,4)
 	movl %eax,EAX(%esp)		# save the return value
 ENTRY(ret_from_sys_call)
-	cli				# need_resched and signals atomic test
+#ifdef CONFIG_ADEOS
+	call SYMBOL_NAME(adeos_stall_ipipe)
+#else /* !CONFIG_ADEOS */
+	cli
+#endif /* CONFIG_ADEOS */
 	cmpl $0,need_resched(%ebx)
 	jne reschedule
 	cmpl $0,sigpending(%ebx)
 	jne signal_return
+#ifdef CONFIG_ADEOS
+	call SYMBOL_NAME(adeos_unstall_ipipe)
+#endif /* CONFIG_ADEOS */
 restore_all:
 	RESTORE_ALL
 
 	ALIGN
 signal_return:
-	sti				# we can get here from an interrupt handler
+#ifdef CONFIG_ADEOS
+	call SYMBOL_NAME(adeos_unstall_ipipe)
+#else /* !CONFIG_ADEOS */
+	sti
+#endif /* CONFIG_ADEOS */
 	testl $(VM_MASK),EFLAGS(%esp)
 	movl %esp,%eax
 	jne v86_signal_return
diff -Naur linux-std/arch/i386/kernel/i8259.c linux-adeos/arch/i386/kernel/i8259.c
--- linux-std/arch/i386/kernel/i8259.c	Tue Sep 18 08:03:09 2001
+++ linux-adeos/arch/i386/kernel/i8259.c	Fri May 31 20:21:53 2002
@@ -290,12 +290,16 @@
 
 handle_real_irq:
 	if (irq & 8) {
+#ifndef CONFIG_ADEOS
 		inb(0xA1);		/* DUMMY - (do we need this?) */
+#endif
 		outb(cached_A1,0xA1);
 		outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
 		outb(0x62,0x20);	/* 'Specific EOI' to master-IRQ2 */
 	} else {
+#ifndef CONFIG_ADEOS
 		inb(0x21);		/* DUMMY - (do we need this?) */
+#endif
 		outb(cached_21,0x21);
 		outb(0x60+irq,0x20);	/* 'Specific EOI' to master */
 	}
@@ -443,7 +447,6 @@
 void __init init_IRQ(void)
 {
 	int i;
-
 #ifndef CONFIG_X86_VISWS_APIC
 	init_ISA_irqs();
 #else
diff -Naur linux-std/arch/i386/kernel/ipipe.c linux-adeos/arch/i386/kernel/ipipe.c
--- linux-std/arch/i386/kernel/ipipe.c	Thu Jan  1 01:00:00 1970
+++ linux-adeos/arch/i386/kernel/ipipe.c	Sun Jun  2 17:13:59 2002
@@ -0,0 +1,439 @@
+/*
+ *   linux/arch/i386/kernel/ipipe.c
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   This code implements the ADEOS interrupt pipeline mechanism.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+#include <asm/system.h>
+#include <asm/hw_irq.h>
+#include <asm/irq.h>
+#include <asm/desc.h>
+
+extern struct desc_struct idt_table[];
+
+extern void __adeos_switch_domain(adomain_t *adp);
+
+/* Lifted from i8259.c */ 
+#define ipipe_set_gate(gate_addr,type,dpl,addr)  \
+do { \
+  int __d0, __d1; \
+  __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
+	"movw %4,%%dx\n\t" \
+	"movl %%eax,%0\n\t" \
+	"movl %%edx,%1" \
+	:"=m" (*((long *) (gate_addr))), \
+	 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
+	:"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
+	 "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
+} while (0)
+
+#define ipipe_set_intr_gate(vector,addr) \
+ipipe_set_gate(idt_table+vector,14,0,addr)
+
+#define ipipe_call_handler(adp,irq) \
+do { \
+   __asm__ __volatile__ ("pushfl; push %cs"); \
+   (adp)->irqs[irq].handler(); \
+} while(0)
+
+#ifdef CONFIG_ADEOS_APIC
+
+#define ipipe_set_irq_bit(adp,irq) \
+do { \
+    set_bit(irq & 0x1f,&adp->irq_indirect_pending[irq >> 5]); \
+    set_bit(irq >> 5,&adp->irq_pending); \
+} while(0)
+
+#else /* !CONFIG_ADEOS_APIC */
+
+#define ipipe_set_irq_bit(adp,irq) set_bit(irq,&adp->irq_pending)
+
+#endif /* CONFIG_ADEOS_APIC */
+
+#define BUILD_IRQ_BODY() \
+__asm__( \
+	"\n" __ALIGN_STR"\n" \
+        SYMBOL_NAME_STR(ipipe_irq_common) ":\n\t" \
+	"pushl %es\n\t" \
+	"pushl %ds\n\t" \
+	"pushl %eax\n\t" \
+	"pushl %ebp\n\t" \
+	"pushl %edi\n\t" \
+	"pushl %esi\n\t" \
+	"pushl %edx\n\t" \
+	"pushl %ecx\n\t" \
+	"pushl %ebx\n\t" \
+	"movl $" STR(__KERNEL_DS) ",%edx\n\t" \
+	"movl %edx,%ds\n\t" \
+	"movl %edx,%es\n\t" \
+	"call " SYMBOL_NAME_STR(ipipe_handle_irq) "\n\t" \
+	"testl %eax,%eax\n\t" \
+	"jnz  1f\n\t" \
+        "popl %ebx\n\t" \
+	"popl %ecx\n\t" \
+	"popl %edx\n\t" \
+	"popl %esi\n\t" \
+	"popl %edi\n\t" \
+	"popl %ebp\n\t" \
+	"popl %eax\n\t" \
+	"popl %ds\n\t" \
+	"popl %es\n\t" \
+	"addl $4,%esp\n\t" \
+        "iret\n\t" \
+        "1: cld\n\t" \
+        "jmp " SYMBOL_NAME_STR(ret_from_intr) "\n");
+
+#define BUILD_IRQ_NAME(irq)  ipipe_irq_##irq(void)
+#define BUILD_1_IRQ(irq) \
+asmlinkage void BUILD_IRQ_NAME(irq); \
+__asm__( \
+	"\n" __ALIGN_STR"\n" \
+        SYMBOL_NAME_STR(ipipe_irq_) #irq ":\n\t" \
+	"pushl $"#irq" \n\t" \
+	"jmp " SYMBOL_NAME_STR(ipipe_irq_common) "\n");
+
+#define BUILD_IRQ_N(x,y) \
+BUILD_1_IRQ(x##y)
+
+#define BUILD_16_IRQS(x) \
+BUILD_IRQ_N(x,0)  BUILD_IRQ_N(x,1)  BUILD_IRQ_N(x,2)  BUILD_IRQ_N(x,3) \
+BUILD_IRQ_N(x,4)  BUILD_IRQ_N(x,5)  BUILD_IRQ_N(x,6)  BUILD_IRQ_N(x,7) \
+BUILD_IRQ_N(x,8)  BUILD_IRQ_N(x,9)  BUILD_IRQ_N(x,a)  BUILD_IRQ_N(x,b) \
+BUILD_IRQ_N(x,c)  BUILD_IRQ_N(x,d)  BUILD_IRQ_N(x,e)  BUILD_IRQ_N(x,f)
+
+BUILD_IRQ_BODY();
+
+BUILD_16_IRQS(0x0)
+#ifdef CONFIG_X86_IO_APIC
+BUILD_16_IRQS(0x1)  BUILD_16_IRQS(0x2)  BUILD_16_IRQS(0x3) BUILD_16_IRQS(0x4)
+BUILD_16_IRQS(0x5)  BUILD_16_IRQS(0x6)  BUILD_16_IRQS(0x7) BUILD_16_IRQS(0x8)
+BUILD_16_IRQS(0x9)  BUILD_16_IRQS(0xa)  BUILD_16_IRQS(0xb) BUILD_16_IRQS(0xc)
+BUILD_16_IRQS(0xd)
+#endif /* CONFIG_X86_IO_APIC */
+
+#define LIST_1_IRQ(irq) &ipipe_irq_ ## irq
+
+#define LIST_IRQ_N(x,y) \
+LIST_1_IRQ(x##y)
+
+#define LIST_16_IRQS(x) \
+LIST_IRQ_N(x,0),  LIST_IRQ_N(x,1),  LIST_IRQ_N(x,2), LIST_IRQ_N(x,3), \
+LIST_IRQ_N(x,4),  LIST_IRQ_N(x,5),  LIST_IRQ_N(x,6), LIST_IRQ_N(x,7), \
+LIST_IRQ_N(x,8),  LIST_IRQ_N(x,9),  LIST_IRQ_N(x,a), LIST_IRQ_N(x,b), \
+LIST_IRQ_N(x,c),  LIST_IRQ_N(x,d),  LIST_IRQ_N(x,e), LIST_IRQ_N(x,f)
+
+static void (*ipipe_irq_handlers[IPIPE_NR_IRQS])(void) = {
+    LIST_16_IRQS(0x0),
+#ifdef CONFIG_X86_IO_APIC
+    LIST_16_IRQS(0x1), LIST_16_IRQS(0x2), LIST_16_IRQS(0x3), LIST_16_IRQS(0x4),
+    LIST_16_IRQS(0x5), LIST_16_IRQS(0x6), LIST_16_IRQS(0x7), LIST_16_IRQS(0x8),
+    LIST_16_IRQS(0x9), LIST_16_IRQS(0xa), LIST_16_IRQS(0xb), LIST_16_IRQS(0xc),
+    LIST_16_IRQS(0xd)
+#endif /* CONFIG_X86_IO_APIC */
+};
+
+/* The pipeline data structure. Enqueues adomain_t objects by priority. */
+struct list_head i_pipeline;
+
+static int ipipe_handle_irq(struct pt_regs regs) __attribute__ ((__unused__));
+
+static __inline__ unsigned long ffnz (unsigned long word) {
+    /* Derived from bitops.h's ffs() */
+    __asm__("bsfl %1, %0"
+	    : "=r" (word)
+	    : "r"  (word));
+    return word;
+}
+
+/* ipipe_sync_events() -- Flush the pending events for the current
+   domain.  This currently only flushes the interrupt log (see
+   "Optimistic interrupt protection" from D. Stodolsky et al. for more
+   on the deferred interrupt mecanism). Every interrupt that occurred
+   while the pipeline was stalled gets played. */
+
+void ipipe_sync_events (void)
+
+{
+    unsigned long mask;
+    unsigned irq;
+
+    do
+	{
+	if (test_and_set_bit(IPIPE_SYNC_FLAG,&adp_current->status))
+	    return;
+
+	set_bit(IPIPE_STALL_FLAG,&adp_current->status);
+
+	/* Keep some fairness among interrupt sources inside the
+	   current domain: don't dispatch all hits of a given
+	   interrupt in a raw but rather cycle through the log until
+	   all interrupts are processed, one hit at a time.  Also note
+	   that in order to avoid fiddling with the processor
+	   interrupt state to have the pending irq mask updated
+	   atomically, the irq flag is first cleared, then reasserted
+	   if it appears that not all hits have been processed yet. */
+
+#ifdef CONFIG_ADEOS_APIC
+
+	while ((mask = adp_current->irq_pending) != 0)
+	    {
+	    do
+		{
+		int level = ffnz(mask);
+		unsigned long _mask = adp_current->irq_indirect_pending[level];
+
+		clear_bit(level,&adp_current->irq_pending);
+
+		do
+		    {
+		    int rank = ffnz(_mask);
+		    irq = (level << 5) + rank;
+		    clear_bit(rank,&adp_current->irq_indirect_pending[level]);
+
+		    ipipe_call_handler(adp_current,irq);
+
+		    if (!atomic_dec_and_test(&adp_current->irqs[irq].hits))
+			{
+			set_bit(rank,&adp_current->irq_indirect_pending[level]);
+			set_bit(level,&adp_current->irq_pending);
+			}
+
+		    clear_bit(rank,&_mask);
+		    }
+		while (_mask != 0);
+
+		clear_bit(level,&mask);
+		}
+	    while (mask != 0);
+	    }
+
+#else /* !CONFIG_ADEOS_APIC */
+
+	while ((mask = adp_current->irq_pending) != 0)
+	    {
+	    do
+		{
+		irq = ffnz(mask);
+		clear_bit(irq,&adp_current->irq_pending);
+
+		ipipe_call_handler(adp_current,irq);
+
+		if (!atomic_dec_and_test(&adp_current->irqs[irq].hits))
+		    set_bit(irq,&adp_current->irq_pending);
+
+		clear_bit(irq,&mask);
+		}
+	    while (mask != 0);
+	    }
+
+#endif /* CONFIG_ADEOS_APIC */
+
+	clear_bit(IPIPE_STALL_FLAG,&adp_current->status);
+	clear_bit(IPIPE_SYNC_FLAG,&adp_current->status);
+	}
+    while (adp_current->irq_pending != 0);
+}
+
+/* ipipe_handle_irq() -- ADEOS' generic IRQ handler. An optimistic
+   interrupt protection log is maintained here for each domain. */
+
+static int ipipe_handle_irq (struct pt_regs regs)
+
+{
+    unsigned irq = regs.orig_eax;
+    struct list_head *pos, *npos;
+    int acked = 0;
+
+    /* First ack, then propagate the interrupt to each domain's log. */
+
+    list_for_each_safe(pos,npos,&i_pipeline) {
+
+    	adomain_t *_adp = list_entry(pos,adomain_t,link);
+
+	/* For each domain handling the incoming IRQ, mark it as
+           pending in its log. */
+
+	if (test_bit(IPIPE_HANDLE_FLAG,&_adp->irqs[irq].control))
+	    {
+	    /* Domains that handle this IRQ are polled for
+	       acknowledging it by decreasing priority order. The
+	       first one who acks it wins. */
+
+	    if (!acked && _adp->irqs[irq].acknowledge != NULL)
+		acked = _adp->irqs[irq].acknowledge(irq);
+
+	    /* Process out-of-band interrupts now. If this IRQ can be
+	       delivered immediately, don't go through the log, but
+	       call its handler directly (no domain switch should be
+	       necessary for this, otherwise the interrupt is logged
+	       as usual). */
+
+	    if (_adp == adp_current &&
+		test_bit(IPIPE_OOB_FLAG,&_adp->irqs[irq].control) &&
+		!test_and_set_bit(IPIPE_STALL_FLAG,&_adp->status))
+	        {
+		ipipe_call_handler(_adp,irq);
+		clear_bit(IPIPE_STALL_FLAG,&_adp->status);
+		}
+	    else
+	        {
+		atomic_inc(&_adp->irqs[irq].hits);
+		ipipe_set_irq_bit(_adp,irq);
+		}
+	    }
+
+	/* If the domain does not want the IRQ to be passed down the
+	   interrupt pipe, exit the loop now. */
+
+	if (!test_bit(IPIPE_PASS_FLAG,&_adp->irqs[irq].control))
+	    break;
+    }
+
+    /* Now walk the pipeline, yielding control to the highest priority
+       domain that has pending interrupt(s). This search does not go
+       beyond the current domain in the pipeline. To understand this
+       code properly, one must keep in mind that domains having a
+       higher priority than the current one are sleeping on the
+       adeos_suspend_domain() service. In addition, domains having a
+       lower priority might otherwise have been preempted by an
+       interrupt dispatched to a more prioritary domain. Once the
+       first and most prioritary stage has been selected here, the
+       subsequent stages will be activated in turn when each visited
+       domain calls adeos_suspend_domain() to wake up its neighbour
+       down the pipeline. */
+
+    list_for_each_safe(pos,npos,&i_pipeline) {
+
+    	adomain_t *_adp = list_entry(pos,adomain_t,link);
+
+	if (test_bit(IPIPE_STALL_FLAG,&_adp->status))
+	    break; /* Stalled stage -- do not go further. */
+
+	if (_adp->irq_pending != 0)
+	    {
+	    if (_adp == adp_current)
+		ipipe_sync_events();
+	    else
+		__adeos_switch_domain(_adp);
+
+	    break;
+	    }
+	else if (_adp == adp_current)
+	    break;
+    }
+
+    return adp_current == adp_root;
+}
+
+void ipipe_init (void) {
+
+    INIT_LIST_HEAD(&i_pipeline);
+#ifdef CONFIG_ADEOS_APIC
+    printk("ADEOS: APIC support enabled.\n");
+#endif /* CONFIG_ADEOS _APIC */
+}
+
+void ipipe_create_stage (adomain_t *adp)
+
+{
+    struct list_head *pos;
+    unsigned long flags;
+    int n;
+
+#ifdef CONFIG_ADEOS_APIC
+    for (n = 0; n < IPIPE_IRQ_IWORDS; n++)
+	adp->irq_indirect_pending[n] = 0;
+#endif
+    for (n = 0; n < IPIPE_NR_IRQS; n++)
+	{
+	atomic_set(&adp->irqs[n].hits,0);
+	adp->irqs[n].acknowledge = NULL;
+	adp->irqs[n].handler = NULL;
+	adp->irqs[n].control = IPIPE_PASS_MASK;	/* Pass but don't handle */
+	}
+
+    INIT_LIST_HEAD(&adp->link);
+
+    ipipe_hw_save_flags_and_cli(flags);
+
+    list_for_each(pos,&i_pipeline) {
+    	adomain_t *_adp = list_entry(pos,adomain_t,link);
+	if (adp->priority > _adp->priority)
+            break;
+    }
+
+    list_add_tail(&adp->link,pos);
+
+    ipipe_hw_restore_flags(flags);
+}
+
+void ipipe_delete_stage (adomain_t *adp)
+
+{
+    unsigned long flags;
+
+    ipipe_hw_save_flags_and_cli(flags);
+    list_del_init(&adp->link);
+    ipipe_hw_restore_flags(flags);
+}
+
+void ipipe_renice_stage (adomain_t *adp, int newpri)
+
+{
+    struct list_head *pos;
+    unsigned long flags;
+
+    /* Allows round-robin effect if newpri == oldpri. */
+
+    ipipe_hw_save_flags_and_cli(flags);
+
+    list_del_init(&adp->link);
+
+    list_for_each(pos,&i_pipeline) {
+    	adomain_t *_adp = list_entry(pos,adomain_t,link);
+	if (newpri > _adp->priority)
+            break;
+    }
+
+    list_add_tail(&adp->link,pos);
+
+    ipipe_hw_restore_flags(flags);
+}
+
+void ipipe_hook_irq (unsigned irq,
+		     void (*handler)(void),
+		     int (*acknowledge)(unsigned irq))
+{
+    unsigned long flags;
+
+    ipipe_hw_save_flags_and_cli(flags);
+
+    adp_current->irqs[irq].handler = handler;
+    adp_current->irqs[irq].acknowledge = acknowledge;
+    adp_current->irqs[irq].control |= IPIPE_HANDLE_MASK;
+    ipipe_set_intr_gate(irq + FIRST_EXTERNAL_VECTOR,ipipe_irq_handlers[irq]);
+
+    ipipe_hw_restore_flags(flags);
+}
diff -Naur linux-std/arch/i386/kernel/irq.c linux-adeos/arch/i386/kernel/irq.c
--- linux-std/arch/i386/kernel/irq.c	Thu Oct 25 22:53:46 2001
+++ linux-adeos/arch/i386/kernel/irq.c	Fri May 31 20:21:53 2002
@@ -580,7 +580,10 @@
 
 	kstat.irqs[cpu][irq]++;
 	spin_lock(&desc->lock);
+#ifndef CONFIG_ADEOS
+	/* IRQ acknowledging is in the hands of the IPIPE exclusively. */
 	desc->handler->ack(irq);
+#endif
 	/*
 	   REPLAY is when Linux resends an IRQ that was dropped earlier
 	   WAITING is used by probe to mark irqs that are being tested
@@ -639,6 +642,7 @@
 
 	if (softirq_pending(cpu))
 		do_softirq();
+
 	return 1;
 }
 
diff -Naur linux-std/arch/i386/kernel/process.c linux-adeos/arch/i386/kernel/process.c
--- linux-std/arch/i386/kernel/process.c	Mon Feb 25 20:37:53 2002
+++ linux-adeos/arch/i386/kernel/process.c	Fri May 31 20:21:53 2002
@@ -132,6 +132,9 @@
 		void (*idle)(void) = pm_idle;
 		if (!idle)
 			idle = default_idle;
+#ifdef CONFIG_ADEOS
+		adeos_suspend_domain();
+#endif /* CONFIG_ADEOS */
 		while (!current->need_resched)
 			idle();
 		schedule();
diff -Naur linux-std/arch/i386/kernel/smp.c linux-adeos/arch/i386/kernel/smp.c
--- linux-std/arch/i386/kernel/smp.c	Fri Dec 21 18:41:53 2001
+++ linux-adeos/arch/i386/kernel/smp.c	Fri May 31 20:21:53 2002
@@ -160,8 +160,12 @@
 	unsigned long cfg;
 	unsigned long flags;
 
+#ifdef CONFIG_ADEOS
+	ipipe_hw_save_flags_and_cli(flags);
+#else
 	__save_flags(flags);
 	__cli();
+#endif
 
 		
 	/*
@@ -185,7 +189,11 @@
 	 */
 	apic_write_around(APIC_ICR, cfg);
 
+#ifdef CONFIG_ADEOS
+	ipipe_hw_restore_flags(flags);
+#else
 	__restore_flags(flags);
+#endif
 }
 
 static inline void send_IPI_mask_sequence(int mask, int vector)
@@ -353,6 +361,7 @@
  */
 
 asmlinkage void smp_invalidate_interrupt (void)
+
 {
 	unsigned long cpu = smp_processor_id();
 
@@ -376,7 +385,10 @@
 		} else
 			leave_mm(cpu);
 	}
+#ifndef CONFIG_ADEOS
+	/* IRQ acknowledging is in the hands of the IPIPE exclusively. */
 	ack_APIC_irq();
+#endif
 	clear_bit(cpu, &flush_cpumask);
 }
 
@@ -597,7 +609,10 @@
  */
 asmlinkage void smp_reschedule_interrupt(void)
 {
+#ifndef CONFIG_ADEOS
+	/* IRQ acknowledging is in the hands of the IPIPE exclusively. */
 	ack_APIC_irq();
+#endif
 }
 
 asmlinkage void smp_call_function_interrupt(void)
@@ -606,7 +621,10 @@
 	void *info = call_data->info;
 	int wait = call_data->wait;
 
+#ifndef CONFIG_ADEOS
+	/* IRQ acknowledging is in the hands of the IPIPE exclusively. */
 	ack_APIC_irq();
+#endif
 	/*
 	 * Notify initiating CPU that I've grabbed the data and am
 	 * about to execute the function
diff -Naur linux-std/arch/i386/kernel/time.c linux-adeos/arch/i386/kernel/time.c
--- linux-std/arch/i386/kernel/time.c	Mon Feb 25 20:37:53 2002
+++ linux-adeos/arch/i386/kernel/time.c	Fri May 31 20:21:53 2002
@@ -496,6 +496,7 @@
 
 		rdtscl(last_tsc_low);
 
+#ifndef CONFIG_ADEOS
 		spin_lock(&i8253_lock);
 		outb_p(0x00, 0x43);     /* latch the count ASAP */
 
@@ -505,6 +506,7 @@
 
 		count = ((LATCH-1) - count) * TICK_SIZE;
 		delay_at_last_interrupt = (count + LATCH/2) / LATCH;
+#endif /* !CONFIG_ADEOS */
 	}
  
 	do_timer_interrupt(irq, NULL, regs);
diff -Naur linux-std/arch/i386/kernel/traps.c linux-adeos/arch/i386/kernel/traps.c
--- linux-std/arch/i386/kernel/traps.c	Sun Sep 30 21:26:08 2001
+++ linux-adeos/arch/i386/kernel/traps.c	Fri May 31 20:21:53 2002
@@ -772,10 +772,53 @@
  * Pentium F0 0F bugfix can have resulted in the mapped
  * IDT being write-protected.
  */
+#ifdef CONFIG_ADEOS
+
+extern irq_desc_t irq_desc[];
+
+static int ipipe_ack_common_irq (unsigned irq) {
+    irq_desc_t *desc = irq_desc + irq;
+    spin_lock(&desc->lock);
+    desc->handler->ack(irq);
+    spin_unlock(&desc->lock);
+    return 1;
+}
+
+static int ipipe_ack_apic_irq (unsigned irq) {
+#ifdef CONFIG_ADEOS_APIC
+    ack_APIC_irq();
+#endif
+    return 1;
+}
+
+void set_intr_gate(unsigned n, void *addr)
+
+{
+    /* Redirect external interrupts only. */
+    if (n < FIRST_EXTERNAL_VECTOR)
+	_set_gate(idt_table+n,14,0,addr);
+    else
+	{
+	unsigned irq = n - FIRST_EXTERNAL_VECTOR;
+	int (*ack)(unsigned);
+
+	if (n < FIRST_SYSTEM_VECTOR)
+	    ack = &ipipe_ack_common_irq;
+	else
+	    ack = &ipipe_ack_apic_irq;
+
+	adeos_virtualize_irq(irq,(void (*)(void))addr,ack);
+	}
+}
+
+#else  /* !CONFIG_ADEOS */
+
 void set_intr_gate(unsigned int n, void *addr)
 {
 	_set_gate(idt_table+n,14,0,addr);
 }
+
+#endif /* CONFIG_ADEOS */
 
 static void __init set_trap_gate(unsigned int n, void *addr)
 {
diff -Naur linux-std/arch/i386/mm/fault.c linux-adeos/arch/i386/mm/fault.c
--- linux-std/arch/i386/mm/fault.c	Mon Feb 25 20:37:53 2002
+++ linux-adeos/arch/i386/mm/fault.c	Fri May 31 20:21:53 2002
@@ -160,7 +160,11 @@
 
 	/* It's safe to allow irq's after cr2 has been saved */
 	if (regs->eflags & X86_EFLAGS_IF)
-		local_irq_enable();
+#ifdef CONFIG_ADEOS
+	    ipipe_hw_sti();
+#else
+	    local_irq_enable();
+#endif
 
 	tsk = current;
 
diff -Naur linux-std/include/asm-i386/adeos.h linux-adeos/include/asm-i386/adeos.h
--- linux-std/include/asm-i386/adeos.h	Thu Jan  1 01:00:00 1970
+++ linux-adeos/include/asm-i386/adeos.h	Sun Jun  2 16:38:02 2002
@@ -0,0 +1,63 @@
+/*
+ *   include/asm-i386/adeos.h
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __I386_ADEOS_H
+#define __I386_ADEOS_H
+
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <linux/list.h>
+
+#if defined(CONFIG_SMP) || \
+    defined(CONFIG_X86_UP_IOAPIC) || \
+    defined(CONFIG_X86_UP_APIC) || \
+    defined(CONFIG_X86_LOCAL_APIC)
+#define CONFIG_ADEOS_APIC
+#endif
+
+#define IPIPE_NR_IRQS    NR_IRQS
+
+typedef struct adomain {
+
+    int *sp;	/* Must always be first. */
+    int *estackbase;
+
+    volatile int status;
+    volatile unsigned long irq_pending;
+#ifdef CONFIG_ADEOS_APIC
+#define IPIPE_IRQ_IWORDS  8
+    volatile unsigned long irq_indirect_pending[IPIPE_IRQ_IWORDS];
+#endif
+
+    struct {
+	atomic_t hits;
+	int (*acknowledge)(unsigned irq);
+	void (*handler)(void);
+	int control;
+    } irqs[IPIPE_NR_IRQS];
+
+    const char *name;
+    int priority;
+    struct list_head link;
+
+} adomain_t;
+
+#endif /* !__I386_ADEOS_H */
diff -Naur linux-std/include/asm-i386/keyboard.h linux-adeos/include/asm-i386/keyboard.h
--- linux-std/include/asm-i386/keyboard.h	Thu Nov 22 20:47:23 2001
+++ linux-adeos/include/asm-i386/keyboard.h	Sun Jun  2 17:01:54 2002
@@ -45,8 +45,16 @@
 
 /* resource allocation */
 #define kbd_request_region()
+#ifdef CONFIG_ADEOS
+#define kbd_request_irq(handler) \
+do { \
+adeos_control_irq(KEYBOARD_IRQ,0,IPIPE_OOB_MASK); \
+request_irq(KEYBOARD_IRQ,handler,0,"keyboard",NULL); \
+} while(0)
+#else  /* !CONFIG_ADEOS */
 #define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
                                              "keyboard", NULL)
+#endif /* CONFIG_ADEOS */
 
 /* How to access the keyboard macros on this platform.  */
 #define kbd_read_input() inb(KBD_DATA_REG)
diff -Naur linux-std/include/asm-i386/system.h linux-adeos/include/asm-i386/system.h
--- linux-std/include/asm-i386/system.h	Thu Nov 22 20:46:18 2001
+++ linux-adeos/include/asm-i386/system.h	Sun Jun  2 17:00:19 2002
@@ -310,6 +310,34 @@
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
 /* interrupt control.. */
+
+#ifdef CONFIG_ADEOS
+
+#include <linux/adeos.h>
+
+#define ipipe_hw_save_flags(x)	__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
+#define ipipe_hw_save_flags_and_cli(x)	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */)
+#define ipipe_hw_restore_flags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
+#define ipipe_hw_cli() 		__asm__ __volatile__("cli": : :"memory")
+#define ipipe_hw_sti()		__asm__ __volatile__("sti": : :"memory")
+
+#define safe_halt()		__asm__ __volatile__("call "SYMBOL_NAME_STR(adeos_unstall_ipipe)"; hlt": : :"memory")
+
+#define __save_flags(x)		((x) = adeos_test_ipipe())
+#define __restore_flags(x) 	adeos_restore_ipipe(x)
+#define __cli() 		adeos_stall_ipipe()
+#define __sti()			adeos_unstall_ipipe()
+/* used in the idle loop; sti takes one instruction cycle to complete */
+
+/* For spinlocks etc */
+
+#define local_irq_save(x)	((x) = adeos_test_and_stall_ipipe())
+#define local_irq_restore(x)	adeos_restore_ipipe(x)
+#define local_irq_disable()	adeos_stall_ipipe()
+#define local_irq_enable()	adeos_unstall_ipipe()
+
+#else /* !CONFIG_ADEOS */
+
 #define __save_flags(x)		__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
 #define __restore_flags(x) 	__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
 #define __cli() 		__asm__ __volatile__("cli": : :"memory")
@@ -322,6 +350,8 @@
 #define local_irq_restore(x)	__restore_flags(x)
 #define local_irq_disable()	__cli()
 #define local_irq_enable()	__sti()
+
+#endif /* CONFIG_ADEOS */
 
 #ifdef CONFIG_SMP
 
diff -Naur linux-std/include/linux/adeos.h linux-adeos/include/linux/adeos.h
--- linux-std/include/linux/adeos.h	Thu Jan  1 01:00:00 1970
+++ linux-adeos/include/linux/adeos.h	Sun Jun  2 17:00:15 2002
@@ -0,0 +1,79 @@
+/*
+ *   include/linux/adeos.h
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LINUX_ADEOS_H
+#define __LINUX_ADEOS_H
+
+#include <asm/adeos.h>
+
+#define ADEOS_ROOT_PRI  99
+
+#define IPIPE_STALL_FLAG  0
+#define IPIPE_SYNC_FLAG   1
+
+#define IPIPE_HANDLE_FLAG 0
+#define IPIPE_PASS_FLAG   1
+#define IPIPE_OOB_FLAG    2
+
+#define IPIPE_HANDLE_MASK  (1 << IPIPE_HANDLE_FLAG)
+#define IPIPE_PASS_MASK    (1 << IPIPE_PASS_FLAG)
+#define IPIPE_OOB_MASK     (1 << IPIPE_OOB_FLAG)
+
+typedef struct adattr {
+
+    const char *name;		/* Domain name -- Warning: won't be dup'ed! */
+    int priority;		/* Priority in interrupt pipeline */
+    void (*entry)(void);	/* Domain entry point */
+    int estacksz;		/* Stack size for entry context -- 0 means unspec */
+
+} adattr_t;
+
+extern adomain_t *adp_current,
+                 *adp_root;
+
+int adeos_register_domain(adomain_t *adp,
+			  adattr_t *attr);
+
+int adeos_unregister_domain(adomain_t *adp);
+
+void adeos_renice_domain(adomain_t *adp,
+			 int newpri);
+
+void adeos_suspend_domain(void);
+
+void adeos_virtualize_irq(unsigned irq,
+			  void (*handler)(void),
+			  int (*acknowledge)(unsigned));
+
+void adeos_control_irq(unsigned irq,
+		       unsigned clrmask,
+		       unsigned setmask);
+
+void adeos_unstall_ipipe(void);
+
+void adeos_stall_ipipe(void);
+
+void adeos_restore_ipipe(unsigned x);
+
+#define adeos_test_ipipe()            test_bit(IPIPE_STALL_FLAG,&adp_current->status)
+#define adeos_test_and_stall_ipipe()  test_and_set_bit(IPIPE_STALL_FLAG,&adp_current->status)
+
+#endif /* !__LINUX_ADEOS_H */
diff -Naur linux-std/init/main.c linux-adeos/init/main.c
--- linux-std/init/main.c	Mon Feb 25 20:38:13 2002
+++ linux-adeos/init/main.c	Fri May 31 20:21:53 2002
@@ -538,6 +538,10 @@
  	cpu_idle();
 } 
 
+#ifdef CONFIG_ADEOS
+void __adeos_init(void);
+#endif
+
 /*
  *	Activate the first processor.
  */
@@ -556,6 +560,9 @@
 	setup_arch(&command_line);
 	printk("Kernel command line: %s\n", saved_command_line);
 	parse_options(command_line);
+#ifdef CONFIG_ADEOS
+	__adeos_init();
+#endif /* CONFIG_ADEOS */
 	trap_init();
 	init_IRQ();
 	sched_init();
diff -Naur linux-std/kernel/Makefile linux-adeos/kernel/Makefile
--- linux-std/kernel/Makefile	Mon Sep 17 06:22:40 2001
+++ linux-adeos/kernel/Makefile	Fri May 31 20:21:53 2002
@@ -9,7 +9,7 @@
 
 O_TARGET := kernel.o
 
-export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
+export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o adeos.o
 
 obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
 	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
@@ -19,6 +19,7 @@
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
 obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_ADEOS) += adeos.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -Naur linux-std/kernel/adeos.c linux-adeos/kernel/adeos.c
--- linux-std/kernel/adeos.c	Thu Jan  1 01:00:00 1970
+++ linux-adeos/kernel/adeos.c	Sun Jun  2 17:00:56 2002
@@ -0,0 +1,267 @@
+/*
+ *   linux/kernel/adeos.c
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   This code implements the architecture-independent ADEOS support.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <asm/system.h>
+
+/* The pre-defined domain slot for the root domain. */
+static adomain_t adeos_root_domain;
+
+/* A constant pointer to the root domain. */
+adomain_t *adp_root = &adeos_root_domain;
+
+/* A pointer to the current domain. */
+adomain_t *adp_current = &adeos_root_domain;
+
+extern void ipipe_init(void);
+
+extern int ipipe_create_stage(adomain_t *adp);
+
+extern int ipipe_delete_stage(adomain_t *adp);
+
+extern int ipipe_renice_stage(adomain_t *adp,
+			      int newpri);
+
+extern void ipipe_hook_irq(unsigned irq,
+			   void (*handler)(void),
+			   int (*acknowledge)(unsigned irq));
+
+extern void ipipe_sync_events(void);
+
+extern void __adeos_init_domain(adomain_t *adp,
+				adattr_t *attr);
+
+extern void __adeos_switch_domain(adomain_t *adp);
+
+extern struct list_head i_pipeline;
+
+/* adeos_init() -- Initialization routine of the ADEOS layer. Called
+   by the host kernel early during the boot procedure. */
+
+void __adeos_init (void)
+
+{
+    adattr_t attr;
+
+    printk("ADEOS enabled.\n");
+    ipipe_init();
+
+    attr.name = "RootDomain";
+    attr.entry = NULL;
+    attr.priority = ADEOS_ROOT_PRI;
+    attr.estacksz = 0;	/* Unused. */
+    adeos_register_domain(&adeos_root_domain,&attr);
+}
+
+/* adeos_register_domain() -- Add a new domain to the system. All
+   client domains must call this routine to register themselves to
+   ADEOS before using its services. */
+
+int adeos_register_domain (adomain_t *adp, adattr_t *attr)
+
+{
+    if (adp_current != adp_root)
+	{
+	printk("ADEOS: Only the root domain may register a new domain.\n");
+	return 1;
+	}
+
+    adp->status = 0;
+    adp->name = attr->name;
+    adp->priority = attr->priority;
+
+    if (attr->entry != NULL)
+	__adeos_init_domain(adp,attr);
+
+    printk("ADEOS: Domain %s registered.\n",adp->name);
+
+    /* Insert the domain in the interrupt pipeline last, so it won't
+       be resumed for processing interrupts until it has a valid stack
+       context. */
+    ipipe_create_stage(adp);
+
+    /* Then, allow the new domain to perform its initialization chores
+       on behalf of its own stack context. */
+    if (attr->entry != NULL)
+	{
+	__adeos_switch_domain(adp);
+
+	if (!adeos_test_ipipe() && adp_current->irq_pending != 0)
+	    ipipe_sync_events();
+	}
+
+    return 0;
+}
+
+/* adeos_unregister_domain() -- Remove a domain from the system. All
+   client domains must call this routine to unregister themselves from
+   the ADEOS layer. */
+
+int adeos_unregister_domain (adomain_t *adp)
+
+{
+    if (adp_current != adp_root)
+	{
+	printk("ADEOS: Only the root domain may unregister a domain.\n");
+	return 1;
+	}
+
+    if (adp == adp_root)
+	{
+	printk("ADEOS: Cannot unregister the root domain.\n");
+	return 1;
+	}
+
+    ipipe_delete_stage(adp);
+    kfree(adp->estackbase);
+
+    printk("ADEOS: Domain %s unregistered.\n",adp->name);
+
+    return 0;
+}
+
+/* adeos_renice_domain() -- Change a domain's priority. This affects
+   the position of the domain in the interrupt pipeline. The higher
+   the priority value, the earlier the domain is informed of incoming
+   events when the pipeline is processed. */
+
+void adeos_renice_domain (adomain_t *adp, int newpri) {
+
+    ipipe_renice_stage(adp,newpri);
+}
+
+/* adeos_suspend_domain() -- tell the ADEOS layer that the current
+   domain is now dormant. The calling domain is switched out, while
+   the next domain in the pipeline is switched in. */
+
+void adeos_suspend_domain (void)
+
+{
+    struct list_head *ln;
+    unsigned long flags;
+
+    ipipe_hw_save_flags_and_cli(flags);
+
+    ln = adp_current->link.next;
+
+    if (ln == &i_pipeline)	/* End of pipeline reached? */
+	{
+	/* Caller should loop on its idle task on return. */
+	ipipe_hw_restore_flags(flags);
+	return;
+	}
+
+    /* A suspending domain implicitely unstalls the pipeline. */
+    clear_bit(IPIPE_STALL_FLAG,&adp_current->status);
+
+    /* Suspend the calling domain, switching to the next one. */
+    __adeos_switch_domain(list_entry(ln,adomain_t,link));
+
+    ipipe_hw_restore_flags(flags);
+
+    /* Now, we are back into the calling domain. Flush its interrupt
+       log (if allowed and needed). */
+    if (!adeos_test_ipipe() && adp_current->irq_pending != 0)
+	ipipe_sync_events();
+
+    /* Return to the point of suspension in the calling domain. */
+}
+
+/* adeos_virtualize_irq() -- Attach a handler (and optionally an hw
+   acknowledge routine) to an interrupt for the current domain. */
+
+void adeos_virtualize_irq (unsigned irq,
+			   void (*handler)(void),
+			   int (*acknowledge)(unsigned irq)) {
+
+    ipipe_hook_irq(irq,handler,acknowledge);
+}
+
+/* adeos_control_irq() -- Change an interrupt mode. This affects the
+   way a given interrupt is handled by ADEOS for the current
+   domain. setmask is a bitmask telling whether:
+   - the interrupt should be passed to the domain (IPIPE_HANDLE_MASK),
+     and/or
+   - the interrupt should be passed down to the lower priority domain(s)
+     in the pipeline (IPIPE_PASS_MASK).
+   This leads to four possibilities:
+   - PASS only => Ignore the interrupt
+   - HANDLE only => Terminate the interrupt (process but don't pass down)
+   - PASS + HANDLE => Accept the interrupt (process and pass down)
+   - <none> => Discard the interrupt
+   clrmask clears the corresponding bits from the control field before
+   setmask is applied.
+*/
+
+void adeos_control_irq (unsigned irq, unsigned clrmask, unsigned setmask)
+
+{
+    unsigned long flags;
+
+    ipipe_hw_save_flags_and_cli(flags);
+
+    adp_current->irqs[irq].control &= ~clrmask;
+    adp_current->irqs[irq].control |= setmask;
+
+    ipipe_hw_restore_flags(flags);
+}
+
+/* adeos_stall_ipipe() -- Stall the interrupt pipeline at the stage
+   occupied by the current domain. */
+
+void adeos_stall_ipipe (void) {
+
+    set_bit(IPIPE_STALL_FLAG,&adp_current->status);
+}
+
+/* adeos_unstall_ipipe() -- Unstall the interrupt pipeline and
+   synchronize pending events. */
+
+void adeos_unstall_ipipe (void)
+
+{
+    clear_bit(IPIPE_STALL_FLAG,&adp_current->status);
+    ipipe_hw_sti();
+
+    if (adp_current->irq_pending != 0)
+	ipipe_sync_events();
+}
+
+/* adeos_restore_ipipe() -- Stall/unstall the interrupt pipeline
+   according to a previously saved state (x). */
+
+void adeos_restore_ipipe (unsigned x)
+
+{
+    if (x)
+	set_bit(IPIPE_STALL_FLAG,&adp_current->status);
+    else
+	{
+	clear_bit(IPIPE_STALL_FLAG,&adp_current->status);
+
+	if (adp_current->irq_pending != 0)
+	    ipipe_sync_events();
+	}
+}
diff -Naur linux-std/kernel/ksyms.c linux-adeos/kernel/ksyms.c
--- linux-std/kernel/ksyms.c	Mon Feb 25 20:38:13 2002
+++ linux-adeos/kernel/ksyms.c	Fri May 31 20:21:53 2002
@@ -559,3 +559,17 @@
 
 EXPORT_SYMBOL(tasklist_lock);
 EXPORT_SYMBOL(pidhash);
+
+#ifdef CONFIG_ADEOS
+EXPORT_SYMBOL(adeos_register_domain);
+EXPORT_SYMBOL(adeos_unregister_domain);
+EXPORT_SYMBOL(adeos_renice_domain);
+EXPORT_SYMBOL(adeos_suspend_domain);
+EXPORT_SYMBOL(adeos_virtualize_irq);
+EXPORT_SYMBOL(adeos_control_irq);
+EXPORT_SYMBOL(adeos_stall_ipipe);
+EXPORT_SYMBOL(adeos_unstall_ipipe);
+EXPORT_SYMBOL(adeos_restore_ipipe);
+EXPORT_SYMBOL(adp_current);
+EXPORT_SYMBOL(adp_root);
+#endif /* CONFIG_ADEOS */
