#
# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
#

--- linux-2.4.28/CREDITS~colinux-0.6.1	2004-11-17 06:54:20.000000000 -0500
+++ linux-2.4.28/CREDITS	2004-11-27 15:59:21.283010512 -0500
@@ -54,6 +54,12 @@
 S: CH-1015 Lausanne
 S: Switzerland
 
+A: Dan Aloni
+E: da-x@gmx.net
+D: Cooperative Linux
+D: Various kernel patches
+S: Israel
+
 N: Tim Alpaerts
 E: tim_alpaerts@toyota-motor-europe.com
 D: 802.2 class II logical link control layer,
--- linux-2.4.28/Documentation/devices.txt~colinux-0.6.1	2004-02-18 08:36:30.000000000 -0500
+++ linux-2.4.28/Documentation/devices.txt	2004-11-27 15:59:21.285010208 -0500
@@ -1926,6 +1926,13 @@
 		 17 = /dev/cosa1c1	2nd board, 2nd channel
 		    ...
 
+    block	coLinux Block devices
+		  0 = /dev/cobd0		First coLinux device
+		  1 = /dev/cobd1		Second coLinux device
+		    ...
+
+                These block devices map to files or devices in the host FS. 
+
 118 char	Solidum ???
 		  0 = /dev/solnp0
 		  1 = /dev/solnp1
--- linux-2.4.28/Makefile~colinux-0.6.1	2004-11-17 06:54:22.000000000 -0500
+++ linux-2.4.28/Makefile	2004-11-27 15:59:30.235649504 -0500
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 28
-EXTRAVERSION =
+EXTRAVERSION = -co-0.6.1
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -27,7 +27,11 @@
 
 AS		= $(CROSS_COMPILE)as
 LD		= $(CROSS_COMPILE)ld
-CC		= $(CROSS_COMPILE)gcc
+ifeq ($(GCCTRACE),Y)
+CC              = $(CROSS_COMPILE)$(COLINUX_ROOT)/bin/tracewrapper.py gcc
+else
+CC              = $(CROSS_COMPILE)gcc
+endif
 CPP		= $(CC) -E
 AR		= $(CROSS_COMPILE)ar
 NM		= $(CROSS_COMPILE)nm
--- linux-2.4.28/arch/i386/config.in~colinux-0.6.1	2004-11-17 06:54:21.000000000 -0500
+++ linux-2.4.28/arch/i386/config.in	2004-11-27 15:59:21.286010056 -0500
@@ -226,13 +226,20 @@
 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
 bool 'Symmetric multi-processing support' CONFIG_SMP
 if [ "$CONFIG_SMP" != "y" ]; then
-   bool 'Local APIC support on uniprocessors' CONFIG_X86_UP_APIC
-   dep_bool 'IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC $CONFIG_X86_UP_APIC
-   if [ "$CONFIG_X86_UP_APIC" = "y" ]; then
-      define_bool CONFIG_X86_LOCAL_APIC y
-   fi
-   if [ "$CONFIG_X86_UP_IOAPIC" = "y" ]; then
-      define_bool CONFIG_X86_IO_APIC y
+   if [ "$CONFIG_COOPERATIVE" = "y" ]; then
+      bool 'Cooperative PIC (COPIC) support' CONFIG_X86_UP_COPIC
+      if [ "$CONFIG_X86_UP_COPIC" = "y" ]; then
+         define_bool CONFIG_X86_COPIC y
+      fi
+   else
+      bool 'Local APIC support on uniprocessors' CONFIG_X86_UP_APIC
+      dep_bool 'IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC $CONFIG_X86_UP_APIC
+      if [ "$CONFIG_X86_UP_APIC" = "y" ]; then
+         define_bool CONFIG_X86_LOCAL_APIC y
+      fi
+      if [ "$CONFIG_X86_UP_IOAPIC" = "y" ]; then
+         define_bool CONFIG_X86_IO_APIC y
+      fi
    fi
 else
    int  'Maximum number of CPUs (2-32)' CONFIG_NR_CPUS 32
@@ -343,12 +350,13 @@
    bool '    Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
 fi
 
+bool 'Cooperative Mode' CONFIG_COOPERATIVE
+
 source drivers/acpi/Config.in
 
 endmenu
 
 source drivers/mtd/Config.in
-
 source drivers/parport/Config.in
 
 source drivers/pnp/Config.in
@@ -445,7 +453,11 @@
 if [ "$CONFIG_VT" = "y" ]; then
    mainmenu_option next_comment
    comment 'Console drivers'
-   bool 'VGA text console' CONFIG_VGA_CONSOLE
+   if [ "$CONFIG_COOPERATIVE" = "n" ]; then
+      bool 'VGA text console' CONFIG_VGA_CONSOLE
+   else
+      bool 'coLinux Pseudo-VGA text console' CONFIG_COOPERATIVE_CONSOLE
+   fi
    bool 'Video mode selection support' CONFIG_VIDEO_SELECT
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
--- linux-2.4.28/arch/i386/kernel/Makefile~colinux-0.6.1	2003-11-28 13:26:19.000000000 -0500
+++ linux-2.4.28/arch/i386/kernel/Makefile	2004-11-27 15:59:21.287009904 -0500
@@ -18,7 +18,7 @@
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
-		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o
+		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o cooperative.o \
 
 
 ifdef CONFIG_PCI
--- /dev/null	2004-04-06 13:56:48.000000000 -0400
+++ linux-2.4.28/arch/i386/kernel/cooperative.c	2004-11-27 15:59:21.287009904 -0500
@@ -0,0 +1,160 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+
+#include <asm/keyboard.h>
+#include <linux/kbd_ll.h>
+#include <linux/cooperative.h>
+#include <asm/smp.h>
+#include <asm/desc.h>
+
+CO_TRACE_STOP;
+
+
+/*
+ * The next asm code is the first Linux code that runs in the 
+ * coLinux kernel context. It receives %ecx which contains the 
+ * address of the passage page. The passage page code sets %ecx 
+ * to this value in its context restore part.
+ */  
+
+asm(
+	""
+	".section .text\n"
+	".globl colinux_start\n"
+	"colinux_start:\n"
+	"       call colinux_start_arch\n"
+	".previous\n"
+	"");
+
+static void colinux_early_cpu_init(void)
+{
+	/*
+	 * On the first switch to Linux we must set up a valid TR because 
+	 * the passage page code assumes such one exists. This is basically
+	 * copied code from cpu_init().
+	 *
+	 * P.S this is protected by CO_TRACE_STOP so that we don't
+	 * have a monitor context switch.
+	 */
+
+	int nr = smp_processor_id();
+	struct tss_struct * t = &init_tss[nr];
+
+	set_tss_desc(nr,t);
+	gdt_table[__TSS(nr)].b &= 0xfffffdff;
+	load_TR(nr);
+	gdt_table[__TSS(nr)].b &= 0xfffffdff;
+
+	__asm__ __volatile__("movl %%cr4, %0" : "=r" (mmu_cr4_features));
+}
+
+void colinux_start_arch()
+{
+	colinux_early_cpu_init();
+	colinux_start_c();
+}
+
+extern void ctrl_alt_del(void);
+
+void co_handle_device_interrupt(co_linux_message_t *message)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (message->device) {
+	case CO_DEVICE_TIMER: {
+		co_linux_message_idle_t data = *(co_linux_message_idle_t *)message->data;
+		
+		if (data.tick_count > HZ) {
+			xtime.tv_sec += data.tick_count / HZ;
+			data.tick_count -= ((data.tick_count / HZ) * HZ);
+		}
+		
+		
+		while (data.tick_count > 0) {
+			struct pt_regs regs = {0, };
+			regs.orig_eax = TIMER_IRQ;
+			do_IRQ(regs);
+
+			data.tick_count--;
+		}
+		break;
+	}
+	case CO_DEVICE_POWER: {
+		co_linux_message_power_t *type = (co_scan_code_t *)message->data;
+		switch (type->type) {
+		case CO_LINUX_MESSAGE_POWER_ALT_CTRL_DEL: {
+			ctrl_alt_del();
+			break;
+		}
+		}
+		break;
+	}
+	
+	case CO_DEVICE_KEYBOARD: {
+		struct pt_regs regs;
+		co_received_message(message);
+		regs.orig_eax = KEYBOARD_IRQ;
+		do_IRQ(regs);
+		break;
+	}
+
+	case CO_DEVICE_NETWORK: {
+		struct pt_regs regs;
+		if (message->size > 1600) {
+			printk("co_handle_device_interrupt: warning, packet len: %d\n", message->size);
+			break;
+		}
+		co_received_message(message);
+		regs.orig_eax = NETWORK_IRQ;
+		do_IRQ(regs);
+		break;
+	}
+	default:
+		break;
+	}
+
+	local_irq_restore(flags);
+}
+
+void co_switch_wrapper_protected(void)
+{
+	/*
+	 * We don't trust the passage page code to safely restore %gs and %fs. 
+	 *
+	 * This wrapper ensures that if %fs or %gs are invalid, the processes
+	 * exits with a segmentation fault rather than bringing down the 
+	 * machine.
+	 **/
+	unsigned long fs = 0;
+	unsigned long gs = 0;
+
+        asm volatile("movl %%fs,%0": "=m" (fs));
+        asm volatile("movl %%gs,%0": "=m" (gs));
+
+	/*
+	 * Nullify the registers so the passage page code restores to 
+	 * null segment values on return.
+	 */
+        asm volatile("movl %0, %%fs;  movl %0, %%gs" : : "r" (0));
+
+	/* And switch... */
+	co_switch();
+
+	/*
+	 * Safely restore the registers.
+	 */
+	loadsegment(fs, fs);
+	loadsegment(gs, gs);
+}
+
+void co_switch_wrapper(void)
+{
+	co_switch_wrapper_protected();
+}
+
+CO_TRACE_CONTINUE;
+
--- linux-2.4.28/arch/i386/kernel/head.S~colinux-0.6.1	2003-11-28 13:26:19.000000000 -0500
+++ linux-2.4.28/arch/i386/kernel/head.S	2004-11-27 15:59:21.287009904 -0500
@@ -320,7 +320,7 @@
 	ret
 
 ENTRY(stack_start)
-	.long SYMBOL_NAME(init_task_union)+8192
+	.long SYMBOL_NAME(init_task_union)+8192-100
 	.long __KERNEL_DS
 
 /* This is the default interrupt "handler" :-) */
@@ -361,12 +361,14 @@
 
 	ALIGN
 	.word 0
+.globl idt_descr    
 idt_descr:
 	.word IDT_ENTRIES*8-1		# idt contains 256 entries
 SYMBOL_NAME(idt):
 	.long SYMBOL_NAME(idt_table)
 
 	.word 0
+.globl gdt_descr    
 gdt_descr:
 	.word GDT_ENTRIES*8-1
 SYMBOL_NAME(gdt):
--- linux-2.4.28/arch/i386/kernel/i387.c~colinux-0.6.1	2003-08-25 07:44:39.000000000 -0400
+++ linux-2.4.28/arch/i386/kernel/i387.c	2004-11-27 15:59:21.288009752 -0500
@@ -342,6 +342,8 @@
 	return 1;
 }
 
+CO_TRACE_STOP;
+
 int save_i387( struct _fpstate *buf )
 {
 	if ( !current->used_math )
@@ -363,6 +365,8 @@
 	}
 }
 
+CO_TRACE_CONTINUE;
+
 static inline int restore_i387_fsave( struct _fpstate *buf )
 {
 	struct task_struct *tsk = current;
@@ -383,6 +387,8 @@
 	return err ? 1 : convert_fxsr_from_user( &tsk->thread.i387.fxsave, buf );
 }
 
+CO_TRACE_STOP;
+
 int restore_i387( struct _fpstate *buf )
 {
 	int err;
@@ -400,6 +406,8 @@
 	return err;
 }
 
+CO_TRACE_CONTINUE;
+
 /*
  * ptrace request handlers.
  */
--- linux-2.4.28/arch/i386/kernel/i8259.c~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/arch/i386/kernel/i8259.c	2004-11-27 15:59:21.288009752 -0500
@@ -24,6 +24,7 @@
 #include <asm/apic.h>
 
 #include <linux/irq.h>
+#include <linux/cooperative.h>
 
 /*
  * Common place to define all x86 IRQ vectors
@@ -121,6 +122,81 @@
 #undef IRQ
 #undef IRQLIST_16
 
+#ifdef CONFIG_COOPERATIVE
+
+CO_TRACE_STOP;
+
+void proxy_interrupt_handler(unsigned long interrupt, struct pt_regs regs)
+{
+	co_passage_page->operation = CO_OPERATION_FORWARD_INTERRUPT;
+	co_passage_page->params[0] = interrupt + 0x20;
+	co_passage_page->params[1] = regs.eip;
+	co_passage_page->params[2] = (unsigned long)(&((&interrupt)[10]));
+	co_passage_page->host_state.flags &= ~(1 << 9); /* Turn IF off */
+
+	co_switch_wrapper();
+	co_callback();
+}
+
+CO_TRACE_CONTINUE;
+
+#define IRQLIST_16(x) \
+	IRQ(x,0) IRQ(x,1) IRQ(x,2) IRQ(x,3) \
+	IRQ(x,4) IRQ(x,5) IRQ(x,6) IRQ(x,7) \
+	IRQ(x,8) IRQ(x,9) IRQ(x,a) IRQ(x,b) \
+	IRQ(x,c) IRQ(x,d) IRQ(x,e) IRQ(x,f)
+
+#define IRQLIST_224 \
+	IRQLIST_16(0x0) IRQLIST_16(0x1) IRQLIST_16(0x2) IRQLIST_16(0x3) \
+	IRQLIST_16(0x4) IRQLIST_16(0x5) IRQLIST_16(0x6) IRQLIST_16(0x7) \
+	IRQLIST_16(0x8) IRQLIST_16(0x9) IRQLIST_16(0xa) IRQLIST_16(0xb) \
+	IRQLIST_16(0xc) IRQLIST_16(0xd)
+
+#define IRQ(x,y) \
+	     extern asmlinkage void IRQ_proxy_##x##y##_interrupt(void);
+IRQLIST_224;
+#undef IRQ
+
+struct _fpstate co_interrupt_register_state;
+
+#define BIRQ(id)						\
+asm(								\
+    "\n"__ALIGN_STR"\n"					\
+    ".section .text\n"					\
+    ".globl IRQ_proxy_" #id "_interrupt\n"	\
+    "IRQ_proxy_" #id "_interrupt:\n"		\
+    "push %eax\n\t"					\
+    SAVE_ALL						\
+								\
+    "pushl $co_interrupt_register_state\n\t"	\
+    "call save_i387\n\t"				\
+    "popl %ebx\n\t"					\
+    "pushl $" #id "\n\t"				\
+    "call proxy_interrupt_handler\n\t"		\
+    "popl %ebx\n\t"					\
+    "pushl $co_interrupt_register_state\n\t"	\
+    "call restore_i387\n\t"				\
+    "popl %ebx\n\t"					\
+								\
+    "jmp ret_from_intr\n"				\
+    ".previous\n"						\
+    );							\
+    
+#define IRQ(x,y) BIRQ(x##y)
+IRQLIST_224;
+#undef IRQ
+
+#define IRQ(x,y) &IRQ_proxy_##x##y##_interrupt,
+void (*proxy_interrupt[NR_IRQS])(void) = {
+    IRQLIST_224
+};
+#undef IRQ
+
+#undef IRQLIST_16
+#undef IRQLIST_224
+
+#endif
+
 /*
  * This is the 'legacy' 8259A Programmable Interrupt Controller,
  * present in the majority of PC/AT boxes.
@@ -441,15 +517,74 @@
 	}
 }
 
+#ifdef CONFIG_X86_COPIC 
+
+/* 
+ * Not like you have any other choice other than using
+ * COPIC in Cooperative mode.
+ */
+
+static void end_COPIC_irq(unsigned int irq)
+{
+}
+
+#define shutdown_COPIC_irq	disable_COPIC_irq
+
+static void mask_and_ack_COPIC(unsigned int irq)
+{
+}
+
+static unsigned int startup_COPIC_irq(unsigned int irq)
+{ 
+	return 0;
+}
+
+void disable_COPIC_irq(unsigned int irq)
+{
+}
+
+void enable_COPIC_irq(unsigned int irq)
+{
+}
+
+static struct hw_interrupt_type co_pic_irq_type = {
+	"CO-PIC",
+	startup_COPIC_irq,
+	shutdown_COPIC_irq,
+	enable_COPIC_irq,
+	disable_COPIC_irq,
+	mask_and_ack_COPIC,
+	end_COPIC_irq,
+	NULL
+};
+
+void __init init_COPIC_irqs(void)
+{
+	int i;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 1;
+		
+		irq_desc[i].handler = &co_pic_irq_type;
+	}
+
+}
+
+#endif
+
 void __init init_IRQ(void)
 {
 	int i;
 
+#ifndef CONFIG_COOPERATIVE
 #ifndef CONFIG_X86_VISWS_APIC
 	init_ISA_irqs();
 #else
 	init_VISWS_APIC_irqs();
 #endif
+
 	/*
 	 * Cover the whole vector space, no vector can escape
 	 * us. (some of these will be overridden and become
@@ -490,6 +625,8 @@
 	set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
 #endif
 
+
+#ifndef CONFIG_COOPERATIVE
 	/*
 	 * Set the clock to HZ Hz, we already have a valid
 	 * vector now:
@@ -509,4 +646,20 @@
 	 */
 	if (boot_cpu_data.hard_math && !cpu_has_fpu)
 		setup_irq(13, &irq13);
+#endif
+
+#else
+	printk("Setting proxy interrupt vectors\n");
+
+#ifdef CONFIG_X86_COPIC 
+	init_COPIC_irqs();
+#endif
+
+	for (i = 0; i < NR_IRQS; i++) {
+		int vector = FIRST_EXTERNAL_VECTOR + i;
+		if (vector != SYSCALL_VECTOR) {
+		    set_intr_gate(vector, proxy_interrupt[i]);
+		}
+	}
+#endif
 }
--- linux-2.4.28/arch/i386/kernel/ioport.c~colinux-0.6.1	2003-06-13 10:51:29.000000000 -0400
+++ linux-2.4.28/arch/i386/kernel/ioport.c	2004-11-27 15:59:21.289009600 -0500
@@ -54,6 +54,7 @@
  */
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
+#ifndef CONFIG_COOPERATIVE
 	struct thread_struct * t = &current->thread;
 	struct tss_struct * tss = init_tss + smp_processor_id();
 
@@ -86,6 +87,10 @@
 	}
 
 	return 0;
+#else
+	/* No ports for yer VM */
+	return -EPERM;
+#endif
 }
 
 /*
@@ -101,6 +106,7 @@
 
 asmlinkage int sys_iopl(unsigned long unused)
 {
+#ifndef CONFIG_COOPERATIVE
 	struct pt_regs * regs = (struct pt_regs *) &unused;
 	unsigned int level = regs->ebx;
 	unsigned int old = (regs->eflags >> 12) & 3;
@@ -114,4 +120,8 @@
 	}
 	regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
 	return 0;
+#else
+	/* No IPL for yer VM */
+	return -EPERM;
+#endif
 }
--- linux-2.4.28/arch/i386/kernel/process.c~colinux-0.6.1	2004-11-17 06:54:21.000000000 -0500
+++ linux-2.4.28/arch/i386/kernel/process.c	2004-11-27 15:59:21.289009600 -0500
@@ -51,6 +51,7 @@
 #include <asm/apic.h>
 
 #include <linux/irq.h>
+#include <linux/cooperative.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
@@ -131,11 +132,15 @@
 	current->counter = -100;
 
 	while (1) {
+#ifdef CONFIG_COOPERATIVE
+		co_idle_processor();
+#else	
 		void (*idle)(void) = pm_idle;
 		if (!idle)
 			idle = default_idle;
 		while (!current->need_resched)
 			idle();
+#endif
 		schedule();
 		check_pgt_cache();
 	}
@@ -280,6 +285,7 @@
  */
 void machine_real_restart(unsigned char *code, int length)
 {
+#ifndef CONFIG_COOPERATIVE
 	unsigned long flags;
 
 	cli();
@@ -363,10 +369,14 @@
 	__asm__ __volatile__ ("ljmp $0x0008,%0"
 				:
 				: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
+#else
+	co_terminate(CO_TERMINATE_REBOOT);
+#endif
 }
 
 void machine_restart(char * __unused)
 {
+#ifndef CONFIG_COOPERATIVE
 #if CONFIG_SMP
 	int cpuid;
 	
@@ -430,16 +440,26 @@
 	}
 
 	machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+#else
+	co_terminate(CO_TERMINATE_REBOOT);
+#endif
 }
 
 void machine_halt(void)
 {
+#ifdef CONFIG_COOPERATIVE
+	co_terminate(CO_TERMINATE_HALT);
+#endif
 }
 
 void machine_power_off(void)
 {
+#ifndef CONFIG_COOPERATIVE
 	if (pm_power_off)
 		pm_power_off();
+#else
+	co_terminate(CO_TERMINATE_POWEROFF);
+#endif
 }
 
 extern void show_trace(unsigned long* esp);
@@ -657,12 +677,20 @@
 	 */
 	tss->esp0 = next->esp0;
 
+#ifdef CONFIG_COOPERATIVE
+	/*
+	 * We would save %fs and %gs using an atomic operation in the
+	 * just before the LDT of the next process is loaded. It is 
+	 * not here, it's in...
+	 */
+#else
 	/*
 	 * Save away %fs and %gs. No need to save %es and %ds, as
 	 * those are always kernel segments while inside the kernel.
 	 */
 	asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
 	asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
+#endif
 
 	/*
 	 * Restore %fs and %gs.
--- linux-2.4.28/arch/i386/kernel/setup.c~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/arch/i386/kernel/setup.c	2004-11-27 15:59:21.291009296 -0500
@@ -108,6 +108,7 @@
 #include <asm/processor.h>
 #include <linux/console.h>
 #include <linux/module.h>
+#include <linux/cooperative.h>
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -782,9 +783,18 @@
 	int len = 0;
 	int userdef = 0;
 
+#ifdef CONFIG_COOPERATIVE
+	/*
+	 * Better to have 'root=/dev/cobd0' here.
+	 */
+	from = co_boot_parameters;
+	snprintf(saved_command_line, COMMAND_LINE_SIZE, "%s", 
+		 co_boot_parameters);
+#else
 	/* Save unparsed command line copy for /proc/cmdline */
 	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+#endif
 
 	for (;;) {
 		if (c != ' ')
@@ -1044,16 +1054,23 @@
 static unsigned long __init setup_memory(void)
 {
 	unsigned long bootmap_size, start_pfn, max_low_pfn;
-
+#ifdef CONFIG_COOPERATIVE
+	unsigned long bootmem_size;
+	unsigned long bootmem_start;
+#endif
 	/*
 	 * partially used pages are not usable - thus
 	 * we are rounding upwards:
 	 */
 	start_pfn = PFN_UP(__pa(&_end));
 
+#ifdef CONFIG_COOPERATIVE
+	max_low_pfn = max_pfn = co_memory_size / PAGE_SIZE;
+#else
 	find_max_pfn();
 
 	max_low_pfn = find_max_low_pfn();
+#endif
 
 #ifdef CONFIG_HIGHMEM
 	highstart_pfn = highend_pfn = max_pfn;
@@ -1065,12 +1082,19 @@
 #endif
 	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
 			pages_to_mb(max_low_pfn));
+
 	/*
 	 * Initialize the boot-time allocator (with low memory only):
 	 */
 	bootmap_size = init_bootmem(start_pfn, max_low_pfn);
 
-	register_bootmem_low_pages(max_low_pfn);
+#ifdef CONFIG_COOPERATIVE
+	bootmap_size = (bootmap_size + PAGE_SIZE - 1) & PAGE_MASK;
+	bootmem_size = (0x800 << PAGE_SHIFT) - bootmap_size;
+	bootmem_start = co_core_end + bootmap_size;
+	
+	free_bootmem(__pa(bootmem_start), bootmem_size);
+#else
 
 	/*
 	 * Reserve the bootmem bitmap itself as well. We do this in two
@@ -1124,7 +1148,7 @@
 		}
 	}
 #endif
-
+#endif
 	return max_low_pfn;
 }
  
@@ -1176,7 +1200,9 @@
 
 void __init setup_arch(char **cmdline_p)
 {
+#ifndef CONFIG_COOPERATIVE
 	unsigned long max_low_pfn;
+#endif
 
 #ifdef CONFIG_VISWS
 	visws_get_board_type_and_rev();
@@ -1186,6 +1212,7 @@
 	blk_nohighio = 1;
 #endif
 
+	boot_cpu_data.hard_math = 1;
  	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
@@ -1203,7 +1230,10 @@
 	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
+
+#ifndef CONFIG_COOPERATIVE
 	setup_memory_region();
+#endif
 	copy_edd();
 
 	if (!MOUNT_ROOT_RDONLY)
@@ -1230,8 +1260,10 @@
 #ifdef CONFIG_SMP
 	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
 #endif
+
 	paging_init();
 
+#ifndef CONFIG_COOPERATIVE
 	dmi_scan_machine();
 
 	/*
@@ -1248,14 +1280,19 @@
 #endif
 
 	register_memory(max_low_pfn);
+#endif	
 
 #ifdef CONFIG_VT
+#ifdef CONFIG_COOPERATIVE_CONSOLE
+	conswitchp = &colinux_con;
+#else
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
 #endif
 #endif
+#endif
 }
 
 static int cachesize_override __initdata = -1;
@@ -3216,29 +3253,41 @@
 	if(current->mm)
 		BUG();
 	enter_lazy_tlb(&init_mm, current, nr);
-
 	t->esp0 = current->thread.esp0;
+
 	set_tss_desc(nr,t);
 	gdt_table[__TSS(nr)].b &= 0xfffffdff;
+
 	load_TR(nr);
 	load_LDT(&init_mm.context);
 
 	/*
 	 * Clear all 6 debug registers:
 	 */
-
+#ifndef CONFIG_COOPERATIVE
 #define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) );
 
 	CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
 
 #undef CD
-
+#endif
 	/*
 	 * Force FPU initialization:
 	 */
 	current->flags &= ~PF_USEDFPU;
 	current->used_math = 0;
+#ifndef CONFIG_COOPERATIVE
 	stts();
+#else
+#if (0)
+	clear_in_cr4(X86_CR4_PVI);
+	clear_in_cr4(X86_CR4_DE);
+	clear_in_cr4(X86_CR4_MCE);
+	clear_in_cr4(X86_CR4_PGE);
+	flush_tlb_all();
+	clear_in_cr4(X86_CR4_OSXMMEXCPT);
+#endif
+#endif
 }
 
 /*
--- linux-2.4.28/arch/i386/kernel/time.c~colinux-0.6.1	2004-02-18 08:36:30.000000000 -0500
+++ linux-2.4.28/arch/i386/kernel/time.c	2004-11-27 15:59:21.292009144 -0500
@@ -84,8 +84,24 @@
 
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 
-static inline unsigned long do_fast_gettimeoffset(void)
+static inline unsigned long long rdtsc_u64(void)
+{
+	register unsigned long eax, edx;
+
+	rdtsc(eax,edx);
+
+	return ((((unsigned long long)edx) << 32) | eax);
+}
+
+#ifdef CONFIG_COOPERATIVE
+static unsigned long long co_last_interrupt_time;
+static unsigned long co_tsc_per_5_ticks;
+static long co_last_time_offset;
+#endif
+
+static inline long do_fast_gettimeoffset(void)
 {
+#ifndef CONFIG_COOPERATIVE
 	register unsigned long eax, edx;
 
 	/* Read the Time Stamp Counter */
@@ -111,6 +127,32 @@
 
 	/* our adjusted time offset in microseconds */
 	return delay_at_last_interrupt + edx;
+#else
+	union { 
+		unsigned long long ll_var;
+		struct { unsigned long low, high; };
+	} differential;
+	unsigned long edx;
+	unsigned long ret = 0;
+
+	differential.ll_var = rdtsc_u64() - co_last_interrupt_time;
+	if (differential.high)
+		return 0;
+	
+	if (co_tsc_per_5_ticks == 0)
+		return 0;
+
+	differential.ll_var *= 50000;
+
+	__asm__("divl %2"
+		:"=a" (ret), "=d" (edx)
+		:"r" (co_tsc_per_5_ticks),
+		 "0" (differential.low), "1" (differential.high));
+
+	ret += co_last_time_offset;
+
+	return ret;
+#endif
 }
 
 #define TICK_SIZE tick
@@ -121,6 +163,8 @@
 
 extern spinlock_t i8259A_lock;
 
+#ifndef CONFIG_COOPERATIVE
+
 #ifndef CONFIG_X86_TSC
 
 /* This function must be called with interrupts disabled 
@@ -254,7 +298,16 @@
 	return count;
 }
 
-static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
+#else
+
+static unsigned long do_slow_gettimeoffset(void)
+{
+	return 0;
+}
+
+#endif
+
+static long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
 
 
 /* IBM Summit (EXA) Cyclone Timer code*/
@@ -305,7 +358,7 @@
 	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
 }
 
-static unsigned long do_gettimeoffset_cyclone(void)
+static long do_gettimeoffset_cyclone(void)
 {
 	u32 offset;
 
@@ -443,7 +496,8 @@
 void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long flags;
-	unsigned long usec, sec;
+	unsigned long sec;
+	long usec;
 
 	read_lock_irqsave(&xtime_lock, flags);
 	usec = do_gettimeoffset();
@@ -461,6 +515,11 @@
 		sec++;
 	}
 
+	if (usec < 0) {
+		usec = usec + 1000000;
+		sec -= 1;
+	}
+
 	tv->tv_sec = sec;
 	tv->tv_usec = usec;
 }
@@ -502,6 +561,7 @@
  */
 static int set_rtc_mmss(unsigned long nowtime)
 {
+#ifndef CONFIG_COOPERATIVE
 	int retval = 0;
 	int real_seconds, real_minutes, cmos_minutes;
 	unsigned char save_control, save_freq_select;
@@ -554,8 +614,13 @@
 	CMOS_WRITE(save_control, RTC_CONTROL);
 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
 	spin_unlock(&rtc_lock);
-
 	return retval;
+#else
+	/*
+	 * Don't let Linux change the system time of the host machine.
+	 */
+	return -1;
+#endif
 }
 
 /* last time the cmos clock got updated */
@@ -603,6 +668,7 @@
 		smp_local_timer_interrupt(regs);
 #endif
 
+#ifndef CONFIG_COOPERATIVE
 	/*
 	 * If we have an externally synchronized Linux clock, then update
 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
@@ -617,6 +683,7 @@
 		else
 			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 	}
+#endif
 	    
 #ifdef CONFIG_MCA
 	if( MCA_bus ) {
@@ -655,6 +722,7 @@
 	 */
 	write_lock(&xtime_lock);
 
+#ifndef CONFIG_COOPERATIVE
 	if(use_cyclone)
 		mark_timeoffset_cyclone();
 	else if (use_tsc) {
@@ -706,7 +774,15 @@
 		count = ((LATCH-1) - count) * TICK_SIZE;
 		delay_at_last_interrupt = (count + LATCH/2) / LATCH;
 	}
-
+#else
+	if (use_tsc) {
+		if (co_last_interrupt_time == 0)
+			co_last_time_offset = 0;
+		else
+			co_last_time_offset = ((long)do_fast_gettimeoffset()) - 10000;
+		co_last_interrupt_time = rdtsc_u64();
+	}
+#endif
 	do_timer_interrupt(irq, NULL, regs);
 
 	write_unlock(&xtime_lock);
@@ -716,6 +792,7 @@
 /* not static: needed by APM */
 unsigned long get_cmos_time(void)
 {
+#ifndef CONFIG_COOPERATIVE
 	unsigned int year, mon, day, hour, min, sec;
 	int i;
 
@@ -753,6 +830,9 @@
 	if ((year += 1900) < 1970)
 		year += 100;
 	return mktime(year, mon, day, hour, min, sec);
+#else
+	return co_get_host_time();
+#endif
 }
 
 static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
@@ -818,6 +898,10 @@
 		if (endlow <= CALIBRATE_TIME)
 			goto bad_ctc;
 
+#ifdef CONFIG_COOPERATIVE
+		co_tsc_per_5_ticks = endlow;
+#endif
+
 		__asm__("divl %2"
 			:"=a" (endlow), "=d" (endhigh)
 			:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
@@ -870,7 +954,13 @@
 
  	if(use_cyclone)
 		init_cyclone_clock();
-		
+
+#ifdef CONFIG_COOPERATIVE
+	/* 
+	 * We pretty much depend on this at the moment...
+	 */
+	set_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability);
+#endif		
 	if (cpu_has_tsc) {
 		unsigned long tsc_quotient = calibrate_tsc();
 		if (tsc_quotient) {
--- linux-2.4.28/arch/i386/kernel/traps.c~colinux-0.6.1	2002-11-28 18:53:09.000000000 -0500
+++ linux-2.4.28/arch/i386/kernel/traps.c	2004-11-27 15:59:21.293008992 -0500
@@ -852,11 +852,20 @@
 	"rorl $16,%%eax" \
 	: "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
 
+CO_TRACE_STOP;
+
+/*
+ * We use this in colinux_early_cpu_init(), so it must be protected 
+ * from traces.
+ */
+
 void set_tss_desc(unsigned int n, void *addr)
 {
 	_set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89);
 }
 
+CO_TRACE_CONTINUE;
+
 void set_ldt_desc(unsigned int n, void *addr, unsigned int size)
 {
 	_set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82);
--- linux-2.4.28/arch/i386/mm/fault.c~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/arch/i386/mm/fault.c	2004-11-27 15:59:21.293008992 -0500
@@ -380,7 +380,11 @@
 		pte_t *pte_k;
 
 		asm("movl %%cr3,%0":"=r" (pgd));
+#ifndef CONFIG_COOPERATIVE
 		pgd = offset + (pgd_t *)__va(pgd);
+#else
+		pgd = offset + (pgd_t *)CO_VA(((unsigned long)pgd));
+#endif
 		pgd_k = init_mm.pgd + offset;
 
 		if (!pgd_present(*pgd_k))
--- linux-2.4.28/arch/i386/mm/init.c~colinux-0.6.1	2004-04-14 09:05:25.000000000 -0400
+++ linux-2.4.28/arch/i386/mm/init.c	2004-11-27 15:59:21.294008840 -0500
@@ -38,6 +38,8 @@
 #include <asm/apic.h>
 #include <asm/tlb.h>
 
+#include <linux/cooperative.h>
+
 mmu_gather_t mmu_gathers[NR_CPUS];
 unsigned long highstart_pfn, highend_pfn;
 static unsigned long totalram_pages;
@@ -122,7 +124,7 @@
 
 /* References to section boundaries */
 
-extern char _text, _etext, _edata, __bss_start, _end;
+extern char _text, _etext, _edata, _sdata, __bss_start, _end;
 extern char __init_begin, __init_end;
 
 static inline void set_pte_phys (unsigned long vaddr,
@@ -204,6 +206,7 @@
 
 static void __init pagetable_init (void)
 {
+#ifndef CONFIG_COOPERATIVE
 	unsigned long vaddr, end;
 	pgd_t *pgd, *pgd_base;
 	int i, j, k;
@@ -300,6 +303,8 @@
 	 */
 	pgd_base[0] = pgd_base[USER_PTRS_PER_PGD];
 #endif
+#else
+#endif
 }
 
 void __init zap_low_mappings (void)
@@ -325,6 +330,7 @@
 	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
 	unsigned int max_dma, high, low;
 
+#ifndef CONFIG_COOPERATIVE
 	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 	low = max_low_pfn;
 	high = highend_pfn;
@@ -338,6 +344,11 @@
 		zones_size[ZONE_HIGHMEM] = high - low;
 #endif
 	}
+#else
+	zones_size[ZONE_DMA] = 0;
+	zones_size[ZONE_NORMAL] = max_low_pfn;
+	zones_size[ZONE_HIGHMEM] = 0;
+#endif
 	free_area_init(zones_size);
 }
 
@@ -485,6 +496,22 @@
 
 	bad_ppro = ppro_with_ram_bug();
 
+#ifdef CONFIG_COOPERATIVE
+	/* 
+	 * Only at this stage, after the buddy allocator's maps 
+	 * have been allocated, we can let the kernel use its
+	 * other pseudo physical space.
+	 */
+	{
+	    unsigned long bootmem_end = co_core_end +
+		(0x800 << PAGE_SHIFT);
+	    unsigned long physical_end = __PAGE_OFFSET + 
+		(max_low_pfn << PAGE_SHIFT);
+
+	    free_bootmem(__pa(bootmem_end), physical_end - bootmem_end);
+	}
+
+#endif
 	/* this will put all low memory onto the freelists */
 	totalram_pages += free_all_bootmem();
 
@@ -529,7 +556,7 @@
 	reservedpages = free_pages_init();
 
 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
-	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_sdata;
 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
 	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
@@ -546,19 +573,21 @@
 	if (!cpu_has_pae)
 		panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
 #endif
+#ifndef CONFIG_COOPERATIVE
 	if (boot_cpu_data.wp_works_ok < 0)
 		test_wp_bit();
-
+#endif
 	/*
 	 * Subtle. SMP is doing it's boot stuff late (because it has to
 	 * fork idle threads) - but it also needs low mappings for the
 	 * protected-mode entry to work. We zap these entries only after
 	 * the WP-bit has been tested.
 	 */
+#ifndef CONFIG_COOPERATIVE
 #ifndef CONFIG_SMP
 	zap_low_mappings();
 #endif
-
+#endif
 }
 
 /* Put this after the callers, so that it cannot be inlined */
--- linux-2.4.28/arch/i386/vmlinux.lds~colinux-0.6.1	2002-02-25 14:37:53.000000000 -0500
+++ linux-2.4.28/arch/i386/vmlinux.lds	2004-11-27 15:59:21.294008840 -0500
@@ -7,50 +7,72 @@
 SECTIONS
 {
   . = 0xC0000000 + 0x100000;
-  _text = .;			/* Text and read-only data */
+  _kernel_start = .;
   .text : {
+        _text = .;			/* Text and read-only data */
 	*(.text)
 	*(.fixup)
 	*(.gnu.warning)
-	} = 0x9090
-
-  _etext = .;			/* End of text section */
+        _etext = .;			/* End of text section */
+  }
 
   .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
+  __ex_table : { 
+     __start___ex_table = .;
+     *(__ex_table) 
+     __stop___ex_table = .;
+  }
 
-  __start___ksymtab = .;	/* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
+  . = ALIGN(4);		
+  __import_table_address : { 
+    __start_import_address = .;
+    *(__im_table_address) 
+    __stop_import_address = .;
+  }
 
+  __ksymtab : { 
+        __start___ksymtab = .;	/* Kernel symbol table */
+        *(__ksymtab) 
+        __stop___ksymtab = .;
+  }
   .data : {			/* Data */
+        _sdata = .;			/* Start of data section */
 	*(.data)
 	CONSTRUCTORS
-	}
+        _edata = .;			/* End of data section */
+  }
 
-  _edata = .;			/* End of data section */
+  . = ALIGN(4096);		/* gdt */
+  .data.gdt : {
+	*(.data.gdt)
+  }
+  .data.idt : {
+	*(.data.idt)
+  }
 
   . = ALIGN(8192);		/* init_task */
-  .data.init_task : { *(.data.init_task) }
+  .data.init_task : { 
+	*(.data.init_task) 
+  }
 
   . = ALIGN(4096);		/* Init code and data */
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);
-  __init_end = .;
+  .init : {
+      __init_begin = .;
+      *(.text.init)
+      *(.data.init)
+      . = ALIGN(16);
+       __setup_start = .;
+      *(.setup.init)
+      __setup_end = .;
+      __initcall_start = .;
+      *(.initcall.init)
+      __initcall_end = .;
+      . = ALIGN(4096);
+      __init_end = .;
+  }
 
   . = ALIGN(4096);
   .data.page_aligned : { *(.data.idt) }
@@ -58,11 +80,11 @@
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
-  __bss_start = .;		/* BSS */
   .bss : {
+	__bss_start = .;		/* BSS */
 	*(.bss)
-	}
-  _end = . ;
+	_end = . ;
+  }
 
   /* Sections to be discarded */
   /DISCARD/ : {
--- linux-2.4.28/drivers/block/Config.in~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/drivers/block/Config.in	2004-11-27 15:59:21.294008840 -0500
@@ -50,6 +50,10 @@
 fi
 dep_bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
 
+if [ "$CONFIG_COOPERATIVE" = "y" ]; then
+   tristate 'coLinux block device support' CONFIG_BLK_DEV_PBD
+fi
+
 bool 'Per partition statistics in /proc/partitions' CONFIG_BLK_STATS
 
 endmenu
--- linux-2.4.28/drivers/block/Makefile~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/drivers/block/Makefile	2004-11-27 15:59:21.295008688 -0500
@@ -31,6 +31,7 @@
 obj-$(CONFIG_BLK_DEV_DAC960)	+= DAC960.o
 obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
 obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
+obj-$(CONFIG_BLK_DEV_PBD)	+= cobd.o
 obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
 
 subdir-$(CONFIG_PARIDE) += paride
--- /dev/null	2004-04-06 13:56:48.000000000 -0400
+++ linux-2.4.28/drivers/block/cobd.c	2004-11-27 15:59:21.295008688 -0500
@@ -0,0 +1,334 @@
+/*
+ *  Copyright (C) 2003 Dan Aloni <da-x@gmx.net>
+ *
+ *  Cooperative Linux Block Device implementation
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/devfs_fs_kernel.h>
+
+#define MAJOR_NR COLINUX_MAJOR
+#define DEVICE_NR(device) MINOR(device)  /* has no partition bits */
+#define DEVICE_NAME "cobd"                /* name for messaging */
+#define DEVICE_NO_RANDOM                 /* no entropy to contribute */
+#define DEVICE_REQUEST cobd_request
+#define DEVICE_OFF(d) /* do-nothing */
+
+#include <linux/blk.h>
+#include <linux/blkpg.h>
+#include <linux/hdreg.h>
+#include <linux/cooperative.h>
+
+#include <asm/uaccess.h>
+
+#define PBD_BLOCK_SIZE 512
+
+static int *cobd_sizes;
+static int *cobd_blksizes;
+static int *cobd_hardsects;
+static int cobd_devs;
+static int cobd_rahead = 1;
+
+struct cobd_device_aliases_minor {
+	int cobd_minor;
+};
+
+struct cobd_device_aliases_major {
+	int sizes[0x100];
+	int blksizes[0x100];
+	int cobd_hardsects[0x100];
+	struct cobd_device_aliases_minor *minors[0x100];
+};
+
+static struct cobd_device_aliases_major *alias_majors;
+
+static int cobd_stat(int dev, co_block_request_t *out_request)
+{
+	co_block_request_t *request;
+	unsigned long flags;
+	long rc = 0;
+
+	local_irq_save(flags);
+	co_passage_page->operation = CO_OPERATION_DEVICE;
+	co_passage_page->params[0] = CO_DEVICE_BLOCK;
+	co_passage_page->params[1] = dev;
+	request = (co_block_request_t *)&co_passage_page->params[2];
+	request->type = CO_BLOCK_STAT;
+	co_switch_wrapper();
+	rc = request->rc;
+	*out_request = *request;
+	local_irq_restore(flags);
+
+	return rc;
+}
+
+static int cobd_ioctl(struct inode * inode, struct file * file,
+		     unsigned int cmd, unsigned long arg)
+{
+	int err;
+	int dev;
+
+	dev = MINOR(inode->i_rdev);
+
+	switch(cmd) {
+
+	case BLKGETSIZE: {
+		unsigned long size;
+		
+		/* Return the device size, expressed in sectors */
+		if (!arg) 
+			return -EINVAL; /* NULL pointer: not valid */
+
+		err = !access_ok (VERIFY_WRITE, arg, sizeof(long));
+		if (err) 
+			return -EFAULT;
+
+		size = (cobd_sizes[dev]) * (1024 / cobd_hardsects[dev]);
+		if (copy_to_user((unsigned long *) arg, &size, sizeof (unsigned long)))
+			return -EFAULT;
+
+		return 0;
+	}
+
+	case BLKGETSIZE64: {
+		unsigned long long size;
+
+		/* Return the device size, expressed in sectors */
+		if (!arg) 
+			return -EINVAL; /* NULL pointer: not valid */
+
+		err = !access_ok (VERIFY_WRITE, arg, sizeof(unsigned long long));
+		if (err) 
+			return -EFAULT;
+
+		size = cobd_sizes[dev];
+		size = size * 1024;
+		if (copy_to_user((unsigned long long *) arg, &size, sizeof (unsigned long long)))
+			return -EFAULT;
+
+		return 0;
+	}
+
+	case BLKRRPART: /* reread partition table: can't do it */
+		return -ENOTTY;
+
+	default:
+		/*
+		 * For ioctls we don't understand, let the block layer
+		 * handle them.
+		 */
+		return blk_ioctl(inode->i_rdev, cmd, arg);
+	}
+
+	return -ENOTTY; /* unknown command */
+}
+
+static int cobd_open(struct inode *inode, struct file *file)
+{
+	co_block_request_t *co_request;
+	co_block_request_t stat_request;
+	unsigned long flags;
+	int ret = 0;
+	int dev = MINOR(inode->i_rdev);
+
+	if (dev >= cobd_devs)
+		return -EIO;
+	
+	if (!cobd_stat(dev, &stat_request)) {
+		unsigned long long size;
+
+		/* Request succeeded */
+		size = stat_request.disk_size;
+		cobd_sizes[dev] = size / 1024;
+	} else {
+		cobd_sizes[dev] = 0;
+	}
+
+	local_irq_save(flags);
+	co_passage_page->operation = CO_OPERATION_DEVICE;
+	co_passage_page->params[0] = CO_DEVICE_BLOCK;
+	co_passage_page->params[1] = DEVICE_NR(inode->i_rdev);
+	co_request = (co_block_request_t *)&co_passage_page->params[2];
+	co_request->type = CO_BLOCK_OPEN;
+	co_switch_wrapper();
+	if (co_request->rc)
+		ret = -EIO;
+	local_irq_restore(flags);    
+
+	return ret;
+}
+
+static int cobd_release(struct inode *inode, struct file *file)
+{
+	co_block_request_t *co_request;
+	unsigned long flags;
+	int ret = 0;
+	local_irq_save(flags);
+
+	co_passage_page->operation = CO_OPERATION_DEVICE;
+	co_passage_page->params[0] = CO_DEVICE_BLOCK;
+	co_passage_page->params[1] = DEVICE_NR(inode->i_rdev);
+	co_request = (co_block_request_t *)&co_passage_page->params[2];
+	co_request->type = CO_BLOCK_CLOSE;
+	co_switch_wrapper();
+	if (co_request->rc)
+		ret = -EIO;
+	local_irq_restore(flags);    
+
+	return ret;
+}
+
+static int cobd_transfer(int dev, const struct request *req)
+{
+	co_block_request_t *co_request;
+	unsigned long flags;
+	int ret = 0;
+
+	local_irq_save(flags);
+
+	co_passage_page->operation = CO_OPERATION_DEVICE;
+	co_passage_page->params[0] = CO_DEVICE_BLOCK;
+	co_passage_page->params[1] = dev;
+	co_request = (co_block_request_t *)&co_passage_page->params[2];
+	if (req->cmd == READ)
+		co_request->type = CO_BLOCK_READ;
+	else
+		co_request->type = CO_BLOCK_WRITE;
+	co_request->offset = ((unsigned long long)req->sector) * PBD_BLOCK_SIZE;
+	co_request->size = req->current_nr_sectors * PBD_BLOCK_SIZE;
+	co_request->address = req->buffer;
+	co_request->rc = 0;
+
+	co_switch_wrapper();
+
+	if (!co_request->rc)
+		ret = 1;
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static void cobd_request(request_queue_t *q)
+{
+	int status;
+	int devno;
+
+	while (1) {
+		INIT_REQUEST;  /* returns when queue is empty */
+
+		devno = DEVICE_NR(CURRENT->rq_dev);
+
+		status = cobd_transfer(devno, CURRENT);
+
+		end_request(status); 
+	}
+}
+
+static int cobd_check_change(kdev_t dev)
+{
+	return 1;
+}
+
+static struct block_device_operations cobd_fops = {
+	owner:	            THIS_MODULE,
+	open:		    cobd_open,
+	release:            cobd_release,
+	ioctl:		    cobd_ioctl,
+	check_media_change: cobd_check_change,
+};
+
+int __init cobd_init(void) 
+{
+	int result;
+	int i;
+
+	if (devfs_register_blkdev(MAJOR_NR, "cobd", &cobd_fops)) {
+		printk(KERN_WARNING "Unable to get major number %d for cobd device\n", MAJOR_NR);
+		return -EIO;
+	}
+
+	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), cobd_request);
+
+	read_ahead[MAJOR_NR] = cobd_rahead;
+	result = -ENOMEM; /* for the possible errors */
+
+	cobd_devs = CO_MODULE_MAX_COBD;
+
+	cobd_sizes = kmalloc(cobd_devs * sizeof(int), GFP_KERNEL);
+	if (!cobd_sizes)
+		goto fail_malloc;
+
+	cobd_blksizes = kmalloc(cobd_devs * sizeof(int), GFP_KERNEL);
+	if (!cobd_blksizes)
+		goto fail_malloc_1;
+
+	cobd_hardsects = kmalloc(cobd_devs * sizeof(int), GFP_KERNEL);
+	if (!cobd_hardsects)
+		goto fail_malloc_2;
+
+	for (i=0; i < cobd_devs; i++) {
+		co_block_request_t request;
+		unsigned long long size = 0;
+	
+		if (!cobd_stat(i, &request)) {
+			/* Request successed */
+			size = request.disk_size;
+			cobd_sizes[i] = size >> 10;
+		} else {
+			cobd_sizes[i] = 0;
+		}
+
+		if (cobd_sizes[i] != 0)
+			printk(KERN_DEBUG "cobd%d size: %d kb\n", i, cobd_sizes[i]);
+
+		cobd_blksizes[i] = PAGE_SIZE;
+		cobd_hardsects[i] = PBD_BLOCK_SIZE;
+	}
+
+	blk_size[MAJOR_NR] = cobd_sizes;
+	blksize_size[MAJOR_NR] = cobd_blksizes;
+	hardsect_size[MAJOR_NR] = cobd_hardsects;
+ 
+	devfs_register_series(NULL, "cobd%u", cobd_devs, DEVFS_FL_DEFAULT,
+			      MAJOR_NR, 0,
+			      S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
+			      &cobd_fops, NULL);
+	
+	printk(KERN_DEBUG "cobd: loaded (max %d devices)\n", cobd_devs);
+
+	return 0;
+
+fail_malloc_2:
+	kfree(cobd_blksizes);
+fail_malloc_1:
+	kfree(cobd_sizes);
+fail_malloc:
+
+	if (devfs_unregister_blkdev(MAJOR_NR, "cobd"))
+		printk(KERN_WARNING "loop: cannot unregister blkdev\n");
+
+	return result;
+}
+
+void cobd_exit(void) 
+{
+	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+   
+	if (devfs_unregister_blkdev(MAJOR_NR, "cobd"))
+		printk(KERN_WARNING "cobd: cannot unregister blkdev\n");
+
+	kfree(blk_size[MAJOR_NR]);
+	kfree(blksize_size[MAJOR_NR]);
+	kfree(hardsect_size[MAJOR_NR]);
+}
+
+module_init(cobd_init);
+module_exit(cobd_exit);
+
+
--- linux-2.4.28/drivers/block/ll_rw_blk.c~colinux-0.6.1	2004-11-17 06:54:21.000000000 -0500
+++ linux-2.4.28/drivers/block/ll_rw_blk.c	2004-11-27 15:59:21.298008232 -0500
@@ -1576,7 +1576,7 @@
 #ifdef CONFIG_BLK_DEV_FD
 	floppy_init();
 #else
-#if defined(__i386__)	/* Do we even need this? */
+#if defined(__i386__) && !defined(CONFIG_COOPERATIVE)	/* Do we even need this? */
 	outb_p(0xc, 0x3f2);
 #endif
 #endif
--- linux-2.4.28/drivers/char/Makefile~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/drivers/char/Makefile	2004-11-27 15:59:21.298008232 -0500
@@ -169,6 +169,10 @@
   KEYBD = dummy_keyb.o
 endif
 
+ifeq ($(CONFIG_COOPERATIVE),y)
+  KEYBD = colx_keyb.o
+endif
+
 obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
 obj-$(CONFIG_SERIAL) += $(SERIAL)
 obj-$(CONFIG_PARPORT_SERIAL) += parport_serial.o
--- /dev/null	2004-04-06 13:56:48.000000000 -0400
+++ linux-2.4.28/drivers/char/colx_keyb.c	2004-11-27 15:59:21.299008080 -0500
@@ -0,0 +1,1228 @@
+/*
+ * linux/drivers/char/pc_keyb.c
+ *
+ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
+ * See keyboard.c for the whole history.
+ *
+ * Major cleanup by Martin Mares, May 1997
+ *
+ * Combined the keyboard and PS/2 mouse handling into one file,
+ * because they share the same hardware.
+ * Johan Myreen <jem@iki.fi> 1998-10-08.
+ *
+ * Code fixes to handle mouse ACKs properly.
+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+ *
+ */
+
+#include <linux/config.h>
+
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+#include <linux/smp_lock.h>
+#include <linux/kd.h>
+#include <linux/pm.h>
+
+#include <asm/keyboard.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include <asm/io.h>
+
+/* Some configuration switches are present in the include file... */
+
+#include <linux/pc_keyb.h>
+
+/* Simple translation table for the SysRq keys */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char pckbd_sysrq_xlate[128] =
+	"\000\0331234567890-=\177\t"			/* 0x00 - 0x0f */
+	"qwertyuiop[]\r\000as"				/* 0x10 - 0x1f */
+	"dfghjkl;'`\000\\zxcv"				/* 0x20 - 0x2f */
+	"bnm,./\000*\000 \000\201\202\203\204\205"	/* 0x30 - 0x3f */
+	"\206\207\210\211\212\000\000789-456+1"		/* 0x40 - 0x4f */
+	"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+	"\r\000/";					/* 0x60 - 0x6f */
+#endif
+
+static void kbd_write_command_w(int data);
+static void kbd_write_output_w(int data);
+#ifdef CONFIG_PSMOUSE
+static void aux_write_ack(int val);
+static void __aux_write_ack(int val);
+static int aux_reconnect = 0;
+#endif
+
+#ifndef kbd_controller_present
+#define kbd_controller_present()	1
+#endif
+static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char handle_kbd_event(void);
+
+/* used only by send_data - set by keyboard_interrupt */
+static volatile unsigned char reply_expected;
+static volatile unsigned char acknowledge;
+static volatile unsigned char resend;
+
+
+#if defined CONFIG_PSMOUSE
+/*
+ *	PS/2 Auxiliary Device
+ */
+
+static int __init psaux_init(void);
+
+#define AUX_RECONNECT1 0xaa	/* scancode1 when ps2 device is plugged (back) in */
+#define AUX_RECONNECT2 0x00	/* scancode2 when ps2 device is plugged (back) in */
+ 
+static struct aux_queue *queue;	/* Mouse data buffer. */
+static int aux_count;
+/* used when we send commands to the mouse that expect an ACK. */
+static unsigned char mouse_reply_expected;
+
+#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
+#define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
+
+#define MAX_RETRIES	60		/* some aux operations take long time*/
+#endif /* CONFIG_PSMOUSE */
+
+/*
+ * Wait for keyboard controller input buffer to drain.
+ *
+ * Don't use 'jiffies' so that we don't depend on
+ * interrupts..
+ *
+ * Quote from PS/2 System Reference Manual:
+ *
+ * "Address hex 0060 and address hex 0064 should be written only when
+ * the input-buffer-full bit and output-buffer-full bit in the
+ * Controller Status register are set 0."
+ */
+
+static void kb_wait(void)
+{
+	unsigned long timeout = KBC_TIMEOUT;
+
+	do {
+		/*
+		 * "handle_kbd_event()" will handle any incoming events
+		 * while we wait - keypresses or mouse movement.
+		 */
+		unsigned char status = handle_kbd_event();
+
+		if (! (status & KBD_STAT_IBF))
+			return;
+		mdelay(1);
+		timeout--;
+	} while (timeout);
+#ifdef KBD_REPORT_TIMEOUTS
+	printk(KERN_WARNING "Keyboard timed out[1]\n");
+#endif
+}
+
+/*
+ * Translation of escaped scancodes to keycodes.
+ * This is now user-settable.
+ * The keycodes 1-88,96-111,119 are fairly standard, and
+ * should probably not be changed - changing might confuse X.
+ * X also interprets scancode 0x5d (KEY_Begin).
+ *
+ * For 1-88 keycode equals scancode.
+ */
+
+#define E0_KPENTER 96
+#define E0_RCTRL   97
+#define E0_KPSLASH 98
+#define E0_PRSCR   99
+#define E0_RALT    100
+#define E0_BREAK   101  /* (control-pause) */
+#define E0_HOME    102
+#define E0_UP      103
+#define E0_PGUP    104
+#define E0_LEFT    105
+#define E0_RIGHT   106
+#define E0_END     107
+#define E0_DOWN    108
+#define E0_PGDN    109
+#define E0_INS     110
+#define E0_DEL     111
+
+#define E1_PAUSE   119
+
+/*
+ * The keycodes below are randomly located in 89-95,112-118,120-127.
+ * They could be thrown away (and all occurrences below replaced by 0),
+ * but that would force many users to use the `setkeycodes' utility, where
+ * they needed not before. It does not matter that there are duplicates, as
+ * long as no duplication occurs for any single keyboard.
+ */
+#define SC_LIM 89
+
+#define FOCUS_PF1 85           /* actual code! */
+#define FOCUS_PF2 89
+#define FOCUS_PF3 90
+#define FOCUS_PF4 91
+#define FOCUS_PF5 92
+#define FOCUS_PF6 93
+#define FOCUS_PF7 94
+#define FOCUS_PF8 95
+#define FOCUS_PF9 120
+#define FOCUS_PF10 121
+#define FOCUS_PF11 122
+#define FOCUS_PF12 123
+
+#define JAP_86     124
+/* tfj@olivia.ping.dk:
+ * The four keys are located over the numeric keypad, and are
+ * labelled A1-A4. It's an rc930 keyboard, from
+ * Regnecentralen/RC International, Now ICL.
+ * Scancodes: 59, 5a, 5b, 5c.
+ */
+#define RGN1 124
+#define RGN2 125
+#define RGN3 126
+#define RGN4 127
+
+static unsigned char high_keys[128 - SC_LIM] = {
+  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
+  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
+  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
+  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
+  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
+};
+
+/* BTC */
+#define E0_MACRO   112
+/* LK450 */
+#define E0_F13     113
+#define E0_F14     114
+#define E0_HELP    115
+#define E0_DO      116
+#define E0_F17     117
+#define E0_KPMINPLUS 118
+/*
+ * My OmniKey generates e0 4c for  the "OMNI" key and the
+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
+ */
+#define E0_OK	124
+/*
+ * New microsoft keyboard is rumoured to have
+ * e0 5b (left window button), e0 5c (right window button),
+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
+ * [or: Windows_L, Windows_R, TaskMan]
+ */
+#define E0_MSLW	125
+#define E0_MSRW	126
+#define E0_MSTM	127
+
+static unsigned char e0_keys[128] = {
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x00-0x07 */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x08-0x0f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x10-0x17 */
+  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,	      /* 0x18-0x1f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x20-0x27 */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x28-0x2f */
+  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,	      /* 0x30-0x37 */
+  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,	      /* 0x38-0x3f */
+  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,	      /* 0x40-0x47 */
+  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
+  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,	      /* 0x50-0x57 */
+  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,	      /* 0x58-0x5f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x60-0x67 */
+  0, 0, 0, 0, 0, 0, 0, E0_MACRO,		      /* 0x68-0x6f */
+  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x70-0x77 */
+  0, 0, 0, 0, 0, 0, 0, 0			      /* 0x78-0x7f */
+};
+
+int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+	if (scancode < SC_LIM || scancode > 255 || keycode > 127)
+	  return -EINVAL;
+	if (scancode < 128)
+	  high_keys[scancode - SC_LIM] = keycode;
+	else
+	  e0_keys[scancode - 128] = keycode;
+	return 0;
+}
+
+int pckbd_getkeycode(unsigned int scancode)
+{
+	return
+	  (scancode < SC_LIM || scancode > 255) ? -EINVAL :
+	  (scancode < 128) ? high_keys[scancode - SC_LIM] :
+	    e0_keys[scancode - 128];
+}
+
+static int do_acknowledge(unsigned char scancode)
+{
+	if (reply_expected) {
+	  /* Unfortunately, we must recognise these codes only if we know they
+	   * are known to be valid (i.e., after sending a command), because there
+	   * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
+	   * keys with such codes :(
+	   */
+		if (scancode == KBD_REPLY_ACK) {
+			acknowledge = 1;
+			reply_expected = 0;
+			return 0;
+		} else if (scancode == KBD_REPLY_RESEND) {
+			resend = 1;
+			reply_expected = 0;
+			return 0;
+		}
+		/* Should not happen... */
+#if 0
+		printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
+		       scancode);
+#endif
+	}
+	return 1;
+}
+
+int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+		    char raw_mode)
+{
+	static int prev_scancode;
+
+	/* special prefix scancodes.. */
+	if (scancode == 0xe0 || scancode == 0xe1) {
+		prev_scancode = scancode;
+		return 0;
+	}
+
+	/* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
+	if (scancode == 0x00 || scancode == 0xff) {
+		prev_scancode = 0;
+		return 0;
+	}
+
+	scancode &= 0x7f;
+
+	if (prev_scancode) {
+	  /*
+	   * usually it will be 0xe0, but a Pause key generates
+	   * e1 1d 45 e1 9d c5 when pressed, and nothing when released
+	   */
+	  if (prev_scancode != 0xe0) {
+	      if (prev_scancode == 0xe1 && scancode == 0x1d) {
+		  prev_scancode = 0x100;
+		  return 0;
+	      } else if (prev_scancode == 0x100 && scancode == 0x45) {
+		  *keycode = E1_PAUSE;
+		  prev_scancode = 0;
+	      } else {
+#ifdef KBD_REPORT_UNKN
+		  if (!raw_mode)
+		    printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
+#endif
+		  prev_scancode = 0;
+		  return 0;
+	      }
+	  } else {
+	      prev_scancode = 0;
+	      /*
+	       *  The keyboard maintains its own internal caps lock and
+	       *  num lock statuses. In caps lock mode E0 AA precedes make
+	       *  code and E0 2A follows break code. In num lock mode,
+	       *  E0 2A precedes make code and E0 AA follows break code.
+	       *  We do our own book-keeping, so we will just ignore these.
+	       */
+	      /*
+	       *  For my keyboard there is no caps lock mode, but there are
+	       *  both Shift-L and Shift-R modes. The former mode generates
+	       *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
+	       *  So, we should also ignore the latter. - aeb@cwi.nl
+	       */
+	      if (scancode == 0x2a || scancode == 0x36)
+		return 0;
+
+	      if (e0_keys[scancode])
+		*keycode = e0_keys[scancode];
+	      else {
+#ifdef KBD_REPORT_UNKN
+		  if (!raw_mode)
+		    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
+			   scancode);
+#endif
+		  return 0;
+	      }
+	  }
+	} else if (scancode >= SC_LIM) {
+	    /* This happens with the FOCUS 9000 keyboard
+	       Its keys PF1..PF12 are reported to generate
+	       55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
+	       Moreover, unless repeated, they do not generate
+	       key-down events, so we have to zero up_flag below */
+	    /* Also, Japanese 86/106 keyboards are reported to
+	       generate 0x73 and 0x7d for \ - and \ | respectively. */
+	    /* Also, some Brazilian keyboard is reported to produce
+	       0x73 and 0x7e for \ ? and KP-dot, respectively. */
+
+	  *keycode = high_keys[scancode - SC_LIM];
+
+	  if (!*keycode) {
+	      if (!raw_mode) {
+#ifdef KBD_REPORT_UNKN
+		  printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
+			 " - ignored\n", scancode);
+#endif
+	      }
+	      return 0;
+	  }
+ 	} else
+	  *keycode = scancode;
+ 	return 1;
+}
+
+char pckbd_unexpected_up(unsigned char keycode)
+{
+	/* unexpected, but this can happen: maybe this was a key release for a
+	   FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
+	if (keycode >= SC_LIM || keycode == 85)
+	    return 0;
+	else
+	    return 0200;
+}
+
+int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data) 
+{
+#if defined CONFIG_PSMOUSE
+       unsigned long flags;
+
+       if (rqst == PM_RESUME) {
+               if (queue) {                    /* Aux port detected */
+                       if (aux_count == 0) {   /* Mouse not in use */ 
+                               spin_lock_irqsave(&kbd_controller_lock, flags);
+			       /*
+				* Dell Lat. C600 A06 enables mouse after resume.
+				* When user touches the pad, it posts IRQ 12
+				* (which we do not process), thus holding keyboard.
+				*/
+			       kbd_write_command(KBD_CCMD_MOUSE_DISABLE);
+			       /* kbd_write_cmd(AUX_INTS_OFF); */ /* Config & lock */
+			       kb_wait();
+			       kbd_write_command(KBD_CCMD_WRITE_MODE);
+			       kb_wait();
+			       kbd_write_output(AUX_INTS_OFF);
+			       spin_unlock_irqrestore(&kbd_controller_lock, flags);
+		       }
+	       }
+       }
+#endif
+       return 0;
+}
+
+
+static inline void handle_mouse_event(unsigned char scancode)
+{
+#ifdef CONFIG_PSMOUSE
+	static unsigned char prev_code;
+	if (mouse_reply_expected) {
+		if (scancode == AUX_ACK) {
+			mouse_reply_expected--;
+			return;
+		}
+		mouse_reply_expected = 0;
+	}
+	else if(scancode == AUX_RECONNECT2 && prev_code == AUX_RECONNECT1
+		&& aux_reconnect) {
+		printk (KERN_INFO "PS/2 mouse reconnect detected\n");
+		queue->head = queue->tail = 0;	/* Flush input queue */
+		__aux_write_ack(AUX_ENABLE_DEV);  /* ping the mouse :) */
+		return;
+	}
+
+	prev_code = scancode;
+	add_mouse_randomness(scancode);
+	if (aux_count) {
+		int head = queue->head;
+
+		queue->buf[head] = scancode;
+		head = (head + 1) & (AUX_BUF_SIZE-1);
+		if (head != queue->tail) {
+			queue->head = head;
+			kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+			wake_up_interruptible(&queue->proc_list);
+		}
+	}
+#endif
+}
+
+static unsigned char kbd_exists = 1;
+
+void handle_keyboard_event(unsigned char scancode)
+{
+#ifdef CONFIG_VT
+	kbd_exists = 1;
+	if (do_acknowledge(scancode))
+		handle_scancode(scancode, !(scancode & 0x80));
+#endif				
+	tasklet_schedule(&keyboard_tasklet);
+}	
+
+/*
+ * This reads the keyboard status port, and does the
+ * appropriate action.
+ *
+ * It requires that we hold the keyboard controller
+ * spinlock.
+ */
+static unsigned char handle_kbd_event(void)
+{
+	unsigned char scancode;
+	co_linux_message_t *message;
+
+	while (co_get_message(&message, CO_DEVICE_KEYBOARD)) {
+		co_scan_code_t *sc = (co_scan_code_t *)message->data;
+		unsigned long scancode = sc->code;
+
+		if (!sc->down)
+			scancode |= 0x80;
+		
+		handle_keyboard_event(scancode);
+
+		co_free_message(message);
+	}
+
+	return 0;
+}
+
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+#ifdef CONFIG_VT
+	kbd_pt_regs = regs;
+#endif
+
+	spin_lock_irq(&kbd_controller_lock);
+	handle_kbd_event();
+	spin_unlock_irq(&kbd_controller_lock);
+}
+
+/*
+ * send_data sends a character to the keyboard and waits
+ * for an acknowledge, possibly retrying if asked to. Returns
+ * the success status.
+ *
+ * Don't use 'jiffies', so that we don't depend on interrupts
+ */
+static int send_data(unsigned char data)
+{
+	return 0;
+}
+
+void pckbd_leds(unsigned char leds)
+{
+	if (kbd_exists && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) {
+		send_data(KBD_CMD_ENABLE);	/* re-enable kbd if any errors */
+		kbd_exists = 0;
+	}
+}
+
+#define DEFAULT_KEYB_REP_DELAY	250
+#define DEFAULT_KEYB_REP_RATE	30	/* cps */
+
+static struct kbd_repeat kbdrate={
+	DEFAULT_KEYB_REP_DELAY,
+	DEFAULT_KEYB_REP_RATE
+};
+
+static unsigned char parse_kbd_rate(struct kbd_repeat *r)
+{
+	static struct r2v{
+		int rate;
+		unsigned char val;
+	} kbd_rates[]={	{5,0x14},
+			{7,0x10},
+			{10,0x0c},
+			{15,0x08},
+			{20,0x04},
+			{25,0x02},
+			{30,0x00}
+	};
+	static struct d2v{
+		int delay;
+		unsigned char val;
+	} kbd_delays[]={{250,0},
+			{500,1},
+			{750,2},
+			{1000,3}
+	};
+	int rate=0,delay=0;
+	if (r != NULL){
+		int i,new_rate=30,new_delay=250;
+		if (r->rate <= 0)
+			r->rate=kbdrate.rate;
+		if (r->delay <= 0)
+			r->delay=kbdrate.delay;
+		for (i=0; i < sizeof(kbd_rates)/sizeof(struct r2v); i++)
+			if (kbd_rates[i].rate == r->rate){
+				new_rate=kbd_rates[i].rate;
+				rate=kbd_rates[i].val;
+				break;
+			}
+		for (i=0; i < sizeof(kbd_delays)/sizeof(struct d2v); i++)
+			if (kbd_delays[i].delay == r->delay){
+				new_delay=kbd_delays[i].delay;
+				delay=kbd_delays[i].val;
+				break;
+			}
+		r->rate=new_rate;
+		r->delay=new_delay;
+	}
+	return (delay << 5) | rate;
+}
+
+static int write_kbd_rate(unsigned char r)
+{
+	if (!send_data(KBD_CMD_SET_RATE) || !send_data(r)){
+		send_data(KBD_CMD_ENABLE); 	/* re-enable kbd if any errors */
+		return 0;
+	}else
+		return 1;
+}
+
+static int pckbd_rate(struct kbd_repeat *rep)
+{
+	if (rep == NULL)
+		return -EINVAL;
+	else{
+		unsigned char r=parse_kbd_rate(rep);
+		struct kbd_repeat old_rep;
+		memcpy(&old_rep,&kbdrate,sizeof(struct kbd_repeat));
+		if (write_kbd_rate(r)){
+			memcpy(&kbdrate,rep,sizeof(struct kbd_repeat));
+			memcpy(rep,&old_rep,sizeof(struct kbd_repeat));
+			return 0;
+		}
+	}
+	return -EIO;
+}
+
+/*
+ * In case we run on a non-x86 hardware we need to initialize both the
+ * keyboard controller and the keyboard.  On a x86, the BIOS will
+ * already have initialized them.
+ *
+ * Some x86 BIOSes do not correctly initialize the keyboard, so the
+ * "kbd-reset" command line options can be given to force a reset.
+ * [Ranger]
+ */
+#ifdef __i386__
+ int kbd_startup_reset __initdata = 0;
+#else
+ int kbd_startup_reset __initdata = 1;
+#endif
+
+/* for "kbd-reset" cmdline param */
+static int __init kbd_reset_setup(char *str)
+{
+	kbd_startup_reset = 1;
+	return 1;
+}
+
+__setup("kbd-reset", kbd_reset_setup);
+
+#define KBD_NO_DATA	(-1)	/* No data */
+#define KBD_BAD_DATA	(-2)	/* Parity or other error */
+
+static int __init kbd_read_data(void)
+{
+	int retval = KBD_NO_DATA;
+
+#if (0)
+	status = kbd_read_status();
+	if (status & KBD_STAT_OBF) {
+		unsigned char data = kbd_read_input();
+
+		retval = data;
+		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
+			retval = KBD_BAD_DATA;
+	}
+#endif
+	return retval;
+}
+
+static void __init kbd_clear_input(void)
+{
+	int maxread = 100;	/* Random number */
+
+	do {
+		if (kbd_read_data() == KBD_NO_DATA)
+			break;
+	} while (--maxread);
+}
+
+static int __init kbd_wait_for_input(void)
+{
+	long timeout = KBD_INIT_TIMEOUT;
+
+	do {
+		int retval = kbd_read_data();
+		if (retval >= 0)
+			return retval;
+		mdelay(1);
+	} while (--timeout);
+	return -1;
+}
+
+static void kbd_write_command_w(int data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_command(data);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
+static void kbd_write_output_w(int data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_output(data);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
+#if defined(__alpha__)
+/*
+ * Some Alphas cannot mask some/all interrupts, so we have to
+ * make sure not to allow interrupts AT ALL when polling for
+ * specific return values from the keyboard.
+ *
+ * I think this should work on any architecture, but for now, only Alpha.
+ */
+static int kbd_write_command_w_and_wait(int data)
+{
+	unsigned long flags;
+	int input;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_command(data);
+	input = kbd_wait_for_input();
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+	return input;
+}
+
+static int kbd_write_output_w_and_wait(int data)
+{
+	unsigned long flags;
+	int input;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_output(data);
+	input = kbd_wait_for_input();
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+	return input;
+}
+#else
+static int kbd_write_command_w_and_wait(int data)
+{
+	kbd_write_command_w(data);
+	return kbd_wait_for_input();
+}
+
+static int kbd_write_output_w_and_wait(int data)
+{
+	kbd_write_output_w(data);
+	return kbd_wait_for_input();
+}
+#endif /* __alpha__ */
+
+#if defined CONFIG_PSMOUSE
+static void kbd_write_cmd(int cmd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_command(KBD_CCMD_WRITE_MODE);
+	kb_wait();
+	kbd_write_output(cmd);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+#endif /* CONFIG_PSMOUSE */
+
+static char * __init initialize_kbd(void)
+{
+	int status;
+
+	/*
+	 * Test the keyboard interface.
+	 * This seems to be the only way to get it going.
+	 * If the test is successful a x55 is placed in the input buffer.
+	 */
+	kbd_write_command_w(KBD_CCMD_SELF_TEST);
+	if (kbd_wait_for_input() != 0x55)
+		return "Keyboard failed self test";
+
+	/*
+	 * Perform a keyboard interface test.  This causes the controller
+	 * to test the keyboard clock and data lines.  The results of the
+	 * test are placed in the input buffer.
+	 */
+	kbd_write_command_w(KBD_CCMD_KBD_TEST);
+	if (kbd_wait_for_input() != 0x00)
+		return "Keyboard interface failed self test";
+
+	/*
+	 * Enable the keyboard by allowing the keyboard clock to run.
+	 */
+	kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
+
+	/*
+	 * Reset keyboard. If the read times out
+	 * then the assumption is that no keyboard is
+	 * plugged into the machine.
+	 * This defaults the keyboard to scan-code set 2.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write_output_w(KBD_CMD_RESET);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+			return "Keyboard reset failed, no ACK";
+	} while (1);
+
+	if (kbd_wait_for_input() != KBD_REPLY_POR)
+		return "Keyboard reset failed, no POR";
+
+	/*
+	 * Set keyboard controller mode. During this, the keyboard should be
+	 * in the disabled state.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write_output_w(KBD_CMD_DISABLE);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+			return "Disable keyboard: no ACK";
+	} while (1);
+
+	kbd_write_command_w(KBD_CCMD_WRITE_MODE);
+	kbd_write_output_w(KBD_MODE_KBD_INT
+			      | KBD_MODE_SYS
+			      | KBD_MODE_DISABLE_MOUSE
+			      | KBD_MODE_KCC);
+
+	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
+	if (!(kbd_write_command_w_and_wait(KBD_CCMD_READ_MODE) & KBD_MODE_KCC))
+	{
+		/*
+		 * If the controller does not support conversion,
+		 * Set the keyboard to scan-code set 1.
+		 */
+		kbd_write_output_w(0xF0);
+		kbd_wait_for_input();
+		kbd_write_output_w(0x01);
+		kbd_wait_for_input();
+	}
+
+	if (kbd_write_output_w_and_wait(KBD_CMD_ENABLE) != KBD_REPLY_ACK)
+		return "Enable keyboard: no ACK";
+
+	/*
+	 * Finally, set the typematic rate to maximum.
+	 */
+	if (kbd_write_output_w_and_wait(KBD_CMD_SET_RATE) != KBD_REPLY_ACK)
+		return "Set rate: no ACK";
+	if (kbd_write_output_w_and_wait(0x00) != KBD_REPLY_ACK)
+		return "Set rate: no 2nd ACK";
+
+	return NULL;
+}
+
+void __init pckbd_init_hw(void)
+{
+	if (!kbd_controller_present()) {
+		kbd_exists = 0;
+		return;
+	}
+
+	kbd_request_region();
+
+	/* Flush any pending input. */
+	kbd_clear_input();
+
+	if (kbd_startup_reset) {
+		char *msg = initialize_kbd();
+		if (msg)
+			printk(KERN_WARNING "initialize_kbd: %s\n", msg);
+	}
+
+#if defined CONFIG_PSMOUSE
+	psaux_init();
+#endif
+
+	kbd_rate = pckbd_rate;
+
+	/* Ok, finally allocate the IRQ, and off we go.. */
+	kbd_request_irq(keyboard_interrupt);
+}
+
+#if defined CONFIG_PSMOUSE
+
+static int __init aux_reconnect_setup (char *str)
+{
+	aux_reconnect = 1;
+	return 1;
+}
+
+__setup("psaux-reconnect", aux_reconnect_setup);
+
+/*
+ * Check if this is a dual port controller.
+ */
+static int __init detect_auxiliary_port(void)
+{
+	unsigned long flags;
+	int loops = 10;
+	int retval = 0;
+
+	/* Check if the BIOS detected a device on the auxiliary port. */
+	if (aux_device_present == 0xaa)
+		return 1;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+
+	/* Put the value 0x5A in the output buffer using the "Write
+	 * Auxiliary Device Output Buffer" command (0xD3). Poll the
+	 * Status Register for a while to see if the value really
+	 * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
+	 * bit is also set to 1 in the Status Register, we assume this
+	 * controller has an Auxiliary Port (a.k.a. Mouse Port).
+	 */
+	kb_wait();
+	kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
+
+	kb_wait();
+	kbd_write_output(0x5a); /* 0x5a is a random dummy value. */
+
+	do {
+		unsigned char status = kbd_read_status();
+
+		if (status & KBD_STAT_OBF) {
+			(void) kbd_read_input();
+			if (status & KBD_STAT_MOUSE_OBF) {
+				printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
+				retval = 1;
+			}
+			break;
+		}
+		mdelay(1);
+	} while (--loops);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+
+	return retval;
+}
+
+/*
+ * Send a byte to the mouse.
+ */
+static void aux_write_dev(int val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+	kb_wait();
+	kbd_write_output(val);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
+/*
+ * Send a byte to the mouse & handle returned ack
+ */
+static void __aux_write_ack(int val)
+{
+	kb_wait();
+	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+	kb_wait();
+	kbd_write_output(val);
+	/* we expect an ACK in response. */
+	mouse_reply_expected++;
+	kb_wait();
+}
+
+static void aux_write_ack(int val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	__aux_write_ack(val);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
+static unsigned char get_from_queue(void)
+{
+	unsigned char result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	result = queue->buf[queue->tail];
+	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+	return result;
+}
+
+
+static inline int queue_empty(void)
+{
+	return queue->head == queue->tail;
+}
+
+static int fasync_aux(int fd, struct file *filp, int on)
+{
+	int retval;
+
+	retval = fasync_helper(fd, filp, on, &queue->fasync);
+	if (retval < 0)
+		return retval;
+	return 0;
+}
+
+
+/*
+ * Random magic cookie for the aux device
+ */
+#define AUX_DEV ((void *)queue)
+
+static int release_aux(struct inode * inode, struct file * file)
+{
+	lock_kernel();
+	fasync_aux(-1, file, 0);
+	if (--aux_count) {
+		unlock_kernel();
+		return 0;
+	}
+	kbd_write_cmd(AUX_INTS_OFF);			    /* Disable controller ints */
+	kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
+	aux_free_irq(AUX_DEV);
+	unlock_kernel();
+	return 0;
+}
+
+/*
+ * Install interrupt handler.
+ * Enable auxiliary device.
+ */
+
+static int open_aux(struct inode * inode, struct file * file)
+{
+	if (aux_count++) {
+		return 0;
+	}
+	queue->head = queue->tail = 0;		/* Flush input queue */
+	if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
+		aux_count--;
+		return -EBUSY;
+	}
+	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE);	/* Enable the
+							   auxiliary port on
+							   controller. */
+	aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
+	kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
+	
+	mdelay(2);			/* Ensure we follow the kbc access delay rules.. */
+
+	send_data(KBD_CMD_ENABLE);	/* try to workaround toshiba4030cdt problem */
+
+	return 0;
+}
+
+/*
+ * Put bytes from input queue to buffer.
+ */
+
+static ssize_t read_aux(struct file * file, char * buffer,
+			size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t i = count;
+	unsigned char c;
+
+	if (queue_empty()) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		add_wait_queue(&queue->proc_list, &wait);
+repeat:
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (queue_empty() && !signal_pending(current)) {
+			schedule();
+			goto repeat;
+		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&queue->proc_list, &wait);
+	}
+	while (i > 0 && !queue_empty()) {
+		c = get_from_queue();
+		put_user(c, buffer++);
+		i--;
+	}
+	if (count-i) {
+		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+		return count-i;
+	}
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	return 0;
+}
+
+/*
+ * Write to the aux device.
+ */
+
+static ssize_t write_aux(struct file * file, const char * buffer,
+			 size_t count, loff_t *ppos)
+{
+	ssize_t retval = 0;
+
+	if (count) {
+		ssize_t written = 0;
+
+		if (count > 32)
+			count = 32; /* Limit to 32 bytes. */
+		do {
+			char c;
+			get_user(c, buffer++);
+			aux_write_dev(c);
+			written++;
+		} while (--count);
+		retval = -EIO;
+		if (written) {
+			retval = written;
+			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
+		}
+	}
+
+	return retval;
+}
+
+/* No kernel lock held - fine */
+static unsigned int aux_poll(struct file *file, poll_table * wait)
+{
+	poll_wait(file, &queue->proc_list, wait);
+	if (!queue_empty())
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+struct file_operations psaux_fops = {
+	read:		read_aux,
+	write:		write_aux,
+	poll:		aux_poll,
+	open:		open_aux,
+	release:	release_aux,
+	fasync:		fasync_aux,
+};
+
+/*
+ * Initialize driver.
+ */
+static struct miscdevice psaux_mouse = {
+	PSMOUSE_MINOR, "psaux", &psaux_fops
+};
+
+static int __init psaux_init(void)
+{
+	int retval;
+
+	if (!detect_auxiliary_port())
+		return -EIO;
+
+	if ((retval = misc_register(&psaux_mouse)))
+		return retval;
+
+	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+	if (queue == NULL) {
+		printk(KERN_ERR "psaux_init(): out of memory\n");
+		misc_deregister(&psaux_mouse);
+		return -ENOMEM;
+	}
+	memset(queue, 0, sizeof(*queue));
+	queue->head = queue->tail = 0;
+	init_waitqueue_head(&queue->proc_list);
+
+#ifdef INITIALIZE_MOUSE
+	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
+	aux_write_ack(AUX_SET_SAMPLE);
+	aux_write_ack(100);			/* 100 samples/sec */
+	aux_write_ack(AUX_SET_RES);
+	aux_write_ack(3);			/* 8 counts per mm */
+	aux_write_ack(AUX_SET_SCALE21);		/* 2:1 scaling */
+#endif /* INITIALIZE_MOUSE */
+	kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
+	kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
+
+	return 0;
+}
+
+#endif /* CONFIG_PSMOUSE */
+
+
+static int blink_frequency = HZ/2;
+
+/* Tell the user who may be running in X and not see the console that we have 
+   panic'ed. This is to distingush panics from "real" lockups. 
+   Could in theory send the panic message as morse, but that is left as an
+   exercise for the reader.  */ 
+void panic_blink(void)
+{ 
+	static unsigned long last_jiffie;
+	static char led;
+	/* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is 
+	   different. */
+	if (!blink_frequency) 
+		return;
+	if (jiffies - last_jiffie > blink_frequency) {
+		led ^= 0x01 | 0x04;
+		while (kbd_read_status() & KBD_STAT_IBF) mdelay(1); 
+		kbd_write_output(KBD_CMD_SET_LEDS);
+		mdelay(1); 
+		while (kbd_read_status() & KBD_STAT_IBF) mdelay(1); 
+		mdelay(1); 
+		kbd_write_output(led);
+		last_jiffie = jiffies;
+	}
+}  
+
+static int __init panicblink_setup(char *str)
+{
+    int par;
+    if (get_option(&str,&par)) 
+	    blink_frequency = par*(1000/HZ);
+    return 1;
+}
+
+/* panicblink=0 disables the blinking as it caused problems with some console
+   switches. otherwise argument is ms of a blink period. */
+__setup("panicblink=", panicblink_setup);
+
--- linux-2.4.28/drivers/char/mem.c~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/drivers/char/mem.c	2004-11-27 15:59:21.304007320 -0500
@@ -667,20 +667,24 @@
 static int memory_open(struct inode * inode, struct file * filp)
 {
 	switch (MINOR(inode->i_rdev)) {
+#ifndef CONFIG_COOPERATIVE
 		case 1:
 			filp->f_op = &mem_fops;
 			break;
 		case 2:
 			filp->f_op = &kmem_fops;
 			break;
+#endif
 		case 3:
 			filp->f_op = &null_fops;
 			break;
+#ifndef CONFIG_COOPERATIVE
 #if defined(CONFIG_ISA) || !defined(__mc68000__)
 		case 4:
 			filp->f_op = &port_fops;
 			break;
 #endif
+#endif
 		case 5:
 			filp->f_op = &zero_fops;
 			break;
@@ -710,12 +714,16 @@
 	umode_t mode;
 	struct file_operations *fops;
     } list[] = { /* list of minor devices */
+#ifndef CONFIG_COOPERATIVE
 	{1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
 	{2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
+#endif
 	{3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
+#ifndef CONFIG_COOPERATIVE
 #if defined(CONFIG_ISA) || !defined(__mc68000__)
 	{4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
 #endif
+#endif
 	{5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
 	{7, "full",    S_IRUGO | S_IWUGO,           &full_fops},
 	{8, "random",  S_IRUGO | S_IWUSR,           &random_fops},
--- linux-2.4.28/drivers/char/vt.c~colinux-0.6.1	2002-11-28 18:53:12.000000000 -0500
+++ linux-2.4.28/drivers/char/vt.c	2004-11-27 15:59:21.305007168 -0500
@@ -90,10 +90,10 @@
  * comments - KDMKTONE doesn't put the process to sleep.
  */
 
-#if defined(__i386__) || defined(__alpha__) || defined(CONFIG_PPC_ISATIMER) \
-    || (defined(__mips__) && defined(CONFIG_ISA)) \
-    || (defined(__arm__) && defined(CONFIG_HOST_FOOTBRIDGE)) \
-    || defined(__x86_64__)
+#if (defined(__i386__) || defined(__alpha__) || defined(CONFIG_PPC_ISATIMER) \
+     || (defined(__mips__) && defined(CONFIG_ISA))			\
+     || (defined(__arm__) && defined(CONFIG_HOST_FOOTBRIDGE))		\
+     || defined(__x86_64__)) && !defined(CONFIG_COOPERATIVE)
 
 static void
 kd_nosound(unsigned long ignored)
--- linux-2.4.28/drivers/net/Config.in~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/drivers/net/Config.in	2004-11-27 15:59:21.306007016 -0500
@@ -287,6 +287,10 @@
    dep_tristate 'iSeries Virtual Ethernet driver support' CONFIG_VETH $CONFIG_PPC_ISERIES
 fi
 
+if [ "$CONFIG_COOPERATIVE" = "y" ]; then
+   tristate 'Coooperative Virtual Ethernet driver support' CONFIG_COOPERATIVE_CONET
+fi
+
 if [ "$CONFIG_4xx" = "y" ]; then
    source drivers/net/ibm_emac/Config.in
 fi
--- linux-2.4.28/drivers/net/Makefile~colinux-0.6.1	2004-08-07 19:26:04.000000000 -0400
+++ linux-2.4.28/drivers/net/Makefile	2004-11-27 15:59:21.306007016 -0500
@@ -212,6 +212,7 @@
 
 # This is also a 82596 and should probably be merged
 obj-$(CONFIG_LP486E) += lp486e.o
+obj-$(CONFIG_COOPERATIVE_CONET) += conet.o
 
 obj-$(CONFIG_ETH16I) += eth16i.o
 obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
--- /dev/null	2004-04-06 13:56:48.000000000 -0400
+++ linux-2.4.28/drivers/net/conet.c	2004-11-27 15:59:21.307006864 -0500
@@ -0,0 +1,309 @@
+/*
+ *  Copyright (C) 2003-2004 Dan Aloni <da-x@gmx.net>
+ *  Copyright (C) 2004 Pat Erley
+ *  Copyright (C) 2004 George Boutwell
+ *
+ *  Cooperative Linux Network Device implementation
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+
+#include <linux/cooperative.h>
+#include <asm/irq.h>
+
+struct conet_priv {
+	struct net_device_stats stats;
+	co_linux_message_t *message;
+	int status;
+	int unit;
+	int enabled;
+};
+
+struct net_device *conet_dev[CO_MODULE_MAX_CONET];
+
+void conet_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr);
+
+static int conet_get_mac(int unit, char *address)
+{
+	unsigned long flags = 0;
+	co_network_request_t *net_request;
+	int result = 0;
+
+	local_irq_save(flags);
+	co_passage_page->operation = CO_OPERATION_DEVICE;
+	co_passage_page->params[0] = CO_DEVICE_NETWORK;
+	net_request = (typeof(net_request))&co_passage_page->params[1];
+	net_request->unit = unit;
+	net_request->type = CO_NETWORK_GET_MAC;
+	co_switch_wrapper();
+	memcpy(address, net_request->mac_address, ETH_ALEN);
+	result = net_request->result;
+	local_irq_restore(flags);
+
+	return result;
+}
+
+int conet_open(struct net_device *dev)
+{
+	struct conet_priv *priv = (struct conet_priv *)dev->priv;
+
+	if (priv->enabled)
+		return 0;
+
+	MOD_INC_USE_COUNT;
+
+	conet_get_mac(priv->unit, dev->dev_addr);
+
+	priv->enabled = 1;
+	
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+int conet_stop(struct net_device *dev)
+{
+	struct conet_priv *priv = (struct conet_priv *)dev->priv;
+
+	priv->enabled = 0;
+
+	netif_stop_queue(dev); /* can't transmit any more */
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+int conet_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int len;
+	char *data;
+	struct conet_priv *priv = (struct conet_priv *)dev->priv;
+
+	len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+	data = skb->data;
+
+	dev->trans_start = jiffies; /* save the timestamp */
+
+	co_send_message(CO_MODULE_LINUX, 
+			CO_MODULE_CONET0 + priv->unit,
+			CO_PRIORITY_DISCARDABLE,
+			CO_MESSAGE_TYPE_OTHER,
+			len,
+			data);
+
+	priv->stats.tx_bytes+=skb->len;
+	priv->stats.tx_packets++;
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+void conet_rx(struct net_device *dev)
+{
+	struct sk_buff *skb;
+	struct conet_priv *priv = (struct conet_priv *)dev->priv;
+	int len;
+	unsigned char *buf;
+	co_linux_message_t *message;
+	
+	message = priv->message;
+	if (message == NULL) {
+		printk("conet rx: no message\n");
+		return;
+	}
+
+	priv->message = NULL;
+
+	len = message->size;
+	buf = message->data;
+
+	/*
+	 * The packet has been retrieved from the transmission
+	 * medium. Build an skb around it, so upper layers can handle it
+	 */
+	skb = dev_alloc_skb(len+2);
+	if (!skb) {
+		printk("conet rx: low on mem - packet dropped\n");
+		priv->stats.rx_dropped++;
+		co_free_message(message);
+		return;
+	}
+
+	memcpy(skb_put(skb, len), buf, len);
+
+	/* Write metadata, and then pass to the receive level */
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
+
+	priv->stats.rx_bytes += len;
+	priv->stats.rx_packets++;
+
+	netif_rx(skb);
+
+	co_free_message(message);
+	return;
+}
+
+void conet_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
+{	
+	co_linux_message_t *message;
+
+	while (co_get_message(&message, CO_DEVICE_NETWORK)) {
+		struct net_device *dev;
+		struct conet_priv *priv;
+
+		if (message->unit < 0  ||  message->unit >= CO_MODULE_MAX_CONET) {
+			printk("conet intrrupt: buggy network reception\n");
+			return;
+		}
+
+		dev = conet_dev[message->unit];
+		if (!netif_running(dev)) {
+			co_free_message(message);
+			continue;
+		}
+
+		priv = (struct conet_priv *)dev->priv;
+		if (priv->message != NULL) {
+			printk("conet intrrupt: freeing unhandled packet\n");
+			co_free_message(message);
+			continue;
+		}
+		
+		priv->message = message;
+		conet_rx(dev); 
+	}
+}
+
+struct net_device_stats* conet_get_stats(struct net_device *dev)
+{
+	return (struct net_device_stats *)dev->priv;
+}
+
+int conet_init(struct net_device *dev)
+{
+	struct conet_priv *priv = (struct conet_priv *)dev->priv;
+
+	memset(&priv->stats, 0, sizeof(priv->stats));
+	
+	ether_setup(dev);
+
+	dev->open            = conet_open;
+	dev->stop            = conet_stop;
+	dev->hard_start_xmit = conet_hard_start_xmit;
+	dev->get_stats       = conet_get_stats;
+	dev->irq             = NETWORK_IRQ;
+
+	SET_MODULE_OWNER(dev);
+
+	return 0;
+}
+
+void conet_uninit(struct net_device *dev)
+{
+}
+
+static struct net_device *conet_create(int unit)
+{
+	struct net_device *dev;
+	struct conet_priv *priv;
+	int result = 0;
+
+	dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	if (!dev) {
+		return ERR_PTR(-ENOMEM);
+	}
+
+	memset(dev, 0, sizeof(struct net_device));
+
+	priv = kmalloc(sizeof(struct conet_priv), GFP_KERNEL);
+	if (priv == NULL) {
+		kfree(dev);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	memset(priv, 0, sizeof(struct conet_priv));
+	priv->unit = unit;
+
+	dev->priv = priv;
+	dev->init = conet_init;
+	dev->uninit = conet_uninit;
+	strcpy(dev->name, "eth%d");
+
+	result = register_netdev(dev);
+	if (result) {
+		printk("conet: error %d registering device \"%s\"\n", result, dev->name);
+		kfree(dev->priv);
+		kfree(dev);
+		return ERR_PTR(-ENODEV);
+	}
+
+	printk("conet%d: initialized\n", priv->unit);
+
+	return dev;
+}
+
+static void conet_destroy(struct net_device *dev)
+{
+	struct conet_priv *priv = (struct conet_priv *) dev->priv;
+
+	printk("conet%d: freed\n", priv->unit);
+
+	unregister_netdev(dev);
+	kfree(dev->priv);
+	kfree(dev);
+}
+
+static int __init conet_init_module(void)
+{
+	int unit = 0, result;
+	struct net_device *dev;
+	char mac_address[6];
+
+	result = request_irq(NETWORK_IRQ, &conet_interrupt, 0, "conet", NULL);
+	
+	printk("conet: loaded (max %d devices)\n", CO_MODULE_MAX_CONET);
+
+	for (unit=0; unit < CO_MODULE_MAX_CONET; unit++) {
+		conet_dev[unit] = NULL;
+		
+		result = conet_get_mac(unit, mac_address);
+		if (!result)
+			continue;
+		
+		dev = conet_create(unit);
+		if (!IS_ERR(dev)) 
+			conet_dev[unit] = dev;
+	}
+
+	return result;
+}
+
+static void __exit conet_cleanup_module(void)
+{
+	int unit = 0;
+
+	free_irq(NETWORK_IRQ, NULL);
+
+	for (unit=0; unit < CO_MODULE_MAX_CONET; unit++) {
+		if (!conet_dev[unit])
+			continue;
+
+		conet_destroy(conet_dev[unit]);
+	}
+}
+
+module_init(conet_init_module);
+module_exit(conet_cleanup_module);
--- linux-2.4.28/drivers/video/Makefile~colinux-0.6.1	2004-02-18 08:36:31.000000000 -0500
+++ linux-2.4.28/drivers/video/Makefile	2004-11-27 15:59:21.307006864 -0500
@@ -15,7 +15,8 @@
 		  fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \
 		  fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \
 		  fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \
-		  cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o
+		  cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o cocon.o \
+	
 
 # Each configuration option enables a list of files.
 
@@ -23,6 +24,7 @@
 obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o
 obj-$(CONFIG_PROM_CONSOLE)        += promcon.o promcon_tbl.o
 obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
+obj-$(CONFIG_COOPERATIVE_CONSOLE)    += cocon.o
 obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
 
 obj-$(CONFIG_FONT_SUN8x16)        += font_sun8x16.o
--- /dev/null	2004-04-06 13:56:48.000000000 -0400
+++ linux-2.4.28/drivers/video/cocon.c	2004-11-27 15:59:21.308006712 -0500
@@ -0,0 +1,484 @@
+/*
+ *  linux/drivers/video/cocon.c -- Cooperative Linux console VGA driver
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ *  Based on code copied from vgacon.c.
+ *
+ *  Dan Aloni <da-x@gmx.net>, 2003-2004 (c)
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/slab.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/init.h>
+
+#include <linux/cooperative.h>
+
+/*
+ *  Interface used by the world
+ */
+
+static const char *cocon_startup(void);
+static void cocon_init(struct vc_data *c, int init);
+static void cocon_deinit(struct vc_data *c);
+static void cocon_clear(struct vc_data *c, int, int, int, int);
+static void cocon_cursor(struct vc_data *c, int mode);
+static int cocon_switch(struct vc_data *c);
+static int cocon_blank(struct vc_data *c, int blank);
+static int cocon_font_op(struct vc_data *c, struct console_font_op *op);
+static int cocon_set_palette(struct vc_data *c, unsigned char *table);
+static int cocon_scrolldelta(struct vc_data *c, int lines);
+static int cocon_set_origin(struct vc_data *c);
+static void cocon_save_screen(struct vc_data *c);
+static int cocon_scroll(struct vc_data *c, int t, int b, int dir, int lines);
+static u8 cocon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse);
+static void cocon_invert_region(struct vc_data *c, u16 *p, int count);
+
+static const char __init *cocon_startup(void)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_STARTUP;
+	co_send_message_restore(flags);
+
+	return "CoCON";
+}
+
+static void cocon_init(struct vc_data *c, int init)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	/* We cannot be loaded as a module, therefore init is always 1 */
+	c->vc_can_do_color = 1;
+	c->vc_cols = 80;
+	c->vc_rows = 25;
+	c->vc_complement_mask = 0x7700;
+	c->vc_visible_origin = 0;
+	c->vc_origin = 0;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_INIT;
+	co_send_message_restore(flags);
+}
+
+static void cocon_deinit(struct vc_data *c)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_DEINIT;
+	co_send_message_restore(flags);
+
+}
+
+static void cocon_clear(struct vc_data *c, int top, int left, int rows, int cols)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->clear + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_CLEAR;
+	message->clear.top = top;
+	message->clear.left = left;
+	message->clear.bottom = top + rows - 1;
+	message->clear.right = left + cols - 1;
+	message->clear.charattr = c->vc_video_erase_char;
+	co_send_message_restore(flags);
+}
+
+static void cocon_putc(struct vc_data *c, int charattr, int y, int x)
+{
+	unsigned long flags;
+	co_message_t *co_message;
+	co_console_message_t *message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->putc + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_PUTC;
+	message->putc.x = x;
+	message->putc.y = y;
+	message->putc.charattr = charattr;
+	co_send_message_restore(flags);
+}
+
+
+static void cocon_putcs(struct vc_data *conp, 
+			const unsigned short *s, int count, int yy, int xx)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	if (count > CO_MAX_PARAM_SIZE/2 - 16) 
+		return;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->putcs + 1)) - ((char *)message) + 
+		count * sizeof(unsigned short);
+	message->type = CO_OPERATION_CONSOLE_PUTCS;
+	message->putcs.x = xx;
+	message->putcs.y = yy;
+	message->putcs.count = count;
+	memcpy(&message->putcs.data, s, count * sizeof(unsigned short));
+	co_send_message_restore(flags);
+}
+
+static u8 cocon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse)
+{
+	u8 attr = color;
+
+	if (underline)
+		attr = (attr & 0xf0) | c->vc_ulcolor;
+	else if (intensity == 0)
+		attr = (attr & 0xf0) | c->vc_halfcolor;
+	if (reverse)
+		attr = ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) & 0x77);
+	if (blink)
+		attr ^= 0x80;
+	if (intensity == 2)
+		attr ^= 0x08;
+
+	return attr;
+}
+
+static void cocon_invert_region(struct vc_data *c, u16 *p, int count)
+{
+	unsigned long flags;
+	co_message_t *co_message;
+	co_console_message_t *message;
+	unsigned x = p - c->vc_origin ;  // UPDATE: vc_origin = 0; but not yet
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->invert + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_INVERT_REGION;
+	message->invert.y = ((unsigned)x)/c->vc_cols;
+	message->invert.x = ((unsigned)x)-(message->invert.y);
+	message->invert.count = count;
+	co_send_message_restore(flags);
+
+	while (count--) {
+		u16 a = scr_readw(p);
+		a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
+		scr_writew(a, p++);
+        }
+
+}
+
+static void cocon_cursor(struct vc_data *c, int mode)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->cursor + 1)) - ((char *)message);;
+	if (mode==CM_ERASE) {
+		message->type = CO_OPERATION_CONSOLE_CURSOR_ERASE;
+		message->cursor.height = 0;
+		co_send_message_restore(flags);
+		return;
+	}
+
+	if(mode==CM_MOVE) {
+		message->type = CO_OPERATION_CONSOLE_CURSOR_MOVE;
+	} else /*(mode==CM_DRAW)*/ {
+		message->type = CO_OPERATION_CONSOLE_CURSOR_DRAW;
+	}
+	message->cursor.x = c->vc_x;
+	message->cursor.y = c->vc_y;
+
+	switch (c->vc_cursor_type & CUR_HWMASK) {
+	case CUR_UNDERLINE:
+		message->cursor.height = 5;
+		break;
+	case CUR_TWO_THIRDS:
+		message->cursor.height = 66;
+		break;
+	case CUR_LOWER_THIRD:
+		message->cursor.height = 33;
+		break;
+	case CUR_LOWER_HALF:
+		message->cursor.height = 50;
+		break;
+	case CUR_NONE:
+		message->cursor.height = 0;
+		break;
+          default:
+		message->cursor.height = 5;
+		break;
+	}
+
+	co_send_message_restore(flags);
+}
+
+static int cocon_switch(struct vc_data *c)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_SWITCH;
+	co_send_message_restore(flags);
+
+	return 1;	/* Redrawing not needed */
+}
+
+static int cocon_set_palette(struct vc_data *c, unsigned char *table)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_SET_PALETTE;
+	co_send_message_restore(flags);
+
+	return 1;
+}
+
+static int cocon_blank(struct vc_data *c, int blank)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_BLANK;
+	co_send_message_restore(flags);
+
+	return 1;
+}
+
+static int cocon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_FONT_OP;
+	co_send_message_restore(flags);
+
+	return 1;
+}
+
+static int cocon_scrolldelta(struct vc_data *c, int lines)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_SCROLLDELTA;
+	co_send_message_restore(flags);
+
+	return 1;
+}
+
+static int cocon_set_origin(struct vc_data *c)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_SET_ORIGIN;
+	co_send_message_restore(flags);
+
+	return 1;
+}
+
+static void cocon_save_screen(struct vc_data *c)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_SAVE_SCREEN;
+	co_send_message_restore(flags);
+}
+
+static int cocon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->scroll + 1)) - ((char *)message);
+	if (dir == SM_UP)
+		message->type = CO_OPERATION_CONSOLE_SCROLL_UP;
+	else
+		message->type = CO_OPERATION_CONSOLE_SCROLL_DOWN;
+	message->scroll.top = t;
+	message->scroll.bottom = b-1;
+	message->scroll.lines = lines;
+	co_send_message_restore(flags);
+
+	return 0;
+}
+
+static void cocon_bmove(struct vc_data *c, int sy, int sx, int dy, int dx, int h, int w)
+{
+	unsigned long flags;
+	co_console_message_t *message;
+	co_message_t *co_message;
+
+	co_message = co_send_message_save(&flags);
+	message = (co_console_message_t *)co_message->data;
+	co_message->from = CO_MODULE_LINUX;
+	co_message->to = CO_MODULE_CONSOLE;
+	co_message->priority = CO_PRIORITY_DISCARDABLE;
+	co_message->type = CO_MESSAGE_TYPE_STRING;
+	co_message->size = ((char *)(&message->bmove + 1)) - ((char *)message);
+	message->type = CO_OPERATION_CONSOLE_BMOVE;
+	message->bmove.row = dy;
+	message->bmove.column = dx;
+	message->bmove.top = sy;
+	message->bmove.left = sx;
+	message->bmove.bottom = sy + h - 1;
+	message->bmove.right = sx + w - 1;
+	co_send_message_restore(flags);
+}
+
+/*
+ *  The console `switch' structure for the VGA based console
+ */
+
+const struct consw colinux_con = {
+	con_startup:		cocon_startup,
+	con_init:		cocon_init,
+	con_deinit:		cocon_deinit,
+	con_clear:		cocon_clear,
+	con_putc:		cocon_putc,
+	con_putcs:		cocon_putcs,
+	con_cursor:		cocon_cursor,
+	con_scroll:		cocon_scroll,
+	con_bmove:		cocon_bmove,
+	con_switch:		cocon_switch,
+	con_blank:		cocon_blank,
+	con_font_op:		cocon_font_op,
+	con_set_palette:	cocon_set_palette,
+	con_scrolldelta:	cocon_scrolldelta,
+	con_set_origin:		cocon_set_origin,
+	con_save_screen:	cocon_save_screen,
+	con_build_attr:		cocon_build_attr,
+	con_invert_region:	cocon_invert_region,
+};
+
+MODULE_LICENSE("GPL");
--- /dev/null	2004-04-06 13:56:48.000000000 -0400
+++ linux-2.4.28/include/asm-i386/cooperative.h	2004-11-27 15:59:21.308006712 -0500
@@ -0,0 +1,175 @@
+#ifndef __LINUX_ASM_COOPERATIVE_H__
+#define __LINUX_ASM_COOPERATIVE_H__
+
+typedef struct {
+	unsigned short size;
+	struct x86_idt_entry *table;
+} __attribute__((packed)) x86_idt_t;
+
+typedef struct {
+	unsigned short limit;
+	struct x86_dt_entry *base;
+} __attribute__((packed)) x86_gdt_t;
+
+typedef struct {
+	unsigned char border2[0x4];
+
+	unsigned long cs;
+        #define CO_ARCH_STATE_STACK_CS "0x04"
+
+	unsigned long ds;
+        #define CO_ARCH_STATE_STACK_DS "0x08"
+
+	unsigned long es;
+        #define CO_ARCH_STATE_STACK_ES "0x0C"
+
+	unsigned long cr3;   
+        #define CO_ARCH_STATE_STACK_CR3 "0x10"
+
+	unsigned long cr4;  
+        #define CO_ARCH_STATE_STACK_CR4 "0x14"
+
+	unsigned long cr2;
+        #define CO_ARCH_STATE_STACK_CR2 "0x18"
+
+	unsigned long cr0;
+        #define CO_ARCH_STATE_STACK_CR0 "0x1C"
+
+	x86_gdt_t gdt;
+        #define CO_ARCH_STATE_STACK_GDT "0x20"
+
+	unsigned long fs;    
+        #define CO_ARCH_STATE_STACK_FS  "0x26"
+
+	unsigned long gs;
+        #define CO_ARCH_STATE_STACK_GS  "0x2A"
+
+	unsigned short ldt;
+        #define CO_ARCH_STATE_STACK_LDT "0x2E"
+
+	x86_idt_t idt;
+        #define CO_ARCH_STATE_STACK_IDT "0x30"
+
+	unsigned short tr;   
+        #define CO_ARCH_STATE_STACK_TR  "0x36"
+
+	unsigned long return_eip; 
+        #define CO_ARCH_STATE_STACK_RETURN_EIP  "0x38"
+
+	unsigned long flags;     
+        #define CO_ARCH_STATE_STACK_FLAGS "0x3C"
+
+	unsigned long esp;        
+        #define CO_ARCH_STATE_STACK_ESP "0x40"
+
+	unsigned long ss;    
+        #define CO_ARCH_STATE_STACK_SS "0x44"
+
+	unsigned long dr0;        
+        #define CO_ARCH_STATE_STACK_DR0 "0x48"
+
+	unsigned long dr1;      
+        #define CO_ARCH_STATE_STACK_DR1 "0x4C"
+
+	unsigned long dr2;       
+        #define CO_ARCH_STATE_STACK_DR2 "0x50"
+
+	unsigned long dr3;
+        #define CO_ARCH_STATE_STACK_DR3 "0x54"
+
+	unsigned long dr6;
+        #define CO_ARCH_STATE_STACK_DR6 "0x58"
+
+	unsigned long dr7;
+        #define CO_ARCH_STATE_STACK_DR7 "0x5C"
+
+	unsigned long other_map;
+        #define CO_ARCH_STATE_STACK_OTHERMAP "0x60"
+
+	unsigned long relocate_eip; 
+        #define CO_ARCH_STATE_STACK_RELOCATE_EIP "0x64"
+        #define CO_ARCH_STATE_STACK_RELOCATE_EIP_AFTER "0x68"
+
+	unsigned long pad1;
+	unsigned long pad2;
+
+	unsigned char fxstate[0x200];
+        #define CO_ARCH_STATE_STACK_FXSTATE "0x70"
+} __attribute__((packed)) co_arch_state_stack_t;
+
+extern void co_debug(const char *fmt, ...);
+
+static inline void co_passage_page_dump_state(co_arch_state_stack_t *state)
+{
+	co_debug("cs: %04x   ds: %04x   es: %04x   fs: %04x   gs: %04x   ss: %04x\n",
+		 state->cs, state->ds, state->es, state->fs, state->gs, state->ss);
+
+	co_debug("cr0: %08x   cr2: %08x   cr3: %08x   cr4: %08x\n",
+		 state->cr0, state->cr2, state->cr3, state->cr4);
+
+	co_debug("dr0: %08x   dr1: %08x  dr2: %08x  dr3: %08x  dr6: %08x  dr7: %08x\n",
+		 state->dr0, state->dr1, state->dr2, state->dr3, state->dr6, state->dr7);
+
+	co_debug("gdt: %08x:%04x   idt:%08x:%04x   ldt:%04x  tr:%04x\n",
+		 state->gdt.base, state->gdt.limit,  state->idt.table, state->idt.size,
+		 state->ldt, state->tr);
+
+	co_debug("return_eip: %08x   flags: %08x   esp: %8x\n",
+		 state->return_eip, state->flags, state->esp);
+
+	co_debug("other_map: %08x   relocate_eip: %08x\n",
+		 state->other_map, state->relocate_eip);
+}
+
+#define CO_MAX_PARAM_SIZE 0x400
+
+typedef struct co_arch_passage_page {
+	union {
+		struct {
+			union {
+				struct {
+					unsigned long temp_pgd_physical;
+					unsigned long dr0;
+					unsigned long dr1;
+					unsigned long dr2;
+					unsigned long dr3;
+					unsigned long dr6;
+					unsigned long dr7; 
+					unsigned char code[0x1c0];
+				} __attribute__((packed));
+				unsigned char pad[0x210];
+			} __attribute__((packed));
+			
+			/* Machine states */
+			co_arch_state_stack_t host_state; 
+			co_arch_state_stack_t linuxvm_state;
+			
+			/* Control parameters */
+			unsigned long operation;
+			unsigned long params[];
+		} __attribute__((packed));
+		unsigned char first_page[0x1000];
+	};
+	unsigned long temp_pgd[0x400];
+	unsigned long temp_pte[2][0x400];
+} co_arch_passage_page_t;
+
+static inline void co_passage_page_dump(co_arch_passage_page_t *page)
+{
+	co_debug("Host state\n");
+	co_passage_page_dump_state(&page->host_state);
+
+	co_debug("Linux state\n");
+	co_passage_page_dump_state(&page->linuxvm_state);
+}
+
+/*
+ * Address space layout:
+ */
+
+#define CO_VPTR_PHYSICAL_TO_PSEUDO_PFN_MAP   (0xff000000)
+#define CO_VPTR_PSEUDO_RAM_PAGE_TABLES       (0xfef00000) 
+#define CO_VPTR_PASSAGE_PAGE                 (0xfeeff000)
+#define CO_VPTR_SELF_MAP                     (0xfec00000)
+
+#endif
--- linux-2.4.28/include/asm-i386/dma.h~colinux-0.6.1	2003-08-25 07:44:43.000000000 -0400
+++ linux-2.4.28/include/asm-i386/dma.h	2004-11-27 15:59:21.309006560 -0500
@@ -268,6 +268,8 @@
  *
  * Assumes DMA flip-flop is clear.
  */
+
+#ifndef CONFIG_COOPERATIVE
 static __inline__ int get_dma_residue(unsigned int dmanr)
 {
 	unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
@@ -281,7 +283,7 @@
 	
 	return (dmanr<=3)? count : (count<<1);
 }
-
+#endif
 
 /* These are in kernel/dma.c: */
 extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
--- linux-2.4.28/include/asm-i386/io.h~colinux-0.6.1	2003-06-13 10:51:38.000000000 -0400
+++ linux-2.4.28/include/asm-i386/io.h	2004-11-27 15:59:21.309006560 -0500
@@ -2,6 +2,7 @@
 #define _ASM_IO_H
 
 #include <linux/config.h>
+#include <linux/cooperative.h>
 
 /*
  * This file contains the definitions for the x86 IO instructions
@@ -45,6 +46,7 @@
 #ifdef __KERNEL__
 
 #include <linux/vmalloc.h>
+#include <linux/cooperative.h>
 
 /*
  * Temporary debugging check to catch old code using
@@ -121,6 +123,9 @@
  
 static inline void * ioremap (unsigned long offset, unsigned long size)
 {
+#ifdef CONFIG_COOPERATIVE
+	panic("ioremap %ld:%ld\n", offset, size); 
+#endif
 	return __ioremap(offset, size, 0);
 }
 
@@ -146,6 +151,9 @@
  
 static inline void * ioremap_nocache (unsigned long offset, unsigned long size)
 {
+#ifdef CONFIG_COOPERATIVE
+	panic("ioremap_nocache %ld:%ld\n", offset, size); 
+#endif
         return __ioremap(offset, size, _PAGE_PCD);
 }
 
@@ -308,6 +316,8 @@
 
 #endif /* __KERNEL__ */
 
+#ifndef CONFIG_COOPERATIVE_NOT
+
 #ifdef SLOW_IO_BY_JUMPING
 #define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
 #else
@@ -427,4 +437,21 @@
 __OUTS(w)
 __OUTS(l)
 
+#else
+
+static inline unsigned long badio(const char *file, int line)
+{
+#ifdef CONFIG_COOPERATIVE
+	panic("badio %s:%d\n", file, line); 
+#endif
+	return 0;
+}
+
+#define outb(port, data) badio(__FILE__, __LINE__)
+#define inb(port) badio(__FILE__, __LINE__)
+#define outb_p(port, data) badio(__FILE__, __LINE__)
+#define inb_p(port) badio(__FILE__, __LINE__)
+
+#endif
+
 #endif
--- linux-2.4.28/include/asm-i386/irq.h~colinux-0.6.1	2002-08-02 20:39:45.000000000 -0400
+++ linux-2.4.28/include/asm-i386/irq.h	2004-11-27 15:59:21.310006408 -0500
@@ -14,6 +14,10 @@
 
 #define TIMER_IRQ 0
 
+#ifdef CONFIG_COOPERATIVE
+#define NETWORK_IRQ  2
+#endif
+
 /*
  * 16 8259A IRQ's, 208 potential APIC interrupt sources.
  * Right now the APIC is mostly only used for SMP.
@@ -23,7 +27,7 @@
  * Since vectors 0x00-0x1f are used/reserved for the CPU,
  * the usable vector space is 0x20-0xff (224 vectors)
  */
-#ifdef CONFIG_X86_IO_APIC
+#if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_X86_COPIC)
 #define NR_IRQS 224
 #else
 #define NR_IRQS 16
--- linux-2.4.28/include/asm-i386/mc146818rtc.h~colinux-0.6.1	2001-11-22 14:46:58.000000000 -0500
+++ linux-2.4.28/include/asm-i386/mc146818rtc.h	2004-11-27 15:59:21.310006408 -0500
@@ -4,6 +4,7 @@
 #ifndef _ASM_MC146818RTC_H
 #define _ASM_MC146818RTC_H
 
+#include <linux/config.h>
 #include <asm/io.h>
 
 #ifndef RTC_PORT
@@ -11,6 +12,7 @@
 #define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
 #endif
 
+#ifndef CONFIG_COOPERATIVE
 /*
  * The yet supported machines all access the RTC index register via
  * an ISA port access but the way to access the date register differs ...
@@ -24,6 +26,11 @@
 outb_p((val),RTC_PORT(1)); \
 })
 
+#else
+#define CMOS_READ(addr) (0)
+#define CMOS_WRITE(val, addr) (0)
+#endif
+
 #define RTC_IRQ 8
 
 #endif /* _ASM_MC146818RTC_H */
--- linux-2.4.28/include/asm-i386/page.h~colinux-0.6.1	2002-08-02 20:39:45.000000000 -0400
+++ linux-2.4.28/include/asm-i386/page.h	2004-11-27 15:59:21.310006408 -0500
@@ -1,6 +1,10 @@
 #ifndef _I386_PAGE_H
 #define _I386_PAGE_H
 
+#ifdef CONFIG_COOPERATIVE
+#define WANT_PAGE_VIRTUAL
+#endif
+
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
@@ -10,6 +14,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/config.h>
+#include <asm/cooperative.h>
 
 #ifdef CONFIG_X86_USE_3DNOW
 
@@ -80,6 +85,22 @@
 
 #define __PAGE_OFFSET		(0xC0000000)
 
+#ifdef CONFIG_COOPERATIVE
+
+#define CO_PPTM_OFFSET     (CO_VPTR_PSEUDO_RAM_PAGE_TABLES)
+#define CO_RPPTM_OFFSET    (CO_VPTR_PHYSICAL_TO_PSEUDO_PFN_MAP)
+
+#define CO_PFN(vaddr)      ((((unsigned long)vaddr) - __PAGE_OFFSET) >> PAGE_SHIFT)
+#define CO_PA(pfn)         (((unsigned long *)CO_PPTM_OFFSET)[pfn])
+#define CO_PFN_PA(vaddr)   CO_PA(CO_PFN(vaddr))
+#define CO_PPTM_SIZE       (max_low_pfn * sizeof(pte_t))
+
+#define CO_VA_PFN(pa)      (((unsigned long *)CO_RPPTM_OFFSET)[((pa) >> PAGE_SHIFT)])
+#define CO_VA_PAGE(pa)     (mem_map + CO_VA_PFN(pa))
+#define CO_VA(pa)          ((CO_VA_PFN(pa) << PAGE_SHIFT) + __PAGE_OFFSET)
+
+#endif
+
 /*
  * This much address space is reserved for vmalloc() and iomap()
  * as well as fixmap mappings.
@@ -96,11 +117,16 @@
  */
 
 #if 1	/* Set to zero for a slightly smaller kernel */
+#ifdef CONFIG_COOPERATIVE
+#define BUG()	do { panic("BUG %s:%d\n", __FILE__, __LINE__); } while(0)
+#else
 #define BUG()				\
  __asm__ __volatile__(	"ud2\n"		\
 			"\t.word %c0\n"	\
 			"\t.long %c1\n"	\
 			 : : "i" (__LINE__), "i" (__FILE__))
+
+#endif
 #else
 #define BUG() __asm__ __volatile__("ud2\n")
 #endif
@@ -129,9 +155,11 @@
 #define VMALLOC_RESERVE		((unsigned long)__VMALLOC_RESERVE)
 #define __MAXMEM		(-__PAGE_OFFSET-__VMALLOC_RESERVE)
 #define MAXMEM			((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
-#define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
+#define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
+
 #define virt_to_page(kaddr)	(mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+
 #define VALID_PAGE(page)	((page - mem_map) < max_mapnr)
 
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
--- linux-2.4.28/include/asm-i386/pgalloc.h~colinux-0.6.1	2003-08-25 07:44:43.000000000 -0400
+++ linux-2.4.28/include/asm-i386/pgalloc.h	2004-11-27 15:59:21.313005952 -0500
@@ -11,8 +11,13 @@
 #define pte_quicklist (current_cpu_data.pte_quick)
 #define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
 
+#ifndef CONFIG_COOPERATIVE
 #define pmd_populate(mm, pmd, pte) \
-		set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
+	set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
+#else
+#define pmd_populate(mm, pmd, pte) \
+	set_pmd(pmd, __pmd(_PAGE_TABLE + (CO_PFN_PA(pte) & PAGE_MASK)))
+#endif
 
 /*
  * Allocate and free page tables.
--- linux-2.4.28/include/asm-i386/pgtable-2level.h~colinux-0.6.1	2002-11-28 18:53:15.000000000 -0500
+++ linux-2.4.28/include/asm-i386/pgtable-2level.h	2004-11-27 15:59:21.313005952 -0500
@@ -58,8 +58,14 @@
 }
 #define ptep_get_and_clear(xp)	__pte(xchg(&(xp)->pte_low, 0))
 #define pte_same(a, b)		((a).pte_low == (b).pte_low)
-#define pte_page(x)		(mem_map+((unsigned long)(((x).pte_low >> PAGE_SHIFT))))
 #define pte_none(x)		(!(x).pte_low)
+
+#ifndef CONFIG_COOPERATIVE
+#define pte_page(x)		(mem_map+((unsigned long)(((x).pte_low >> PAGE_SHIFT))))
 #define __mk_pte(page_nr,pgprot) __pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
+#else
+#define pte_page(x)		CO_VA_PAGE((x).pte_low)
+#define __mk_pte(page_nr,pgprot) __pte((CO_PA(page_nr) & PAGE_MASK) | pgprot_val(pgprot))
+#endif
 
 #endif /* _I386_PGTABLE_2LEVEL_H */
--- linux-2.4.28/include/asm-i386/pgtable.h~colinux-0.6.1	2002-11-28 18:53:15.000000000 -0500
+++ linux-2.4.28/include/asm-i386/pgtable.h	2004-11-27 15:59:21.313005952 -0500
@@ -320,8 +320,13 @@
 
 #define page_pte(page) page_pte_prot(page, __pgprot(0))
 
+#ifndef CONFIG_COOPERATIVE
 #define pmd_page(pmd) \
-((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+	((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+#else
+#define pmd_page(pmd) \
+	(CO_VA(pmd_val(pmd)))
+#endif
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
--- linux-2.4.28/include/asm-i386/processor.h~colinux-0.6.1	2004-02-18 08:36:32.000000000 -0500
+++ linux-2.4.28/include/asm-i386/processor.h	2004-11-27 15:59:21.314005800 -0500
@@ -181,8 +181,18 @@
 #define X86_CR4_OSFXSR		0x0200	/* enable fast FPU save and restore */
 #define X86_CR4_OSXMMEXCPT	0x0400	/* enable unmasked SSE exceptions */
 
+#ifndef CONFIG_COOPERATIVE
 #define load_cr3(pgdir) \
-	asm volatile("movl %0,%%cr3": :"r" (__pa(pgdir)));
+asm volatile("movl %0,%%cr3": :"r" (__pa(pgdir)));
+#else
+/*
+ * In coLinux Mode we can't load CR3 with the pseudo physical
+ * address. Instead, we need to translate the pseudo physical address
+ * to the real physical address.
+ */
+#define load_cr3(pgdir) \
+asm volatile("movl %0,%%cr3": :"r" (CO_PFN_PA(pgdir)));
+#endif
 
 /*
  * Save the cr4 feature set we're using (ie
--- linux-2.4.28/include/asm-i386/system.h~colinux-0.6.1	2004-04-14 09:05:40.000000000 -0400
+++ linux-2.4.28/include/asm-i386/system.h	2004-11-27 15:59:21.314005800 -0500
@@ -12,7 +12,15 @@
 struct task_struct;	/* one of the stranger aspects of C forward declarations.. */
 extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
 
+#ifdef CONFIG_COOPERATIVE
+#define prepare_to_switch()     {					\
+   asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->thread.fs));	\
+   asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->thread.gs));	\
+}
+#else
 #define prepare_to_switch()	do { } while(0)
+#endif
+
 #define switch_to(prev,next,last) do {					\
 	asm volatile("pushl %%esi\n\t"					\
 		     "pushl %%edi\n\t"					\
--- linux-2.4.28/include/linux/console.h~colinux-0.6.1	2004-02-18 08:36:32.000000000 -0500
+++ linux-2.4.28/include/linux/console.h	2004-11-27 15:59:21.315005648 -0500
@@ -55,6 +55,7 @@
 extern const struct consw dummy_con;	/* dummy console buffer */
 extern const struct consw fb_con;	/* frame buffer based console */
 extern const struct consw vga_con;	/* VGA text console */
+extern const struct consw colinux_con;	/* coLinux Mode text console */
 extern const struct consw newport_con;	/* SGI Newport console  */
 extern const struct consw prom_con;	/* SPARC PROM console */
 
--- /dev/null	2004-04-06 13:56:48.000000000 -0400
+++ linux-2.4.28/include/linux/cooperative.h	2004-11-27 15:59:21.315005648 -0500
@@ -0,0 +1,323 @@
+#ifndef __LINUX_COOPERATIVE_H__
+#define __LINUX_COOPERATIVE_H__
+
+#ifdef __KERNEL__
+#ifndef CO_KERNEL
+#define CO_COLINUX_KERNEL
+#define CO_KERNEL
+#endif
+#endif
+
+extern void co_debug(const char *fmt, ...);
+
+#include <asm/cooperative.h>
+
+#define CO_LINUX_ABI_VERSION    1
+
+#pragma pack(0)
+
+#define CO_BOOTPARAM_STRING_LENGTH 0x100
+
+extern char co_boot_parameters[CO_BOOTPARAM_STRING_LENGTH];
+
+typedef enum {
+	CO_OPERATION_EMPTY=0,
+	CO_OPERATION_START,
+	CO_OPERATION_IDLE,
+	CO_OPERATION_TERMINATE,
+	CO_OPERATION_MESSAGE_TO_MONITOR,
+	CO_OPERATION_MESSAGE_FROM_MONITOR,
+	CO_OPERATION_FORWARD_INTERRUPT,
+	CO_OPERATION_DEVICE,
+	CO_OPERATION_GET_TIME,
+	CO_OPERATION_DEBUG_LINE,
+	CO_OPERATION_GET_HIGH_PREC_QUOTIENT,
+	CO_OPERATION_TRACE_POINT,
+} co_operation_t;
+
+#define CO_MODULE_MAX_CONET  16
+#define CO_MODULE_MAX_COBD  32
+
+typedef enum {
+	CO_MODULE_LINUX,
+	CO_MODULE_MONITOR,
+	CO_MODULE_DAEMON,
+	CO_MODULE_IDLE,
+	CO_MODULE_KERNEL_SWITCH,
+	CO_MODULE_USER_SWITCH,
+	CO_MODULE_CONSOLE,
+	CO_MODULE_PRINTK,
+
+	CO_MODULE_CONET0,
+	CO_MODULE_CONET_END=CO_MODULE_CONET0+CO_MODULE_MAX_CONET-1,
+
+	CO_MODULE_COBD0,
+	CO_MODULE_COBD_END=CO_MODULE_COBD0+CO_MODULE_MAX_COBD-1,
+} co_module_t;
+
+typedef enum {
+	CO_PRIORITY_DISCARDABLE=0,
+	CO_PRIORITY_IMPORTANT,
+} co_priority_t;
+
+typedef enum {
+	CO_MESSAGE_TYPE_STRING=0,
+	CO_MESSAGE_TYPE_OTHER=1,
+} co_message_type_t;
+
+typedef struct {
+	co_module_t from;
+	co_module_t to;
+	co_priority_t priority;
+	co_message_type_t type;
+	unsigned long size;
+	char data[0];
+} __attribute__((packed)) co_message_t;
+
+typedef enum {
+	CO_DEVICE_BLOCK=0,
+	CO_DEVICE_CONSOLE,
+	CO_DEVICE_KEYBOARD,
+	CO_DEVICE_NETWORK,
+	CO_DEVICE_TIMER,
+	CO_DEVICE_POWER,
+
+	CO_DEVICES_TOTAL,
+} co_device_t;
+
+typedef struct {
+	unsigned char code;
+	int down;
+} co_scan_code_t;
+
+typedef enum {
+	CO_LINUX_MESSAGE_POWER_ALT_CTRL_DEL=0,
+} co_linux_message_power_type_t;
+
+typedef struct {
+	co_linux_message_power_type_t type;
+} __attribute__((packed)) co_linux_message_power_t;
+
+typedef struct {
+	unsigned long tick_count;
+} __attribute__((packed)) co_linux_message_idle_t;
+
+typedef struct {
+	co_device_t device;
+	unsigned long unit;
+	unsigned long size;
+	char data[];
+} __attribute__((packed)) co_linux_message_t;
+
+typedef enum {
+	CO_TERMINATE_END=0,
+	CO_TERMINATE_REBOOT,
+	CO_TERMINATE_POWEROFF,
+	CO_TERMINATE_PANIC,
+	CO_TERMINATE_HALT,
+	CO_TERMINATE_FORCED_OFF,
+	CO_TERMINATE_FORCED_END,
+	CO_TERMINATE_INVALID_OPERATION,
+} co_termination_reason_t;
+
+typedef void (*co_switcher_t)(co_arch_passage_page_t *page, 
+			      unsigned char *from,
+			      unsigned char *to);
+
+#define co_passage_page_func_low(_from_,_to_)	\
+	(((co_switcher_t)(co_passage_page->code))	\
+	 (co_passage_page,				\
+	  (char *)&_from_.border2,			\
+	  (char *)&_to_.border2))
+
+#define co_passage_page_func(_from_,_to_)				\
+	co_passage_page_func_low(co_passage_page->_from_, co_passage_page->_to_)
+
+#ifdef CO_KERNEL
+# ifdef CO_COLINUX_KERNEL
+#  define co_passage_page  ((co_arch_passage_page_t *)(CO_VPTR_PASSAGE_PAGE))
+#  define co_current (co_passage_page->linuxvm_state)
+#  define co_other (co_passage_page->host_state)
+# else
+#  define co_passage_page  (cmon->passage_page)
+#  define co_other (co_passage_page->linuxvm_state)
+#  define co_current (co_passage_page->host_state)
+# endif
+
+# define co_switch() co_passage_page_func_low(co_current, co_other)
+#endif
+
+/*
+ * Defines operations on various virtual devices.
+ */
+
+typedef enum {
+	CO_OPERATION_CONSOLE_STARTUP=0,
+	CO_OPERATION_CONSOLE_INIT=1,
+	CO_OPERATION_CONSOLE_DEINIT,
+	CO_OPERATION_CONSOLE_CLEAR,
+	CO_OPERATION_CONSOLE_PUTC,
+	CO_OPERATION_CONSOLE_PUTCS,
+	CO_OPERATION_CONSOLE_CURSOR_DRAW,
+	CO_OPERATION_CONSOLE_CURSOR_ERASE,
+	CO_OPERATION_CONSOLE_CURSOR_MOVE,
+	CO_OPERATION_CONSOLE_SCROLL_UP,
+	CO_OPERATION_CONSOLE_SCROLL_DOWN,
+	CO_OPERATION_CONSOLE_BMOVE,
+	CO_OPERATION_CONSOLE_SWITCH,
+	CO_OPERATION_CONSOLE_BLANK,
+	CO_OPERATION_CONSOLE_FONT_OP,
+	CO_OPERATION_CONSOLE_SET_PALETTE,
+	CO_OPERATION_CONSOLE_SCROLLDELTA,
+	CO_OPERATION_CONSOLE_SET_ORIGIN,
+	CO_OPERATION_CONSOLE_SAVE_SCREEN,
+	CO_OPERATION_CONSOLE_INVERT_REGION,
+} co_operation_console_t;
+
+
+typedef char co_console_code;
+typedef unsigned short co_console_character;
+typedef unsigned short co_console_unit;
+
+typedef struct {
+	co_console_unit x;
+	co_console_unit y;
+	co_console_unit height;
+} __attribute__((packed)) co_cursor_pos_t;
+
+typedef struct {
+	co_operation_console_t type;
+	union {
+		struct {
+			co_console_unit top;  
+			co_console_unit bottom;
+			co_console_unit lines;
+		} scroll;
+		struct {
+			co_console_unit y;
+			co_console_unit x;
+			co_console_unit count;
+			co_console_character data[];
+		} putcs;
+		struct {
+			co_console_unit x;
+			co_console_unit y;
+			co_console_character charattr;
+		} putc;
+		struct {
+			co_console_unit top;
+			co_console_unit left;
+			co_console_unit bottom;
+			co_console_unit right;
+			co_console_character charattr;
+		} clear;
+		struct {
+			co_console_unit y;
+			co_console_unit x;
+			co_console_unit count;
+		} invert;
+		struct {
+			co_console_unit row;
+			co_console_unit column;
+			co_console_unit top;
+			co_console_unit left;
+			co_console_unit bottom;
+			co_console_unit right;
+		} bmove;
+		co_cursor_pos_t cursor;
+	};
+} __attribute__((packed)) co_console_message_t;
+
+typedef struct {	
+	unsigned long index;
+	unsigned long flags;
+	unsigned long func;
+	unsigned long pid;
+} __attribute__((packed)) co_trace_point_info_t;
+
+extern void co_printk(char *line);
+extern void co_callback(void);
+extern void co_switch_wrapper(void);
+extern void co_idle_processor(void);
+extern void co_terminate(co_termination_reason_t reason);
+
+extern void co_send_message(co_module_t from, 
+			    co_module_t to,
+			    co_priority_t priority,
+			    co_message_type_t type,
+			    unsigned long size,
+			    char *data);
+extern co_message_t *co_send_message_save(unsigned long *flags);
+extern co_message_t *co_get_message_save(unsigned long *flags);
+extern void co_send_message_restore(unsigned long flags);
+
+extern void co_handle_device_interrupt(co_linux_message_t *message);
+extern void co_received_message(co_linux_message_t *message);
+extern int co_get_message(co_linux_message_t **message, co_device_t device);
+extern void co_free_message(co_linux_message_t *message);
+
+extern unsigned long co_bootmem_pages;
+extern unsigned long co_core_end;
+extern unsigned long co_memory_size;
+extern unsigned long co_rpptm_size;
+
+extern unsigned long co_get_host_time(void);
+extern void handle_keyboard_event(unsigned char scancode);
+
+typedef enum {
+	CO_BLOCK_OPEN=0,
+	CO_BLOCK_STAT,
+	CO_BLOCK_READ,
+	CO_BLOCK_WRITE,
+	CO_BLOCK_CLOSE,
+	CO_BLOCK_GET_ALIAS,
+} co_block_request_type_t;
+
+typedef enum {
+	CO_NETWORK_GET_MAC=0,
+} co_network_request_type_t;
+
+#ifdef CO_KERNEL
+/* If we are compiling kernel code (Linux or Host Driver) */
+# ifdef CO_COLINUX_KERNEL
+/* Inside Linux, vm_ptr_t considered a valid pointer in its virtual address space */
+typedef void *vm_ptr_t;
+#  else
+/* But inside the host, the type is considered not to be a pointer in its own address space */
+typedef unsigned long vm_ptr_t;
+# endif
+
+typedef struct {
+	co_block_request_type_t type;
+	long rc;
+	union {
+		struct {
+			unsigned long long offset;
+			unsigned long long size;
+			unsigned long long disk_size;
+			vm_ptr_t address;
+		};
+		struct {
+			char alias[20];
+		};
+	};
+} __attribute__((packed)) co_block_request_t;
+
+typedef struct {
+	co_network_request_type_t type;
+	unsigned long unit;
+	char mac_address[6];
+	char _pad[2];
+	int result;
+} __attribute__((packed)) co_network_request_t;
+
+#endif
+
+#ifndef COLINUX_TRACE
+#define CO_TRACE_STOP
+#define CO_TRACE_CONTINUE
+#endif
+
+#pragma pack()
+
+#endif
--- linux-2.4.28/include/linux/major.h~colinux-0.6.1	2003-06-13 10:51:38.000000000 -0400
+++ linux-2.4.28/include/linux/major.h	2004-11-27 15:59:21.315005648 -0500
@@ -142,6 +142,7 @@
 #define LVM_CHAR_MAJOR	109	/* Logical Volume Manager */
 
 #define	UMEM_MAJOR	116	/* http://www.umem.com/ Battery Backed RAM */
+#define COLINUX_MAJOR  117 
 
 #define RTF_MAJOR	150
 #define RAW_MAJOR	162
--- linux-2.4.28/init/do_mounts.c~colinux-0.6.1	2003-11-28 13:26:21.000000000 -0500
+++ linux-2.4.28/init/do_mounts.c	2004-11-27 15:59:21.316005496 -0500
@@ -255,6 +255,9 @@
 	{ "ftld", 0x2c18 },
 	{ "mtdblock", 0x1f00 },
 	{ "nb", 0x2b00 },
+#ifdef CONFIG_COOPERATIVE
+	{ "cobd",     0x7500 },
+#endif
 	{ NULL, 0 }
 };
 
--- linux-2.4.28/init/main.c~colinux-0.6.1	2004-11-17 06:54:22.000000000 -0500
+++ linux-2.4.28/init/main.c	2004-11-27 15:59:21.317005344 -0500
@@ -74,6 +74,8 @@
 #include <asm/smp.h>
 #endif
 
+#include <linux/cooperative.h>
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -305,7 +307,14 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 static void __init smp_init(void)
 {
+#ifdef CONFIG_COOPERATIVE
+	/* 
+	 * It doesn't work yet because I haven't implemented the 
+	 * timer interrupt yet 
+	 */
+#else
 	APIC_init_uniprocessor();
+#endif
 }
 #else
 #define smp_init()	do { } while (0)
--- linux-2.4.28/kernel/Makefile~colinux-0.6.1	2001-09-17 00:22:40.000000000 -0400
+++ linux-2.4.28/kernel/Makefile	2004-11-27 15:59:21.317005344 -0500
@@ -14,7 +14,7 @@
 obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
 	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
 	    sysctl.o acct.o capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o context.o
+	    signal.o sys.o kmod.o context.o cooperative.o
 
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
--- /dev/null	2004-04-06 13:56:48.000000000 -0400
+++ linux-2.4.28/kernel/cooperative.c	2004-11-27 15:59:21.318005192 -0500
@@ -0,0 +1,337 @@
+/*
+ *  linux/kernel/cooperative.c
+ *
+ *  Code for Cooperative mode (coLinux)
+ *
+ *  Dan Aloni <da-x@gmx.net>, 2003 (C).
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/cooperative.h>
+
+CO_TRACE_STOP;
+
+void start_kernel(void);
+extern char _kernel_start, _end;
+
+unsigned long co_core_end = 0;
+unsigned long co_memory_size = 0;
+char co_boot_parameters[CO_BOOTPARAM_STRING_LENGTH];
+
+void colinux_start_c()
+{
+	co_core_end = co_passage_page->params[0];
+	co_memory_size = co_passage_page->params[1];
+	memcpy(co_boot_parameters, &co_passage_page->params[2], 
+	       sizeof(co_boot_parameters));
+
+	start_kernel();
+
+	co_terminate(CO_TERMINATE_END);
+}
+
+co_message_t *co_send_message_save(unsigned long *flags)
+{
+	local_irq_save(*flags);
+	co_passage_page->operation = CO_OPERATION_MESSAGE_TO_MONITOR;
+	co_passage_page->params[0] = 1;
+	return (co_message_t *)(&co_passage_page->params[1]);	
+}
+
+void co_send_message_restore(unsigned long flags)
+{
+	co_switch_wrapper();
+	local_irq_restore(flags);
+}
+
+void co_send_message_s(co_message_t *message, char *data)
+{
+	if ((sizeof(co_message_t) + message->size) < 2000) {
+		co_message_t *params;
+		unsigned long flags;
+		
+		local_irq_save(flags);
+		co_passage_page->operation = CO_OPERATION_MESSAGE_TO_MONITOR;
+		co_passage_page->params[0] = 1;
+		params = (co_message_t *)(&co_passage_page->params[1]);
+		*params = *message;
+		memcpy(params->data, data, message->size);
+		co_switch_wrapper();
+		local_irq_restore(flags);
+		return;
+	}
+}
+
+void co_send_message(co_module_t from, 
+		     co_module_t to,
+		     co_priority_t priority,
+		     co_message_type_t type,
+		     unsigned long size,
+		     char *data)
+{
+	co_message_t params;
+
+	params.from = from;
+	params.to = to;
+	params.priority = priority;
+	params.type = type;
+	params.size = size;
+
+	co_send_message_s(&params, data);
+}
+
+void co_receive_message(co_message_t *message)
+{
+	struct {
+		co_message_t message;
+		co_linux_message_t linux_part;
+	} *linux_message;
+	
+	linux_message = (typeof(linux_message))message;
+
+	co_handle_device_interrupt(&linux_message->linux_part);
+}
+
+void co_callback(void)
+{
+	while (co_passage_page->operation == CO_OPERATION_MESSAGE_FROM_MONITOR) {
+		co_receive_message((co_message_t *)&co_passage_page->params[1]);
+		if (co_passage_page->params[0] == 0) {
+			break;
+		}
+		
+		co_passage_page->operation = CO_OPERATION_MESSAGE_FROM_MONITOR;
+		co_switch_wrapper();
+	}
+}
+
+void co_idle_processor(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	co_passage_page->operation = CO_OPERATION_IDLE;
+	co_switch_wrapper();
+	co_callback();
+	local_irq_restore(flags);
+}
+
+void co_printk(char *line)
+{
+	co_send_message(CO_MODULE_LINUX, 
+			CO_MODULE_PRINTK,
+			CO_PRIORITY_DISCARDABLE,
+			CO_MESSAGE_TYPE_STRING,
+			strlen(line)+1,
+			line);
+}
+
+void co_debug_line(char *line)
+{
+	unsigned long flags;
+
+	if (!line)
+		return;
+
+	if (strlen(line) > 0x200)
+		return;
+		
+	local_irq_save(flags);
+	co_passage_page->operation = CO_OPERATION_DEBUG_LINE;
+	strcpy((char *)&co_passage_page->params[0], line);
+	co_switch_wrapper();
+	local_irq_restore(flags);
+}
+
+void co_trace_ent_name(void *func, const char *name)
+{
+	static int reenterent = 0;
+	static int count = 0;
+	static char private_buffer[0x100];
+	unsigned long flags;
+
+	if (reenterent)
+		return;
+
+	reenterent = 1;
+
+	local_irq_save(flags);
+	count += 1;
+
+	if (count > 1900000) {
+		snprintf(private_buffer, sizeof(private_buffer), "%d: %d: %x %s\n", count, current->pid, func, name);
+		co_debug_line(private_buffer);
+	}
+
+	local_irq_restore(flags);
+
+	reenterent = 0;
+}
+
+static unsigned long trace_index = 0;
+
+void co_trace_ent(void *func)
+{
+	unsigned long flags;
+	co_trace_point_info_t *trace_point;
+
+	local_irq_save(flags);
+	trace_index++;
+	co_passage_page->operation = CO_OPERATION_TRACE_POINT;
+	trace_point = (co_trace_point_info_t *)&co_passage_page->params[0];
+	trace_point->pid = 0;
+	if (current)
+		trace_point->pid = current->pid;
+	trace_point->index = trace_index;
+	trace_point->flags = 1;
+	trace_point->func = (unsigned long)(func);
+	co_switch_wrapper();
+	local_irq_restore(flags);
+}
+
+void co_trace_ret(void *func)
+{
+	unsigned long flags;
+	co_trace_point_info_t *trace_point;
+
+	local_irq_save(flags);
+	trace_index++;
+	co_passage_page->operation = CO_OPERATION_TRACE_POINT;
+	trace_point = (co_trace_point_info_t *)&co_passage_page->params[0];
+	trace_point->pid = 0;
+	if (current)
+		trace_point->pid = current->pid;
+	trace_point->index = trace_index;
+	trace_point->flags = 0;
+	trace_point->func = (unsigned long)(func);
+	co_switch_wrapper();
+	local_irq_restore(flags);
+}
+
+void co_debug(const char *fmt, ...)
+{
+	static char co_buf[1024];
+	unsigned long flags;
+	va_list args;
+
+	local_irq_save(flags);
+	va_start(args, fmt);
+	vsnprintf(co_buf, sizeof(co_buf), fmt, args);
+	va_end(args);
+	co_debug_line(co_buf);
+	local_irq_restore(flags);
+}
+
+void co_terminate(co_termination_reason_t reason)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	co_passage_page->operation = CO_OPERATION_TERMINATE;
+	co_passage_page->params[0] = reason;
+	co_switch_wrapper();
+	local_irq_restore(flags);
+}
+
+unsigned long co_get_host_time(void)
+{
+	unsigned long flags;
+	unsigned long time;
+
+	local_irq_save(flags);
+	co_passage_page->operation = CO_OPERATION_GET_TIME;
+	co_switch_wrapper();
+	time = co_passage_page->params[0];
+	local_irq_restore(flags);
+
+	return time;
+}
+
+typedef struct {
+	struct list_head node;
+	co_linux_message_t msg;
+} co_linux_message_node_t;
+
+typedef struct {
+	struct list_head list;
+	int num_messages;
+} co_linux_message_queue_t;
+
+co_linux_message_queue_t *co_msgqueues = NULL;
+
+void co_received_message(co_linux_message_t *message)
+{
+	co_linux_message_node_t *copy;
+	co_linux_message_queue_t *queue;
+
+	if (!co_msgqueues)
+		return;
+
+	if (message->device < 0  ||  (message->device >= CO_DEVICES_TOTAL))
+		return;
+
+	copy = (co_linux_message_node_t *)kmalloc(sizeof(co_linux_message_node_t) + message->size, GFP_ATOMIC);
+	if (!copy)
+		return;
+
+	queue = &co_msgqueues[message->device];
+	memcpy(&copy->msg, message, sizeof(co_linux_message_t) + message->size);
+	list_add(&copy->node, &queue->list);
+	queue->num_messages++;
+}
+
+static int __init initcall_message_queues(void)
+{
+	int queue_index;
+
+	co_msgqueues = kmalloc(sizeof(co_linux_message_queue_t) * CO_DEVICES_TOTAL, GFP_KERNEL);
+	if (!co_msgqueues) {
+		panic("Unable to allocate message queues\n");
+	}
+
+	for (queue_index=0; queue_index < CO_DEVICES_TOTAL; queue_index++) {
+		co_linux_message_queue_t *queue = &co_msgqueues[queue_index];
+		queue->num_messages = 0;
+		INIT_LIST_HEAD(&queue->list);
+	}
+
+	return 0;
+}
+
+__initcall(initcall_message_queues);
+
+int co_get_message(co_linux_message_t **message, co_device_t device)
+{	
+	co_linux_message_queue_t *queue;
+	co_linux_message_node_t *node;
+
+	if (!co_msgqueues)
+		return 0;
+
+	queue = &co_msgqueues[device];
+	if (list_empty(&queue->list))
+		return 0;
+
+	node = list_entry(queue->list.prev, co_linux_message_node_t, node);
+	list_del(&node->node);
+	queue->num_messages--;
+	*message = &node->msg;
+	return 1;
+}
+
+void co_free_message(co_linux_message_t *message)
+{
+	co_linux_message_node_t *node = NULL;
+
+	node = (co_linux_message_node_t *)(((char *)message) - ((long)&node->msg));
+
+	kfree(node);
+}
+
+
+CO_TRACE_CONTINUE;
--- linux-2.4.28/kernel/panic.c~colinux-0.6.1	2004-11-17 06:54:22.000000000 -0500
+++ linux-2.4.28/kernel/panic.c	2004-11-27 15:59:21.318005192 -0500
@@ -18,6 +18,8 @@
 #include <linux/interrupt.h>
 #include <linux/console.h>
 
+#include <linux/cooperative.h>
+
 asmlinkage void sys_sync(void);	/* it's really int */
 
 int panic_timeout;
@@ -70,6 +72,8 @@
 		sys_sync();
 	bust_spinlocks(0);
 
+	co_terminate(CO_TERMINATE_PANIC);
+
 #ifdef CONFIG_SMP
 	smp_send_stop();
 #endif
--- linux-2.4.28/kernel/printk.c~colinux-0.6.1	2004-11-17 06:54:22.000000000 -0500
+++ linux-2.4.28/kernel/printk.c	2004-11-27 15:59:21.319005040 -0500
@@ -29,6 +29,8 @@
 
 #include <asm/uaccess.h>
 
+#include <linux/cooperative.h>
+
 #if !defined(CONFIG_LOG_BUF_SHIFT) || (CONFIG_LOG_BUF_SHIFT == 0)
 #if defined(CONFIG_MULTIQUAD) || defined(CONFIG_IA64)
 #define LOG_BUF_LEN	(65536)
@@ -433,6 +435,9 @@
 	printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
 	va_end(args);
 
+#ifdef CONFIG_COOPERATIVE
+	co_printk(printk_buf);
+#endif
 	/*
 	 * Copy the output into log_buf.  If the caller didn't provide
 	 * appropriate log level tags, we insert them here
@@ -459,6 +464,7 @@
 		spin_unlock_irqrestore(&logbuf_lock, flags);
 		goto out;
 	}
+
 	if (!down_trylock(&console_sem)) {
 		/*
 		 * We own the drivers.  We can drop the spinlock and let