diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/adeos/armv.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/adeos/armv.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/adeos/armv.c	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/adeos/armv.c	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,491 @@
+/*
+ *   linux/adeos/armv.c
+ *
+ *   Copyright (C) 2002-2005 Philippe Gerum.
+ *
+ *   Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ *   	various tweaks, fixes (e.g. call asm_do_IRQ() instead of do_IRQ() and
+ *   	optimizations (e.g. backport of unthreaded support from Adeos/x86 for 2.6)
+ *
+ *   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.
+ *
+ *   Architecture-dependent ADEOS support for ARM.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <asm/hardware.h>
+#include <asm/mach/irq.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#ifdef CONFIG_ARCH_EP93XX
+#include <asm/arch/ep93xx_tsc.h>
+#endif
+
+extern spinlock_t __adeos_pipelock;
+
+extern struct irqdesc irq_desc[];
+
+extern struct pt_regs __adeos_irq_regs;
+
+asmlinkage void asm_do_IRQ(int irq,
+			   struct pt_regs *regs);
+
+struct irqdesc __adeos_std_irq_desc[NR_IRQS];
+
+static void __adeos_override_irq_mask (unsigned irq)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    __adeos_std_irq_desc[irq].mask(irq);
+    __adeos_lock_irq(adp_cpu_current[cpuid],cpuid,irq);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+}
+
+static void __adeos_override_irq_unmask (unsigned irq)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    __adeos_unlock_irq(adp_cpu_current[cpuid],irq);
+    __adeos_std_irq_desc[irq].unmask(irq);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+}
+
+static void __adeos_override_irq_mask_ack (unsigned irq)
+
+{
+    unsigned long adflags, hwflags;
+    adeos_declare_cpuid;
+
+    adeos_hw_local_irq_save(hwflags);
+    adflags = adeos_test_and_stall_pipeline();
+#ifdef CONFIG_PREEMPT
+    preempt_disable();
+#endif /* CONFIG_PREEMPT */
+    __adeos_std_irq_desc[irq].mask_ack(irq);
+    /* No locking here, since this would prevent to sync the stage. */
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+    adeos_restore_pipeline_nosync(adp_cpu_current[cpuid],adflags,cpuid);
+    adeos_hw_local_irq_restore(hwflags);
+}
+
+static int __adeos_ack_irq (unsigned irq)
+
+{
+    struct irqdesc *desc = irq_desc + irq;
+    desc->mask_ack(irq);
+    return 1;
+}
+
+/* __adeos_enable_pipeline() -- Take over the interrupt control from
+   the root domain (i.e. Linux). After this routine has returned, all
+   interrupts go through the pipeline. */
+
+void __adeos_enable_pipeline (void)
+
+{
+    unsigned long flags;
+    unsigned irq;
+
+    flags = adeos_critical_enter(NULL);
+
+    /* First, virtualize all interrupts from the root domain. */
+
+    for (irq = 0; irq < NR_IRQS; irq++)
+	/* Note that according to Russel King asm_do_IRQ() has to be used as the
+	 * handler, not do_IRQ() (at least for 2.4.21-rmk7) as the original
+	 * ADEOS code had here. <mike@firmix.at> */
+	adeos_virtualize_irq(irq,
+			     (void (*)(unsigned))&asm_do_IRQ,
+			     &__adeos_ack_irq,
+			     IPIPE_HANDLE_MASK|IPIPE_PASS_MASK);
+
+    /* Interpose on the IRQ control routines so we can make them
+       atomic using hw masking and prevent the interrupt log from
+       being untimely flushed. */
+
+    for (irq = 0; irq < NR_IRQS; irq++)
+	__adeos_std_irq_desc[irq] = irq_desc[irq];
+
+    /* The original controller structs are often shared, so we first
+       save them all before changing any of them. Notice that we don't
+       redirect the ack handler since the relevant IC management code
+       is already Adeos-aware. */
+
+    for (irq = 0; irq < NR_IRQS; irq++)
+	{
+	if (irq_desc[irq].mask != NULL)
+	    irq_desc[irq].mask = &__adeos_override_irq_mask;
+
+	if (irq_desc[irq].unmask != NULL)
+	    irq_desc[irq].unmask = &__adeos_override_irq_unmask;
+
+	if (irq_desc[irq].mask_ack != NULL)
+	    irq_desc[irq].mask_ack = &__adeos_override_irq_mask_ack;
+	}
+
+#ifdef CONFIG_ADEOS_MODULE
+    adp_pipelined = 1;
+#endif /* CONFIG_ADEOS_MODULE */
+
+    adeos_critical_exit(flags);
+}
+
+/* __adeos_disable_pipeline() -- Disengage the pipeline. */
+
+void __adeos_disable_pipeline (void)
+
+{
+    unsigned long flags;
+    unsigned irq;
+
+    flags = adeos_critical_enter(NULL);
+
+    /* Restore interrupt controllers. */
+
+    for (irq = 0; irq < NR_IRQS; irq++)
+	irq_desc[irq] = __adeos_std_irq_desc[irq];
+
+#ifdef CONFIG_ADEOS_MODULE
+    adp_pipelined = 0;
+#endif /* CONFIG_ADEOS_MODULE */
+
+    adeos_critical_exit(flags);
+}
+
+/* adeos_virtualize_irq_from() -- Attach a handler (and optionally a
+   hw acknowledge routine) to an interrupt for the given domain. */
+
+int adeos_virtualize_irq_from (adomain_t *adp,
+			       unsigned irq,
+			       void (*handler)(unsigned irq),
+			       int (*acknowledge)(unsigned irq),
+			       unsigned modemask)
+{
+    unsigned long flags;
+    int err;
+
+    if (irq >= IPIPE_NR_IRQS)
+	return -EINVAL;
+
+    if (adp->irqs[irq].control & IPIPE_SYSTEM_MASK)
+	return -EPERM;
+	
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    if (handler != NULL)
+	{
+	/* A bit of hack here: if we are re-virtualizing an IRQ just
+	   to change the acknowledge routine by passing the special
+	   ADEOS_SAME_HANDLER value, then allow to recycle the current
+	   handler for the IRQ. This allows Linux device drivers
+	   managing shared IRQ lines to call adeos_virtualize_irq() in
+	   addition to request_irq() just for the purpose of
+	   interposing their own shared acknowledge routine. */
+
+	if (handler == ADEOS_SAME_HANDLER)
+	    {
+	    handler = adp->irqs[irq].handler;
+
+	    if (handler == NULL)
+		{
+		err = -EINVAL;
+		goto unlock_and_exit;
+		}
+	    }
+	else if ((modemask & IPIPE_EXCLUSIVE_MASK) != 0 &&
+		 adp->irqs[irq].handler != NULL)
+	    {
+	    err = -EBUSY;
+	    goto unlock_and_exit;
+	    }
+	
+	if ((modemask & (IPIPE_SHARED_MASK|IPIPE_PASS_MASK)) == IPIPE_SHARED_MASK)
+	    {
+	    err = -EINVAL;
+	    goto unlock_and_exit;
+	    }
+
+	if ((modemask & IPIPE_STICKY_MASK) != 0)
+	    modemask |= IPIPE_HANDLE_MASK;
+	}
+    else
+	modemask &= ~(IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK|IPIPE_SHARED_MASK);
+
+    if (acknowledge == NULL)
+	{
+	if ((modemask & IPIPE_SHARED_MASK) == 0)
+	    /* Acknowledge handler unspecified -- this is ok in
+	       non-shared management mode, but we will force the use
+	       of the Linux-defined handler instead. */
+	    acknowledge = adp_root->irqs[irq].acknowledge;
+	else
+	    {
+	    /* A valid acknowledge handler to be called in shared mode
+	       is required when declaring a shared IRQ. */
+	    err = -EINVAL;
+	    goto unlock_and_exit;
+	    }
+	}
+
+    adp->irqs[irq].handler = handler;
+    adp->irqs[irq].acknowledge = acknowledge;
+    adp->irqs[irq].control = modemask;
+
+    if (irq < NR_IRQS &&
+	handler != NULL &&
+	!adeos_virtual_irq_p(irq) &&
+	(modemask & IPIPE_ENABLE_MASK) != 0)
+	{
+	if (adp != adp_current)
+	    {
+	    /* IRQ enable/disable state is domain-sensitive, so we may
+	       not change it for another domain. What is allowed
+	       however is forcing some domain to handle an interrupt
+	       source, by passing the proper 'adp' descriptor which
+	       thus may be different from adp_current. */
+	    err = -EPERM;
+	    goto unlock_and_exit;
+	    }
+
+	enable_irq(irq);
+	}
+
+    err = 0;
+
+unlock_and_exit:
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return err;
+}
+
+/* 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
+   - DYNAMIC is currently an alias of HANDLE since it marks an interrupt
+   which is processed by the current domain but not implicitely passed
+   down to the pipeline, letting the domain's handler choose on a case-
+   by-case basis whether the interrupt propagation should be forced
+   using adeos_propagate_irq().
+   clrmask clears the corresponding bits from the control field before
+   setmask is applied.
+*/
+
+int adeos_control_irq (unsigned irq,
+		       unsigned clrmask,
+		       unsigned setmask)
+{
+    struct irqdesc *desc;
+    unsigned long flags;
+
+    if (irq >= IPIPE_NR_IRQS)
+	return -EINVAL;
+
+    if (adp_current->irqs[irq].control & IPIPE_SYSTEM_MASK)
+	return -EPERM;
+	
+    if (((setmask|clrmask) & IPIPE_SHARED_MASK) != 0)
+	return -EINVAL;
+	
+    desc = irq_desc + irq;
+
+    if (adp_current->irqs[irq].handler == NULL)
+	setmask &= ~(IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK);
+
+    if ((setmask & IPIPE_STICKY_MASK) != 0)
+	setmask |= IPIPE_HANDLE_MASK;
+
+    if ((clrmask & (IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK)) != 0)	/* If one goes, both go. */
+	clrmask |= (IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK);
+
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    adp_current->irqs[irq].control &= ~clrmask;
+    adp_current->irqs[irq].control |= setmask;
+
+    if ((setmask & IPIPE_ENABLE_MASK) != 0)
+	enable_irq(irq);
+    else if ((clrmask & IPIPE_ENABLE_MASK) != 0)
+	disable_irq(irq);
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return 0;
+}
+
+#ifdef CONFIG_ADEOS_THREADS
+
+static inline unsigned long __current_domain_access_control (void)
+
+{
+    unsigned long domain_access_control;
+    __asm__ __volatile__ ("mrc p15, 0, %0, c3, c0" : "=r" (domain_access_control));
+    return domain_access_control;
+}
+
+void __adeos_init_domain (adomain_t *adp, adattr_t *attr)
+
+{
+    int estacksz = attr->estacksz > 0 ? attr->estacksz : 8192, _cpuid;
+    unsigned long init_arch_flags, init_domain_access_control;
+    adeos_declare_cpuid;
+
+    adeos_load_cpuid();
+    adeos_hw_local_irq_flags(init_arch_flags);
+    init_domain_access_control = __current_domain_access_control();
+
+    for (_cpuid = 0; _cpuid < smp_num_cpus; _cpuid++)
+	{
+	int **psp = &adp->esp[_cpuid];
+
+	adp->estackbase[_cpuid] = (int *)kmalloc(estacksz,GFP_KERNEL);
+    
+	if (adp->estackbase[_cpuid] == NULL)
+	    panic("Adeos: No memory for domain stack on CPU #%d",_cpuid);
+
+	adp->esp[_cpuid] = adp->estackbase[_cpuid];
+	**psp = 0;
+	*psp = (int *)(((unsigned long)*psp + estacksz - 60) & ~0x3);
+	*--(*psp) = (int)attr->entry; /* r14=lr */
+	*--(*psp) = 0;		/* r11=fp */
+	*--(*psp) = 0;		/* r10=sl */
+	*--(*psp) = 0;		/* r9 */
+	*--(*psp) = 0;		/* r8 */
+	*--(*psp) = 0;		/* r7 */
+	*--(*psp) = 0;		/* r6 */
+	*--(*psp) = 0;		/* r5 */
+	*--(*psp) = 0;		/* r4 */
+	*--(*psp) = 0;		/* r3 */
+	*--(*psp) = 0;		/* r2 */
+	*--(*psp) = 0;		/* r1 */
+	*--(*psp) = (_cpuid == cpuid); /* r0=iflag */
+	*--(*psp) = init_arch_flags;	/* cpsr_SVC */
+	*--(*psp) = init_domain_access_control;
+	}
+}
+
+#else /* !CONFIG_ADEOS_THREADS */
+
+void __adeos_init_domain (adomain_t *adp, adattr_t *attr)
+
+{}
+
+#endif /* CONFIG_ADEOS_THREADS */
+
+void __adeos_cleanup_domain (adomain_t *adp)
+
+{
+    adeos_unstall_pipeline_from(adp);
+
+#ifdef CONFIG_ADEOS_THREADS
+    if (adp->estackbase[0] != NULL)
+	kfree(adp->estackbase[0]);
+#endif /* CONFIG_ADEOS_THREADS */
+}
+
+int adeos_get_sysinfo (adsysinfo_t *info)
+
+{
+    info->ncpus = 1;
+#ifndef CONFIG_ARCH_EP93XX
+    info->cpufreq = CLOCK_TICK_RATE;
+#else
+    /* use TSC frequency, because that's what cpufreq is used for,
+     * although it has nothing to do with CPU-frequency on EP-93XX
+     * it's just timer4's frequency */
+    info->cpufreq = FREQ_EP93XX_TSC;
+#endif
+    info->archdep.tmirq = ADEOS_TIMER_IRQ;
+
+    return 0;
+}
+
+int adeos_tune_timer (unsigned long ns, int flags)
+
+{
+    unsigned long x, hz;
+
+    if (flags & ADEOS_RESET_TIMER)
+	hz = HZ;
+    else
+	{
+	hz = 1000000000 / ns;
+
+	if (hz < HZ)
+	    return -EINVAL;
+	}
+
+    adeos_hw_local_irq_save(x);
+
+    __adeos_tune_timer(hz);
+
+    adeos_hw_local_irq_restore(x);
+
+    return 0;
+}
+
+/* adeos_send_ipi() -- Send a specified service IPI to a set of
+   processors. */
+
+int adeos_send_ipi (unsigned ipi, cpumask_t cpumask)
+
+{
+    printk(KERN_WARNING "Adeos: Call to unimplemented adeos_send_ipi() from %s\n",adp_current->name);
+    return 0;
+}
+
+EXPORT_SYMBOL(__adeos_std_irq_desc);
+
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/adeos/generic.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/adeos/generic.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/adeos/generic.c	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/adeos/generic.c	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,641 @@
+/*
+ *   linux/adeos/generic.c
+ *
+ *   Copyright (C) 2002 Philippe Gerum.
+ *
+ *   Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ *   	backport from Adeos for 2.6 to 2.4
+ *
+ *   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.
+ *
+ *   Architecture-independent ADEOS services.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/wrapper.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+MODULE_DESCRIPTION("Adeos nanokernel");
+MODULE_AUTHOR("Philippe Gerum");
+MODULE_LICENSE("GPL");
+
+/* 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)
+
+{
+    struct list_head *pos;
+    unsigned long flags;
+    int n;
+
+    if (adp_current != adp_root)
+	{
+	printk(KERN_WARNING "Adeos: Only the root domain may register a new domain.\n");
+	return -EPERM;
+	}
+
+    flags = adeos_critical_enter(NULL);
+
+    list_for_each(pos,&__adeos_pipeline) {
+    	adomain_t *_adp = list_entry(pos,adomain_t,p_link);
+	if (_adp->domid == attr->domid)
+            break;
+    }
+
+    adeos_critical_exit(flags);
+
+    if (pos != &__adeos_pipeline)
+	/* A domain with the given id already exists -- fail. */
+	return -EBUSY;
+
+    for (n = 0; n < ADEOS_NR_CPUS; n++)
+	{
+	/* Each domain starts in sleeping state on every CPU. */
+	adp->cpudata[n].status = (1 << IPIPE_SLEEP_FLAG);
+#ifdef CONFIG_ADEOS_THREADS
+	adp->estackbase[n] = NULL;
+#endif /* CONFIG_ADEOS_THREADS */
+	}
+
+    adp->name = attr->name;
+    adp->priority = attr->priority;
+    adp->domid = attr->domid;
+    adp->dswitch = attr->dswitch;
+    adp->flags = 0;
+    adp->ptd_setfun = attr->ptdset;
+    adp->ptd_getfun = attr->ptdget;
+    adp->ptd_keymap = 0;
+    adp->ptd_keycount = 0;
+    adp->ptd_keymax = attr->nptdkeys;
+
+    for (n = 0; n < ADEOS_NR_EVENTS; n++)
+	/* Event handlers must be cleared before the i-pipe stage is
+	   inserted since an exception may occur on behalf of the new
+	   emerging domain. */
+	adp->events[n].handler = NULL;
+
+    if (attr->entry != NULL)
+	__adeos_init_domain(adp,attr);
+
+    /* Insert the domain in the interrupt pipeline last, so it won't
+       be resumed for processing interrupts until it has a valid stack
+       context. */
+
+    __adeos_init_stage(adp);
+
+    INIT_LIST_HEAD(&adp->p_link);
+
+    flags = adeos_critical_enter(NULL);
+
+    list_for_each(pos,&__adeos_pipeline) {
+    	adomain_t *_adp = list_entry(pos,adomain_t,p_link);
+	if (adp->priority > _adp->priority)
+            break;
+    }
+
+    list_add_tail(&adp->p_link,pos);
+
+    adeos_critical_exit(flags);
+
+    printk(KERN_WARNING "Adeos: Domain %s registered.\n",adp->name);
+
+    /* Finally, allow the new domain to perform its initialization
+       chores. */
+
+    if (attr->entry != NULL)
+	{
+	adeos_declare_cpuid;
+
+	adeos_lock_cpu(flags);
+
+#ifdef CONFIG_ADEOS_THREADS
+	__adeos_switch_to(adp_root,adp,cpuid);
+#else /* !CONFIG_ADEOS_THREADS */
+	adp_cpu_current[cpuid] = adp;
+	attr->entry(1);
+	adp_cpu_current[cpuid] = adp_root;
+#endif /* CONFIG_ADEOS_THREADS */
+
+	adeos_load_cpuid();	/* Processor might have changed. */
+
+	if (!test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status) &&
+	    adp_root->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage(IPIPE_IRQMASK_ANY);
+
+	adeos_unlock_cpu(flags);
+	}
+
+    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)
+
+{
+    unsigned long flags;
+    unsigned event;
+
+    if (adp_current != adp_root)
+	{
+	printk(KERN_WARNING "Adeos: Only the root domain may unregister a domain.\n");
+	return -EPERM;
+	}
+
+    if (adp == adp_root)
+	{
+	printk(KERN_WARNING "Adeos: Cannot unregister the root domain.\n");
+	return -EPERM;
+	}
+
+    for (event = 0; event < ADEOS_NR_EVENTS; event++)
+	/* Need this to update the monitor count. */
+	adeos_catch_event_from(adp,event,NULL);
+
+#ifdef CONFIG_SMP
+    {
+    int _cpuid;
+    unsigned irq;
+
+    /* In the SMP case, wait for the logged events to drain on other
+       processors before eventually removing the domain from the
+       pipeline. */
+
+    adeos_unstall_pipeline_from(adp);
+
+    flags = adeos_critical_enter(NULL);
+
+    for (irq = 0; irq < IPIPE_NR_IRQS; irq++)
+	{
+	clear_bit(IPIPE_HANDLE_FLAG,&adp->irqs[irq].control);
+	clear_bit(IPIPE_STICKY_FLAG,&adp->irqs[irq].control);
+	set_bit(IPIPE_PASS_FLAG,&adp->irqs[irq].control);
+	}
+
+    adeos_critical_exit(flags);
+
+    for (_cpuid = 0; _cpuid < smp_num_cpus; _cpuid++)
+	{
+	for (irq = 0; irq < IPIPE_NR_IRQS; irq++)
+	    while (adp->cpudata[_cpuid].irq_hits[irq] > 0)
+		cpu_relax();
+
+	while (test_bit(IPIPE_XPEND_FLAG,&adp->cpudata[_cpuid].status))
+	    cpu_relax();
+
+	while (!test_bit(IPIPE_SLEEP_FLAG,&adp->cpudata[_cpuid].status))
+	     cpu_relax();
+	}
+    }
+#endif /* CONFIG_SMP */
+
+    /* Simply remove the domain from the pipeline and we are almost
+       done. */
+
+    flags = adeos_critical_enter(NULL);
+    list_del_init(&adp->p_link);
+    adeos_critical_exit(flags);
+
+    __adeos_cleanup_domain(adp);
+
+    printk(KERN_WARNING "Adeos: Domain %s unregistered.\n",adp->name);
+
+    return 0;
+}
+
+/* adeos_propagate_irq() -- Force a given IRQ propagation on behalf of
+   a running interrupt handler to the next domain down the pipeline.
+   Returns non-zero if a domain has received the interrupt
+   notification, zero otherwise.
+   This call is useful for handling shared interrupts among domains.
+   e.g. pipeline = [domain-A]---[domain-B]...
+   Both domains share IRQ #X.
+   - domain-A handles IRQ #X but does not pass it down (i.e. Terminate
+   or Dynamic interrupt control mode)
+   - domain-B handles IRQ #X (i.e. Terminate or Accept interrupt
+   control modes).
+   When IRQ #X is raised, domain-A's handler determines whether it
+   should process the interrupt by identifying its source. If not,
+   adeos_propagate_irq() is called so that the next domain down the
+   pipeline which handles IRQ #X is given a chance to process it. This
+   process can be repeated until the end of the pipeline is
+   reached. */
+
+/* adeos_schedule_irq() -- Almost the same as adeos_propagate_irq(),
+   but attempts to pend the interrupt for the current domain first. */
+
+int __adeos_schedule_irq (unsigned irq, struct list_head *head)
+
+{
+    struct list_head *ln;
+    unsigned long flags;
+    adeos_declare_cpuid;
+
+    if (irq >= IPIPE_NR_IRQS ||
+	(adeos_virtual_irq_p(irq) && !test_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map)))
+	return -EINVAL;
+
+    adeos_lock_cpu(flags);
+
+    ln = head;
+
+    while (ln != &__adeos_pipeline)
+	{
+	adomain_t *adp = list_entry(ln,adomain_t,p_link);
+
+	if (test_bit(IPIPE_HANDLE_FLAG,&adp->irqs[irq].control))
+	    {
+	    adp->cpudata[cpuid].irq_hits[irq]++;
+	    __adeos_set_irq_bit(adp,cpuid,irq);
+	    adeos_unlock_cpu(flags);
+	    return 1;
+	    }
+
+	ln = adp->p_link.next;
+	}
+
+    adeos_unlock_cpu(flags);
+
+    return 0;
+}
+
+/* adeos_free_irq() -- Return a previously allocated virtual/soft
+   pipelined interrupt to the pool of allocatable interrupts. */
+
+int adeos_free_irq (unsigned irq)
+
+{
+    if (irq >= IPIPE_NR_IRQS)
+	return -EINVAL;
+
+    clear_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map);
+
+    return 0;
+}
+
+cpumask_t adeos_set_irq_affinity (unsigned irq, cpumask_t cpumask)
+
+{
+#ifdef CONFIG_SMP
+     if (irq >= IPIPE_NR_XIRQS)
+	 /* Allow changing affinity of external IRQs only. */
+	 return CPU_MASK_NONE;
+
+     if (num_online_cpus() > 1)
+	 /* Allow changing affinity of external IRQs only. */
+	 return __adeos_set_irq_affinity(irq,cpumask);
+#endif /* CONFIG_SMP */
+
+    return CPU_MASK_NONE;
+}
+
+/* adeos_catch_event_from() -- Interpose an event handler starting
+   from a given domain. */
+
+int adeos_catch_event_from (adomain_t *adp, unsigned event, void (*handler)(adevinfo_t *))
+
+{
+    if (event >= ADEOS_NR_EVENTS)
+	return -EINVAL;
+
+    if (!xchg(&adp->events[event].handler,handler))
+	{
+	if (handler)
+	    __adeos_event_monitors[event]++;
+	}
+    else if (!handler)
+	__adeos_event_monitors[event]--;
+
+    return 0;
+}
+
+void adeos_init_attr (adattr_t *attr)
+
+{
+    attr->name = "Anonymous";
+    attr->domid = 1;
+    attr->entry = NULL;
+    attr->estacksz = 0;	/* Let ADEOS choose a reasonable stack size */
+    attr->priority = ADEOS_ROOT_PRI;
+    attr->dswitch = NULL;
+    attr->nptdkeys = 0;
+    attr->ptdset = NULL;
+    attr->ptdget = NULL;
+}
+
+int adeos_alloc_ptdkey (void)
+
+{
+    unsigned long flags;
+    int key = -1;
+
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    if (adp_current->ptd_keycount < adp_current->ptd_keymax)
+	{
+	key = ffz(adp_current->ptd_keymap);
+	set_bit(key,&adp_current->ptd_keymap);
+	adp_current->ptd_keycount++;
+	}
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return key;
+}
+
+int adeos_free_ptdkey (int key)
+
+{
+    unsigned long flags; 
+
+    if (key < 0 || key >= adp_current->ptd_keymax)
+	return -EINVAL;
+
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    if (test_and_clear_bit(key,&adp_current->ptd_keymap))
+	adp_current->ptd_keycount--;
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return 0;
+}
+
+int adeos_set_ptd (int key, void *value)
+
+{
+    if (key < 0 || key >= adp_current->ptd_keymax)
+	return -EINVAL;
+
+    if (!adp_current->ptd_setfun)
+	{
+	printk(KERN_WARNING "Adeos: No ptdset hook for %s\n",adp_current->name);
+	return -EINVAL;
+	}
+
+    adp_current->ptd_setfun(key,value);
+
+    return 0;
+}
+
+void *adeos_get_ptd (int key)
+
+{
+    if (key < 0 || key >= adp_current->ptd_keymax)
+	return NULL;
+
+    if (!adp_current->ptd_getfun)
+	{
+	printk(KERN_WARNING "Adeos: No ptdget hook for %s\n",adp_current->name);
+	return NULL;
+	}
+
+    return adp_current->ptd_getfun(key);
+}
+
+int adeos_init_mutex (admutex_t *mutex)
+
+{
+    admutex_t initm = ADEOS_MUTEX_UNLOCKED;
+    *mutex = initm;
+    return 0;
+}
+
+#ifdef CONFIG_ADEOS_THREADS
+
+int adeos_destroy_mutex (admutex_t *mutex)
+
+{
+    if (!adeos_spin_trylock(&mutex->lock) &&
+	adp_current != adp_root &&
+	mutex->owner != adp_current)
+	return -EBUSY;
+
+    return 0;
+}
+
+static inline void __adeos_sleepon_mutex (admutex_t *mutex, adomain_t *sleeper, int cpuid)
+
+{
+    adomain_t *owner = mutex->owner;
+
+    /* Make the current domain (== sleeper) wait for the mutex to be
+       released. Adeos' pipelined scheme guarantees that the new
+       sleeper _is_ more prioritary than any aslept domain since we
+       have stalled each sleeper's stage. Must be called with local hw
+       interrupts off. */
+
+    sleeper->m_link = mutex->sleepq;
+    mutex->sleepq = sleeper;
+    __adeos_switch_to(adp_cpu_current[cpuid],owner,cpuid);
+    mutex->owner = sleeper;
+    adeos_spin_unlock(&mutex->lock);
+}
+
+unsigned long adeos_lock_mutex (admutex_t *mutex)
+
+{
+    unsigned long flags, hwflags;
+    adeos_declare_cpuid;
+    adomain_t *adp;
+
+    if (!adp_pipelined)
+	{
+	adeos_hw_local_irq_save(hwflags);
+	flags = !adeos_hw_test_iflag(hwflags);
+	adeos_spin_lock(&mutex->lock);
+	return flags;
+	}
+
+    adeos_lock_cpu(hwflags);
+
+    adp = adp_cpu_current[cpuid];
+
+    flags = __test_and_set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+    /* Two cases to handle here on SMP systems, only one for UP:
+       1) in case of a conflicting access from a prioritary domain
+       running on the same cpu, make this domain sleep on the mutex,
+       and resume the current owner so it can release the lock asap.
+       2) in case of a conflicting access from any domain on a
+       different cpu than the current owner's, simply enter a spinning
+       loop. Note that testing mutex->owncpu is safe since it is only
+       changed by the current owner, and set to -1 when the mutex is
+       unlocked. */
+
+#ifdef CONFIG_SMP
+    while (!adeos_spin_trylock(&mutex->lock))
+	{
+	if (mutex->owncpu == cpuid)
+	    {
+	    __adeos_sleepon_mutex(mutex,adp,cpuid);
+	    adeos_load_cpuid();
+	    }
+	}
+
+    mutex->owncpu = cpuid;
+#else  /* !CONFIG_SMP */
+    while (mutex->owner != NULL && mutex->owner != adp)
+	__adeos_sleepon_mutex(mutex,adp,cpuid);
+#endif /* CONFIG_SMP */
+
+    mutex->owner = adp;
+
+    adeos_unlock_cpu(hwflags);
+
+    return flags;
+}
+
+void adeos_unlock_mutex (admutex_t *mutex, unsigned long flags)
+
+{
+    unsigned long hwflags;
+    adeos_declare_cpuid;
+    adomain_t *adp;
+
+    if (!adp_pipelined)
+	{
+	adeos_spin_unlock(&mutex->lock);
+
+	if (flags)
+	    adeos_hw_cli();
+	else
+	    adeos_hw_sti();
+
+	return;
+	}
+
+#ifdef CONFIG_SMP
+    mutex->owncpu = -1;
+#endif /* CONFIG_SMP */
+
+    if (!flags)
+	adeos_hw_sti();	/* Absolutely needed. */
+	
+    adeos_lock_cpu(hwflags);
+
+    if (mutex->sleepq != NULL)
+	{
+	adomain_t *sleeper = mutex->sleepq;
+	/* Wake up the first most prioritary sleeper. */
+	mutex->sleepq = sleeper->m_link;
+	__adeos_switch_to(adp_cpu_current[cpuid],sleeper,cpuid);
+	adeos_load_cpuid();
+	}
+    else
+	{
+	mutex->owner = NULL;
+	adeos_spin_unlock(&mutex->lock);
+	}
+
+    adp = adp_cpu_current[cpuid];
+
+    if (flags)
+	__set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+    else
+	{
+	__clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+	
+	if (adp->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage(IPIPE_IRQMASK_ANY);
+	}
+
+    adeos_unlock_cpu(hwflags);
+}
+
+#else /* !CONFIG_ADEOS_THREADS */
+
+int adeos_destroy_mutex (admutex_t *mutex)
+
+{
+    if (!adeos_spin_trylock(&mutex->lock) &&
+	adp_current != adp_root)
+	return -EBUSY;
+
+    return 0;
+}
+
+unsigned long adeos_lock_mutex (admutex_t *mutex)
+
+{
+    unsigned long flags; /* FIXME: won't work on SPARC */
+    adeos_spin_lock_irqsave(&mutex->lock,flags);
+    return flags;
+}
+
+void adeos_unlock_mutex (admutex_t *mutex, unsigned long flags)
+
+{
+    adeos_spin_unlock_irqrestore(&mutex->lock,flags);
+}
+
+#endif /* CONFIG_ADEOS_THREADS */
+
+void __adeos_takeover (void)
+
+{
+    __adeos_enable_pipeline();
+    printk(KERN_WARNING "Adeos: Pipelining started.\n");
+}
+
+#ifdef MODULE
+
+static int __init adeos_init_module (void)
+
+{
+    __adeos_takeover();
+    return 0;
+}
+
+static void __exit adeos_exit_module (void)
+
+{
+    __adeos_disable_pipeline();
+    printk(KERN_WARNING "Adeos: Pipelining stopped.\n");
+}
+
+module_init(adeos_init_module);
+module_exit(adeos_exit_module);
+
+#endif /* MODULE */
+
+EXPORT_SYMBOL(adeos_register_domain);
+EXPORT_SYMBOL(adeos_unregister_domain);
+EXPORT_SYMBOL(adeos_virtualize_irq_from);
+EXPORT_SYMBOL(adeos_control_irq);
+EXPORT_SYMBOL(__adeos_schedule_irq);
+EXPORT_SYMBOL(adeos_free_irq);
+EXPORT_SYMBOL(adeos_send_ipi);
+EXPORT_SYMBOL(adeos_catch_event_from);
+EXPORT_SYMBOL(adeos_init_attr);
+EXPORT_SYMBOL(adeos_get_sysinfo);
+EXPORT_SYMBOL(adeos_tune_timer);
+EXPORT_SYMBOL(adeos_alloc_ptdkey);
+EXPORT_SYMBOL(adeos_free_ptdkey);
+EXPORT_SYMBOL(adeos_set_ptd);
+EXPORT_SYMBOL(adeos_get_ptd);
+EXPORT_SYMBOL(adeos_set_irq_affinity);
+EXPORT_SYMBOL(adeos_init_mutex);
+EXPORT_SYMBOL(adeos_destroy_mutex);
+EXPORT_SYMBOL(adeos_lock_mutex);
+EXPORT_SYMBOL(adeos_unlock_mutex);
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/adeos/Makefile linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/adeos/Makefile
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/adeos/Makefile	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/adeos/Makefile	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,33 @@
+#
+# Makefile for the Adeos layer.
+#
+
+O_TARGET := built-in.o
+
+list-multi	:= adeos.o
+export-objs	:= generic.o
+adeos-objs	:= generic.o
+
+ifdef CONFIG_X86
+adeos-objs	+= x86.o
+endif
+
+ifdef CONFIG_ARM
+ifdef CONFIG_UCLINUX
+adeos-objs	+= armnommu.o
+else
+adeos-objs	+= armv.o
+export-objs	+= armv.o
+endif
+endif
+
+ifdef CONFIG_PPC
+adeos-objs	+= ppc.o
+endif
+
+obj-$(CONFIG_ADEOS)	+= adeos.o
+
+include $(TOPDIR)/Rules.make
+
+adeos.o: $(adeos-objs)
+	$(LD) -r -o $@ $(adeos-objs)
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/config.in linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/config.in
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/config.in	2004-08-03 19:25:37.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/config.in	2005-08-12 15:41:58.000000000 -0600
@@ -556,6 +556,13 @@ if [ "$CONFIG_SA1100_ACCELENT" = "y" ]; 
    fi
 fi
 bool 'Networking support' CONFIG_NET
+
+tristate 'Adeos support' CONFIG_ADEOS
+if [ "$CONFIG_ADEOS" != "n" ]; then
+   define_bool CONFIG_ADEOS_CORE y
+   bool 'Adeos domains are threads' CONFIG_ADEOS_THREADS
+fi
+
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
@@ -789,7 +796,9 @@ if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
     # -- ahaigh@arm.com (23 August 2002)
     define_bool CONFIG_FRAME_POINTER n
 else
+    if [ "$CONFIG_ARCH_EP9301" != "y" ]; then
     define_bool CONFIG_FRAME_POINTER y
+    fi
 fi
 
 bool 'Verbose user fault messages' CONFIG_DEBUG_USER
@@ -797,6 +806,9 @@ bool 'Include debugging information in k
 dep_bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE $CONFIG_CPU_26
 
 bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+if [ "$CONFIG_ARCH_EP9301" = "y" ]; then
+    dep_bool '  Compile Kernel with frame pointers' CONFIG_FRAME_POINTER $CONFIG_DEBUG_KERNEL
+fi
 dep_bool '  Debug memory allocations' CONFIG_DEBUG_SLAB $CONFIG_DEBUG_KERNEL
 dep_bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_DEBUG_KERNEL
 dep_bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK $CONFIG_DEBUG_KERNEL
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/adeos.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/adeos.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/adeos.c	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/adeos.c	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,527 @@
+/*
+ *   linux/arch/arm/kernel/adeos.c
+ *
+ *   Copyright (C) 2002-2005 Philippe Gerum.
+ *
+ *   Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ *   	various tweaks, fixes (e.g. call asm_do_IRQ() instead of do_IRQ() and
+ *   	optimizations, backport of unthreaded support from Adeos/x86 for 2.6
+ *
+ *   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.
+ *
+ *   Architecture-dependent ADEOS core support for ARM.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/arch/irq.h>
+
+asmlinkage void asm_do_IRQ(int irq,
+			   struct pt_regs *regs);
+
+struct pt_regs __adeos_irq_regs;
+
+/* adeos_critical_enter() -- Grab the superlock for entering a global
+   critical section. On this uniprocessor-only arch, this is identical
+   to hw cli(). */
+
+unsigned long adeos_critical_enter (void (*syncfn)(void))
+
+{
+    unsigned long flags;
+    adeos_hw_local_irq_save(flags);
+    return flags;
+}
+
+/* adeos_critical_exit() -- Release the superlock. */
+
+void adeos_critical_exit (unsigned long flags) {
+
+    adeos_hw_local_irq_restore(flags);
+}
+
+void __adeos_init_stage (adomain_t *adp)
+
+{
+    int cpuid, n;
+
+    for (cpuid = 0; cpuid < ADEOS_NR_CPUS; cpuid++)
+	{
+	adp->cpudata[cpuid].irq_pending_hi = 0;
+
+	for (n = 0; n < IPIPE_IRQ_IWORDS; n++)
+	    adp->cpudata[cpuid].irq_pending_lo[n] = 0;
+
+	for (n = 0; n < IPIPE_NR_IRQS; n++)
+	    adp->cpudata[cpuid].irq_hits[n] = 0;
+	}
+
+    for (n = 0; n < IPIPE_NR_IRQS; n++)
+	{
+	adp->irqs[n].acknowledge = NULL;
+	adp->irqs[n].handler = NULL;
+	adp->irqs[n].control = IPIPE_PASS_MASK;	/* Pass but don't handle */
+	}
+}
+
+/* compute number of most-significant 1-bit (100...0 -> 31, 00...01 -> 0), input
+ * must not be 0 */
+
+#if __LINUX_ARM_ARCH__ >= 5
+
+extern inline int flnz (unsigned long word)
+
+{
+    /* clz is only supported >= ARMv5 */
+    int i;
+    /* effect of "clz i, word":
+     * if (word == 0) i = 32; else i = 31 - (bit position of most significant '1' in word) */
+    __asm__(
+	"clz %0, %1"
+	: /* output */ "=r" (i)
+	: /* input */  "r"  (word)
+    );
+    /* word != 0 => i = 31 - (bit position of most significant '1' in word) */
+    return 31 - i;
+}
+
+#else /* __LINUX_ARM_ARCH__ < 5 */
+
+static int flnz (unsigned long word)
+
+{
+    int i = 0;
+
+    if ((word & 0xFFFF0000UL) != 0) {
+	word >>= 16;
+	i += 16;
+    }
+    if ((word & 0xFF00UL) != 0) {
+	word >>= 8;
+	i += 8;
+    }
+    if ((word & 0xF0UL) != 0) {
+	word >>= 4;
+	i += 4;
+    }
+    if ((word & 0xCUL) != 0) {
+	word >>= 2;
+	i += 2;
+    }
+    if ((word & 0x2UL) != 0)
+	i += 1;
+    return i;
+}
+
+#endif /* __LINUX_ARM_ARCH__ >= 5 */
+
+/* __adeos_sync_stage() -- Flush the pending IRQs for the current
+   domain (and processor).  This routine flushes the interrupt log
+   (see "Optimistic interrupt protection" from D. Stodolsky et al. for
+   more on the deferred interrupt scheme). Every interrupt that
+   occurred while the pipeline was stalled gets played.  WARNING:
+   callers on SMP boxen should always check for CPU migration on
+   return of this routine. One can control the kind of interrupts
+   which are going to be sync'ed using the syncmask
+   parameter. IPIPE_IRQMASK_ANY plays them all, IPIPE_IRQMASK_VIRT
+   plays virtual interrupts only. This routine must be called with hw
+   interrupts off. */
+
+void __adeos_sync_stage (unsigned long syncmask)
+
+{
+    unsigned long mask, submask;
+    struct adcpudata *cpudata;
+    adeos_declare_cpuid;
+    int level, rank;
+    adomain_t *adp;
+    unsigned irq;
+
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled());
+
+    adeos_load_cpuid();
+    adp = adp_cpu_current[cpuid];
+    cpudata = &adp->cpudata[cpuid];
+
+    do
+	{
+	/* The policy here is to keep the dispatching code
+	   interrupt-free by stalling the current stage. If the upper
+	   domain handler (which we call) wants to re-enable
+	   interrupts while in a safe portion of the code
+	   (e.g. SA_INTERRUPT flag unset for Linux's sigaction()), it
+	   will have to unstall (then stall again before returning to
+	   us!) the stage when it sees fit. */
+
+	while ((mask = (cpudata->irq_pending_hi & syncmask)) != 0)
+	    {
+	    /* Give a slight priority advantage to high-numbered IRQs
+	       like the virtual ones. */
+	    level = flnz(mask);
+	    __clear_bit(level,&cpudata->irq_pending_hi);
+
+	    while ((submask = cpudata->irq_pending_lo[level]) != 0)
+		{
+		rank = flnz(submask);
+		irq = (level << IPIPE_IRQ_ISHIFT) + rank;
+
+		if (test_bit(IPIPE_LOCK_FLAG,&adp->irqs[irq].control))
+		    {
+		    __clear_bit(rank,&cpudata->irq_pending_lo[level]);
+		    continue;
+		    }
+
+		if (--cpudata->irq_hits[irq] == 0)
+		    __clear_bit(rank,&cpudata->irq_pending_lo[level]);
+
+		/* Allow the sync routine to be reentered on behalf of
+		   the IRQ handler and any execution context switched
+		   in by the IRQ handler. The latter also means that
+		   returning from the switched out context is always
+		   safe even if the sync routine has been reentered in
+		   the meantime. */
+
+		__set_bit(IPIPE_STALL_FLAG,&cpudata->status);
+
+#ifdef CONFIG_ADEOS_PROFILING
+		__adeos_profile_data[cpuid].irqs[irq].n_synced++;
+		adeos_hw_tsc(__adeos_profile_data[cpuid].irqs[irq].t_synced);
+#endif /* CONFIG_ADEOS_PROFILING */
+
+		if (adp == adp_root)
+		    adeos_hw_sti();
+
+		((void (*)(unsigned, struct pt_regs *))adp->irqs[irq].handler)(irq,&__adeos_irq_regs);
+
+		adeos_hw_cli();
+
+		__clear_bit(IPIPE_STALL_FLAG,&cpudata->status);
+		}
+	    }
+	}
+    while ((cpudata->irq_pending_hi & syncmask) != 0);
+}
+
+/* __adeos_walk_pipeline(): Must be called with local interrupts
+   disabled. */
+
+static inline void __adeos_walk_pipeline (struct list_head *pos, int cpuid)
+
+{
+    adomain_t *this_domain = adp_cpu_current[cpuid];
+
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled());
+
+    while (pos != &__adeos_pipeline)
+	{
+    	adomain_t *next_domain = list_entry(pos,adomain_t,p_link);
+
+	if (test_bit(IPIPE_STALL_FLAG,&next_domain->cpudata[cpuid].status))
+	    break; /* Stalled stage -- do not go further. */
+
+	if (next_domain->cpudata[cpuid].irq_pending_hi != 0)
+	    {
+	    if (next_domain == this_domain)
+		__adeos_sync_stage(IPIPE_IRQMASK_ANY);
+	    else
+		{
+		__adeos_switch_to(this_domain,next_domain,cpuid);
+
+		adeos_load_cpuid(); /* Processor might have changed. */
+
+		if (!test_bit(IPIPE_STALL_FLAG,&this_domain->cpudata[cpuid].status) &&
+		    this_domain->cpudata[cpuid].irq_pending_hi != 0)
+		    __adeos_sync_stage(IPIPE_IRQMASK_ANY);
+		}
+
+	    break;
+	    }
+	else if (next_domain == this_domain)
+	    break;
+
+	pos = next_domain->p_link.next;
+	}
+}
+
+/* __adeos_handle_irq() -- ADEOS's generic IRQ handler. An optimistic
+   interrupt protection log is maintained here for each domain.
+   Interrupts are off on entry.
+   Please note that this function is never called if RTAI immediate interrupt
+   dispatching is active (see entry-armv.S and arm/hal.c) */
+
+asmlinkage int __adeos_handle_irq (int irq, struct pt_regs *regs)
+
+{
+    struct list_head *head, *pos;
+    adeos_declare_cpuid;
+    int m_ack, s_ack;
+
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled());
+
+    m_ack = irq & 0x100;
+    irq &= 0xff;
+
+    if (unlikely(!adp_pipelined))
+	{
+	/* Note that according to Russel King asm_do_IRQ() has to be called (at
+	 * least for 2.4.21-rmk7), not do_IRQ() as the original ADEOS code had
+	 * here. <mike@firmix.at> */
+	asm_do_IRQ(irq,regs);
+	return 1; /* do Linux return-to-user stuff */
+	}
+
+    if (!adeos_virtual_irq_p(irq))
+	irq = fixup_irq(irq);
+
+    if (irq >= IPIPE_NR_IRQS)
+	{
+	printk(KERN_ERR "ADEOS: spurious interrupt %d\n",irq);
+	goto out;
+	}
+
+    adeos_load_cpuid();
+
+#ifdef CONFIG_ADEOS_PROFILING
+    __adeos_profile_data[cpuid].irqs[irq].n_handled++;
+    adeos_hw_tsc(__adeos_profile_data[cpuid].irqs[irq].t_handled);
+#endif /* CONFIG_ADEOS_PROFILING */
+
+    s_ack = m_ack;
+
+    if (unlikely(test_bit(IPIPE_STICKY_FLAG,&adp_cpu_current[cpuid]->irqs[irq].control)))
+	head = &adp_cpu_current[cpuid]->p_link;
+    else
+	head = __adeos_pipeline.next;
+
+    /* Ack the interrupt. */
+
+    pos = head;
+
+    while (pos != &__adeos_pipeline)
+	{
+    	adomain_t *next_domain = list_entry(pos,adomain_t,p_link);
+
+	/* For each domain handling the incoming IRQ, mark it as
+           pending in its log. */
+
+	if (test_bit(IPIPE_HANDLE_FLAG,&next_domain->irqs[irq].control))
+	    {
+	    /* Domains that handle this IRQ are polled for
+	       acknowledging it by decreasing priority order. The
+	       interrupt must be made pending _first_ in the domain's
+	       status flags before the PIC is unlocked. */
+
+	    next_domain->cpudata[cpuid].irq_hits[irq]++;
+	    __adeos_set_irq_bit(next_domain,cpuid,irq);
+
+	    /* Always get the first master acknowledge available. Once
+	       we've got it, allow slave acknowledge handlers to run
+	       (until one of them stops us). */
+
+	    if (!m_ack)
+		m_ack = next_domain->irqs[irq].acknowledge(irq);
+	    else if (test_bit(IPIPE_SHARED_FLAG,&next_domain->irqs[irq].control) && !s_ack)
+		s_ack = next_domain->irqs[irq].acknowledge(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,&next_domain->irqs[irq].control))
+	    break;
+
+	pos = next_domain->p_link.next;
+	}
+
+    if (likely(irq == ADEOS_TIMER_IRQ))
+	{
+	__adeos_irq_regs.ARM_cpsr = regs->ARM_cpsr;
+	__adeos_irq_regs.ARM_pc = regs->ARM_pc;
+	}
+
+    /* Now walk the pipeline, yielding control to the highest priority
+       domain that has pending interrupt(s) or immediately to the
+       current domain if the interrupt has been marked as
+       'sticky'. 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 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. */
+
+    __adeos_walk_pipeline(head,cpuid);
+
+    adeos_load_cpuid();
+
+out:
+    /* Tell entry-code if it should perform Linux stuff when returning to user
+     * space (return != 0) or not (return == 0). (Linux doesn't expect
+     * schedule() etc. to be called when interrupts are disabled from its
+     * perspective (i.e. root-ipipe is stalled) or current domain is not Linux.) */
+    return (adp_cpu_current[cpuid] == adp_root &&
+	    !test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status));
+}
+
+/* adeos_trigger_irq() -- Push the interrupt to the pipeline entry
+   just like if it has been actually received from a hw source. This
+   both works for real and virtual interrupts. This also means that
+   the current domain might be immediately preempted by a more
+   prioritary domain who happens to handle this interrupt. */
+
+int adeos_trigger_irq (unsigned irq)
+
+{
+    struct pt_regs regs;
+    unsigned long flags;
+
+    if (irq >= IPIPE_NR_IRQS ||
+	(adeos_virtual_irq_p(irq) && !test_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map)))
+	return -EINVAL;
+
+    adeos_hw_local_irq_save(flags);
+
+    regs.ARM_cpsr = flags;
+
+    __adeos_handle_irq(irq | 0x100,&regs);
+
+    adeos_hw_local_irq_restore(flags);
+
+    return 1;
+}
+
+extern inline void __save_root_stall_flag_to_ibit (struct pt_regs *regs)
+
+{
+    adeos_declare_cpuid;
+    if (test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status))
+	regs->ARM_cpsr |= I_BIT;
+    else
+	regs->ARM_cpsr &= ~I_BIT;
+}
+
+/* Save the root's domain stall bit in the user's CPSR I-bit (assumption:
+ * hw-interrupt are always enabled in user-space) so that the proper pipeline
+ * state for the root stage can be restored when returning from one of the
+ * following exception:
+ * 	swi (swi should (can?) only be used in user mode!)
+ * 	irq in user mode
+ * 	undefined instruction in user mode
+ * 	data abort in user mode
+ * 	prefetch abort in user mode
+ * 	return from fork (returns to user mode)
+ *  i.e. all those that go through ret_fast_syscall, ret_disable_irq or
+ *  ret_to_user, see entry-common.S and entry-armv.S */
+asmlinkage void __adeos_user_exception_save_root (struct pt_regs *regs)
+
+{
+    if (likely(adp_pipelined))
+	__save_root_stall_flag_to_ibit(regs);
+}
+
+asmlinkage int __adeos_enter_syscall (struct pt_regs *regs, int scno)
+
+{
+    /* hw-irqs are enabled when this function is entered */
+    if (unlikely(__adeos_event_monitors[ADEOS_SYSCALL_PROLOGUE] > 0))
+	{
+	long oldip = regs->ARM_ip;
+	int stop_event;
+
+	ADEOS_PARANOIA_ASSERT(!adeos_hw_irqs_disabled());
+
+	regs->ARM_ip = scno;
+	stop_event = __adeos_handle_event(ADEOS_SYSCALL_PROLOGUE,regs);
+	regs->ARM_ip = oldip;
+
+	/* We might enter here over a non-root domain and exit over
+	 * the root one as a result of the issued syscall, so the interrupt
+	 * flag might not have been fixed-up during entering the kernel.
+	 * If the event is propageted (i.e. linux handles the syscall) we
+	 * need to fix up the interrupt flag as
+	 * __adeos_user_exception_save_root() is called upon returning to user
+	 * space. */
+	if (!stop_event)
+	    __save_root_stall_flag_to_ibit(regs);
+
+	return stop_event;
+	}
+
+    return 0;
+}
+
+asmlinkage int __adeos_exit_syscall (void)
+
+{
+    /* hw-irqs are enabled when this function is entered */
+    if (unlikely(__adeos_event_monitors[ADEOS_SYSCALL_EPILOGUE] > 0))
+	return __adeos_handle_event(ADEOS_SYSCALL_EPILOGUE,NULL);
+
+    return 0;
+}
+
+asmlinkage void __adeos_ret_to_user_restore_root (struct pt_regs *regs)
+
+{
+    adeos_declare_cpuid;
+
+    if (unlikely(!adp_pipelined))
+	return;
+
+    ADEOS_PARANOIA_ASSERT(!adeos_hw_irqs_disabled());
+
+    /* Restore root's ipipe stall state as it used to be on kernel entry.
+     * Side-effect: hw-irqs are forced to be enabled in user-mode. */
+
+    if (regs->ARM_cpsr & I_BIT)
+	{
+	regs->ARM_cpsr &= ~I_BIT;
+	adeos_hw_cli();
+	__set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	}
+    else
+	{
+	adeos_hw_cli();
+	__clear_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+
+	/* Sync all IRQs here, who knows when the next interrupt will happen 
+	 * (only then will the stage be synced!). */
+	if (adp_root->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage(IPIPE_IRQMASK_ANY);
+	}
+    /* We return with hw-irqs disabled, ready for restoring registers. */
+}
+
+/* default handler for Adeos syscall (will be replaced by non-root domain, e.g.
+ * RTAI for LXRT calls and SRQs */
+asmlinkage int __adeos_handle_syscall(struct pt_regs *regs)
+
+{
+    /* just return error code and do fast return from syscall */
+    *(long long*)&regs->ARM_r0 = -ENODEV;
+    return 1;
+}
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/armksyms.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/armksyms.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/armksyms.c	2004-07-22 13:48:58.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/armksyms.c	2005-08-12 15:41:58.000000000 -0600
@@ -56,6 +56,7 @@ extern int sys_exit(int);
  */
 extern void __ashldi3(void);
 extern void __ashrdi3(void);
+extern void __divdi3(void);
 extern void __divsi3(void);
 extern void __lshrdi3(void);
 extern void __modsi3(void);
@@ -86,6 +87,36 @@ extern void __do_softirq(void);
   __attribute__((section("__ksymtab"))) =	\
     { (unsigned long)&orig, __kstrtab_##sym };
 
+#ifdef CONFIG_ADEOS_CORE
+#ifdef CONFIG_ADEOS_MODULE
+EXPORT_SYMBOL(adp_pipelined);
+#include <asm/arch/irq.h>
+EXPORT_SYMBOL(asm_do_IRQ);
+#endif /* CONFIG_ADEOS_MODULE */
+EXPORT_SYMBOL(adeos_critical_enter);
+EXPORT_SYMBOL(adeos_critical_exit);
+EXPORT_SYMBOL(adeos_trigger_irq);
+EXPORT_SYMBOL(__adeos_sync_stage);
+EXPORT_SYMBOL(__adeos_irq_regs);
+EXPORT_SYMBOL(__adeos_tune_timer);
+#ifdef CONFIG_ADEOS_THREADS
+EXPORT_SYMBOL(__adeos_switch_domain);
+#endif /* CONFIG_ADEOS_THREADS */
+EXPORT_SYMBOL(__adeos_handle_irq);
+/* The following are per-platform convenience exports which are needed
+   by some Adeos domains loaded as kernel modules. */
+extern struct irqdesc irq_desc[];
+EXPORT_SYMBOL_NOVERS(irq_desc);
+EXPORT_SYMBOL_NOVERS(__switch_to);
+extern void show_regs(struct pt_regs * regs);
+EXPORT_SYMBOL_NOVERS(show_regs);
+EXPORT_SYMBOL(adeos_syscall_entry);
+EXPORT_SYMBOL(adeos_irq_entry);
+EXPORT_SYMBOL(adeos_root_domain);
+/* for debugging */
+EXPORT_SYMBOL(__backtrace);
+#endif /* CONFIG_ADEOS_CORE */
+
 /*
  * floating point math emulator support.
  * These symbols will never change their calling convention...
@@ -227,6 +258,7 @@ EXPORT_SYMBOL_NOVERS(__put_user_8);
 	/* gcc lib functions */
 EXPORT_SYMBOL_NOVERS(__ashldi3);
 EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(__divdi3);
 EXPORT_SYMBOL_NOVERS(__divsi3);
 EXPORT_SYMBOL_NOVERS(__lshrdi3);
 EXPORT_SYMBOL_NOVERS(__modsi3);
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/entry-armv.S linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/entry-armv.S
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/entry-armv.S	2004-08-03 19:25:38.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/entry-armv.S	2005-08-12 15:41:58.000000000 -0600
@@ -4,6 +4,13 @@
  *  Copyright (C) 1996,1997,1998 Russell King.
  *  ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk)
  *
+ *  Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ *  	Adeos support for EP93xx
+ *
+ *  Copyright (C) 2005 Adriano Bess (awbess@gmail.com)
+ *                     Ronald Gomes (ronaldfloripa@ig.com.br),
+ *                     Automatisa Sistemas
+ *     Small fixes on Adeos for TS7200 board
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -16,7 +23,6 @@
 #include <linux/config.h>
 #include "entry-header.S"
 
-
 #ifdef IOC_BASE
 /* IOC / IOMD based hardware */
 #include <asm/hardware/iomd.h>
@@ -459,6 +465,9 @@ ENTRY(soft_irq_mask)
                 .macro  disable_fiq
                 .endm
 
+		@ get number of irq from PIC
+		@ is irq <=> Z flag is 0 (ne), number of interrupt to be
+		@ handled is in \irqnr
 // Exit:        irqnr   Highest priority IRQ currently active
 //              flags   NE      irqnr valid
 //                      EQ      irqnr not valid (spurious IRQ)
@@ -662,6 +671,9 @@ ENTRY(anakin_active_irqs)
 /*
  * Invalid mode handlers
  */
+#ifdef CONFIG_ADEOS_CORE
+/* No need to change anything here, kernel will panic anyhow. */
+#endif
 __pabt_invalid:	sub	sp, sp, #S_FRAME_SIZE		@ Allocate frame size in one go
 		stmia	sp, {r0 - lr}			@ Save XXX r0 - lr
 		ldr	r4, .LCabt
@@ -711,12 +723,27 @@ __dabt_svc:	sub	sp, sp, #S_FRAME_SIZE
 		ldr	r2, .LCabt
 		add	r0, sp, #S_FRAME_SIZE
 		ldmia	r2, {r2 - r4}			@ get pc, cpsr
+#ifdef CONFIG_ADEOS_CORE
+		@ Earliest point we can enable hw-interrupts because of values
+		@ saved in __temp_abt (i.e. disabled irqs guards against values
+		@ being changed).
+		@ No other domain than root should generate this
+		@ exception => it is OK to enable irqs.
+@ *TODO* check if root domain? (call __adeos_handle_event(SIGxxx)?)
+		@ There is no need to restore root's stall state (as it is not
+		@ changed by the exception).
+		enable_irq ip
+#endif /* CONFIG_ADEOS_CORE */
 		add	r5, sp, #S_SP
 		mov	r1, lr
 		stmia	r5, {r0 - r4}			@ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+#ifdef CONFIG_ADEOS_CORE
+		@ Interrupts are alredy enabled.
+#else /* !CONFIG_ADEOS_CORE */
 		mrs	r9, cpsr			@ Enable interrupts if they were
 		tst	r3, #I_BIT
 		biceq	r9, r9, #I_BIT			@ previously
+#endif /* CONFIG_ADEOS_CORE */
 /*
  * This routine must not corrupt r9
  */
@@ -727,11 +754,14 @@ __dabt_svc:	sub	sp, sp, #S_FRAME_SIZE
 #else
 		bl	cpu_data_abort
 #endif
+#ifdef CONFIG_ADEOS_CORE
+		@ cpu_data_abort does not change hw-irqs, no need to reenable them.
+#else /* !CONFIG_ADEOS_CORE */
 		msr	cpsr_c, r9
+#endif /* !CONFIG_ADEOS_CORE */
 		mov	r2, sp
 		bl	SYMBOL_NAME(do_DataAbort)
-		mov	r0, #I_BIT | MODE_SVC
-		msr	cpsr_c, r0
+		disable_irq r0				@ disable interrupt hard
 		ldr	r0, [sp, #S_PSR]
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
@@ -751,7 +781,11 @@ __irq_svc:	sub	sp, sp, #S_FRAME_SIZE
 		@ routine called with r0 = irq number, r1 = struct pt_regs *
 		@
 		adrsvc	ne, lr, 1b
+#ifdef CONFIG_ADEOS_CORE
+		ldrne	pc, adeos_irq_entry		@ ...(r0 = irq number, r1 = struct pt_regs *)
+#else /* !CONFIG_ADEOS_CORE */
 		bne	asm_do_IRQ
+#endif /*CONFIG_ADEOS_CORE */
 		ldr	r0, [sp, #S_PSR]		@ irqs are already disabled
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
@@ -764,6 +798,17 @@ __und_svc:	sub	sp, sp, #S_FRAME_SIZE
 		ldr	r7, .LCund
 		mov	r6, lr
 		ldmia	r7, {r7 - r9}
+#ifdef CONFIG_ADEOS_CORE
+		@ Earliest point we can enable hw-interrupts because of values
+		@ saved in __temp_und (i.e. disabled irqs guards against values
+		@ being changed).
+		@ No other domain than root should generate this
+		@ exception => it is OK to enable irqs.
+@ *TODO* check if root domain? (call __adeos_handle_event(SIGxxx)?)
+		@ There is no need to restore root's stall state (as it is not
+		@ changed by the exception).
+		enable_irq ip
+#endif /* CONFIG_ADEOS_CORE */
 		add	r5, sp, #S_FRAME_SIZE
 		add	r4, sp, #S_SP
 		stmia	r4, {r5 - r9}			@ save sp_SVC, lr_SVC, pc, cpsr, old_ro
@@ -771,12 +816,21 @@ __und_svc:	sub	sp, sp, #S_FRAME_SIZE
 		adrsvc	al, r9, 1f			@ r9  = normal FP return
 		bl	call_fpe			@ lr  = undefined instr return
 
+#ifdef CONFIG_ADEOS_CORE
+		@ undefined instruction -> inform Adeos about it (this is *not* the
+		@ "FPU usage" event because there is no FPU support in Adeos for ARM)
+		mov	r0, #4				@ SIGILL
+		mov	r1, sp				@ struct pt_regs *regs
+		bl	__adeos_handle_event
+		cmp	r0, #0
+		bne	1f				@ !propagate -> return
+#endif /* CONFIG_ADEOS_CORE */
+
 		mov	r0, r5				@ unsigned long pc
 		mov	r1, sp				@ struct pt_regs *regs
 		bl	SYMBOL_NAME(do_undefinstr)
 
-1:		mov	r0, #I_BIT | MODE_SVC
-		msr	cpsr_c, r0
+1:		disable_irq r0
 		ldr	lr, [sp, #S_PSR]		@ Get SVC cpsr
 		msr	spsr, lr
 		ldmia	sp, {r0 - pc}^			@ Restore SVC registers
@@ -787,18 +841,32 @@ __pabt_svc:	sub	sp, sp, #S_FRAME_SIZE
 		ldr	r2, .LCabt
 		add	r0, sp, #S_FRAME_SIZE
 		ldmia	r2, {r2 - r4}			@ get pc, cpsr
+#ifdef CONFIG_ADEOS_CORE
+		@ Earliest point we can enable hw-interrupts because of values
+		@ saved in __temp_abt (i.e. disabled irqs guards against values
+		@ being changed).
+		@ No other domain than root should generate this
+		@ exception => it is OK to enable irqs.
+@ *TODO* check if root domain? (call __adeos_handle_event(SIGxxx)?)
+		@ There is no need to restore root's stall state (as it is not
+		@ changed by the exception).
+		enable_irq ip
+#endif /* CONFIG_ADEOS_CORE */
 		add	r5, sp, #S_SP
 		mov	r1, lr
 		stmia	r5, {r0 - r4}			@ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+#ifdef CONFIG_ADEOS_CORE
+		@ Interrupts are already enabled.
+#else /* !CONFIG_ADEOS_CORE */
 		mrs	r9, cpsr			@ Enable interrupts if they were
 		tst	r3, #I_BIT
 		biceq	r9, r9, #I_BIT			@ previously
 		msr	cpsr_c, r9
+#endif /* CONFIG_ADEOS_CORE */
 		mov	r0, r2				@ address (pc)
 		mov	r1, sp				@ regs
 		bl	SYMBOL_NAME(do_PrefetchAbort)	@ call abort handler
-		mov	r0, #I_BIT | MODE_SVC
-		msr	cpsr_c, r0
+		disable_irq r0
 		ldr	r0, [sp, #S_PSR]
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
@@ -811,7 +879,12 @@ __pabt_svc:	sub	sp, sp, #S_FRAME_SIZE
 .LCprocfns:	.word	SYMBOL_NAME(processor)
 #endif
 .LCfp:		.word	SYMBOL_NAME(fp_enter)
-
+#ifdef CONFIG_ADEOS_CORE
+		@ Hook for RTAI immediate irq dispatching.
+		.globl SYMBOL_NAME(adeos_irq_entry)
+SYMBOL_NAME(adeos_irq_entry):
+		.word	SYMBOL_NAME(__adeos_handle_irq)	@ Adeos default irq handler
+#endif /* CONFIG_ADEOS_CORE */
 		irq_prio_table
 
 /*
@@ -825,6 +898,20 @@ __dabt_usr:	sub	sp, sp, #S_FRAME_SIZE		@
 		ldmia	r7, {r2 - r4}			@ Get USR pc, cpsr
 		stmia	r5, {r2 - r4}			@ Save USR pc, cpsr, old_r0
 		stmdb	r5, {sp, lr}^
+#ifdef CONFIG_ADEOS_CORE
+		@ Earliest point we can enable hw-interrupts because of
+		@ "stmdb ...,{ }^" (it stores the user registers which are
+		@ protected by the disabled irqs).
+		enable_irq ip
+		mov	r5, r1				@ save registers
+		mov	r6, r2
+		mov	r4, r3
+		mov	r0, sp				@ regs (arg for func.)
+		bl	SYMBOL_NAME(__adeos_user_exception_save_root)
+		mov	r3, r4				@ restore registers
+		mov	r2, r6
+		mov	r1, r5
+#endif
 		alignment_trap r7, r7, __temp_abt
 		zero_fp
 #ifdef MULTI_CPU
@@ -834,8 +921,11 @@ __dabt_usr:	sub	sp, sp, #S_FRAME_SIZE		@
 #else
 		bl	cpu_data_abort
 #endif
-		mov	r2, #MODE_SVC
-		msr	cpsr_c, r2			@ Enable interrupts
+#ifdef CONFIG_ADEOS_CORE
+		@ Interrupts are already enabled.
+#else /* !CONFIG_ADEOS_CORE */
+		enable_irq r2				@ Enable interrupts
+#endif /* CONFIG_ADEOS_CORE */
 		mov	r2, sp
 		adrsvc	al, lr, ret_from_exception
 		b	SYMBOL_NAME(do_DataAbort)
@@ -851,15 +941,46 @@ __irq_usr:	sub	sp, sp, #S_FRAME_SIZE
 		alignment_trap r4, r7, __temp_irq
 		zero_fp
 1:		get_irqnr_and_base r0, r6, r5, lr
+#ifdef CONFIG_ADEOS_CORE
+		beq	2f				@ no irq -> fast return
+		/* assert(was-irq) */
+		mov	r1, sp
+		mov	lr, pc
+		ldr	pc, adeos_irq_entry		@ ...(r0 = irq number, r1 = struct pt_regs *)
+		@ Adeos irq handler returns with hw-irqs disabled.
+		teq	r0, #0				@ r0 = return code of adeos_irq_entry()
+		/* r0 == 0 <=> irq did not happen in Linux context OR root-ipipe is stalled
+		 *	do a fast return to user-mode to avoid schedule etc.
+		 *	(either context is not right or interrupt would never
+		 *	have happened without Adeos (so Linux doesn't expect
+		 *	schedule etc.))
+		 * r0 != 0 <=> irq did happen in Linux context and root-ipipe is not stalled
+		 *	"normal" interrupt in Linux context, do like original
+		 *	code and return to user-mode via ret_to_user
+		 */
+		bne 3f
+2:		/* assert(!was-irq || !in-linux-context || root-ipipe-is-stalled) */
+		restore_user_regs
+3:		/* assert(was-irq && in-linux-context && !root-ipipe-is-stalled) */
+		@ We have to fix-up the interrupt flag in the saved CPSR
+		@ so that ret_to_user restores the stall state correctly.
+		enable_irq ip				@ do it with hw-irqs enabled
+		mov	r0, sp
+		bl	SYMBOL_NAME(__adeos_user_exception_save_root)
+		mov	why, #0				@ hw-irqs are still enabled
+		get_current_task tsk
+		b	ret_to_user
+#else /* !CONFIG_ADEOS_CORE */
 		movne	r1, sp
 		adrsvc	ne, lr, 1b
 		@
 		@ routine called with r0 = irq number, r1 = struct pt_regs *
 		@
 		bne	asm_do_IRQ
-		mov	why, #0
+		mov	why, #0				@ we come here with interrupts already disabled
 		get_current_task tsk
 		b	ret_to_user
+#endif /* CONFIG_ADEOS_CORE */
 
 		.ltorg
 
@@ -871,6 +992,14 @@ __und_usr:	sub	sp, sp, #S_FRAME_SIZE		@ 
 		ldmia	r4, {r5 - r7}
 		stmia	r8, {r5 - r7}			@ Save USR pc, cpsr, old_r0
 		stmdb	r8, {sp, lr}^			@ Save user sp, lr
+#ifdef CONFIG_ADEOS_CORE
+		@ Earliest point we can enable hw-interrupts because of
+		@ "stmdb ...,{ }^" (it stores the user registers which are
+		@ protected by the disabled irqs).
+		enable_irq ip
+		mov	r0, sp				@ regs (arg for func.)
+		bl	SYMBOL_NAME(__adeos_user_exception_save_root)
+#endif /* CONFIG_ADEOS_CORE */
 		alignment_trap r4, r7, __temp_und
 		zero_fp
 		tst	r6, #T_BIT			@ Thumb mode
@@ -878,17 +1007,27 @@ __und_usr:	sub	sp, sp, #S_FRAME_SIZE		@ 
 		adrsvc	al, r9, ret_from_exception	@ r9  = normal FP return
 		adrsvc	al, lr, fpundefinstr		@ lr  = undefined instr return
 
-call_fpe:	enable_irq r10
-		get_current_task r10
+call_fpe:	get_current_task r10
 		mov	r8, #1
 		strb	r8, [r10, #TSK_USED_MATH]	@ set current->used_math
 		ldr	r4, .LCfp
 		add	r10, r10, #TSS_FPESAVE		@ r10 = workspace
 		ldr	pc, [r4]			@ Call FP module USR entry point
 
-fpundefinstr:	mov	r0, #MODE_SVC
-		msr	cpsr_c, r0			@ Enable interrupts
+fpundefinstr:	enable_irq r0				@ Enable interrupts
+#ifdef CONFIG_ADEOS_CORE
+		@ undefined instruction -> inform Adeos about it (this is *not* the
+		@ "FPU usage" event because there is no FPU support in Adeos for ARM)
+		mov	r5, lr				@ save lr
+		mov	r0, #4				@ SIGILL
+		mov	r1, sp				@ struct pt_regs *regs
+		bl	__adeos_handle_event
+		cmp	r0, #0
+		bne	ret_from_exception		@ !propagate -> return
+		mov	r0, r5				@ r0 = old lr
+#else /* !CONFIG_ADEOS_CORE */
 		mov	r0, lr
+#endif /* CONFIG_ADEOS_CORE */
 		mov	r1, sp
 		adrsvc	al, lr, ret_from_exception
 		b	SYMBOL_NAME(do_undefinstr)
@@ -901,10 +1040,21 @@ __pabt_usr:	sub	sp, sp, #S_FRAME_SIZE		@
 		ldmia	r4, {r5 - r7}			@ Get USR pc, cpsr
 		stmia	r8, {r5 - r7}			@ Save USR pc, cpsr, old_r0
 		stmdb	r8, {sp, lr}^			@ Save sp_usr lr_usr
+#ifdef CONFIG_ADEOS_CORE
+		@ Earliest point we can enable hw-interrupts because of
+		@ "stmdb ...,{ }^" (it stores the user registers which are
+		@ protected by the disabled irqs).
+		enable_irq ip
+		mov	r0, sp				@ regs
+		bl	SYMBOL_NAME(__adeos_user_exception_save_root)
+#endif /* CONFIG_ADEOS_CORE */
 		alignment_trap r4, r7, __temp_abt
 		zero_fp
-		mov	r0, #MODE_SVC
-		msr	cpsr_c, r0			@ Enable interrupts
+#ifdef CONFIG_ADEOS_CORE
+		@ Interrupts are already enabled.
+#else /* !CONFIG_ADEOS_CORE */
+		enable_irq r0				@ Enable interrupts
+#endif /* CONFIG_ADEOS_CORE */
 		mov	r0, r5				@ address (pc)
 		mov	r1, sp				@ regs
 		bl	SYMBOL_NAME(do_PrefetchAbort)	@ call abort handler
@@ -913,7 +1063,12 @@ __pabt_usr:	sub	sp, sp, #S_FRAME_SIZE		@
  * This is the return code to user mode for abort handlers
  */
 ENTRY(ret_from_exception)
+#ifdef CONFIG_ADEOS_CORE
+		@ hw-irqs should already be enabled, but be paranoid
+		enable_irq r1
+#else /* !CONFIG_ADEOS_CORE */
 		disable_irq r1
+#endif /* CONFIG_ADEOS_CORE */
 		mov	why, #0
 		get_current_task tsk
 		b	ret_to_user
@@ -927,6 +1082,11 @@ ENTRY(fp_enter)
  * r0 = previous, r1 = next, return previous.
  * previous and next are guaranteed not to be the same.
  */
+#ifdef CONFIG_ADEOS_CORE
+/* I think hw-irqs must be disabled on entry to protect spsr_svc from being
+ * modified by an interrupt. (Although I haven't found anything in plain
+ * Linux that guarantees irqs to be disabled ...) */
+#endif
 ENTRY(__switch_to)
 		stmfd	sp!, {r4 - sl, fp, lr}		@ Store most regs on stack
 		mrs	ip, cpsr
@@ -939,6 +1099,34 @@ ENTRY(__switch_to)
 		msr	spsr, ip			@ Save tasks CPSR into SPSR for this return
 		ldmfd	sp!, {r4 - sl, fp, pc}^		@ Load all regs saved previously
 
+#ifdef CONFIG_ADEOS_CORE
+#ifdef CONFIG_ADEOS_THREADS
+/*
+ * Domain switch code. Interrupts must be off on entry.
+ * r0 = incoming domain, r1 = &adp_cpu_current[cpuid]
+ * Contributed by Jerome Poichet <jerome@kingofsofa.org>
+ */
+
+ENTRY(__adeos_switch_domain)
+	stmfd   sp!, {r0 - sl, fp, lr}  @ push most registers onto stack (scratch ip never)
+	mrs     ip, cpsr                @ get current cpsr_SVC and
+	str     ip, [sp, #-4]!          @ push it onto stack
+	mrc     p15, 0, r2, c3, c0      @ get current domain_access_control and
+	str     r2, [sp, #-4]!          @ push it onto stack
+
+	ldr     r2, [r1]                @ r2 = adp_cpu_current[cpuid] (outgoing domain)
+	str     sp, [r2, #4]            @ save outgoing sp_SVC
+	str     r0, [r1]                @ adp_cpu_current[cpuid] = incoming_domain
+	ldr     sp, [r0, #4]            @ load incoming sp_SVC
+
+	ldr     r2, [sp], #4            @ pop previous domain_access_control from stack
+	ldr     ip, [sp], #4            @ pop previous cpsr_SVC from stack
+	mcr     p15, 0, r2, c3, c0      @ restore previous domain_access_control
+	msr     spsr, ip                @ replace current spsr_SVC with previous cpsr_SVC
+	ldmfd   sp!, {r0 - sl, fp, pc}^ @ pop previous registers, pc = previous lr
+#endif /* CONFIG_ADEOS_THREADS */
+#endif /* CONFIG_ADEOS_CORE */
+
 		.section ".text.init",#alloc,#execinstr
 /*
  * Vector stubs.  NOTE that we only align 'vector_IRQ' to a cache line boundary,
@@ -1161,6 +1349,19 @@ __stubs_end:
 
 		.equ	__real_stubs_start, .LCvectors + 0x200
 
+/*
+ * Exception vectors (see ARM Architecture Reference Manual, 2.6 Exceptions)
+ * Vector base is either 0x00000000 or 0xffff0000.
+ *   offset	execption type
+ *   00		reset
+ *   04		undefined instruction
+ *   08		software interrupt
+ *   0C		prefetch abort (instruction fetch memory abort)
+ *   10		data abort (data access memory abort)
+ *   14		address ecxeption (no longer used)
+ *   18		interrupt
+ *   1C		fast interrupt
+ */
 .LCvectors:	swi	SYS_ERROR0
 		b	__real_stubs_start + (vector_undefinstr - __stubs_start)
 		ldr	pc, __real_stubs_start + (.LCvswi - __stubs_start)
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/entry-common.S linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/entry-common.S
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/entry-common.S	2004-07-22 13:48:58.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/entry-common.S	2005-08-12 15:41:58.000000000 -0600
@@ -3,6 +3,9 @@
  *
  *  Copyright (C) 2000 Russell King
  *
+ *  Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ *  	Adeos support for EP93xx
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -27,6 +30,57 @@ ENTRY(__do_softirq)
 	bl	do_softirq
 	ldmfd	sp!, {r0 - r3, ip, pc}
 
+#ifdef CONFIG_ADEOS_CORE
+/*
+ * This is how user mode exceptions are handled under Adeos (i.e. when
+ * hw-irqs are enabled, how to return to user mode, etc.):
+ * + ret_from_fork
+ *	enable-irq
+ *	...
+ *	goto ret_disable_irq
+ * + __sys_trace_return
+ *	enable-irq
+ *	...
+ *	goto ret_disable_irq
+ * + vector_swi:
+ *	enable-irq
+ *	if (is-adeos-syscall) {
+ *	    r = adeos_syscall_entry(pt_regs)
+ *	    if (r != 0) { disable_irq; goto adeos_fast_ret }
+ *	    enable-irq
+ *	    goto ret_to_user
+ *	}
+ *	if (__adeos_enter_syscall() != 0) { disable-irq; goto adeos_fast_ret }
+ *	__adeos_user_exception_save_root()
+ *	syscall()
+ *	goto ret_fast_syscall
+ * + __irq_usr (if (was-irq && in-linux-context && !root-ipipe-is-stalled)):
+ *	if (adeos_irq_entry(irq, regs) == 0) restore_user_regs
+ *	enable-irq
+ *	__adeos_user_exception_save_root()
+ *	goto ret_to_user
+ * + __und_usr:
+ *	enable-irq
+ *	__adeos_user_exception_save_root()
+ *	fp-emu()
+ *	if (!fp-was-ok) { enable-irq; if (__adeos_handle_event()) do_undefinstr() }
+ *	goto ret_from_exception
+ * + __dabt_usr:
+ *	enable-irq
+ *	__adeos_user_exception_save_root()
+ *	cpu_data_abort()
+ *	do_DataAbort()
+ *	goto ret_from_exception
+ * + __pabt_usr:
+ *	enable-irq
+ *	__adeos_user_exception_save_root()
+ *	do_PrefetchAbort()
+ *	goto ret_from_exception
+ * + ret_from_exception:
+ * 	enable-irq
+ * 	goto ret_to_user
+ */
+#endif /* CONFIG_ADEOS_CORE */	
 	.align	5
 /*
  * This is the fast syscall return path.  We do as little as
@@ -34,12 +88,32 @@ ENTRY(__do_softirq)
  * stack.
  */
 ret_fast_syscall:
+#ifdef CONFIG_ADEOS_CORE
+	mov	r7, r0				@ save return code
+	bl	__adeos_exit_syscall
+	cmp	r0, #0
+	mov	r0, r7				@ restore return code
+	bne	1f				@ don't propagate (but restore root's ipipe stall flag)
+#else /* !CONFIG_ADEOS_CORE */	
 	disable_irq r1				@ ensure IRQs are disabled
+#endif /* CONFIG_ADEOS_CORE */	
 	ldr	r1, [tsk, #TSK_NEED_RESCHED]
 	ldr	r2, [tsk, #TSK_SIGPENDING]
 	teq	r1, #0				@ need_resched || sigpending
 	teqeq	r2, #0
 	bne	slow
+#ifdef CONFIG_ADEOS_CORE
+1:	@ Entered from ret_fast_syscall if (!need_resched && !sigpending)
+	@ || __adeos_exit_syscall() says do not propagate.
+	@ Restore root's ipipe stall flag.
+	mov	r7, r0				@ save r0
+	add	r0, sp, #S_OFF			@ let r0 point to user regs
+	bl	SYMBOL_NAME(__adeos_ret_to_user_restore_root)
+	@ comes back with hw-irqs disabled
+	mov	r0, r7				@ restore r0
+adeos_fast_ret:
+	@ hw-irqs must be disabled here!
+#endif /* CONFIG_ADEOS_CORE */
 	fast_restore_user_regs
 
 /*
@@ -55,9 +129,11 @@ slow:	str	r0, [sp, #S_R0+S_OFF]!	@ retur
 reschedule:
 	bl	SYMBOL_NAME(schedule)
 ret_disable_irq:
+#ifndef CONFIG_ADEOS_CORE
+	@ We disable irqs just before restoring the registers, not now.
 	disable_irq r1				@ ensure IRQs are disabled
-ENTRY(ret_to_user)
-ret_slow_syscall:
+#endif /* !CONFIG_ADEOS_CORE */
+ENTRY(ret_to_user)				@ return from exception to user-mode
 	ldr	r1, [tsk, #TSK_NEED_RESCHED]
 	ldr	r2, [tsk, #TSK_SIGPENDING]
 	teq	r1, #0				@ need_resched => schedule()
@@ -65,6 +141,12 @@ ret_slow_syscall:
 1:	teq	r2, #0				@ sigpending => do_signal()
 	bne	__do_signal
 restore:
+#ifdef CONFIG_ADEOS_CORE
+	@ Restore root's ipipe stall flag.
+	mov	r0, sp				@ let r0 point to user regs
+	bl	SYMBOL_NAME(__adeos_ret_to_user_restore_root)
+	@ comes back with hw-irqs disabled
+#endif /* CONFIG_ADEOS_CORE */
 	restore_user_regs
 
 __do_signal:
@@ -73,7 +155,9 @@ __do_signal:
 	mov	r1, sp				@ 'regs'
 	mov	r2, why				@ 'syscall'
 	bl	SYMBOL_NAME(do_signal)		@ note the bl above sets lr
+#ifndef CONFIG_ADEOS_CORE
 	disable_irq r1				@ ensure IRQs are disabled
+#endif /* !CONFIG_ADEOS_CORE */
 	b	restore
 
 /*
@@ -82,6 +166,11 @@ __do_signal:
  * calling schedule_tail).
  */
 ENTRY(ret_from_fork)
+#ifdef CONFIG_ADEOS_CORE
+	enable_irq ip				@ should already be enabled, be paranoid
+	@ Note, that the i_bit in the saved cpsr is 0 and the new process
+	@ will be started with an unstalled stage.
+#endif /* CONFIG_ADEOS_CORE */
 	bl	SYMBOL_NAME(schedule_tail)
 	get_current_task tsk
 	ldr	ip, [tsk, #TSK_PTRACE]		@ check for syscall tracing
@@ -143,9 +232,27 @@ ENTRY(vector_swi)
 	str	r4, [sp, #-S_OFF]!		@ push fifth arg
 
 	get_current_task tsk
-	ldr	ip, [tsk, #TSK_PTRACE]		@ check for syscall tracing
 	bic	scno, scno, #0xff000000		@ mask off SWI op-code
+#ifdef CONFIG_ADEOS_CORE
+	ldr	tbl, .adeos_syscall_magic	@ check if it is the Adeos syscall
+	cmp	scno, tbl
+	beq	handle_adeos_syscall
+#endif /* CONFIG_ADEOS_CORE */
 	eor	scno, scno, #OS_NUMBER << 20	@ check OS number
+#ifdef CONFIG_ADEOS_CORE
+	add	r0, sp, #S_OFF			@ let r0 point to user regs
+	mov	r1, scno
+	bl	__adeos_enter_syscall		@ event "enter Linux syscall"
+	cmp     r0, #0				@ r0 == 0 <=> propagate
+	movne	r0, #-EINVAL			@ !propagate -> return EINVAL
+	disable_irq_cond ne			@ !propagate -> disable hw-irqs
+	addeq	tbl, sp, #S_OFF			@ propagate -> tbl = saved user regs
+	bne	adeos_fast_ret			@ !propagate -> fast-return
+	mov	r0, tbl				@ saved regs
+	bl	SYMBOL_NAME(__adeos_user_exception_save_root)
+	ldmia	tbl, {r0-r3}			@ restore syscall args from saved regs
+#endif /* CONFIG_ADEOS_CORE */
+	ldr	ip, [tsk, #TSK_PTRACE]		@ check for syscall tracing
 	adr	tbl, sys_call_table		@ load syscall table pointer
 	tst	ip, #PT_TRACESYS		@ are we tracing syscalls?
 	bne	__sys_trace
@@ -161,6 +268,27 @@ ENTRY(vector_swi)
 	bcs	SYMBOL_NAME(arm_syscall)	
 	b	SYMBOL_NAME(sys_ni_syscall)	@ not private func
 
+#ifdef CONFIG_ADEOS_CORE
+handle_adeos_syscall:
+	@ handle Adeos syscall (used by RTAI for LXRT calls and SRQs)
+	ldr	ip, adeos_syscall_entry
+	add	r0, sp, #S_OFF			@ r0 <- ptr to saved regs
+	mov	lr, pc
+	mov	pc, ip				@ adeos_syscall_entry(pt_regs*)
+	cmp	r0 , #0				@ slow or fast return?
+	@ long long return value is in saved r0/r1, r0 is not loaded from stack
+	@ by fast_restore_user_regs => load it here.
+	ldrne	r0, [sp, #S_R0 + S_OFF]
+	@ r0 != 0 -> fast
+	disable_irq_cond ne
+	bne	adeos_fast_ret
+	@ r0 == 0 -> slow return
+	enable_irq ip
+	add	sp, sp, #S_OFF			@ fix stack-pointer for restore_user_regs
+	mov	why, #0				@ no longer a real syscall
+	b	ret_to_user
+#endif /* CONFIG_ADEOS_CORE */
+
 	/*
 	 * This is the really slow path.  We're going to be doing
 	 * context switches, and waiting for our parent to respond.
@@ -178,6 +306,9 @@ __sys_trace:
 	b	2b
 
 __sys_trace_return:
+#ifdef CONFIG_ADEOS_CORE
+	enable_irq ip				@ should already be enabled, be paranoid
+#endif /* CONFIG_ADEOS_CORE */
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
 	mov	r1, sp
 	mov	r0, #1				@ trace exit [IP = 1]
@@ -190,6 +321,15 @@ __sys_trace_return:
 __cr_alignment:
 	.word	SYMBOL_NAME(cr_alignment)
 #endif
+#ifdef CONFIG_ADEOS_CORE
+	@ special syscall to make transition from user-space to kernel-space
+	@ (used by RTAI to implement LXRT calls and SRQs)
+.adeos_syscall_magic:
+	.word	0x9ffff0				@ see asm-arm/rtai_vectors.h
+	.globl SYMBOL_NAME(adeos_syscall_entry)
+SYMBOL_NAME(adeos_syscall_entry):
+	.word	SYMBOL_NAME(__adeos_handle_syscall)	@ Adeos default syscall handler
+#endif /* CONFIG_ADEOS_CORE */
 
 	.type	sys_call_table, #object
 ENTRY(sys_call_table)
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/entry-header.S linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/entry-header.S
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/entry-header.S	2004-07-22 13:48:58.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/entry-header.S	2005-08-12 15:41:58.000000000 -0600
@@ -71,11 +71,12 @@
 
 #ifdef CONFIG_CPU_32
 	.macro	set_cpsr_c, reg, mode
-#if 1
+#if 0
 	/* broken binutils */
 	mov	\reg, \mode
 	msr	cpsr_c, \reg
 #else
+	/* binutils 2.14.90 are OK -- mike@firmix.at */
 	msr	cpsr_c, \mode
 #endif
 	.endm
@@ -88,6 +89,16 @@
 	set_cpsr_c \temp, #MODE_SVC
 	.endm
 
+#ifdef CONFIG_ADEOS_CORE
+	.macro	set_cpsr_c_cond, cond, mode
+	msr\cond cpsr_c, \mode
+	.endm
+
+	.macro	disable_irq_cond, cond
+	set_cpsr_c_cond \cond, #I_BIT | MODE_SVC
+	.endm
+#endif
+
 		.macro	save_user_regs
 		sub	sp, sp, #S_FRAME_SIZE
 		stmia	sp, {r0 - r12}			@ Calling r0 - r12
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/irq.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/irq.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/irq.c	2004-08-03 19:25:38.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/irq.c	2005-08-12 15:41:58.000000000 -0600
@@ -152,6 +152,10 @@ int get_irq_list(char *buf)
 	return p - buf;
 }
 
+#ifdef CONFIG_ADEOS_CORE
+/* increase performance by disabling IRQ lock detection */
+#define check_irq_lock(desc, irq, regs)		(0)
+#else /* !CONFIG_ADEOS_CORE */
 /*
  * IRQ lock detection.
  *
@@ -183,6 +187,7 @@ static int check_irq_lock(struct irqdesc
 	}
 	return 0;
 }
+#endif /* CONFIG_ADEOS_CORE */
 
 static void
 __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
@@ -220,6 +225,9 @@ void do_IRQ(int irq, struct pt_regs * re
 	 * Acknowledge and clear the IRQ, but (if its
 	 * a level-based IRQ, don't mask it)
 	 */
+#ifdef CONFIG_ADEOS_CORE
+    if (!adp_pipelined)
+#endif /* CONFIG_ADEOS_CORE */
 	desc->mask_ack(irq);
 
 	/*
@@ -310,6 +318,11 @@ static void do_pending_irqs(struct pt_re
  */
 asmlinkage void asm_do_IRQ(int irq, struct pt_regs *regs)
 {
+#ifdef CONFIG_ADEOS_CORE
+    /* Only fix-up irq if pipline is not active (then it was already done
+     * in __adeos_handle_irq(). <mike@firmix.at> */
+    if (!adp_pipelined)
+#endif /* CONFIG_ADEOS_CORE */
 	irq = fixup_irq(irq);
 
 	/*
@@ -346,6 +359,7 @@ asmlinkage void asm_do_IRQ(int irq, stru
 	return;
 }
 
+#ifndef CONFIG_ADEOS_CORE /* increase performance by disabling IRQ lock detection */
 static void irqlck_timeout(unsigned long _data)
 {
 	struct irqdesc *desc = (struct irqdesc *)_data;
@@ -364,6 +378,7 @@ static void irqlck_timeout(unsigned long
 
 	spin_unlock(&irq_controller_lock);
 }
+#endif /* !CONFIG_ADEOS_CORE */
 
 #ifdef CONFIG_ARCH_ACORN
 void do_ecard_IRQ(int irq, struct pt_regs *regs)
@@ -678,9 +693,11 @@ void __init init_IRQ(void)
 		irq_desc[irq].mask     = dummy_mask_unmask_irq;
 		irq_desc[irq].unmask   = dummy_mask_unmask_irq;
 		INIT_LIST_HEAD(&irq_desc[irq].pend);
+#ifndef CONFIG_ADEOS_CORE /* increase performance by disabling IRQ lock detection */
 		init_timer(&irq_desc[irq].lck_timer);
 		irq_desc[irq].lck_timer.data = (unsigned long)&irq_desc[irq];
 		irq_desc[irq].lck_timer.function = irqlck_timeout;
+#endif /* !CONFIG_ADEOS_CORE */
 	}
 
 	init_arch_irq();
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/Makefile linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/Makefile
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/Makefile	2004-07-22 13:48:58.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/Makefile	2005-08-12 15:41:58.000000000 -0600
@@ -39,7 +39,7 @@ obj-m		:=
 obj-n		:=
 obj-		:=
 
-export-objs	:= armksyms.o dma.o ecard.o fiq.o io.o oldlatches.o time.o
+export-objs	:= adeos.o armksyms.o dma.o ecard.o fiq.o io.o oldlatches.o time.o
 
 no-irq-arch	:= $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \
 		   $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
@@ -52,6 +52,7 @@ ifneq ($(findstring y,$(no-irq-arch)),y)
   obj-y		+= irq-arch.o
 endif
 
+obj-$(CONFIG_ADEOS_CORE) += adeos.o
 obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o
 obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o
 obj-$(CONFIG_ARCH_RISCSTATION) += time-acorn.o
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/process.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/process.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/process.c	2004-07-22 13:48:58.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/process.c	2005-08-12 15:41:58.000000000 -0600
@@ -72,10 +72,22 @@ void (*pm_power_off)(void);
  */
 void default_idle(void)
 {
+#ifdef CONFIG_ADEOS_CORE
+	/* if we don't do a hard cli, we might miss an interrupt and
+	 * sleep for an indefinite time (system lock-up or increased
+	 * interrupt latency) --<mike@firmix@at> */
+	adeos_hw_cli();
+#else
 	local_irq_disable();
+#endif
 	if (!current->need_resched && !hlt_counter)
 		arch_idle();
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_sti();
+	ADEOS_PARANOIA_ASSERT(test_bit(IPIPE_STALL_FLAG, &adp_root->cpudata[adeos_processor_id()].status) == 0);
+#else
 	local_irq_enable();
+#endif
 }
 
 /*
@@ -91,12 +103,19 @@ void cpu_idle(void)
 	current->counter = -100;
 
 	while (1) {
+#ifdef CONFIG_ADEOS_CORE
+		adeos_suspend_domain();
+		leds_event(led_idle_start);
+		while (!current->need_resched)
+			default_idle();
+#else /* !CONFIG_ADEOS_CORE */
 		void (*idle)(void) = pm_idle;
 		if (!idle)
 			idle = default_idle;
 		leds_event(led_idle_start);
 		while (!current->need_resched)
 			idle();
+#endif /* CONFIG_ADEOS_CORE */
 		leds_event(led_idle_end);
 		schedule();
 #ifndef CONFIG_NO_PGT_CACHE
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/setup.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/setup.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/setup.c	2004-07-22 13:48:58.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/setup.c	2005-08-12 15:41:58.000000000 -0600
@@ -554,6 +554,20 @@ void __init setup_arch(char **cmdline_p)
 	conswitchp = &dummy_con;
 #endif
 #endif
+
+#if 0
+	/* *DEBUG* initialise ports for debbuging with oscillioscope */
+	/* EGPIO0/A0 */
+	outl(inl(GPIO_AINTEN) & ~1UL, GPIO_AINTEN);	/* no interrupt on A0 */
+	outl(inl(GPIO_AEOI)   |  1UL, GPIO_AEOI);	/* clear interrupt */
+	outl(inl(GPIO_PADDR)  |  1UL, GPIO_PADDR);	/* set to output */
+	outl(inl(GPIO_PADR)   & ~1UL, GPIO_PADR);	/* set value to 0 */
+	/* EGPIO9/B1 */
+	outl(inl(GPIO_BINTEN) & ~2UL, GPIO_BINTEN);      /* disable interrupt */
+	outl(inl(GPIO_BEOI)   |  2UL, GPIO_BEOI);        /* clear interrupt */
+	outl(inl(GPIO_PBDDR)  |  2UL, GPIO_PBDDR);       /* set to output */
+	outl(inl(GPIO_PBDR)   & ~2UL, GPIO_PBDR);        /* set value to 0 */
+#endif
 }
 
 static const char *hwcap_str[] = {
@@ -593,6 +607,23 @@ static int c_show(struct seq_file *m, vo
 	seq_printf(m, "Serial\t\t: %08x%08x\n",
 		   system_serial_high, system_serial_low);
 
+#if 0
+	/* *DEBUG* */
+	static struct { char *n; unsigned long o; } x[] = {
+	    { "IRQSTATUS", VIC0IRQSTATUS},
+	    { "RAWINTR", VIC0RAWINTR},
+	    { "INTENABLE", VIC0INTENABLE},
+	    { "SOFTINT", VIC0SOFTINT},
+	};
+	unsigned long base[2] = {VIC0_BASE, VIC1_BASE};
+	int i, j;
+	for (i = 0; i < 2; ++i) {
+	    for (j = 0; j < 4; ++j) {
+		seq_printf(m, "VIC%d%s\t: %08x\n", i, x[j].n, inl(base[i] + (x[j].o - VIC0_BASE)));
+
+	    }
+	}
+#endif
 	return 0;
 }
 
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/time.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/time.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/time.c	2004-07-22 13:48:58.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/time.c	2005-08-12 15:41:58.000000000 -0600
@@ -224,3 +224,15 @@ void __init time_init(void)
 
 	setup_timer();
 }
+
+#ifdef CONFIG_ADEOS_CORE
+
+/* Simply inline the arch-specific code to set the frequency of the
+   timer. Interrrupts must be masked on entry. */
+
+void __adeos_tune_timer (unsigned long hz) {
+
+    __adeos_set_timer(hz);
+}
+
+#endif /* CONFIG_ADEOS_CORE */
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/traps.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/traps.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/kernel/traps.c	2004-07-22 13:48:58.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/kernel/traps.c	2005-08-12 15:41:58.000000000 -0600
@@ -44,6 +44,7 @@ const char *processor_modes[]=
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
+#ifdef CONFIG_FRAME_POINTER
 /*
  * Stack pointers should always be within the kernels view of
  * physical memory.  If it is not there, then we can't dump
@@ -56,6 +57,7 @@ static int verify_stack(unsigned long sp
 
 	return 0;
 }
+#endif
 
 /*
  * Dump out the contents of some memory nicely...
@@ -184,12 +186,21 @@ NORET_TYPE void die(const char *str, str
 {
 	struct task_struct *tsk = current;
 
+#ifdef CONFIG_ADEOS_CORE
+       if (adp_current != adp_root)
+           adeos_set_printk_sync(adp_current);
+#endif /* CONFIG_ADEOS_CORE */
 	console_verbose();
 	spin_lock_irq(&die_lock);
 
 	printk("Internal error: %s: %x\n", str, err);
 	printk("CPU: %d\n", smp_processor_id());
 	show_regs(regs);
+#ifdef CONFIG_ADEOS_CORE
+       if (adp_current != adp_root)
+           printk("Adeos domain %s", adp_current->name);
+       else
+#endif /* CONFIG_ADEOS_CORE */
 	printk("Process %s (pid: %d, stack limit = 0x%p)\n",
 		current->comm, current->pid, tsk + 1);
 
@@ -285,6 +296,10 @@ asmlinkage void bad_mode(struct pt_regs 
 {
 	unsigned int vectors = vectors_base();
 
+#ifdef CONFIG_ADEOS_CORE
+       if (adp_current != adp_root)
+           adeos_set_printk_sync(adp_current);
+#endif /* CONFIG_ADEOS_CORE */
 	console_verbose();
 
 	printk(KERN_CRIT "Bad mode in %s handler detected: mode %s\n",
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/lib/udivdi3.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/lib/udivdi3.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/lib/udivdi3.c	2004-07-22 13:48:57.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/lib/udivdi3.c	2005-08-12 15:41:58.000000000 -0600
@@ -240,3 +240,42 @@ __umoddi3 (UDItype u, UDItype v)
   return w;
 }
 
+/* added signed variant for RTAI */
+
+static inline DItype
+__negdi2 (DItype u)
+{
+  DIunion w;
+  DIunion uu;
+
+  uu.ll = u;
+
+  w.s.low = -uu.s.low;
+  w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
+
+  return w.ll;
+}
+
+DItype
+__divdi3 (DItype u, DItype v)
+{
+  word_type c = 0;
+  DIunion uu, vv;
+  DItype w;
+
+  uu.ll = u;
+  vv.ll = v;
+
+  if (uu.s.high < 0)
+    c = ~c,
+    uu.ll = __negdi2 (uu.ll);
+  if (vv.s.high < 0)
+    c = ~c,
+    vv.ll = __negdi2 (vv.ll);
+
+  w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
+  if (c)
+    w = __negdi2 (w);
+
+  return w;
+}
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mach-ep93xx/irq.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mach-ep93xx/irq.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mach-ep93xx/irq.c	2004-07-22 13:48:59.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mach-ep93xx/irq.c	2005-08-12 15:41:58.000000000 -0600
@@ -50,6 +50,24 @@
  *
  ************************************************************************/
 
+static void ep93xx_mask_ack_irq_timer1(unsigned int irq)
+{
+	outl((1 << IRQ_TIMER1), VIC0INTENCLEAR);
+	outl(1, TIMER1CLEAR);
+}
+ 
+static void ep93xx_mask_ack_irq_timer2(unsigned int irq)
+{
+	outl((1 << IRQ_TIMER2), VIC0INTENCLEAR);
+	outl(1, TIMER2CLEAR);
+}
+ 
+static void ep93xx_mask_ack_irq_timer3(unsigned int irq)
+{
+	outl((1 << (IRQ_TIMER3 - 32)), VIC1INTENCLEAR );
+	outl(1, TIMER3CLEAR);
+}
+ 
 static void ep93xx_mask_irq(unsigned int irq)
 {
 	if (irq < 32)
@@ -89,5 +107,10 @@ void __init ep93xx_init_irq(void)
 		irq_desc[i].mask	= ep93xx_mask_irq;
 		irq_desc[i].unmask	= ep93xx_unmask_irq;
 	}
+	/* let mask_ack of selected irqs really ack on hardware level 
+	 * (makes live a lot easier with Adeos) */
+	irq_desc[IRQ_TIMER1].mask_ack = ep93xx_mask_ack_irq_timer1;
+	irq_desc[IRQ_TIMER2].mask_ack = ep93xx_mask_ack_irq_timer2;
+	irq_desc[IRQ_TIMER3].mask_ack = ep93xx_mask_ack_irq_timer3;
+	/* TODO: add ack functions for other interrupts? */
 }
-
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mach-ep93xx/Makefile linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mach-ep93xx/Makefile
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mach-ep93xx/Makefile	2004-07-22 13:48:59.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mach-ep93xx/Makefile	2005-08-12 15:41:58.000000000 -0600
@@ -16,7 +16,7 @@ obj-m			:=
 obj-n			:=
 obj-			:=
 
-export-objs		:= pcipool.o
+export-objs		:= time.o ssp.o
 
 obj-$(CONFIG_EP93XX_DMA)+= dma_ep93xx.o
 
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mach-ep93xx/ssp.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mach-ep93xx/ssp.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mach-ep93xx/ssp.c	2004-07-22 13:48:59.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mach-ep93xx/ssp.c	2005-08-12 15:41:58.000000000 -0600
@@ -28,6 +28,7 @@
  *  I2S Codec CS4228        = EGPIO7 == 1
  *  Serial Flash AT25F1024  = EGPIO7 == 0
  */
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <asm/irq.h>
 
@@ -692,3 +693,5 @@ static int SSP_Write_I2SCodec
 	 */
 	return 0;
 }
+
+EXPORT_SYMBOL(SSPDriver);
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mach-ep93xx/time.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mach-ep93xx/time.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mach-ep93xx/time.c	2004-07-22 13:48:59.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mach-ep93xx/time.c	2005-08-12 15:41:58.000000000 -0600
@@ -6,19 +6,33 @@
  * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA.  All rights reserved.
  *  Copyright (C) 2002-2003 Cirrus Logic, Inc.
  *
+ * Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ * 	tie wall-clock to TSC (i.e. timer4)
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/arch-ep93xx/ep93xx_tsc.h>
 
 extern int (*set_rtc)(void);
 
+/* EP93XX-based 64 bit TSC (overflow time: ~600000 years) */
+volatile ep93xx_tsc_t ep93xx_tsc;
+
+/* jiffies counter without overflow problems (overflow time: ~6 billion years
+ * @ HZ=100) to keep jiffies in sync with TSC) */
+volatile unsigned long long ep93xx_jiffies_done;
+
+
 static int ep93xx_set_rtc(void)
 {
 	outl( xtime.tv_sec, RTCLR );
@@ -37,7 +51,58 @@ static int ep93xx_rtc_init(void)
 	return 0;
 }
 
-__initcall(ep93xx_rtc_init);
+//__initcall(ep93xx_rtc_init);
+
+
+/* return time since last jiffy tick, in usecs */
+static unsigned long
+ep93xx_gettimeoffset(void)
+{
+    /* Reading 64-bit value ep93xx_jiffies_done is safe although it is modified
+     * in timer interrupt handler (because this function is called with irqs disabled).
+     * This is even true for RTAI (value is only modified in Linux context). */
+    unsigned long long tsc_offset = ep93xx_rdtsc() - (ep93xx_jiffies_done * FREQ_EP93XX_TSC) / HZ;
+    return (tsc_offset * 1000000LLU) / (unsigned long long)FREQ_EP93XX_TSC;
+}
+
+/* set up EP93xx timers */
+void __init
+ep93xx_setup_timer(void)
+{
+    extern unsigned long (*gettimeoffset)(void);
+    gettimeoffset = ep93xx_gettimeoffset;
 
+    /*
+     * Timer 1 is used to generate the periodic jiffies timer interrupt.
+     * It has a clock frequency of ca. 508.47 kHz.
+     *
+     * Timer 4 is the upwards counting time-stamp counter (TSC). It has a exact
+     * clock frequency of 983.04 kHz and is used as an absolute reference
+     * clock, i.e. jiffies are synced to it (makes life a lot easier with
+     * RTAI) and the wall-clock time-offset is also calculated from it (so RTAI
+     * can change timer 1's load-value without effecting the wall-clock).
+     */
+
+    /* set up 64 bit tsc and jiffies handling */
+    ep93xx_tsc.ll = 0;
+    ep93xx_jiffies_done = 0;
+
+    /* disable timers */
+    outl(0, TIMER1CONTROL);
+    outl(0, TIMER4VALUEHIGH);
+
+    /* set timer 1 reload value for periodic mode (defined by value of
+     * include/asm-arm/arch-ep93xx/timex.h:CLOCK_TICK_RATE) */
+    outl(LATCH - 1, TIMER1LOAD);
+
+    /* start timers */
+    outl(0x100, TIMER4VALUEHIGH);	/* 983.04 kHz clock */
+    outl(0xc8, TIMER1CONTROL);		/* periodic mode, 508 kHz clock */
 
+    xtime.tv_sec = inl(RTCDR);
+}
 
+#ifdef CONFIG_ADEOS_CORE
+EXPORT_SYMBOL(ep93xx_tsc);
+EXPORT_SYMBOL(ep93xx_jiffies_done);
+#endif /* CONFIG_ADEOS_CORE */
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/Makefile linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/Makefile
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/Makefile	2004-08-23 09:50:06.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/Makefile	2005-08-12 15:41:58.000000000 -0600
@@ -13,7 +13,7 @@ GZFLAGS		:=-9
 CFLAGS		+=-Uarm -fno-common -pipe
 
 ifeq ($(CONFIG_FRAME_POINTER),y)
-CFLAGS		:=$(CFLAGS:-fomit-frame-pointer=-mapcs -mno-sched-prolog)
+CFLAGS		+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
 endif
 
 CFLAGS		:=$(CFLAGS:-O2=-Os)
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mm/ioremap.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mm/ioremap.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mm/ioremap.c	2004-08-03 19:25:39.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mm/ioremap.c	2005-08-12 15:41:58.000000000 -0600
@@ -107,6 +107,9 @@ remap_area_pages(unsigned long address, 
 		if (remap_area_pmd(pmd, address, end - address,
 					 pfn + (address >> PAGE_SHIFT), flags))
 			break;
+#ifdef CONFIG_ADEOS_CORE
+		set_pgdir(address, *dir);
+#endif
 		error = 0;
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mm/proc-arm920.S linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mm/proc-arm920.S
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/arch/arm/mm/proc-arm920.S	2004-08-03 19:25:39.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/arch/arm/mm/proc-arm920.S	2005-08-12 15:41:58.000000000 -0600
@@ -465,8 +465,8 @@ ENTRY(cpu_arm920_set_pgd)
 	bcs	2b				@ entries 63 to 0
 	subs	r1, r1, #1 << 5
 	bcs	1b				@ segments 7 to 0
-#endif
 	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+#endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
@@ -576,6 +576,13 @@ __arm920_setup:
 #ifndef CONFIG_CPU_ICACHE_DISABLE
 	orr	r0, r0, #0x1000			@ ...1 .... .... ....
 #endif
+#if 0 /* don't use it, no improvment in avg/worst case latency */
+#ifdef CONFIG_ADEOS_CORE
+	@ enable round-robin cache replacement
+	@ (because worst case it is more predictable)
+	orr	r0, r0, #0x4000			@ .1.. .... .... ....
+#endif /* CONFIG_ADEOS_CORE */
+#endif
 	mov	pc, lr
 
 	.text
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/Documentation/adeos.txt linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/Documentation/adeos.txt
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/Documentation/adeos.txt	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/Documentation/adeos.txt	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,172 @@
+
+The Adeos nanokernel is based on research and publications made in the
+early '90s on the subject of nanokernels. Our basic method was to
+reverse the approach described in most of the papers on the subject.
+Instead of first building the nanokernel and then building the client
+OSes, we started from a live and known-to-be-functional OS, Linux, and
+inserted a nanokernel beneath it. Starting from Adeos, other client
+OSes can now be put side-by-side with the Linux kernel.
+
+To this end, Adeos enables multiple domains to exist simultaneously on
+the same hardware. None of these domains see each other, but all of
+them see Adeos. A domain is most probably a complete OS, but there is
+no assumption being made regarding the sophistication of what's in
+a domain.
+
+To share the hardware among the different OSes, Adeos implements an
+interrupt pipeline (ipipe). Every OS domain has an entry in the ipipe.
+Each interrupt that comes in the ipipe is passed on to every domain
+in the ipipe. Instead of disabling/enabling interrupts, each domain
+in the pipeline only needs to stall/unstall his pipeline stage. If
+an ipipe stage is stalled, then the interrupts do not progress in the
+ipipe until that stage has been unstalled. Each stage of the ipipe
+can, of course, decide to do a number of things with an interrupt.
+Among other things, it can decide that it's the last recipient of the
+interrupt. In that case, the ipipe does not propagate the interrupt
+to the rest of the domains in the ipipe.
+
+No hosted domain is allowed to use the real hardware cli/sti. But this
+is OK, since the stall/unstall calls achieve the same functionality.
+
+Our approach is based on the following papers (links to these
+papers are provided at the bottom of this message):
+[1] D. Probert, J. Bruno, and M. Karzaorman. "Space: a new approach to
+operating system abstraction." In: International Workshop on Object
+Orientation in Operating Systems, pages 133-137, October 1991.
+[2] D. Probert, J. Bruno. "Building fundamentally extensible application-
+specific operating systems in Space", March 1995.
+[3] D. Cheriton, K. Duda. "A caching model of operating system kernel
+functionality". In: Proc. Symp. on Operating Systems Design and
+Implementation, pages 179-194, Monterey CA (USA), 1994.
+[4] D. Engler, M. Kaashoek, and J. O'Toole Jr. "Exokernel: an operating
+system architecture for application-specific resource management",
+December 1995.
+
+If you don't want to go fetch the complete papers, here's a summary.
+The first 2 discuss the Space nanokernel, the 3rd discussed the cache
+nanokernel, and the last discusses exokernel.
+
+The complete Adeos approach has been thoroughly documented in a whitepaper
+published more than a year ago entitled "Adaptive Domain Environment
+for Operating Systems" and available here: http://www.opersys.com/adeos
+The current implementation is slightly different. Mainly, we do not
+implement the functionality to move Linux out of ring 0. Although of
+interest, this approach is not very portable.
+
+Instead, our patch taps right into Linux's main source of control
+over the hardware, the interrupt dispatching code, and inserts an
+interrupt pipeline which can then serve all the nanokernel's clients,
+including Linux.
+
+This is not a novelty in itself. Other OSes have been modified in such
+a way for a wide range of purposes. One of the most interesting
+examples is described by Stodolsky, Chen, and Bershad in a paper
+entitled "Fast Interrupt Priority Management in Operating System
+Kernels" published in 1993 as part of the Usenix Microkernels and
+Other Kernel Architectures Symposium. In that case, cli/sti were
+replaced by virtual cli/sti which did not modify the real interrupt
+mask in any way. Instead, interrupts were defered and delivered to
+the OS upon a call to the virtualized sti.
+
+Mainly, this resulted in increased performance for the OS. Although
+we haven't done any measurements on Linux's interrupt handling
+performance with Adeos, our nanokernel includes by definition the
+code implementing the technique described in the abovementioned
+Stodolsky paper, which we use to redirect the hardware interrupt flow
+to the pipeline.
+
+i386 and armnommu are currently supported. Most of the
+architecture-dependent code is easily portable to other architectures.
+
+Aside of adding the Adeos module (driver/adeos), we also modified some
+files to tap into Linux interrupt and system event dispatching (all
+the modifications are encapsulated in #ifdef CONFIG_ADEOS_*/#endif).
+
+We modified the idle task so it gives control back to Adeos in order for
+the ipipe to continue propagation.
+
+We modified init/main.c to initialize Adeos very early in the startup.
+
+Of course, we also added the appropriate makefile modifications and
+config options so that you can choose to enable/disable Adeos as
+part of the kernel build configuration.
+
+Adeos' public API is fully documented here:
+http://home.gna.org/adeos/doc/api/index.html.
+
+In Linux's case, adeos_register_domain() is called very early during
+system startup.
+
+To add your domain to the ipipe, you need to:
+1) Register your domain with Adeos using adeos_register_domain()
+2) Call adeos_virtualize_irq() for all the IRQs you wish to be
+notified about in the ipipe.
+
+That's it. Provided you gave Adeos appropriate handlers in step
+#2, your interrupts will be delivered via the ipipe.
+
+During runtime, you may change your position in the ipipe using
+adeos_renice_domain(). You may also stall/unstall the pipeline
+and change the ipipe's handling of the interrupts according to your
+needs.
+
+Over x86, Adeos supports SMP, and local/IO-APIC on UP.
+
+Here are some of the possible uses for Adeos (this list is far
+from complete):
+1) Much like User-Mode Linux, it should now be possible to have 2
+Linux kernels living side-by-side on the same hardware. In contrast
+to UML, this would not be 2 kernels one ontop of the other, but
+really side-by-side. Since Linux can be told at boot time to use
+only one portion of the available RAM, on a 128MB machine this
+would mean that the first could be made to use the 0-64MB space and
+the second would use the 64-128MB space. We realize that many
+modifications are required. Among other things, one of the 2 kernels
+will not need to conduct hardware initialization. Nevertheless, this
+possibility should be studied closer.
+
+2) It follows from #1 that adding other kernels beside Linux should
+be feasible. BSD is a prime candidate, but it would also be nice to
+see what virtualizers such as VMWare and Plex86 could do with Adeos.
+Proprietary operating systems could potentially also be accomodated.
+
+3) All the previous work that has been done on nanokernels should now
+be easily ported to Linux. Mainly, we would be very interested to
+hear about extensions to Adeos. Primarily, we have no mechanisms
+currently enabling multiple domains to share information. The papers
+mentioned earlier provide such mechanisms, but we'd like to see
+actual practical examples.
+
+4) Kernel debuggers' main problem (tapping into the kernel's
+interrupts) is solved and it should then be possible to provide
+patchless kernel debuggers. They would then become loadable kernel
+modules.
+
+5) Drivers who require absolute priority and dislike other kernel
+portions who use cli/sti can now create a domain of their own
+and place themselves before Linux in the ipipe. This provides a
+mechanism for the implementation of systems that can provide guaranteed
+realtime response.
+
+Philippe Gerum <rpm@xenomai.org>
+Karim Yaghmour <karim@opersys.com>
+
+----------------------------------------------------------------------
+Links to papers:
+1-
+http://citeseer.nj.nec.com/probert91space.html
+ftp://ftp.cs.ucsb.edu/pub/papers/space/iwooos91.ps.gz (not working)
+http://www4.informatik.uni-erlangen.de/~tsthiel/Papers/Space-iwooos91.ps.gz
+
+2-
+http://www.cs.ucsb.edu/research/trcs/abstracts/1995-06.shtml
+http://www4.informatik.uni-erlangen.de/~tsthiel/Papers/Space-trcs95-06.ps.gz
+
+3-
+http://citeseer.nj.nec.com/kenneth94caching.html
+http://guir.cs.berkeley.edu/projects/osprelims/papers/cachmodel-OSkernel.ps.gz
+
+4-
+http://citeseer.nj.nec.com/engler95exokernel.html
+ftp://ftp.cag.lcs.mit.edu/multiscale/exokernel.ps.Z
+----------------------------------------------------------------------
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/drivers/char/tty_io.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/drivers/char/tty_io.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/drivers/char/tty_io.c	2004-08-03 19:28:46.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/drivers/char/tty_io.c	2005-08-12 15:41:58.000000000 -0600
@@ -1948,12 +1948,12 @@ static void flush_to_ldisc(void *private
 		queue_task(&tty->flip.tqueue, &tq_timer);
 		return;
 	}
+	save_flags(flags); cli();
 	if (tty->flip.buf_num) {
 		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
 		fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
 		tty->flip.buf_num = 0;
 
-		save_flags(flags); cli();
 		tty->flip.char_buf_ptr = tty->flip.char_buf;
 		tty->flip.flag_buf_ptr = tty->flip.flag_buf;
 	} else {
@@ -1961,7 +1961,6 @@ static void flush_to_ldisc(void *private
 		fp = tty->flip.flag_buf;
 		tty->flip.buf_num = 1;
 
-		save_flags(flags); cli();
 		tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
 		tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
 	}
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/drivers/serial/ep93xx_amba.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/drivers/serial/ep93xx_amba.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/drivers/serial/ep93xx_amba.c	2004-08-24 13:26:50.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/drivers/serial/ep93xx_amba.c	2005-08-12 15:41:58.000000000 -0600
@@ -348,11 +348,30 @@ csambauart_rx_chars(struct uart_port *po
 	status = UART_GET_FR(port);
 	while (UART_RX_DATA(status) && max_count--) {
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+#if 1
+			/* no room in flip buffer (TTY_DONT_FLIP is set),
+			 * discard rx FIFO contents to clear IRQ *FIXME*
+			 * Hardware with auto flow control would benefit from
+			 * leaving the data in the FIFO and disabling the rx IRQ
+			 * until space becomes available. */
+			do {
+				UART_GET_CHAR(port);
+				port->icount.overrun++;
+				status = UART_GET_FR(port);
+			} while (UART_RX_DATA(status) && (max_count-- > 0));
+			return;
+#else
+			/* calling this from irq is not allowed (although a lot
+			 * of drivers do it, but with Adeos it really shows!)
+			 * -<mike@firmix.at> */
 			tty->flip.tqueue.routine((void *)tty);
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
+				/* having this here is dangerous (system-lock up
+				 * due to message flood) -<mike@firmix.at> */
+				/* printk(KERN_WARNING "TTY_DONT_FLIP set\n"); */
 				return;
 			}
+#endif
 		}
 
 		ch = UART_GET_CHAR(port);
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/adeos.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/adeos.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/adeos.h	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/adeos.h	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,321 @@
+/*
+ *   include/asm-arm/adeos.h
+ *
+ *   Copyright (C) 2002,2003,2004 Philippe Gerum.
+ *
+ *   Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ *	support for EP9301, backport of unthreaded support from Adeos/x86 for 2.6
+ *
+ *   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 __ARM_ADEOS_H
+#define __ARM_ADEOS_H
+
+struct task_struct;
+
+#include <asm/irq.h>
+#include <asm/siginfo.h>
+#include <asm/ptrace.h>
+#include <asm/bitops.h>
+#include <linux/list.h>
+#include <linux/threads.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/irqs.h>
+
+#ifdef CONFIG_ARCH_EP9301
+#define ADEOS_ARCH_STRING	"r17c3/arm-ep9301"
+#define ADEOS_MAJOR_NUMBER	17
+#define ADEOS_MINOR_NUMBER	3
+#define ADEOS_TIMER_IRQ		IRQ_TIMER1
+#else
+#error "Adeos: unsupported ARM architecture, sorry..."
+#endif /* CONFIG_ARCH_EP9301 */
+
+typedef unsigned long cpumask_t;
+#define CPU_MASK_NONE		((cpumask_t)0)
+
+#define ADEOS_NR_CPUS          1
+#define adeos_processor_id()   0
+/* Array references using this index should be optimized out. */
+#define adeos_declare_cpuid    const int cpuid = 0
+#define adeos_load_cpuid()      do { /* nop */ } while(0)
+#define adeos_lock_cpu(flags)   adeos_hw_local_irq_save(flags)
+#define adeos_unlock_cpu(flags) adeos_hw_local_irq_restore(flags)
+#define adeos_get_cpu(flags)    do { flags = flags; } while(0)
+#define adeos_put_cpu(flags)    do { /* nop */ } while(0)
+#define adp_current             (adp_cpu_current[0])
+
+/* ARM fault traps */
+#define ADEOS_NR_FAULTS         32
+/* Pseudo-vectors used for kernel events */
+#define ADEOS_FIRST_KEVENT      ADEOS_NR_FAULTS
+#define ADEOS_SYSCALL_PROLOGUE  (ADEOS_FIRST_KEVENT)
+#define ADEOS_SYSCALL_EPILOGUE  (ADEOS_FIRST_KEVENT + 1)
+#define ADEOS_SCHEDULE_HEAD     (ADEOS_FIRST_KEVENT + 2)
+#define ADEOS_SCHEDULE_TAIL     (ADEOS_FIRST_KEVENT + 3)
+#ifdef CONFIG_ADEOS_EVENT_ENTER_PROCESS
+#define ADEOS_ENTER_PROCESS     (ADEOS_FIRST_KEVENT + 4)
+#endif /* CONFIG_ADEOS_EVENT_ENTER_PROCESS */
+#define ADEOS_EXIT_PROCESS      (ADEOS_FIRST_KEVENT + 5)
+#define ADEOS_SIGNAL_PROCESS    (ADEOS_FIRST_KEVENT + 6)
+#define ADEOS_KICK_PROCESS      (ADEOS_FIRST_KEVENT + 7)
+#define ADEOS_LAST_KEVENT       (ADEOS_KICK_PROCESS)
+#ifdef CONFIG_ADEOS_EVENT_RENICE_PROCESS
+#define ADEOS_RENICE_PROCESS    (ADEOS_FIRST_KEVENT + 8)
+#undef ADEOS_LAST_KEVENT
+#define ADEOS_LAST_KEVENT       (ADEOS_RENICE_PROCESS)
+#endif /* CONFIG_ADEOS_EVENT_RENICE_PROCESS */
+#ifdef CONFIG_ADEOS_EVENT_USER_PROCESS
+#define ADEOS_USER_EVENT        (ADEOS_FIRST_KEVENT + 9)
+#undef ADEOS_LAST_KEVENT
+#define ADEOS_LAST_KEVENT       (ADEOS_USER_EVENT)
+#endif /* !CONFIG_ADEOS_EVENT_USER_PROCESS */
+
+#define ADEOS_NR_EVENTS         (ADEOS_LAST_KEVENT + 1)
+
+typedef struct adevinfo {
+
+    unsigned domid;
+    unsigned event;
+    void *evdata;
+
+    volatile int propagate;	/* Private */
+
+} adevinfo_t;
+
+typedef struct adsysinfo {
+
+    int ncpus;			/* Number of CPUs on board */
+
+    unsigned long long cpufreq;	/* CPU frequency (in Hz) */
+
+    /* Arch-dependent block */
+
+    struct {
+	unsigned tmirq;		/* Timer tick IRQ */
+    } archdep;
+
+} adsysinfo_t;
+
+#define IPIPE_NR_XIRQS   NR_IRQS
+/* Number of virtual IRQs */
+#define IPIPE_NR_VIRQS   BITS_PER_LONG
+/* First virtual IRQ # */
+#define IPIPE_VIRQ_BASE  (((IPIPE_NR_XIRQS + BITS_PER_LONG - 1) / BITS_PER_LONG) * BITS_PER_LONG)
+/* Total number of IRQ slots */
+#define IPIPE_NR_IRQS     (IPIPE_VIRQ_BASE + IPIPE_NR_VIRQS)
+/* Number of indirect words needed to map the whole IRQ space. */
+#define IPIPE_IRQ_IWORDS  ((IPIPE_NR_IRQS + BITS_PER_LONG - 1) / BITS_PER_LONG)
+#define IPIPE_IRQ_IMASK   (BITS_PER_LONG - 1)
+#define IPIPE_IRQ_ISHIFT  5	/* 2^5 for 32bits arch. */
+
+#define IPIPE_IRQMASK_ANY   (~0UL)
+#define IPIPE_IRQMASK_VIRT  (IPIPE_IRQMASK_ANY << (IPIPE_VIRQ_BASE / BITS_PER_LONG))
+
+typedef struct adomain {
+
+    /* -- Section: offset-based references may be made on these fields
+       from inline assembly code. Please don't move or reorder. */
+    void (*dswitch)(void)	/* Domain switch hook */
+	__attribute__ ((__aligned__ (32))); /* align every element of array (gcc bug workaround) */
+#ifdef CONFIG_ADEOS_THREADS
+    int *esp[ADEOS_NR_CPUS];	/* Domain stack pointers */
+#endif /* CONFIG_ADEOS_THREADS */
+    /* -- End of section. */
+
+    struct list_head p_link;	/* Link in pipeline */
+
+    struct adcpudata {
+	volatile unsigned long status;
+	volatile unsigned long irq_pending_hi;
+	volatile unsigned long irq_pending_lo[IPIPE_IRQ_IWORDS];
+	volatile unsigned irq_hits[IPIPE_NR_IRQS];
+#ifdef CONFIG_ADEOS_THREADS
+	adevinfo_t event_info;
+#endif /* CONFIG_ADEOS_THREADS */
+    } cpudata[ADEOS_NR_CPUS];
+
+    struct {
+	int (*acknowledge)(unsigned irq);
+	void (*handler)(unsigned irq);
+	unsigned long control;
+    } irqs[IPIPE_NR_IRQS];
+
+    struct {
+	void (*handler)(adevinfo_t *evinfo);
+    } events[ADEOS_NR_EVENTS];
+
+    unsigned long flags;
+
+    struct adomain *m_link;	/* Link in mutex sleep queue */
+
+    unsigned domid;
+
+    const char *name;
+
+    int priority;
+
+    int ptd_keymax;
+    int ptd_keycount;
+    unsigned long ptd_keymap;
+    void (*ptd_setfun)(int, void *);
+    void *(*ptd_getfun)(int);
+
+#ifdef CONFIG_ADEOS_THREADS
+    int *estackbase[ADEOS_NR_CPUS];
+#endif /* CONFIG_ADEOS_THREADS */
+
+} adomain_t __attribute__ ((__aligned__ (32)));
+
+#define adeos_hw_test_iflag(x)        (!((x) & I_BIT)) /* We don't use the FIRQs */
+
+#define adeos_hw_irqs_disabled()	\
+({					\
+	unsigned long flags;		\
+	adeos_hw_local_irq_flags(flags);	\
+	!adeos_hw_test_iflag(flags);	\
+})
+
+/* The following macros must be used hw interrupts off. */
+
+#define __adeos_set_irq_bit(adp,cpuid,irq) \
+do { \
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled()); \
+    if (!test_bit(IPIPE_LOCK_FLAG,&(adp)->irqs[irq].control)) { \
+        __set_bit(irq & IPIPE_IRQ_IMASK,&(adp)->cpudata[cpuid].irq_pending_lo[irq >> IPIPE_IRQ_ISHIFT]); \
+        __set_bit(irq >> IPIPE_IRQ_ISHIFT,&(adp)->cpudata[cpuid].irq_pending_hi); \
+       } \
+} while(0)
+
+#define __adeos_clear_pend(adp,cpuid,irq) \
+do { \
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled()); \
+    __clear_bit(irq & IPIPE_IRQ_IMASK,&(adp)->cpudata[cpuid].irq_pending_lo[irq >> IPIPE_IRQ_ISHIFT]); \
+    if ((adp)->cpudata[cpuid].irq_pending_lo[irq >> IPIPE_IRQ_ISHIFT] == 0) \
+        __clear_bit(irq >> IPIPE_IRQ_ISHIFT,&(adp)->cpudata[cpuid].irq_pending_hi); \
+} while(0)
+
+#define __adeos_lock_irq(adp,cpuid,irq) \
+do { \
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled()); \
+    if (!__test_and_set_bit(IPIPE_LOCK_FLAG,&(adp)->irqs[irq].control)) \
+	__adeos_clear_pend(adp,cpuid,irq); \
+} while(0)
+
+#define __adeos_unlock_irq(adp,irq) \
+do { \
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled()); \
+    int __cpuid, __nr_cpus = smp_num_cpus;			       \
+    if (__test_and_clear_bit(IPIPE_LOCK_FLAG,&(adp)->irqs[irq].control)) \
+	for (__cpuid = 0; __cpuid < __nr_cpus; __cpuid++)      \
+         if ((adp)->cpudata[__cpuid].irq_hits[irq] > 0) { \
+           __set_bit(irq & IPIPE_IRQ_IMASK,&(adp)->cpudata[__cpuid].irq_pending_lo[irq >> IPIPE_IRQ_ISHIFT]); \
+           __set_bit(irq >> IPIPE_IRQ_ISHIFT,&(adp)->cpudata[__cpuid].irq_pending_hi); \
+         } \
+} while(0)
+
+#define __adeos_clear_irq(adp,irq) \
+do { \
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled()); \
+    int __cpuid, __nr_cpus = smp_num_cpus; \
+    __clear_bit(IPIPE_LOCK_FLAG,&(adp)->irqs[irq].control); \
+    for (__cpuid = 0; __cpuid < __nr_cpus; __cpuid++) {	\
+       (adp)->cpudata[__cpuid].irq_hits[irq] = 0; \
+       __adeos_clear_pend(adp,__cpuid,irq); \
+    } \
+} while(0)
+
+#define adeos_virtual_irq_p(irq)		((irq) >= IPIPE_VIRQ_BASE && (irq) < IPIPE_NR_IRQS)
+
+#define adeos_hw_save_flags_and_sti(x)		do { adeos_hw_local_irq_flags(x); adeos_hw_sti(); } while(0)
+
+#define adeos_hw_tsc(t)				0
+#define adeos_cpu_freq()			CLOCK_TICK_RATE
+
+#ifdef CONFIG_PREEMPT
+#define adeos_spin_lock(x)   			_raw_spin_lock(x)
+#define adeos_spin_unlock(x) 			_raw_spin_unlock(x)
+#define adeos_spin_trylock(x)			_raw_spin_trylock(x)
+#else /* !CONFIG_PREEMPT */
+#define adeos_spin_lock(x)   			spin_lock(x)
+#define adeos_spin_unlock(x) 			spin_unlock(x)
+#define adeos_spin_trylock(x)			spin_trylock(x)
+#endif /* CONFIG_PREEMPT */
+
+#define adeos_spin_lock_irqsave(x,flags)	do { adeos_hw_local_irq_save(flags); adeos_spin_lock(x); } while (0)
+#define adeos_spin_unlock_irqrestore(x,flags)	do { adeos_spin_unlock(x); adeos_hw_local_irq_restore(flags); } while (0)
+#define adeos_spin_lock_disable(x)		do { adeos_hw_cli(); adeos_spin_lock(x); } while (0)
+#define adeos_spin_unlock_enable(x)		do { adeos_spin_unlock(x); adeos_hw_sti(); } while (0)
+
+/* Private interface -- Internal use only */
+
+struct adattr;
+
+void __adeos_init(void);
+
+void __adeos_init_domain(adomain_t *adp,
+			 struct adattr *attr);
+
+void __adeos_cleanup_domain(adomain_t *adp);
+
+#define __adeos_check_machine() do { } while(0)
+
+void __adeos_enable_pipeline(void);
+
+void __adeos_disable_pipeline(void);
+
+void __adeos_init_stage(adomain_t *adp);
+
+void FASTCALL(__adeos_sync_stage(unsigned long syncmask));
+
+void __adeos_tune_timer(unsigned long hz);
+
+asmlinkage int __adeos_handle_irq(int irq,
+				   struct pt_regs *regs);
+
+#ifdef CONFIG_ADEOS_THREADS
+
+asmlinkage int __adeos_switch_domain(adomain_t *adp,
+				     adomain_t **currentp);
+
+/* Called with hw interrupts off. */
+extern inline void __adeos_switch_to(adomain_t *out,
+				     adomain_t *in,
+				     int cpuid)
+{
+    extern adomain_t *adp_cpu_current[];
+
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled());
+
+    __adeos_switch_domain(in,&adp_cpu_current[cpuid]);
+
+    if (out->dswitch != NULL)
+	out->dswitch();
+}
+
+#endif /* CONFIG_ADEOS_THREADS */
+
+extern struct pt_regs __adeos_irq_regs;
+
+/* hook for non-Linux syscalls (i.e. RTAI syscall) (see linux/arch/arm/kernel/entry-common.S) */
+extern int (*adeos_syscall_entry)(struct pt_regs *regs);
+
+/* hook for interrupt handling (default value: __adeos_handle_irq, see
+ * linux/arch/arm/kernel/entry-armv.S) */
+extern int (*adeos_irq_entry)(int irq, struct pt_regs *regs);
+
+#endif /* !__ARM_ADEOS_H */
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/ep93xx_tsc.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/ep93xx_tsc.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/ep93xx_tsc.h	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/ep93xx_tsc.h	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,122 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/ep93xx_rdtsc.h
+ *
+ * 64 bit time-stamp counter (TSC) for absolute real-time clock without
+ * overflow-problems (>1/2 million years).
+ *
+ * Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH <mike@firmix.at>
+ *
+ * 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.
+ *
+ * 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 __ASM_ARM_ARCH_EP93XX_H_
+#define __ASM_ARM_ARCH_EP93XX_H_
+
+/* tsc's clock frequency (EP93XX's timer 4) */
+#define FREQ_EP93XX_TSC	(983040)
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* jiffies counter without overflow problems (overflow time: ~6 billion years
+ * @ HZ=100) to keep Linux-jiffies in sync with 64 bit TSC */
+extern volatile unsigned long long ep93xx_jiffies_done;
+
+/*
+ * 64 bit tsc from hardware's 32 bit tsc, hardware has actually 40 bits, but
+ * even this is not enough to avoid an overflow during a reboot-less time (for
+ * a TSC clock frequency of 983040 Hz):
+ *	bits	overflow
+ *	32	1.2 hours
+ *	40	13 days
+ *	64	595034 years
+ */
+typedef union _ep93xx_tsc_t {
+    unsigned long long	ll;
+    struct {
+	unsigned long	low;
+	unsigned long	high;
+    } u;
+} ep93xx_tsc_t;
+extern volatile ep93xx_tsc_t ep93xx_tsc;
+
+/* read EP93XX-based 64 bit TSC irq-safe (overflow time: ~600000 years) */
+extern inline unsigned long long
+ep93xx_rdtsc(void)
+{
+    register ep93xx_tsc_t tsc;
+    register unsigned long low_now;
+    
+    /* get snapshot of global tsc (ldm is irq-safe!) */
+    __asm__(
+	"ldmia %[glbl_tsc], %M[tsc]\n"
+	: /* output */	[tsc] "=r" (tsc.ll)
+	: /* input  */	[glbl_tsc] "r" (&ep93xx_tsc.ll),
+			"m" (ep93xx_tsc)
+    );
+    /* read current low tsc (i.e. low 32 bits of hardware timer) */
+    low_now = inl(TIMER4VALUELOW);
+    /* check for overflow in relation to global ep93xx_tsc and correct high 32
+     * bits if necessary */
+    if (low_now < tsc.u.low)
+	++tsc.u.high;
+    tsc.u.low = low_now;
+    return tsc.ll;
+}
+
+/* irq-safe read & update in-memory tsc (good place to call this is the 100 HZ
+ * interrupt) */
+extern inline unsigned long long
+ep93xx_read_and_update_tsc(void)
+{
+    register ep93xx_tsc_t tsc;
+    register unsigned long low_now;
+    int do_update;
+
+    /* get snapshot of global tsc (ldm is irq safe!) */
+    __asm__(
+	"ldmia %[glbl_tsc], %M[tsc]\n"
+	: /* output */	[tsc] "=r" (tsc.ll)
+	: /* input  */	[glbl_tsc] "r" (&ep93xx_tsc.ll),
+			"m" (ep93xx_tsc)
+    );
+    /* read current low tsc (i.e. low 32 bits of hardware timer) */
+    low_now = inl(TIMER4VALUELOW);
+    /* check for overflow in relation to global ep93xx_tsc and correct high 32
+     * bits if necessary */
+    if (low_now < tsc.u.low)
+	++tsc.u.high;
+    /* update at least 4 times per period (i.e. each 18 minutes) */
+    do_update = (low_now - tsc.u.low >= 0x40000000);
+    tsc.u.low = low_now;
+    if (do_update) {
+	/* update global tsc (stm is irq-safe!) */
+	__asm__(
+	    "stmia %[glbl_tsc], %M[tsc]\n"
+	    : /* output */	"=m" (ep93xx_tsc)
+	    : /* input  */	[tsc] "r" (tsc.ll),
+	    			[glbl_tsc] "r" (&ep93xx_tsc.ll)
+	);
+    }
+
+    return tsc.ll;
+}
+
+#endif /* __KERNEL */
+
+#endif /* __ASM_ARM_ARCH_EP93XX_H_ */
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/irq.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/irq.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/irq.h	2004-07-22 13:50:54.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/irq.h	2005-08-12 15:41:58.000000000 -0600
@@ -17,4 +17,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#ifndef _ASM_ARCH_EP93XX_IRQ_H
+#define _ASM_ARCH_EP93XX_IRQ_H
+
 #define fixup_irq(i)	(i)
+
+#endif /* _ASM_ARCH_EP93XX_IRQ_H */
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/system.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/system.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/system.h	2004-09-10 12:47:33.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/system.h	2005-08-12 15:41:58.000000000 -0600
@@ -21,16 +21,17 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
 
+#include <linux/config.h>
 #include <asm/arch/platform.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 
-static void arch_idle(void)
+static inline void arch_idle(void)
 {
 	cpu_do_idle();
 }
 
-extern __inline__ void arch_reset(char mode)
+extern inline void arch_reset(char mode)
 {
     //
     // Enable the watchdog timer so that it will reset the part.
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/time.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/time.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/time.h	2005-01-18 15:35:57.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/time.h	2005-08-12 15:41:58.000000000 -0600
@@ -5,6 +5,9 @@
  *
  * Copyright (C) 2002-2003 Cirrus Logic, Inc.
  *
+ * Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ * 	more Adeos/RTAI friendly
+ *
  * 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
@@ -22,32 +25,48 @@
 #include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/ep93xx_tsc.h>
 
 /* First timer channel used for timer interrupt */
 
 /*
  * IRQ handler for the timer
+ *
+ * interrupts are disabled because timer_irq has SA_INTERRUPT set (see
+ * arch/arm/time.c) (of course not if Adeos is active)
  */
-static void ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void
+ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-
-    // ...clear the interrupt
-    outl( 1, TIMER1CLEAR );
-
+    /* Note, that the irq needs to be acked on a timer-hardware specific
+     * level (i.e. write 1 to TIMER1CLEAR). But because
+     * irq_desc[IRQ_TIMER1].mask_ack does that (non-standard modification), it
+     * does not have to be done here. This makes this function safe to use when
+     * RTAI/Adeos is active and handles the interrupts */
+    do_leds();
+    {
+	/* full jiffies according to TSC (i.e. absolute clock) */
+	unsigned long long realtime_jiffies =
+	    (ep93xx_read_and_update_tsc() * HZ) / FREQ_EP93XX_TSC;
+	/* call do_timer() as often as it is necessary to keep jiffies in sync
+	 * with TSC, take care that jiffies are never ahead the TSC
+	 * (gettimeoffset is unsigned) */
+	while (ep93xx_jiffies_done < realtime_jiffies) {
     do_timer(regs);
+	    ++ep93xx_jiffies_done;
+	}
+    }
     do_profile(regs);
 }
 
 /*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up timer interrupt
  */
-extern __inline__ void setup_timer(void)
+extern inline void
+setup_timer(void)
 {
+    ep93xx_setup_timer();
     timer_irq.handler = ep93xx_timer_interrupt;
-
-    /* 
-     * Make irqs happen for the system timer
-     */
     setup_arm_irq(IRQ_TIMER1, &timer_irq);
 
     /*
@@ -69,3 +88,14 @@ extern __inline__ void setup_timer(void)
     outl( 0xC8, TIMER1CONTROL );
 }
 
+
+#ifdef CONFIG_ADEOS_CORE
+static inline void
+__adeos_set_timer(unsigned long hz)
+{
+    unsigned long delay = (CLOCK_TICK_RATE + hz/2) / hz - 1;
+    outl(0, TIMER1CONTROL);         	/* stop timer */
+    outl(delay, TIMER1LOAD);		/* set load value */
+    outl(0xc8, TIMER1CONTROL);		/* set 508 kHz clock, periodic mode & enable timer */
+}
+#endif /* CONFIG_ADEOS_CORE */
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/timex.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/timex.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/arch-ep93xx/timex.h	2004-07-22 13:50:54.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/arch-ep93xx/timex.h	2005-08-12 15:41:58.000000000 -0600
@@ -5,6 +5,9 @@
  *
  *  Copyright (C) 1999 ARM Limited
  *
+ * Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ * 	corrected CLOCK_TICK_RATE, added defines for exact frequency
+ *  
  * 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
@@ -23,4 +26,21 @@
 /*
  * ??
  */
-#define CLOCK_TICK_RATE		(50000000 / 16)
+#ifndef _ASM_ARM_ARCH_EP93XX_H
+#define _ASM_ARM_ARCH_EP93XX_H
+
+/*
+ * The original value of 508000 is completly wrong. Table 4-2 on page 74 of the
+ * EP9301 User's Manual gives the frequency as 508.4689 kHz and specifies that
+ * all timer clocks are derived from the external 14.7456 MHz oscillator by
+ * division. Hence, the correct frequency is most likely
+ * 14745.6 / 29 = 508.468965... kHz (rounded integer: 508469 Hz).
+ * -- Michael Neuhauser <mike@firimix.at>
+ */
+#define CLOCK_TICK_RATE		(508469)
+
+/* exact value (non-standard macros) */
+#define CLOCK_TICK_RATE_NUM	(14745600)
+#define CLOCK_TICK_RATE_DEN	(29)
+
+#endif /* _ASM_ARM_ARCH_EP93XX_H */
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/atomic.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/atomic.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/atomic.h	2004-07-22 13:50:53.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/atomic.h	2005-08-12 15:41:58.000000000 -0600
@@ -26,9 +26,19 @@ typedef struct { volatile int counter; }
 
 #define ATOMIC_INIT(i)	{ (i) }
 
-#ifdef __KERNEL__
+/* RTAI needs some atomic functions in user-space (for liblxrt) */
+#if defined(__KERNEL__) || defined(CONFIG_ADEOS_CORE)
+
 #include <asm/proc/system.h>
 
+#ifdef CONFIG_ADEOS_CORE
+#define _atomic_save_flags_cli(x)	adeos_hw_local_irq_save(flags)
+#define _atomic_restore_flags(x)	adeos_hw_local_irq_restore(flags)
+#else
+#define _atomic_save_flags_cli(x)	local_irq_save(x)
+#define _atomic_restore_flags(x)	local_irq_restore(x)
+#endif
+
 #define atomic_read(v)	((v)->counter)
 #define atomic_set(v,i)	(((v)->counter) = (i))
 
@@ -36,36 +46,36 @@ static inline void atomic_add(int i, vol
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	_atomic_save_flags_cli(flags);
 	v->counter += i;
-	local_irq_restore(flags);
+	_atomic_restore_flags(flags);
 }
 
 static inline void atomic_sub(int i, volatile atomic_t *v)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	_atomic_save_flags_cli(flags);
 	v->counter -= i;
-	local_irq_restore(flags);
+	_atomic_restore_flags(flags);
 }
 
 static inline void atomic_inc(volatile atomic_t *v)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	_atomic_save_flags_cli(flags);
 	v->counter += 1;
-	local_irq_restore(flags);
+	_atomic_restore_flags(flags);
 }
 
 static inline void atomic_dec(volatile atomic_t *v)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	_atomic_save_flags_cli(flags);
 	v->counter -= 1;
-	local_irq_restore(flags);
+	_atomic_restore_flags(flags);
 }
 
 static inline int atomic_dec_and_test(volatile atomic_t *v)
@@ -73,10 +83,10 @@ static inline int atomic_dec_and_test(vo
 	unsigned long flags;
 	int val;
 
-	local_irq_save(flags);
+	_atomic_save_flags_cli(flags);
 	val = v->counter;
 	v->counter = val -= 1;
-	local_irq_restore(flags);
+	_atomic_restore_flags(flags);
 
 	return val == 0;
 }
@@ -86,10 +96,10 @@ static inline int atomic_add_negative(in
 	unsigned long flags;
 	int val;
 
-	local_irq_save(flags);
+	_atomic_save_flags_cli(flags);
 	val = v->counter;
 	v->counter = val += i;
-	local_irq_restore(flags);
+	_atomic_restore_flags(flags);
 
 	return val < 0;
 }
@@ -98,9 +108,9 @@ static inline void atomic_clear_mask(uns
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	_atomic_save_flags_cli(flags);
 	*addr &= ~mask;
-	local_irq_restore(flags);
+	_atomic_restore_flags(flags);
 }
 
 /* Atomic operations are already serializing on ARM */
@@ -109,5 +119,5 @@ static inline void atomic_clear_mask(uns
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#endif
+#endif /* defined(__KERNEL__) || defined(CONFIG_ADEOS_CORE) */
 #endif
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/bitops.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/bitops.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/bitops.h	2004-07-22 13:50:53.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/bitops.h	2005-08-12 15:41:58.000000000 -0600
@@ -86,7 +86,7 @@ extern int find_next_zero_bit(void * add
 /*
  * This routine doesn't need to be atomic.
  */
-static inline int test_bit(int nr, const void * addr)
+static inline int test_bit(int nr, const volatile void * addr)
 {
     return (((unsigned char *) addr)[nr >> 3] >> (nr & 7)) & 1;
 }	
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/hw_irq.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/hw_irq.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/hw_irq.h	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/hw_irq.h	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,7 @@
+/*
+ * hw_irq.h
+ *
+ * just a dummy for include/linux/irq.c
+ */
+
+#include <asm/irq.h>
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/irq.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/irq.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/irq.h	2004-07-22 13:50:53.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/irq.h	2005-08-12 15:41:58.000000000 -0600
@@ -1,6 +1,7 @@
 #ifndef __ASM_ARM_IRQ_H
 #define __ASM_ARM_IRQ_H
 
+#include <linux/linkage.h>
 #include <asm/arch/irqs.h>
 
 #ifndef irq_cannonicalize
@@ -23,6 +24,8 @@
 
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
+extern asmlinkage void asm_do_IRQ(int irq, struct pt_regs *regs);
+
 
 #endif
 
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/mach/irq.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/mach/irq.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/mach/irq.h	2004-07-22 13:50:53.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/mach/irq.h	2005-08-12 15:41:58.000000000 -0600
@@ -10,6 +10,8 @@
 #ifndef __ASM_ARM_MACH_IRQ_H
 #define __ASM_ARM_MACH_IRQ_H
 
+#include <linux/config.h>
+
 struct irqdesc {
 	unsigned int	 triggered: 1;		/* IRQ has occurred	      */
 	unsigned int	 running  : 1;		/* IRQ is running             */
@@ -28,6 +30,7 @@ struct irqdesc {
 	void (*unmask)(unsigned int irq);	/* Unmask IRQ		      */
 	struct irqaction *action;
 
+#ifndef CONFIG_ADEOS_CORE			/* no IRQ lock detection to increase performance */
 	/*
 	 * IRQ lock detection
 	 */
@@ -36,6 +39,7 @@ struct irqdesc {
 	unsigned int	 lck_jif;
 	int		 lck_warned;
 	struct timer_list	lck_timer;
+#endif /* !CONFIG_ADEOS_CORE */
 };
 
 extern struct irqdesc irq_desc[];
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/pgalloc.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/pgalloc.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/pgalloc.h	2004-07-22 13:50:53.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/pgalloc.h	2005-08-12 15:41:58.000000000 -0600
@@ -138,4 +138,33 @@ static inline pgd_t *pgd_alloc(struct mm
 
 extern int do_check_pgt_cache(int, int);
 
+#ifdef CONFIG_ADEOS_CORE
+extern inline void set_pgdir(unsigned long address, pgd_t entry)
+{
+	struct task_struct * p;
+	pgd_t *pgd;
+#ifdef CONFIG_SMP
+	int i;
+#endif
+
+	read_lock(&tasklist_lock);
+	for_each_task(p) {
+		if (!p->mm)
+			continue;
+		*pgd_offset(p->mm,address) = entry;
+	}
+	read_unlock(&tasklist_lock);
+#ifndef CONFIG_SMP
+	for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)__pgd_next(pgd))
+		pgd[pgd_index(address)] = entry;
+#else
+	/* To pgd_alloc/pgd_free, one holds master kernel lock and so does our callee, so we can
+	   modify pgd caches of other CPUs as well. -jj */
+	for (i = 0; i < NR_CPUS; i++)
+		for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)__pgd_next(pgd))
+			pgd[pgd_index(address)] = entry;
+#endif
+}
+#endif /* CONFIG_ADEOS_CORE */
+
 #endif
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/proc-armv/processor.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/proc-armv/processor.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/proc-armv/processor.h	2004-08-03 19:17:09.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/proc-armv/processor.h	2005-08-12 15:41:58.000000000 -0600
@@ -18,6 +18,7 @@
 #ifndef __ASM_PROC_PROCESSOR_H
 #define __ASM_PROC_PROCESSOR_H
 
+#include <linux/config.h>
 #include <asm/proc/domain.h>
 
 #define KERNEL_STACK_SIZE	PAGE_SIZE
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/proc-armv/system.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/proc-armv/system.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/proc-armv/system.h	2004-07-22 13:50:54.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/proc-armv/system.h	2005-08-12 15:41:58.000000000 -0600
@@ -42,6 +42,114 @@ extern unsigned long cr_alignment;	/* de
 #define vectors_base()	(0)
 #endif
 
+/* ========================================================================= */
+#if defined(CONFIG_ADEOS_CORE)
+
+/* --------------------------------- Adeos --------------------------------- */
+
+extern inline void __adeos_stall_root(void);
+
+extern inline void __adeos_unstall_root(void);
+
+extern inline unsigned long __adeos_test_root(void);
+
+extern inline unsigned long __adeos_test_and_stall_root(void);
+
+void __adeos_restore_root(unsigned long flags);
+
+#define __stf()                 __adeos_unstall_root()
+#define __clf()                 __adeos_stall_root()
+
+#define local_save_flags(x)	((x) = __adeos_test_root())
+#define local_irq_save(x)	((x) = __adeos_test_and_stall_root())
+#define local_irq_restore(x)	__adeos_restore_root(x)
+#define local_irq_set(x)	do { ((x) = __adeos_test_root()); __adeos_unstall_root(); } while (0)
+#define local_irq_disable()	__adeos_stall_root()
+#define local_irq_enable()	__adeos_unstall_root()
+
+#define irqs_disabled()         __adeos_test_root()
+
+#define adeos_hw_cli() \
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ cli\n"		\
+"	orr	%0, %0, #128\n"					\
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory");						\
+	})
+
+#define adeos_hw_sti()	\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ sti\n"		\
+"	bic	%0, %0, #128\n"					\
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory");						\
+	})
+
+
+#define adeos_hw_stf()	\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ stf\n"		\
+"	bic	%0, %0, #64\n"					\
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory");						\
+	})
+
+#define adeos_hw_clf()	\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ clf\n"		\
+"	orr	%0, %0, #64\n"					\
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory");						\
+	})
+
+
+#define adeos_hw_local_irq_save(x) \
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ save_flags_cli\n"	\
+"	orr	%1, %0, #128\n"					\
+"	msr	cpsr_c, %1"					\
+	: "=r" (x), "=r" (temp)					\
+	:							\
+	: "memory");						\
+	})
+
+#define adeos_hw_local_irq_restore(x) \
+	__asm__ __volatile__(					\
+	"msr	cpsr_c, %0		@ restore_flags\n"	\
+	:							\
+	: "r" (x)						\
+	: "memory")
+
+#define adeos_hw_local_irq_flags(x) \
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ save_flags\n"		\
+	  : "=r" (x)						\
+	  :							\
+	  : "memory")
+
+#else /* !CONFIG_ADEOS_CORE */
+
+/* ------------------------------- Linux ------------------------------ */
+
+
 /*
  * Save the current interrupt enable state & disable IRQs
  */
@@ -151,6 +259,9 @@ extern unsigned long cr_alignment;	/* de
 	: "r" (x)						\
 	: "memory")
 
+#endif /* CONFIG_ADEOS_CORE */
+/* ========================================================================= */
+
 #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
 /*
  * On the StrongARM, "swp" is terminally broken since it bypasses the
@@ -165,8 +276,22 @@ extern unsigned long cr_alignment;	/* de
  * dependent on the processor type.
  */
 #define swp_is_buggy
+#else
+#undef swp_is_buggy
 #endif
 
+#ifdef CONFIG_ADEOS_CORE
+
+#define _xchg_save_flags_cli(flags)	adeos_hw_local_irq_save(flags)
+#define _xchg_restore_flags(flags)	adeos_hw_local_irq_restore(flags)
+
+#else /* !CONFIG_ADEOS_CORE */
+
+#define _xchg_save_flags_cli(flags)	local_irq_save(flags)
+#define _xchg_restore_flags(flags)	local_irq_restore(flags)
+
+#endif /* CONFIG_ADEOS_CORE */
+
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 {
 	extern void __bad_xchg(volatile void *, int);
@@ -178,17 +303,17 @@ static inline unsigned long __xchg(unsig
 	switch (size) {
 #ifdef swp_is_buggy
 		case 1:
-			local_irq_save(flags);
+			_xchg_save_flags_cli(flags);
 			ret = *(volatile unsigned char *)ptr;
 			*(volatile unsigned char *)ptr = x;
-			local_irq_restore(flags);
+			_xchg_restore_flags(flags);
 			break;
 
 		case 4:
-			local_irq_save(flags);
+			_xchg_save_flags_cli(flags);
 			ret = *(volatile unsigned long *)ptr;
 			*(volatile unsigned long *)ptr = x;
-			local_irq_restore(flags);
+			_xchg_restore_flags(flags);
 			break;
 #else
 		case 1:	__asm__ __volatile__ ("swpb %0, %1, [%2]"
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/system.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/system.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/asm-arm/system.h	2004-07-22 13:50:53.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/asm-arm/system.h	2005-08-12 15:41:58.000000000 -0600
@@ -54,8 +54,36 @@ extern asmlinkage void __backtrace(void)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
+#ifdef CONFIG_ADEOS_CORE
+
+/* the cli is needed to because of the mm-switch (cache, TLB) and __switch_to() */
+#define prepare_to_switch(prev, next) \
+	do { \
+    		struct { struct task_struct *prev, *next; } arg = { (prev), (next) }; \
+    		__adeos_schedule_head(&arg); \
+	} while(0)
+
+#else /* !CONFIG_ADEOS_CORE */
+
 #define prepare_to_switch()    do { } while(0)
 
+#endif /* CONFIG_ADEOS_CORE */
+
+#ifdef CONFIG_EP93XX_CRUNCH
+#include <asm/arch/crunch.h>
+#define crunch_switch(prev, next)			\
+	do {						\
+		if (prev->flags & PF_USEDFPU) {		\
+			save_crunch(prev);		\
+			crunch_disable();		\
+		}					\
+		prev->flags &= ~PF_USEDFPU;		\
+		mb();					\
+	} while (0)
+#else
+#define crunch_switch(prev, next)	do { } while (0);
+#endif
+
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
  * `prev' will never be the same as `next'.
@@ -63,12 +91,32 @@ extern asmlinkage void __backtrace(void)
  */
 extern struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next);
 
+#ifdef CONFIG_ADEOS_CORE
+
+/* make a copy of the original definition */
+#define switch_to_orig(prev, next, last)		\
+	do {			 			\
+		crunch_switch(prev, next);		\
+		last = __switch_to(prev, next);		\
+		mb();					\
+	} while (0)
+
+/* add sti to original code to revert cli from from prepare_to_switch() */
+#define switch_to(prev, next, last)			\
+	do {			 			\
+		switch_to_orig(prev, next, last);	\
+	} while (0)
+
+#else /* !CONFIG_ADEOS_CORE */
+
 #define switch_to(prev,next,last)		\
 	do {			 		\
 		last = __switch_to(prev,next);	\
 		mb();				\
 	} while (0)
 
+#endif /* CONFIG_ADEOS_CORE */
+
 /* For spinlocks etc */
 #define __save_flags_cli(x)	local_irq_save(x)
 #define __save_flags(x)		local_save_flags(x)
@@ -94,12 +142,14 @@ extern struct task_struct *__switch_to(s
 #define clf()			__clf()
 #define stf()			__stf()
 
+#ifndef CONFIG_ADEOS_CORE
 #define irqs_disabled()			\
 ({					\
 	unsigned long flags;		\
 	local_save_flags(flags);	\
 	flags & PSR_I_BIT;		\
 })
+#endif /* !CONFIG_ADEOS_CORE */
 
 #define save_flags(x)		local_save_flags(x)
 #define restore_flags(x)	local_irq_restore(x)
@@ -111,4 +161,8 @@ extern struct task_struct *__switch_to(s
 
 #endif /* __KERNEL__ */
 
+#define HAVE_DISABLE_HLT
+void disable_hlt(void);
+void enable_hlt(void);
+
 #endif
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/linux/adeos.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/linux/adeos.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/linux/adeos.h	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/linux/adeos.h	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,543 @@
+/*
+ *   include/linux/adeos.h
+ *
+ *   Copyright (C) 2002,2003,2004 Philippe Gerum.
+ *
+ *   Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ *   	various tweaks, fixes and optimizations, backport of unthreaded
+ *   	support from Adeos/x86 for 2.6
+ *
+ *   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 <linux/kernel.h>
+
+/* be paranoid and check assumptions (mostly if hw-irqs are off)? */
+#undef ADEOS_PARANOIA
+//#define ADEOS_PARANOIA	1
+#ifdef ADEOS_PARANOIA
+#define ADEOS_PARANOIA_ASSERT(cond)	BUG_ON(!(cond))
+#else
+#define ADEOS_PARANOIA_ASSERT(cond)	do { /* nop */ } while (0)
+#endif
+
+#include <asm/adeos.h>
+
+#define ADEOS_VERSION_PREFIX  "2.4"
+#define ADEOS_VERSION_STRING  (ADEOS_VERSION_PREFIX ADEOS_ARCH_STRING)
+#define ADEOS_RELEASE_NUMBER  (0x02040000|((ADEOS_MAJOR_NUMBER&0xff)<<8)|(ADEOS_MINOR_NUMBER&0xff))
+
+#define ADEOS_ROOT_PRI       100
+#define ADEOS_ROOT_ID        0
+#define ADEOS_ROOT_NPTDKEYS  4	/* Must be <= 32 */
+
+#define ADEOS_RESET_TIMER  0x1
+#define ADEOS_SAME_HANDLER ((void (*)(unsigned))(-1))
+
+/* Global domain flags */
+#define ADEOS_SPRINTK_FLAG 0	/* Synchronous printk() allowed */
+#define ADEOS_PPRINTK_FLAG 1	/* Asynchronous printk() request pending */
+
+/* Per-cpu pipeline flags.
+   WARNING: some implementation might refer to those flags
+   non-symbolically in assembly portions (e.g. x86). */
+#define IPIPE_STALL_FLAG   0	/* Stalls a pipeline stage */
+#define IPIPE_XPEND_FLAG   1	/* Exception notification is pending */
+#define IPIPE_SLEEP_FLAG   2	/* Domain has self-suspended */
+
+#define IPIPE_HANDLE_FLAG    0
+#define IPIPE_PASS_FLAG      1
+#define IPIPE_ENABLE_FLAG    2
+#define IPIPE_DYNAMIC_FLAG   IPIPE_HANDLE_FLAG
+#define IPIPE_EXCLUSIVE_FLAG 3
+#define IPIPE_STICKY_FLAG    4
+#define IPIPE_SYSTEM_FLAG    5
+#define IPIPE_LOCK_FLAG      6
+#define IPIPE_SHARED_FLAG    7
+#define IPIPE_CALLASM_FLAG   8	/* Arch-dependent -- might be unused. */
+
+#define IPIPE_HANDLE_MASK    (1 << IPIPE_HANDLE_FLAG)
+#define IPIPE_PASS_MASK      (1 << IPIPE_PASS_FLAG)
+#define IPIPE_ENABLE_MASK    (1 << IPIPE_ENABLE_FLAG)
+#define IPIPE_DYNAMIC_MASK   IPIPE_HANDLE_MASK
+#define IPIPE_EXCLUSIVE_MASK (1 << IPIPE_EXCLUSIVE_FLAG)
+#define IPIPE_STICKY_MASK    (1 << IPIPE_STICKY_FLAG)
+#define IPIPE_SYSTEM_MASK    (1 << IPIPE_SYSTEM_FLAG)
+#define IPIPE_LOCK_MASK      (1 << IPIPE_LOCK_FLAG)
+#define IPIPE_SHARED_MASK    (1 << IPIPE_SHARED_FLAG)
+#define IPIPE_CALLASM_MASK   (1 << IPIPE_CALLASM_FLAG)
+
+#define IPIPE_DEFAULT_MASK  (IPIPE_HANDLE_MASK|IPIPE_PASS_MASK)
+
+typedef struct adattr {
+
+    unsigned domid;		/* Domain identifier -- Magic value set by caller */
+    const char *name;		/* Domain name -- Warning: won't be dup'ed! */
+    int priority;		/* Priority in interrupt pipeline */
+    void (*entry)(int);		/* Domain entry point */
+    int estacksz;		/* Stack size for entry context -- 0 means unspec */
+    void (*dswitch)(void);	/* Handler called each time the domain is switched in */
+    int nptdkeys;		/* Max. number of per-thread data keys */
+    void (*ptdset)(int,void *);	/* Routine to set pt values */
+    void *(*ptdget)(int);	/* Routine to get pt values */
+
+} adattr_t;
+
+typedef struct admutex {
+
+    spinlock_t lock;
+
+#ifdef CONFIG_ADEOS_THREADS
+    adomain_t *sleepq, /* Pending domain queue */
+	      *owner;	/* Domain owning the mutex */
+#ifdef CONFIG_SMP
+    volatile int owncpu;
+#define ADEOS_MUTEX_UNLOCKED { SPIN_LOCK_UNLOCKED, NULL, NULL, -1 }
+#else  /* !CONFIG_SMP */
+#define ADEOS_MUTEX_UNLOCKED { SPIN_LOCK_UNLOCKED, NULL, NULL }
+#endif /* CONFIG_SMP */
+#else /* !CONFIG_ADEOS_THREADS */
+#define ADEOS_MUTEX_UNLOCKED { SPIN_LOCK_UNLOCKED }
+#endif /* CONFIG_ADEOS_THREADS */
+
+} admutex_t;
+
+#ifdef CONFIG_ADEOS_MODULE
+extern int adp_pipelined;
+#else  /* !CONFIG_ADEOS_MODULE */
+#define adp_pipelined		(1)	/* optimize away flag tests if not compiled as module */
+#endif /* CONFIG_ADEOS_MODULE */
+
+#ifdef SMP
+
+extern adomain_t *adp_cpu_current[],
+                 *adp_root;
+
+#else
+
+extern adomain_t adeos_root_domain;
+extern adomain_t *adp_cpu_current[];
+#define adp_root (&adeos_root_domain)
+
+#endif
+
+extern int __adeos_event_monitors[];
+
+extern unsigned __adeos_printk_virq;
+
+extern unsigned long __adeos_virtual_irq_map;
+
+extern struct list_head __adeos_pipeline;
+
+extern spinlock_t __adeos_pipelock;
+
+#ifdef CONFIG_ADEOS_PROFILING
+
+typedef struct adprofdata {
+
+    struct {
+	unsigned long long t_handled;
+	unsigned long long t_synced;
+	unsigned long n_handled;
+	unsigned long n_synced;
+    } irqs[IPIPE_NR_IRQS];
+
+} adprofdata_t;
+
+extern adprofdata_t __adeos_profile_data[ADEOS_NR_CPUS];
+
+#endif /* CONFIG_ADEOS_PROFILING */
+
+/* Private interface */
+
+#ifdef CONFIG_PROC_FS
+void __adeos_init_proc(void);
+#endif /* CONFIG_PROC_FS */
+
+void __adeos_takeover(void);
+
+asmlinkage int __adeos_handle_event(unsigned event,
+				    void *evdata);
+
+void __adeos_sync_console(unsigned irq);
+
+void __adeos_dump_state(void);
+
+static inline void __adeos_schedule_head(void *evdata) {
+
+    if (__adeos_event_monitors[ADEOS_SCHEDULE_HEAD] > 0)
+	__adeos_handle_event(ADEOS_SCHEDULE_HEAD,evdata);
+}
+
+static inline int __adeos_schedule_tail(void *evdata) {
+
+    if (__adeos_event_monitors[ADEOS_SCHEDULE_TAIL] > 0)
+	return __adeos_handle_event(ADEOS_SCHEDULE_TAIL,evdata);
+
+    return 0;
+}
+
+#ifdef CONFIG_ADEOS_EVENT_ENTER_PROCESS
+static inline void __adeos_enter_process(void) {
+
+    if (__adeos_event_monitors[ADEOS_ENTER_PROCESS] > 0)
+	__adeos_handle_event(ADEOS_ENTER_PROCESS,NULL);
+}
+#endif /* CONFIG_ADEOS_EVENT_ENTER_PROCESS */
+
+static inline void __adeos_exit_process(void *evdata) {
+
+    if (__adeos_event_monitors[ADEOS_EXIT_PROCESS] > 0)
+	__adeos_handle_event(ADEOS_EXIT_PROCESS,evdata);
+}
+
+static inline int __adeos_signal_process(void *evdata) {
+
+    if (__adeos_event_monitors[ADEOS_SIGNAL_PROCESS] > 0)
+	return __adeos_handle_event(ADEOS_SIGNAL_PROCESS,evdata);
+
+    return 0;
+}
+
+static inline void __adeos_kick_process(void *evdata) {
+
+    if (__adeos_event_monitors[ADEOS_KICK_PROCESS] > 0)
+	__adeos_handle_event(ADEOS_KICK_PROCESS,evdata);
+}
+
+#ifdef CONFIG_ADEOS_EVENT_RENICE_PROCESS
+static inline int __adeos_renice_process(void *evdata) {
+
+    if (__adeos_event_monitors[ADEOS_RENICE_PROCESS] > 0)
+	return __adeos_handle_event(ADEOS_RENICE_PROCESS,evdata);
+
+    return 0;
+}
+#endif /* CONFIG_ADEOS_EVENT_RENICE_PROCESS */
+
+void __adeos_stall_root(void);
+
+void __adeos_unstall_root(void);
+
+unsigned long __adeos_test_root(void);
+
+unsigned long __adeos_test_and_stall_root(void);
+
+void FASTCALL(__adeos_restore_root(unsigned long flags));
+
+void __adeos_schedule_back_root(struct task_struct *prev);
+
+int FASTCALL(__adeos_schedule_irq(unsigned irq,
+				  struct list_head *head));
+
+#define __adeos_pipeline_head_p(adp) (&(adp)->p_link == __adeos_pipeline.next)
+
+#ifdef CONFIG_ADEOS_THREADS
+
+static inline int __adeos_domain_work_p (adomain_t *adp, int cpuid)
+
+{
+    return (!test_bit(IPIPE_SLEEP_FLAG,&adp->cpudata[cpuid].status) ||
+	    (!test_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status) &&
+	     adp->cpudata[cpuid].irq_pending_hi != 0) ||
+	    test_bit(IPIPE_XPEND_FLAG,&adp->cpudata[cpuid].status));
+}
+
+#else /* !CONFIG_ADEOS_THREADS */
+
+/* Called with hw interrupts off. */
+static inline void __adeos_switch_to (adomain_t *out, adomain_t *in, int cpuid)
+
+{
+    void adeos_suspend_domain(void);
+    int s;
+
+    ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled());
+
+    adp_cpu_current[cpuid] = in;
+
+    if (in->dswitch)
+	in->dswitch();
+
+    /* Make sure adeos_suspend_domain() will not sync beyond the
+       current domain. "in" is guaranteed to be closer than "out" from
+       the head of the pipeline (and obviously different). */
+    s = __test_and_clear_bit(IPIPE_SLEEP_FLAG,&out->cpudata[cpuid].status);
+
+    adeos_suspend_domain(); /* Sync stage and propagate interrupts. */
+
+    if (s)
+	__set_bit(IPIPE_SLEEP_FLAG,&out->cpudata[cpuid].status);
+
+    adeos_load_cpuid(); /* Processor might have changed. */
+
+    if (adp_cpu_current[cpuid] == in)
+	/* Otherwise, something has changed the current domain under
+	   our feet recycling the register set; do not override. */
+	adp_cpu_current[cpuid] = out;
+}
+
+#endif /* CONFIG_ADEOS_THREADS */
+
+/* Public interface */
+
+int adeos_register_domain(adomain_t *adp,
+			  adattr_t *attr);
+
+int adeos_unregister_domain(adomain_t *adp);
+
+void adeos_suspend_domain(void);
+
+int adeos_virtualize_irq_from(adomain_t *adp,
+			      unsigned irq,
+			      void (*handler)(unsigned irq),
+			      int (*acknowledge)(unsigned irq),
+			      unsigned modemask);
+
+static inline int adeos_virtualize_irq(unsigned irq,
+				       void (*handler)(unsigned irq),
+				       int (*acknowledge)(unsigned irq),
+				       unsigned modemask) {
+
+    return adeos_virtualize_irq_from(adp_current,
+				     irq,
+				     handler,
+				     acknowledge,
+				     modemask);
+}
+
+int adeos_control_irq(unsigned irq,
+		      unsigned clrmask,
+		      unsigned setmask);
+
+cpumask_t adeos_set_irq_affinity(unsigned irq,
+				 cpumask_t cpumask);
+
+static inline int adeos_share_irq (unsigned irq, int (*acknowledge)(unsigned irq)) {
+
+    return adeos_virtualize_irq(irq,
+				ADEOS_SAME_HANDLER,
+				acknowledge,
+				IPIPE_SHARED_MASK|IPIPE_HANDLE_MASK|IPIPE_PASS_MASK);
+}
+
+unsigned adeos_alloc_irq(void);
+
+int adeos_free_irq(unsigned irq);
+
+int FASTCALL(adeos_trigger_irq(unsigned irq));
+
+static inline int adeos_propagate_irq(unsigned irq) {
+
+    return __adeos_schedule_irq(irq,adp_current->p_link.next);
+}
+
+static inline int adeos_schedule_irq(unsigned irq) {
+
+    return __adeos_schedule_irq(irq,&adp_current->p_link);
+}
+
+int FASTCALL(adeos_send_ipi(unsigned ipi,
+			    cpumask_t cpumask));
+
+static inline void adeos_stall_pipeline_from (adomain_t *adp)
+
+{
+    adeos_declare_cpuid;
+#ifdef CONFIG_SMP
+    unsigned long flags;
+
+    adeos_lock_cpu(flags);
+
+    __set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+    if (!__adeos_pipeline_head_p(adp))
+	adeos_unlock_cpu(flags);
+#else /* CONFIG_SMP */
+    set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+    if (__adeos_pipeline_head_p(adp))
+	adeos_hw_cli();
+#endif /* CONFIG_SMP */
+}
+
+static inline unsigned long adeos_test_pipeline_from (adomain_t *adp)
+
+{
+    unsigned long flags, s;
+    adeos_declare_cpuid;
+    
+    adeos_get_cpu(flags);
+    s = test_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+    adeos_put_cpu(flags);
+
+    return s;
+}
+
+static inline unsigned long adeos_test_and_stall_pipeline_from (adomain_t *adp)
+
+{
+    adeos_declare_cpuid;
+    unsigned long s;
+#ifdef CONFIG_SMP
+    unsigned long flags;
+
+    adeos_lock_cpu(flags);
+
+    s = __test_and_set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+    if (!__adeos_pipeline_head_p(adp))
+	adeos_unlock_cpu(flags);
+#else /* CONFIG_SMP */
+    s = test_and_set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+    if (__adeos_pipeline_head_p(adp))
+	adeos_hw_cli();
+#endif /* CONFIG_SMP */
+    
+    return s;
+}
+
+void FASTCALL(adeos_unstall_pipeline_from(adomain_t *adp));
+
+static inline unsigned long adeos_test_and_unstall_pipeline_from(adomain_t *adp)
+
+{
+    unsigned long flags, s;
+    adeos_declare_cpuid;
+    
+    adeos_get_cpu(flags);
+    s = test_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+    adeos_unstall_pipeline_from(adp);
+    adeos_put_cpu(flags);
+
+    return s;
+}
+
+static inline void adeos_unstall_pipeline(void)
+
+{
+    adeos_unstall_pipeline_from(adp_current);
+}
+
+static inline unsigned long adeos_test_and_unstall_pipeline(void)
+
+{
+    return adeos_test_and_unstall_pipeline_from(adp_current);
+}
+
+static inline unsigned long adeos_test_pipeline (void)
+
+{
+    return adeos_test_pipeline_from(adp_current);
+}
+
+static inline unsigned long adeos_test_and_stall_pipeline (void)
+
+{
+    return adeos_test_and_stall_pipeline_from(adp_current);
+}
+
+static inline void adeos_restore_pipeline_from (adomain_t *adp, unsigned long flags)
+
+{
+    if (flags)
+	adeos_stall_pipeline_from(adp);
+    else
+	adeos_unstall_pipeline_from(adp);
+}
+
+static inline void adeos_stall_pipeline (void)
+
+{
+    adeos_stall_pipeline_from(adp_current);
+}
+
+static inline void adeos_restore_pipeline (unsigned long flags)
+
+{
+    adeos_restore_pipeline_from(adp_current,flags);
+}
+
+static inline void adeos_restore_pipeline_nosync (adomain_t *adp, unsigned long flags, int cpuid)
+
+{
+    /* If cpuid is current, then it must be held on entry
+       (adeos_get_cpu/adeos_hw_local_irq_save/adeos_hw_cli). */
+
+    if (flags)
+	set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+    else
+	clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+}
+
+int adeos_catch_event_from(adomain_t *adp,
+			   unsigned event,
+			   void (*handler)(adevinfo_t *));
+
+static inline int adeos_catch_event (unsigned event, void (*handler)(adevinfo_t *))
+
+{
+    return adeos_catch_event_from(adp_current,event,handler);
+}
+
+static inline void adeos_propagate_event(adevinfo_t *evinfo)
+
+{
+    evinfo->propagate = 1;
+}
+
+void adeos_init_attr(adattr_t *attr);
+
+int adeos_get_sysinfo(adsysinfo_t *sysinfo);
+
+int adeos_tune_timer(unsigned long ns,
+		     int flags);
+
+int adeos_alloc_ptdkey(void);
+
+int adeos_free_ptdkey(int key);
+
+int adeos_set_ptd(int key,
+		  void *value);
+
+void *adeos_get_ptd(int key);
+
+unsigned long adeos_critical_enter(void (*syncfn)(void));
+
+void adeos_critical_exit(unsigned long flags);
+
+int adeos_init_mutex(admutex_t *mutex);
+
+int adeos_destroy_mutex(admutex_t *mutex);
+
+unsigned long FASTCALL(adeos_lock_mutex(admutex_t *mutex));
+
+void FASTCALL(adeos_unlock_mutex(admutex_t *mutex,
+				 unsigned long flags));
+
+static inline void adeos_set_printk_sync (adomain_t *adp) {
+    set_bit(ADEOS_SPRINTK_FLAG,&adp->flags);
+}
+
+static inline void adeos_set_printk_async (adomain_t *adp) {
+    clear_bit(ADEOS_SPRINTK_FLAG,&adp->flags);
+}
+
+#endif /* !__LINUX_ADEOS_H */
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/linux/sched.h linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/linux/sched.h
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/include/linux/sched.h	2004-08-03 19:17:32.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/include/linux/sched.h	2005-08-12 15:41:58.000000000 -0600
@@ -125,6 +125,10 @@ struct completion;
 
 #include <linux/spinlock.h>
 
+#ifdef CONFIG_ADEOS_CORE
+#include <linux/adeos.h>
+#endif /* CONFIG_ADEOS_CORE */
+
 /*
  * This serializes "schedule()" and also protects
  * the run-queue from deletions/modifications (but
@@ -415,6 +419,10 @@ struct task_struct {
 
 /* journalling filesystem info */
 	void *journal_info;
+
+#ifdef CONFIG_ADEOS_CORE
+        void *ptd[ADEOS_ROOT_NPTDKEYS];
+#endif /* CONFIG_ADEOS_CORE */
 };
 
 /*
@@ -465,6 +473,12 @@ extern void yield(void);
  */
 extern struct exec_domain	default_exec_domain;
 
+#ifdef CONFIG_ADEOS_CORE
+#define INIT_TASK_ADEOS		ptd: { [0 ... ADEOS_ROOT_NPTDKEYS - 1] = 0 },
+#else
+#define INIT_TASK_ADEOS		/* nothing */
+#endif
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -510,6 +524,7 @@ extern struct exec_domain	default_exec_d
     blocked:		{{0}},						\
     alloc_lock:		SPIN_LOCK_UNLOCKED,				\
     journal_info:	NULL,						\
+    INIT_TASK_ADEOS							\
 }
 
 
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/init/main.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/init/main.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/init/main.c	2004-08-03 19:33:51.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/init/main.c	2005-08-12 15:41:58.000000000 -0600
@@ -370,6 +370,9 @@ asmlinkage void __init start_kernel(void
 	parse_options(command_line);
 	trap_init();
 	init_IRQ();
+#ifdef CONFIG_ADEOS_CORE
+	__adeos_init();
+#endif /* CONFIG_ADEOS_CORE */
 	sched_init();
 	softirq_init();
 	time_init();
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/adeos.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/adeos.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/adeos.c	1969-12-31 17:00:00.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/adeos.c	2005-08-12 15:41:58.000000000 -0600
@@ -0,0 +1,783 @@
+/*
+ *   linux/kernel/adeos.c
+ *
+ *   Copyright (C) 2002,2003,2004 Philippe Gerum.
+ *
+ *   Copyright (C) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at)
+ *   	various tweaks, fixes and optimizations (e.g. no adp_root variable, no
+ *   	adp_pipelined unless module) backport of unthreaded support from
+ *   	Adeos/x86 for 2.6, general sync Adeos/x86 for 2.6
+ *
+ *   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.
+ *
+ *   Architecture-independent ADEOS core support.
+ */
+
+#include <linux/sched.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif /* CONFIG_PROC_FS */
+
+/* The pre-defined domain slot for the root domain. */
+adomain_t adeos_root_domain;
+
+/* A pointer to the current domain. */
+adomain_t *adp_cpu_current[ADEOS_NR_CPUS] = { [ 0 ... ADEOS_NR_CPUS - 1] = &adeos_root_domain };
+
+/* The spinlock protecting from races while modifying the pipeline. */
+spinlock_t __adeos_pipelock = SPIN_LOCK_UNLOCKED;
+
+/* The pipeline data structure. Enqueues adomain_t objects by priority. */
+struct list_head __adeos_pipeline;
+
+#ifdef CONFIG_ADEOS_MODULE
+/* A global flag telling whether Adeos pipelining is engaged. */
+int adp_pipelined;
+#endif /* CONFIG_ADEOS_MODULE */
+
+/* An array of global counters tracking domains monitoring events. */
+int __adeos_event_monitors[ADEOS_NR_EVENTS] = { [ 0 ... ADEOS_NR_EVENTS - 1] = 0 };
+
+/* The allocated VIRQ map. */
+unsigned long __adeos_virtual_irq_map = 0;
+
+/* A VIRQ to kick printk() output out when the root domain is in control. */
+unsigned __adeos_printk_virq;
+
+#ifdef CONFIG_ADEOS_PROFILING
+adprofdata_t __adeos_profile_data[ADEOS_NR_CPUS];
+#endif /* CONFIG_ADEOS_PROFILING */
+
+static void __adeos_set_root_ptd (int key, void *value) {
+
+    current->ptd[key] = value;
+}
+
+static void *__adeos_get_root_ptd (int key) {
+
+    return current->ptd[key];
+}
+
+/* adeos_init() -- Initialization routine of the ADEOS layer. Called
+   by the host kernel early during the boot procedure. */
+
+void __adeos_init (void)
+
+{
+    adomain_t *adp = &adeos_root_domain;
+
+    __adeos_check_machine();	/* Do platform dependent checks first. */
+
+    /*
+      A lightweight registration code for the root domain. Current
+      assumptions are:
+      - We are running on the boot CPU, and secondary CPUs are still
+      lost in space.
+      - adeos_root_domain has been zero'ed.
+    */
+
+    INIT_LIST_HEAD(&__adeos_pipeline);
+
+    adp->name = "Linux";
+    adp->domid = ADEOS_ROOT_ID;
+    adp->priority = ADEOS_ROOT_PRI;
+    adp->ptd_setfun = &__adeos_set_root_ptd;
+    adp->ptd_getfun = &__adeos_get_root_ptd;
+    adp->ptd_keymax = ADEOS_ROOT_NPTDKEYS;
+
+    __adeos_init_stage(adp);
+
+    INIT_LIST_HEAD(&adp->p_link);
+    list_add_tail(&adp->p_link,&__adeos_pipeline);
+
+    __adeos_printk_virq = adeos_alloc_irq(); /* Cannot fail here. */
+    adp->irqs[__adeos_printk_virq].handler = &__adeos_sync_console; 
+    adp->irqs[__adeos_printk_virq].acknowledge = NULL; 
+    adp->irqs[__adeos_printk_virq].control = IPIPE_HANDLE_MASK; 
+
+    printk(KERN_INFO "Adeos %s: Root domain %s registered.\n",
+	   ADEOS_VERSION_STRING,
+	   adp->name);
+
+#ifdef CONFIG_ADEOS
+    __adeos_takeover();
+#endif /* CONFIG_ADEOS */
+}
+
+/* adeos_handle_event() -- Adeos' generic event handler. This routine
+   calls the per-domain handlers registered for a given
+   exception/event. Each domain before the one which raised the event
+   in the pipeline will get a chance to process the event. The latter
+   will eventually be allowed to process its own event too if a valid
+   handler exists for it.  Handler executions are always scheduled by
+   the domain which raised the event for the prioritary domains
+   wanting to be notified of such event.  Note: evdata might be
+   NULL. */
+
+#ifdef CONFIG_ADEOS_THREADS
+
+asmlinkage int __adeos_handle_event (unsigned event, void *evdata)
+/* asmlinkage is there just in case -mregparm is used... */
+{
+    struct list_head *pos, *npos;
+    adomain_t *this_domain;
+    unsigned long flags;
+    adeos_declare_cpuid;
+    adevinfo_t evinfo;
+    int propagate = 1;
+
+    adeos_lock_cpu(flags);
+
+    this_domain = adp_cpu_current[cpuid];
+
+    list_for_each_safe(pos,npos,&__adeos_pipeline) {
+
+    	adomain_t *next_domain = list_entry(pos,adomain_t,p_link);
+
+	if (next_domain->events[event].handler != NULL)
+	    {
+	    if (next_domain == this_domain)
+		{
+		adeos_unlock_cpu(flags);
+		evinfo.domid = this_domain->domid;
+		evinfo.event = event;
+		evinfo.evdata = evdata;
+		evinfo.propagate = 0;
+		this_domain->events[event].handler(&evinfo);
+		propagate = evinfo.propagate;
+		goto done;
+		}
+
+	    next_domain->cpudata[cpuid].event_info.domid = this_domain->domid;
+	    next_domain->cpudata[cpuid].event_info.event = event;
+	    next_domain->cpudata[cpuid].event_info.evdata = evdata;
+	    next_domain->cpudata[cpuid].event_info.propagate = 0;
+	    __set_bit(IPIPE_XPEND_FLAG,&next_domain->cpudata[cpuid].status);
+
+	    /* Let the prioritary domain process the event. */
+	    __adeos_switch_to(this_domain,next_domain,cpuid);
+	    
+	    adeos_load_cpuid();	/* Processor might have changed. */
+
+	    if (!next_domain->cpudata[cpuid].event_info.propagate)
+		{
+		propagate = 0;
+		break;
+		}
+	    }
+
+	if (next_domain == this_domain)
+	    break;
+    }
+
+    adeos_unlock_cpu(flags);
+
+done:
+    return !propagate;
+}
+
+#else /* !CONFIG_ADEOS_THREADS */
+
+asmlinkage int __adeos_handle_event (unsigned event, void *evdata)
+/* asmlinkage is there just in case CONFIG_REGPARM is enabled... */
+{
+    adomain_t *start_domain, *this_domain, *next_domain;
+    struct list_head *pos, *npos;
+    unsigned long flags;
+    adeos_declare_cpuid;
+    adevinfo_t evinfo;
+    int propagate = 1;
+
+    adeos_lock_cpu(flags);
+
+    start_domain = this_domain = adp_cpu_current[cpuid];
+
+    list_for_each_safe(pos,npos,&__adeos_pipeline) {
+
+    	next_domain = list_entry(pos,adomain_t,p_link);
+
+	if (next_domain->events[event].handler != NULL)
+	    {
+	    adp_cpu_current[cpuid] = next_domain;
+	    adeos_unlock_cpu(flags);
+	    evinfo.domid = start_domain->domid;
+	    evinfo.event = event;
+	    evinfo.evdata = evdata;
+	    evinfo.propagate = 0;
+	    next_domain->events[event].handler(&evinfo);
+	    adeos_lock_cpu(flags);
+
+	    if (adp_cpu_current[cpuid] != next_domain)
+		/* Something has changed the current domain under our
+		   feet recycling the register set; take note. */
+		this_domain = adp_cpu_current[cpuid];
+
+	    propagate = evinfo.propagate;
+	    }
+
+	if (next_domain == this_domain || !propagate)
+	    break;
+    }
+
+    adp_cpu_current[cpuid] = this_domain;
+
+    adeos_unlock_cpu(flags);
+
+    return !propagate;
+}
+
+#endif /* CONFIG_ADEOS_THREADS */
+
+void __adeos_stall_root (void)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+
+#ifdef CONFIG_SMP
+	unsigned long flags;
+	adeos_lock_cpu(flags);
+	__set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	adeos_unlock_cpu(flags);
+#else /* !CONFIG_SMP */
+	set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+#endif /* CONFIG_SMP */
+	}
+    else
+	adeos_hw_cli();
+}
+
+void __adeos_unstall_root (void)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+
+	adeos_hw_cli();
+
+	adeos_load_cpuid();
+
+	__clear_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+
+	if (adp_root->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage(IPIPE_IRQMASK_ANY);
+	}
+
+    adeos_hw_sti();	/* Needed in both cases. */
+}
+
+unsigned long __adeos_test_root (void)
+
+{
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	unsigned long s;
+
+#ifdef CONFIG_SMP
+	unsigned long flags;
+	adeos_lock_cpu(flags);
+	s = test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	adeos_unlock_cpu(flags);
+#else /* !CONFIG_SMP */
+	s = test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+#endif /* CONFIG_SMP */
+
+	return s;
+	}
+
+    return adeos_hw_irqs_disabled();
+}
+
+unsigned long __adeos_test_and_stall_root (void)
+
+{
+    unsigned long flags;
+
+    if (likely(adp_pipelined))
+	{
+	adeos_declare_cpuid;
+	unsigned long s;
+
+#ifdef CONFIG_SMP
+	adeos_lock_cpu(flags);
+	s = __test_and_set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+	adeos_unlock_cpu(flags);
+#else /* !CONFIG_SMP */
+	s = test_and_set_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status);
+#endif /* CONFIG_SMP */
+
+	return s;
+	}
+
+    adeos_hw_local_irq_save(flags);
+
+    return !adeos_hw_test_iflag(flags);
+}
+
+void __adeos_restore_root (unsigned long flags)
+
+{
+    if (flags)
+	__adeos_stall_root();
+    else
+	__adeos_unstall_root();
+}
+
+/* adeos_unstall_pipeline_from() -- Unstall the interrupt pipeline and
+   synchronize pending events from a given domain. */
+
+void adeos_unstall_pipeline_from (adomain_t *adp)
+
+{
+    adomain_t *this_domain;
+    struct list_head *pos;
+    unsigned long flags;
+    adeos_declare_cpuid;
+
+    adeos_lock_cpu(flags);
+
+    __clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+    this_domain = adp_cpu_current[cpuid];
+
+    if (adp == this_domain)
+	{
+	if (adp->cpudata[cpuid].irq_pending_hi != 0)
+	    __adeos_sync_stage(IPIPE_IRQMASK_ANY);
+
+	goto release_cpu_and_exit;
+	}
+
+    /* Attempt to flush all events that might be pending at the
+       unstalled domain level. This code is roughly lifted from
+       arch/i386/kernel/adeos.c:__adeos_walk_pipeline(). */
+
+    list_for_each(pos,&__adeos_pipeline) {
+
+    	adomain_t *next_domain = list_entry(pos,adomain_t,p_link);
+
+	if (test_bit(IPIPE_STALL_FLAG,&next_domain->cpudata[cpuid].status))
+	    break; /* Stalled stage -- do not go further. */
+
+	if (next_domain->cpudata[cpuid].irq_pending_hi != 0)
+	    {
+	    /* Since the critical IPI might be triggered by the
+	       following actions, the current domain might not be
+	       linked to the pipeline anymore after its handler
+	       returns on SMP boxen, even if the domain remains valid
+	       (see adeos_unregister_domain()), so don't make any
+	       hazardous assumptions here. */
+
+	    if (next_domain == this_domain)
+		__adeos_sync_stage(IPIPE_IRQMASK_ANY);
+	    else
+		{
+		__adeos_switch_to(this_domain,next_domain,cpuid);
+
+		adeos_load_cpuid(); /* Processor might have changed. */
+
+		if (!test_bit(IPIPE_STALL_FLAG,&this_domain->cpudata[cpuid].status) &&
+		    this_domain->cpudata[cpuid].irq_pending_hi != 0)
+		    __adeos_sync_stage(IPIPE_IRQMASK_ANY);
+		}
+	    
+	    break;
+	    }
+	else if (next_domain == this_domain)
+	    break;
+    }
+
+release_cpu_and_exit:
+
+    if (__adeos_pipeline_head_p(adp))
+	adeos_hw_sti();
+    else
+	adeos_unlock_cpu(flags);
+}
+
+/* adeos_suspend_domain() -- tell the ADEOS layer that the current
+   domain is now dormant. The calling domain is switched out, while
+   the next domain with work in progress or pending in the pipeline is
+   switched in. */
+
+#ifdef CONFIG_ADEOS_THREADS
+
+#define __flush_pipeline_stage() \
+do { \
+    if (!test_bit(IPIPE_STALL_FLAG,&cpudata->status) && \
+	cpudata->irq_pending_hi != 0) \
+	{ \
+	__adeos_sync_stage(IPIPE_IRQMASK_ANY); \
+	adeos_load_cpuid(); \
+	cpudata = &this_domain->cpudata[cpuid]; \
+	} \
+} while(0)
+
+void adeos_suspend_domain (void)
+
+{
+    adomain_t *this_domain, *next_domain;
+    struct adcpudata *cpudata;
+    struct list_head *ln;
+    unsigned long flags;
+    adeos_declare_cpuid;
+
+    adeos_lock_cpu(flags);
+
+    this_domain = next_domain = adp_cpu_current[cpuid];
+    cpudata = &this_domain->cpudata[cpuid];
+
+    /* A suspending domain implicitely unstalls the pipeline. */
+    __clear_bit(IPIPE_STALL_FLAG,&cpudata->status);
+
+    /* Make sure that no event remains stuck in the pipeline. This
+       could happen with emerging SMP instances, or domains which
+       forget to unstall their stage before calling us. */
+    __flush_pipeline_stage();
+
+    for (;;)
+	{
+	ln = next_domain->p_link.next;
+
+	if (ln == &__adeos_pipeline)	/* End of pipeline reached? */
+	    /* Caller should loop on its idle task on return. */
+	    goto release_cpu_and_exit;
+
+	next_domain = list_entry(ln,adomain_t,p_link);
+
+	/* Make sure the domain was preempted (i.e. not sleeping) or
+	   has some event to process before switching to it. */
+
+	if (__adeos_domain_work_p(next_domain,cpuid))
+	    break;
+	}
+
+    /* Mark the outgoing domain as aslept (i.e. not preempted). */
+    __set_bit(IPIPE_SLEEP_FLAG,&cpudata->status);
+
+    /* Suspend the calling domain, switching to the next one. */
+    __adeos_switch_to(this_domain,next_domain,cpuid);
+
+    /* Clear the sleep bit for the incoming domain. */
+    __clear_bit(IPIPE_SLEEP_FLAG,&cpudata->status);
+
+#ifdef CONFIG_SMP
+    adeos_load_cpuid();	/* Processor might have changed. */
+    cpudata = &this_domain->cpudata[cpuid];
+#endif /* CONFIG_SMP */
+
+    /* Now, we are back into the calling domain. Flush the interrupt
+       log and fire the event interposition handler if needed.  CPU
+       migration is allowed in SMP-mode on behalf of an event handler
+       provided that the current domain raised it. Otherwise, it's
+       not. */
+
+    __flush_pipeline_stage();
+
+    if (__test_and_clear_bit(IPIPE_XPEND_FLAG,&cpudata->status))
+	{
+	adeos_unlock_cpu(flags);
+	this_domain->events[cpudata->event_info.event].handler(&cpudata->event_info);
+	return;
+	}
+
+release_cpu_and_exit:
+
+    adeos_unlock_cpu(flags);
+
+    /* Return to the point of suspension in the calling domain. */
+}
+
+#else /* !CONFIG_ADEOS_THREADS */
+
+void adeos_suspend_domain (void)
+
+{
+    adomain_t *this_domain, *next_domain;
+    struct list_head *ln;
+    unsigned long flags;
+    adeos_declare_cpuid;
+
+    adeos_lock_cpu(flags);
+
+    this_domain = next_domain = adp_cpu_current[cpuid];
+
+    __clear_bit(IPIPE_STALL_FLAG,&this_domain->cpudata[cpuid].status);
+
+    if (this_domain->cpudata[cpuid].irq_pending_hi != 0)
+	goto sync_stage;
+
+    for (;;)
+	{
+	ln = next_domain->p_link.next;
+
+	if (ln == &__adeos_pipeline)
+	    break;
+
+	next_domain = list_entry(ln,adomain_t,p_link);
+
+	if (!test_bit(IPIPE_SLEEP_FLAG,&next_domain->cpudata[cpuid].status) ||
+	    test_bit(IPIPE_STALL_FLAG,&next_domain->cpudata[cpuid].status))
+	    break;
+
+	if (next_domain->cpudata[cpuid].irq_pending_hi == 0)
+	    continue;
+
+	adp_cpu_current[cpuid] = next_domain;
+
+	if (next_domain->dswitch)
+	    next_domain->dswitch();
+
+ sync_stage:
+
+	__adeos_sync_stage(IPIPE_IRQMASK_ANY);
+
+	adeos_load_cpuid();	/* Processor might have changed. */
+
+	if (adp_cpu_current[cpuid] != next_domain)
+	    /* Something has changed the current domain under our feet
+	       recycling the register set; take note. */
+	    this_domain = adp_cpu_current[cpuid];
+	}
+
+    adp_cpu_current[cpuid] = this_domain;
+
+    adeos_unlock_cpu(flags);
+}
+
+#endif /* CONFIG_ADEOS_THREADS */
+
+/* adeos_alloc_irq() -- Allocate a virtual/soft pipelined interrupt.
+   Virtual interrupts are handled in exactly the same way than their
+   hw-generated counterparts. This is a very basic, one-way only,
+   inter-domain communication system (see adeos_trigger_irq()).  Note:
+   it is not necessary for a domain to allocate a virtual interrupt to
+   trap it using adeos_virtualize_irq(). The newly allocated VIRQ
+   number which can be passed to other IRQ-related services is
+   returned on success, zero otherwise (i.e. no more virtual interrupt
+   channel is available). We need this service as part of the Adeos
+   bootstrap code, hence it must reside in a built-in area. */
+
+unsigned adeos_alloc_irq (void)
+
+{
+    unsigned long flags, irq = 0;
+    int ipos;
+
+    adeos_spin_lock_irqsave(&__adeos_pipelock,flags);
+
+    if (__adeos_virtual_irq_map != ~0)
+	{
+	ipos = ffz(__adeos_virtual_irq_map);
+	set_bit(ipos,&__adeos_virtual_irq_map);
+	irq = ipos + IPIPE_VIRQ_BASE;
+	}
+
+    adeos_spin_unlock_irqrestore(&__adeos_pipelock,flags);
+
+    return irq;
+}
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/proc_fs.h>
+
+static struct proc_dir_entry *adeos_proc_entry;
+
+static int __adeos_read_proc (char *page,
+			      char **start,
+			      off_t off,
+			      int count,
+			      int *eof,
+			      void *data)
+{
+    unsigned long ctlbits;
+    struct list_head *pos;
+    unsigned irq, _irq;
+    char *p = page;
+    int len;
+
+#ifdef CONFIG_ADEOS_MODULE
+    p += sprintf(p,"Adeos %s -- Pipelining: %s",ADEOS_VERSION_STRING,adp_pipelined ? "active" : "stopped");
+#else /* !CONFIG_ADEOS_MODULE */
+    p += sprintf(p,"Adeos %s -- Pipelining: permanent",ADEOS_VERSION_STRING);
+#endif /* CONFIG_ADEOS_MODULE */
+#ifdef CONFIG_ADEOS_THREADS
+    p += sprintf(p, " (threaded)\n\n");
+#else /* CONFIG_ADEOS_THREADS */
+    p += sprintf(p, " (unthreaded)\n\n");
+#endif /* CONFIG_ADEOS_THREADS */
+
+    spin_lock(&__adeos_pipelock);
+
+    list_for_each(pos,&__adeos_pipeline) {
+
+    	adomain_t *adp = list_entry(pos,adomain_t,p_link);
+
+	p += sprintf(p,"%8s: priority=%d, id=0x%.8x, ptdkeys=%d/%d\n",
+		     adp->name,
+		     adp->priority,
+		     adp->domid,
+		     adp->ptd_keycount,
+		     adp->ptd_keymax);
+	irq = 0;
+
+	while (irq < IPIPE_NR_IRQS)
+	    {
+	    ctlbits = (adp->irqs[irq].control & (IPIPE_HANDLE_MASK|IPIPE_PASS_MASK|IPIPE_STICKY_MASK));
+
+	    if (irq >= IPIPE_NR_XIRQS && !adeos_virtual_irq_p(irq))
+		{
+		/* There might be a hole between the last external IRQ
+		   and the first virtual one; skip it. */
+		irq++;
+		continue;
+		}
+
+	    if (adeos_virtual_irq_p(irq) && !test_bit(irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map))
+		{
+		/* Non-allocated virtual IRQ; skip it. */
+		irq++;
+		continue;
+		}
+
+	    /* Attempt to group consecutive IRQ numbers having the
+	       same virtualization settings in a single line. */
+
+	    _irq = irq;
+
+	    while (++_irq < IPIPE_NR_IRQS)
+		{
+		if (adeos_virtual_irq_p(_irq) != adeos_virtual_irq_p(irq) ||
+		    (adeos_virtual_irq_p(_irq) &&
+		     !test_bit(_irq - IPIPE_VIRQ_BASE,&__adeos_virtual_irq_map)) ||
+		    ctlbits != (adp->irqs[_irq].control & (IPIPE_HANDLE_MASK|IPIPE_PASS_MASK|IPIPE_STICKY_MASK)))
+		    break;
+		}
+
+	    if (_irq == irq + 1)
+		p += sprintf(p,"\tirq%u: ",irq);
+	    else
+		p += sprintf(p,"\tirq%u-%u: ",irq,_irq - 1);
+
+	    /* Statuses are as follows:
+	       o "accepted" means handled _and_ passed down the
+	       pipeline.
+	       o "grabbed" means handled, but the interrupt might be
+	       terminated _or_ passed down the pipeline depending on
+	       what the domain handler asks for to Adeos.
+	       o "passed" means unhandled by the domain but passed
+	       down the pipeline.
+	       o "discarded" means unhandled and _not_ passed down the
+	       pipeline. The interrupt merely disappears from the
+	       current domain down to the end of the pipeline. */
+
+	    if (ctlbits & IPIPE_HANDLE_MASK)
+		{
+		if (ctlbits & IPIPE_PASS_MASK)
+		    p += sprintf(p,"accepted");
+		else
+		    p += sprintf(p,"grabbed");
+		}
+	    else if (ctlbits & IPIPE_PASS_MASK)
+		p += sprintf(p,"passed");
+	    else
+		p += sprintf(p,"discarded");
+
+	    if (ctlbits & IPIPE_STICKY_MASK)
+		p += sprintf(p,", sticky");
+
+	    if (ctlbits & IPIPE_SHARED_MASK)
+		p += sprintf(p,", shared");
+
+	    if (adeos_virtual_irq_p(irq))
+		p += sprintf(p,", virtual");
+
+	    p += sprintf(p,"\n");
+
+	    irq = _irq;
+	    }
+    }
+
+    spin_unlock(&__adeos_pipelock);
+
+    len = p - page;
+
+    if (len <= off + count)
+	*eof = 1;
+
+    *start = page + off;
+
+    len -= off;
+
+    if (len > count)
+	len = count;
+
+    if (len < 0)
+	len = 0;
+
+    return len;
+}
+
+void __adeos_init_proc (void) {
+
+    adeos_proc_entry = create_proc_read_entry("adeos",
+					      0444,
+					      NULL,
+					      &__adeos_read_proc,
+					      NULL);
+}
+
+#endif /* CONFIG_PROC_FS */
+
+void __adeos_dump_state (void)
+
+{
+    int _cpuid, nr_cpus = smp_num_cpus;
+    struct list_head *pos;
+    unsigned long flags;
+    adeos_declare_cpuid;
+
+    adeos_lock_cpu(flags);
+
+    printk(KERN_WARNING "Adeos: Current domain=%s on CPU #%d [stackbase=%p]\n",
+	   adp_current->name,
+	   cpuid,
+#ifdef CONFIG_ADEOS_THREADS
+	   (void *)adp_current->estackbase[cpuid]
+#else /* !CONFIG_ADEOS_THREADS */
+	   current
+#endif /* CONFIG_ADEOS_THREADS */
+	   );
+
+    list_for_each(pos,&__adeos_pipeline) {
+
+        adomain_t *adp = list_entry(pos,adomain_t,p_link);
+
+        for (_cpuid = 0; _cpuid < nr_cpus; _cpuid++)
+            printk(KERN_WARNING "%8s[cpuid=%d]: priority=%d, status=0x%lx, pending_hi=0x%lx\n",
+                   adp->name,
+                   _cpuid,
+                   adp->priority,
+                   adp->cpudata[_cpuid].status,
+                   adp->cpudata[_cpuid].irq_pending_hi);
+    }
+
+    adeos_unlock_cpu(flags);
+}
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/exit.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/exit.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/exit.c	2004-07-22 13:50:27.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/exit.c	2005-08-12 15:41:58.000000000 -0600
@@ -439,6 +439,9 @@ fake_volatile:
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	acct_process(code);
 #endif
+#ifdef CONFIG_ADEOS_CORE
+	__adeos_exit_process(tsk);
+#endif /* CONFIG_ADEOS_CORE */
 	__exit_mm(tsk);
 
 	lock_kernel();
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/fork.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/fork.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/fork.c	2004-08-03 19:33:52.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/fork.c	2005-08-12 15:41:58.000000000 -0600
@@ -240,7 +240,13 @@ static struct mm_struct * mm_init(struct
 	atomic_set(&mm->mm_count, 1);
 	init_rwsem(&mm->mmap_sem);
 	mm->page_table_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_ADEOS_CORE
+	adeos_spin_lock(&init_mm.page_table_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	mm->pgd = pgd_alloc(mm);
+#ifdef CONFIG_ADEOS_CORE
+	adeos_spin_unlock(&init_mm.page_table_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	mm->def_flags = 0;
 	if (mm->pgd)
 		return mm;
@@ -272,7 +278,14 @@ struct mm_struct * mm_alloc(void)
 inline void __mmdrop(struct mm_struct *mm)
 {
 	BUG_ON(mm == &init_mm);
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_sti();
+	adeos_spin_lock(&init_mm.page_table_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	pgd_free(mm->pgd);
+#ifdef CONFIG_ADEOS_CORE
+	adeos_spin_unlock(&init_mm.page_table_lock);
+#endif /* CONFIG_ADEOS_CORE */
 	check_pgt_cache();
 	destroy_context(mm);
 	free_mm(mm);
@@ -816,6 +829,15 @@ int do_fork(unsigned long clone_flags, u
 	nr_threads++;
 	write_unlock_irq(&tasklist_lock);
 
+#ifdef CONFIG_ADEOS_CORE
+	{
+	int k;
+
+	for (k = 0; k < ADEOS_ROOT_NPTDKEYS; k++)
+	    p->ptd[k] = NULL;
+	}
+#endif /* CONFIG_ADEOS_CORE */
+
 	if (p->ptrace & PT_PTRACED)
 		send_sig(SIGSTOP, p, 1);
 
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/ksyms.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/ksyms.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/ksyms.c	2004-08-03 19:33:52.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/ksyms.c	2005-08-12 15:41:58.000000000 -0600
@@ -59,6 +59,34 @@
 #include <linux/kmod.h>
 #endif
 
+#ifdef CONFIG_ADEOS_CORE
+EXPORT_SYMBOL(adeos_suspend_domain);
+EXPORT_SYMBOL(adp_cpu_current);
+EXPORT_SYMBOL(adeos_alloc_irq);
+EXPORT_SYMBOL(__adeos_init_stage);
+EXPORT_SYMBOL(__adeos_handle_event);
+EXPORT_SYMBOL(__adeos_stall_root);
+EXPORT_SYMBOL(__adeos_unstall_root);
+EXPORT_SYMBOL(__adeos_test_root);
+EXPORT_SYMBOL(__adeos_test_and_stall_root);
+EXPORT_SYMBOL(__adeos_restore_root);
+EXPORT_SYMBOL(__adeos_schedule_back_root);
+EXPORT_SYMBOL(__adeos_dump_state);
+EXPORT_SYMBOL(adeos_unstall_pipeline_from);
+extern struct list_head __adeos_pipeline;
+EXPORT_SYMBOL(__adeos_pipeline);
+extern spinlock_t __adeos_pipelock;
+EXPORT_SYMBOL(__adeos_pipelock);
+extern unsigned long __adeos_virtual_irq_map;
+EXPORT_SYMBOL(__adeos_virtual_irq_map);
+EXPORT_SYMBOL(__adeos_event_monitors);
+/* The following are convenience exports which are needed by some
+   Adeos domains loaded as kernel modules. */
+EXPORT_SYMBOL_NOVERS(__mmdrop);
+EXPORT_SYMBOL_NOVERS(do_fork);
+EXPORT_SYMBOL_NOVERS(do_exit);
+#endif /* CONFIG_ADEOS_CORE */
+
 extern void set_device_ro(kdev_t dev,int flag);
 
 extern void *sys_call_table;
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/Makefile linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/Makefile
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/Makefile	2004-07-22 13:50:27.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/Makefile	2005-08-12 15:41:58.000000000 -0600
@@ -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 \
+export-objs = adeos.o signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
 	      printk.o fork.o cpufreq.o
 
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
@@ -22,6 +22,7 @@ obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
 obj-$(CONFIG_PM) += pm.o
 obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+obj-$(CONFIG_ADEOS_CORE) += adeos.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/panic.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/panic.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/panic.c	2004-08-03 19:33:52.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/panic.c	2005-08-12 15:41:58.000000000 -0600
@@ -68,6 +68,9 @@ NORET_TYPE void panic(const char * fmt, 
 		printk(KERN_EMERG "In idle task - not syncing\n");
 	else
 		sys_sync();
+#ifdef CONFIG_ADEOS_CORE
+	__adeos_dump_state();
+#endif /* CONFIG_ADEOS_CORE */
 	bust_spinlocks(0);
 
 #ifdef CONFIG_SMP
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/printk.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/printk.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/printk.c	2004-08-03 19:33:52.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/printk.c	2005-08-12 15:41:58.000000000 -0600
@@ -29,6 +29,17 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_ADEOS_CORE
+#undef spin_lock_irq
+#define	spin_lock_irq(lock)                 adeos_spin_lock_disable(lock)
+#undef spin_unlock_irq
+#define	spin_unlock_irq(lock)               adeos_spin_unlock_enable(lock)
+#undef spin_lock_irqsave
+#define	spin_lock_irqsave(lock, flags)      adeos_spin_lock_irqsave(lock,flags)
+#undef spin_unlock_irqrestore
+#define spin_unlock_irqrestore(lock, flags) adeos_spin_unlock_irqrestore(lock,flags)
+#endif /* CONFIG_ADEOS_CORE */
+
 #if !defined(CONFIG_LOG_BUF_SHIFT) || (CONFIG_LOG_BUF_SHIFT == 0)
 #if defined(CONFIG_MULTIQUAD) || defined(CONFIG_IA64)
 #define LOG_BUF_LEN	(65536)
@@ -450,6 +461,21 @@ asmlinkage int printk(const char *fmt, .
 			log_level_unknown = 1;
 	}
 
+#ifdef CONFIG_ADEOS_CORE
+	if (adp_current != adp_root && !test_bit(ADEOS_SPRINTK_FLAG,&adp_current->flags)) {
+	    /* When operating in asynchronous printk() mode, ensure
+	       the console drivers and klogd wakeup are only run by
+	       Linux, delegating the actual output to the root domain
+	       by mean of a virtual IRQ kicking our sync handler. If
+	       the current domain has a lower priority than Linux,
+	       then we'll get immediately preempted by it. In
+	       synchronous printk() mode, immediately call the console
+	       drivers. */
+	    spin_unlock_irqrestore(&logbuf_lock, flags);
+	    adeos_trigger_irq(__adeos_printk_virq);
+	    goto out;
+	}
+#endif /* CONFIG_ADEOS_CORE */
 	if (!arch_consoles_callable()) {
 		/*
 		 * On some architectures, the consoles are not usable
@@ -458,7 +484,11 @@ asmlinkage int printk(const char *fmt, .
 		spin_unlock_irqrestore(&logbuf_lock, flags);
 		goto out;
 	}
+#ifdef CONFIG_ADEOS_CORE
+ 	if (adp_current != adp_root || !down_trylock(&console_sem)) {
+#else /* !CONFIG_ADEOS_CORE */
 	if (!down_trylock(&console_sem)) {
+#endif /* CONFIG_ADEOS_CORE */
 		/*
 		 * We own the drivers.  We can drop the spinlock and let
 		 * release_console_sem() print the text
@@ -528,12 +558,38 @@ void release_console_sem(void)
 		call_console_drivers(_con_start, _log_end);
 	}
 	console_may_schedule = 0;
+#ifdef CONFIG_ADEOS_CORE
+	if (adp_root != adp_current) {
+	    spin_unlock_irqrestore(&logbuf_lock, flags);
+	    return;
+	}
+	spin_unlock_irqrestore(&logbuf_lock, flags);
+	up(&console_sem);
+#else /* !CONFIG_ADEOS_CORE */
 	up(&console_sem);
 	spin_unlock_irqrestore(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS_CORE */
 	if (must_wake_klogd && !oops_in_progress)
 		wake_up_interruptible(&log_wait);
 }
 
+#ifdef CONFIG_ADEOS_CORE
+void __adeos_sync_console (unsigned virq) {
+
+    /* This handler always runs on behalf of the root (Linux) domain. */
+    unsigned long flags;
+
+    spin_lock_irqsave(&logbuf_lock, flags);
+
+    if (arch_consoles_callable() && !down_trylock(&console_sem)) {
+	spin_unlock_irqrestore(&logbuf_lock, flags);
+        console_may_schedule = 0;
+	release_console_sem();
+    } else
+	spin_unlock_irqrestore(&logbuf_lock, flags);
+}
+#endif /* CONFIG_ADEOS_CORE */
+
 /** console_conditional_schedule - yield the CPU if required
  *
  * If the console code is currently allowed to sleep, and
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/sched.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/sched.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/sched.c	2004-08-03 19:33:52.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/sched.c	2005-08-12 15:41:58.000000000 -0600
@@ -532,6 +532,9 @@ needs_resched:
 asmlinkage void schedule_tail(struct task_struct *prev)
 {
 	__schedule_tail(prev);
+#ifdef CONFIG_ADEOS_EVENT_ENTER_PROCESS
+	__adeos_enter_process();
+#endif /* CONFIG_ADEOS_EVENT_ENTER_PROCESS */
 }
 
 /*
@@ -551,6 +554,10 @@ asmlinkage void schedule(void)
 	struct list_head *tmp;
 	int this_cpu, c;
 
+#ifdef CONFIG_ADEOS_CORE
+	if (adp_current != adp_root) /* Let's be helpful and conservative. */
+	    return;
+#endif /* CONFIG_ADEOS_CORE */
 
 	spin_lock_prefetch(&runqueue_lock);
 
@@ -668,7 +675,13 @@ repeat_schedule:
 	 * but prev is set to (the just run) 'last' process by switch_to().
 	 * This might sound slightly confusing but makes tons of sense.
 	 */
+#ifdef CONFIG_ADEOS_CORE
+	prepare_to_switch(prev, next);
+	/* disable hw-irqs (for sake of LXRT scheduler), are re-enabled after switch */
+	adeos_hw_cli();
+#else /* !CONFIG_ADEOS_CORE */
 	prepare_to_switch();
+#endif /* CONFIG_ADEOS_CORE */
 	{
 		struct mm_struct *mm = next->mm;
 		struct mm_struct *oldmm = prev->active_mm;
@@ -693,6 +706,13 @@ repeat_schedule:
 	 * stack.
 	 */
 	switch_to(prev, next, prev);
+#ifdef CONFIG_ADEOS_CORE
+	adeos_hw_sti();
+	if (__adeos_schedule_tail(prev) > 0)
+	    /* Some event handler asked for a truncated
+	       scheduling tail. Just obey. */
+	    return;
+#endif /* CONFIG_ADEOS_CORE */
 	__schedule_tail(prev);
 
 same_process:
@@ -702,6 +722,20 @@ same_process:
 	return;
 }
 
+#ifdef CONFIG_ADEOS_CORE
+
+void __adeos_schedule_back_root (struct task_struct *prev)
+
+{
+    __schedule_tail(prev);
+    reacquire_kernel_lock(current);
+#ifdef CONFIG_PREEMPT
+    preempt_enable_no_resched();
+#endif /* CONFIG_PREEMPT */
+}
+
+#endif /* CONFIG_ADEOS_CORE */
+
 /*
  * The core wakeup function.  Non-exclusive wakeups (nr_exclusive == 0) just wake everything
  * up.  If it's an exclusive wakeup (nr_exclusive == small +ve number) then we wake all the
@@ -989,6 +1023,13 @@ static int setscheduler(pid_t pid, int p
 		goto out_unlock;
 
 	retval = 0;
+#ifdef CONFIG_ADEOS_EVENT_RENICE_PROCESS
+	{
+	struct { struct task_struct *task; int policy; struct sched_param *param; } evdata = { p, policy, &lp };
+	if (__adeos_renice_process(&evdata))
+	    goto out_unlock;
+	}
+#endif /* CONFIG_ADEOS_EVENT_RENICE_PROCESS */
 	p->policy = policy;
 	p->rt_priority = lp.sched_priority;
 
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/signal.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/signal.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/signal.c	2004-08-03 19:33:52.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/signal.c	2005-08-12 15:41:58.000000000 -0600
@@ -496,6 +496,13 @@ static inline void signal_wake_up(struct
 {
 	t->sigpending = 1;
 
+#ifdef CONFIG_ADEOS_CORE
+	{
+	struct { struct task_struct *t; } evdata = { t };
+	__adeos_kick_process(&evdata);
+	}
+#endif /* CONFIG_ADEOS_CORE */
+
 #ifdef CONFIG_SMP
 	/*
 	 * If the task is running on a different CPU 
@@ -554,6 +561,17 @@ printk("SIG queue (%s:%d): %d ", t->comm
 	if (!sig || !t->sig)
 		goto out_nolock;
 
+#ifdef CONFIG_ADEOS_CORE
+	/* If some domain handler in the pipeline doesn't ask for
+	   propagation, return success pretending that 'sig' was
+	   delivered. */
+	{
+	struct { struct task_struct *task; int sig; } evdata = { t, sig };
+	if (__adeos_signal_process(&evdata))
+	    goto out_nolock;
+	}
+#endif /* CONFIG_ADEOS_CORE */
+
 	spin_lock_irqsave(&t->sigmask_lock, flags);
 	handle_stop_signal(sig, t);
 
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/sysctl.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/sysctl.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/kernel/sysctl.c	2004-08-03 19:33:52.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/kernel/sysctl.c	2005-08-12 15:41:58.000000000 -0600
@@ -360,6 +360,9 @@ void __init sysctl_init(void)
 #ifdef CONFIG_PROC_FS
 	register_proc_table(root_table, proc_sys_root);
 	init_irq_proc();
+#ifdef CONFIG_ADEOS_CORE
+	__adeos_init_proc();
+#endif /* CONFIG_ADEOS_CORE */
 #endif
 }
 
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/Makefile linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/Makefile
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/Makefile	2005-03-11 09:02:10.000000000 -0700
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/Makefile	2005-08-12 15:42:54.000000000 -0600
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 26
-EXTRAVERSION =-vrs1-cirrus-1-2-1-ts8
+EXTRAVERSION =-vrs1-cirrus-1-2-1-ts8-rt
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -18,7 +18,7 @@ FINDHPATH	= $(HPATH)/asm $(HPATH)/linux 
 
 HOSTCC  	= gcc
 HOSTCFLAGS	= -Wall -Wstrict-prototypes -Os -fomit-frame-pointer
-CROSS_COMPILE = $(shell cd $(TOPDIR)/../../tools/crosstool/arm-9tdmi-linux-gnu/gcc-3.3.4-glibc-2.3.2/bin/ && pwd)/arm-9tdmi-linux-gnu-
+CROSS_COMPILE   = /usr/local/opt/crosstool/arm-linux/gcc-3.3.4-glibc-2.3.2/bin/arm-linux-
 #
 # Include the make variables (CC, etc...)
 #
@@ -34,7 +34,7 @@ OBJCOPY		= $(CROSS_COMPILE)objcopy
 OBJDUMP		= $(CROSS_COMPILE)objdump
 MAKEFILES	= $(TOPDIR)/.config
 GENKSYMS	= /sbin/genksyms
-DEPMOD		= /sbin/depmod
+DEPMOD		= /usr/local/opt/crosstool/arm-linux/gcc-3.3.4-glibc-2.3.2/sbin/depmod
 MODFLAGS	= -DMODULE
 CFLAGS_KERNEL	=
 PERL		= perl
@@ -126,13 +126,14 @@ CORE_FILES	=kernel/kernel.o mm/mm.o fs/f
 NETWORKS	=net/network.o
 
 LIBS		=$(TOPDIR)/lib/lib.a
-SUBDIRS		=kernel drivers mm fs net ipc lib crypto
+SUBDIRS		=kernel adeos drivers mm fs net ipc lib crypto
 
 DRIVERS-n :=
 DRIVERS-y :=
 DRIVERS-m :=
 DRIVERS-  :=
 
+DRIVERS-$(CONFIG_ADEOS) += adeos/built-in.o
 DRIVERS-$(CONFIG_ACPI_BOOT) += drivers/acpi/acpi.o
 DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
 DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
diff -urNpb linux-2.4.26-vrs1-cirrus-1-2-1-ts8/mm/memory.c linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/mm/memory.c
--- linux-2.4.26-vrs1-cirrus-1-2-1-ts8/mm/memory.c	2004-08-03 19:33:53.000000000 -0600
+++ linux-2.4.26-vrs1-cirrus-1-2-1-ts8-rt/mm/memory.c	2005-08-12 15:41:58.000000000 -0600
@@ -492,13 +492,32 @@ int get_user_pages(struct task_struct *t
 
 		vma = find_extend_vma(mm, start);
 
+#if 0
 		if ( !vma || (pages && vma->vm_flags & VM_IO) || !(flags & vma->vm_flags) )
+#else
+		/* fix for lock-up upon mlockall() & mmap(/dev/mem) (i.e. to access
+		 * hardware in real-time process) */
+		int vm_io = vma ? vma->vm_flags & VM_IO : 0;
+		if (!vma || (pages && vm_io) || !(flags & vma->vm_flags))
+#endif
 			return i ? : -EFAULT;
 
 		spin_lock(&mm->page_table_lock);
 		do {
+#if 0
 			struct page *map;
 			while (!(map = follow_page(mm, start, write))) {
+#else
+			/* fix for lock-up upon mlockall() & mmap(/dev/mem) (i.e. to access
+			 * hardware in real-time process) */
+			struct page *map = NULL;
+			/*
+			 * We don't follow pagetables for VM_IO regions - they
+			 * have no pageframes. And the caller passed NULL
+			 * for `pages' anyway.
+			 */
+			while (!vm_io && !(map = follow_page(mm,start,write))) { 
+#endif
 				spin_unlock(&mm->page_table_lock);
 				switch (handle_mm_fault(mm, vma, start, write)) {
 				case 1:
