summaryrefslogtreecommitdiff
path: root/packages/linux/linux-colinux-2.4.28/colinux-0.6.1.patch
diff options
context:
space:
mode:
authorKoen Kooi <koen@openembedded.org>2005-06-30 08:19:37 +0000
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>2005-06-30 08:19:37 +0000
commitc8e5702127e507e82e6f68a4b8c546803accea9d (patch)
tree00583491f40ecc640f2b28452af995e3a63a09d7 /packages/linux/linux-colinux-2.4.28/colinux-0.6.1.patch
parent87ec8ca4d2e2eb4d1c1e1e1a6b46a395d56805b9 (diff)
import clean BK tree at cset 1.3670
Diffstat (limited to 'packages/linux/linux-colinux-2.4.28/colinux-0.6.1.patch')
-rw-r--r--packages/linux/linux-colinux-2.4.28/colinux-0.6.1.patch5156
1 files changed, 5156 insertions, 0 deletions
diff --git a/packages/linux/linux-colinux-2.4.28/colinux-0.6.1.patch b/packages/linux/linux-colinux-2.4.28/colinux-0.6.1.patch
index e69de29bb2..fca3c277ee 100644
--- a/packages/linux/linux-colinux-2.4.28/colinux-0.6.1.patch
+++ b/packages/linux/linux-colinux-2.4.28/colinux-0.6.1.patch
@@ -0,0 +1,5156 @@
+
+#
+# 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