]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/linux-colinux-2.6.10/colinux-0.6.2.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / linux-colinux-2.6.10 / colinux-0.6.2.patch
1 diff -urN a/CREDITS b/CREDITS
2 --- a/CREDITS
3 +++ b/CREDITS
4 @@ -52,6 +52,12 @@
5  S: Buenos Aires
6  S: Argentina
7  
8 +A: Dan Aloni
9 +E: da-x@colinux.org
10 +D: Cooperative Linux
11 +D: Various kernel patches
12 +S: Israel
13 +
14  N: Tim Alpaerts
15  E: tim_alpaerts@toyota-motor-europe.com
16  D: 802.2 class II logical link control layer,
17 diff -urN a/Makefile b/Makefile
18 --- a/Makefile
19 +++ b/Makefile
20 @@ -319,6 +319,11 @@
21  AS             = $(CROSS_COMPILE)as
22  LD             = $(CROSS_COMPILE)ld
23  CC             = $(CROSS_COMPILE)gcc
24 +ifeq ($(GCCTRACE),Y)
25 +CC              = $(CORSS_COMPILE)$(COLINUX_ROOT)/bin/tracewrapper.py gcc
26 +else
27 +CC             = $(CROSS_COMPILE)gcc
28 +endif
29  CPP            = $(CC) -E
30  AR             = $(CROSS_COMPILE)ar
31  NM             = $(CROSS_COMPILE)nm
32 diff -urN a/arch/i386/Kconfig b/arch/i386/Kconfig
33 --- a/arch/i386/Kconfig
34 +++ b/arch/i386/Kconfig
35 @@ -205,6 +205,7 @@
36  
37  config M586TSC
38         bool "Pentium-Classic"
39 +       depends on !COOPERATIVE
40         help
41           Select this for a Pentium Classic processor with the RDTSC (Read
42           Time Stamp Counter) instruction for benchmarking.
43 @@ -543,6 +544,10 @@
44           If you have a system with several CPUs, you do not need to say Y
45           here: the IO-APIC will be used automatically.
46  
47 +config X86_UP_COPIC
48 +       bool 'Cooperative PIC (COPIC) support' 
49 +       depends on COOPERATIVE
50 +
51  config X86_LOCAL_APIC
52         bool
53         depends on !SMP && X86_UP_APIC
54 @@ -555,7 +560,7 @@
55  
56  config X86_TSC
57         bool
58 -       depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ
59 +       depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ && !COOPERATIVE
60         default y
61  
62  config X86_MCE
63 @@ -882,6 +887,10 @@
64  
65  source kernel/power/Kconfig
66  
67 +config COOPERATIVE
68 +       bool 'Cooperative Mode'
69 +       default y
70 +
71  source "drivers/acpi/Kconfig"
72  
73  menu "APM (Advanced Power Management) BIOS Support"
74 diff -urN a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
75 --- a/arch/i386/kernel/Makefile
76 +++ b/arch/i386/kernel/Makefile
77 @@ -17,6 +17,7 @@
78  obj-$(CONFIG_X86_MSR)          += msr.o
79  obj-$(CONFIG_X86_CPUID)                += cpuid.o
80  obj-$(CONFIG_MICROCODE)                += microcode.o
81 +obj-$(CONFIG_COOPERATIVE)       += cooperative.o
82  obj-$(CONFIG_APM)              += apm.o
83  obj-$(CONFIG_X86_SMP)          += smp.o smpboot.o
84  obj-$(CONFIG_X86_TRAMPOLINE)   += trampoline.o
85 diff -urN a/arch/i386/kernel/cooperative.c b/arch/i386/kernel/cooperative.c
86 --- a/arch/i386/kernel/cooperative.c
87 +++ b/arch/i386/kernel/cooperative.c
88 @@ -0,0 +1,340 @@
89 +#include <linux/kernel.h>
90 +#include <linux/string.h>
91 +#include <linux/interrupt.h>
92 +#include <linux/mm.h>
93 +
94 +#include <linux/cooperative_internal.h>
95 +#include <asm/cooperative_internal.h>
96 +#include <asm/smp.h>
97 +#include <asm/desc.h>
98 +#include <asm/mmu_context.h>
99 +#include <asm/debugreg.h>
100 +#include <asm/i387.h>
101 +
102 +CO_TRACE_STOP;
103 +
104 +
105 +/*
106 + * The next asm code is the first Linux code that runs in the 
107 + * coLinux kernel context. It receives %ecx which contains the 
108 + * address of the passage page. The passage page code sets %ecx 
109 + * to this value in its context restore part.
110 + */  
111 +
112 +asm(
113 +       ""
114 +       ".section .text\n"
115 +       ".globl co_start\n"
116 +       "co_start:\n"
117 +       "       call co_start_arch\n"
118 +       ".previous\n"
119 +       "");
120 +
121 +static int co_passage_page_holding_count = 0;
122 +
123 +static void co_early_cpu_init(void)
124 +{
125 +       /*
126 +        * On the first switch to Linux we must set up a valid TR because 
127 +        * the passage page code assumes such one exists. This is basically
128 +        * copied code from cpu_init().
129 +        *
130 +        * P.S this is protected by CO_TRACE_STOP so that we don't
131 +        * have a monitor context switch.
132 +        */
133 +        int cpu = smp_processor_id();
134 +        struct tss_struct * t = &per_cpu(init_tss, cpu);
135 +        struct thread_struct *thread = &current->thread;
136 +
137 +       /*
138 +        * Initialize the per-CPU GDT with the boot GDT,
139 +        * and set up the GDT descriptor:
140 +        */
141 +       memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table, GDT_SIZE);
142 +       cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
143 +       cpu_gdt_descr[cpu].address = (unsigned long)&per_cpu(cpu_gdt_table, cpu);
144 +
145 +        /*
146 +         * Set up the per-thread TLS descriptor cache:
147 +         */
148 +        memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu), GDT_ENTRY_TLS_ENTRIES * 8);
149 +
150 +        __asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
151 +        __asm__ __volatile__("lidt %0" : : "m" (idt_descr));
152 +
153 +        /*
154 +         * Delete NT
155 +         */
156 +        __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
157 +
158 +        /*
159 +         * Set up and load the per-CPU TSS and LDT
160 +         */
161 +        atomic_inc(&init_mm.mm_count);
162 +        current->active_mm = &init_mm;
163 +        enter_lazy_tlb(&init_mm, current);
164 +
165 +        load_esp0(t, thread);
166 +        set_tss_desc(cpu,t);
167 +        per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff;
168 +
169 +        load_TR_desc();
170 +
171 +        load_LDT(&init_mm.context);
172 +
173 +        /* Set up doublefault TSS pointer in the GDT */
174 +        __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
175 +        per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_DOUBLEFAULT_TSS].b &= 0xfffffdff;
176 +
177 +        /* Clear %fs and %gs. */
178 +        asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
179 +
180 +       __asm__ __volatile__("movl %%cr4, %0" : "=r" (mmu_cr4_features));
181 +}
182 +
183 +asm(
184 +       ""
185 +       ".section .text\n"
186 +       ".globl co_arch_start_kernel\n"
187 +       "co_arch_start_kernel:\n"
188 +       "       call co_startup_entry\n"
189 +       ".previous\n"
190 +       "");
191 +
192 +void co_start_arch(void)
193 +{
194 +       co_early_cpu_init();
195 +       co_start_kernel();
196 +}
197 +
198 +extern void ctrl_alt_del(void);
199 +
200 +void co_handle_jiffies(long count)
201 +{
202 +       unsigned long flags;
203 +       struct pt_regs regs;
204 +
205 +       if (count > HZ) {
206 +               xtime.tv_sec += count / HZ;
207 +               count -= ((count / HZ) * HZ);
208 +       }
209 +               
210 +       while (count > 0) {
211 +               local_irq_save(flags);
212 +               regs.orig_eax = TIMER_IRQ;
213 +               do_IRQ(&regs);
214 +               local_irq_restore(flags);
215 +
216 +               count--;
217 +       }
218 +}
219 +
220 +void co_handle_incoming_message(co_message_node_t *node_message)
221 +{
222 +       unsigned long flags;
223 +       struct pt_regs regs;
224 +       co_linux_message_t *message;
225 +
226 +       message = (co_linux_message_t *)&node_message->msg.data;
227 +
228 +       switch (message->device) {
229 +       case CO_DEVICE_POWER: {
230 +               co_linux_message_power_t *type = (co_linux_message_power_t *)message->data;
231 +               switch (type->type) {
232 +               case CO_LINUX_MESSAGE_POWER_ALT_CTRL_DEL: {
233 +                       ctrl_alt_del();
234 +                       break;
235 +               }
236 +               }
237 +               co_free_message(node_message);
238 +               break;
239 +       }
240 +
241 +       case CO_DEVICE_KEYBOARD: {
242 +               co_queue_incoming_message(node_message);
243 +
244 +               local_irq_save(flags);
245 +               regs.orig_eax = KEYBOARD_IRQ;
246 +               do_IRQ(&regs);
247 +               local_irq_restore(flags);
248 +               break;
249 +       }
250 +       
251 +       case CO_DEVICE_NETWORK: {
252 +               co_queue_incoming_message(node_message);
253 +
254 +               local_irq_save(flags);
255 +               regs.orig_eax = NETWORK_IRQ;
256 +               do_IRQ(&regs);
257 +               local_irq_restore(flags);
258 +               break;
259 +       }
260 +
261 +       case CO_DEVICE_SERIAL: {
262 +               co_queue_incoming_message(node_message);
263 +
264 +               local_irq_save(flags);
265 +               cocd_interrupt();
266 +               local_irq_restore(flags);
267 +               break;
268 +       }
269 +
270 +       default:
271 +               co_free_message(node_message);
272 +               break;
273 +       }
274 +}
275 +
276 +void co_switch_wrapper_protected(void)
277 +{
278 +       kernel_fpu_begin();
279 +
280 +       /*
281 +        * We don't trust the passage page code to safely restore %gs and %fs. 
282 +        *
283 +        * This wrapper ensures that if %fs or %gs are invalid, the processes
284 +        * exits with a segmentation fault rather than bringing down the 
285 +        * machine.
286 +        **/
287 +       unsigned long fs = 0;
288 +       unsigned long gs = 0;
289 +
290 +        asm volatile("movl %%fs,%0": "=m" (fs));
291 +        asm volatile("movl %%gs,%0": "=m" (gs));
292 +
293 +       /*
294 +        * Nullify the registers so the passage page code restores to 
295 +        * null segment values on return.
296 +        */
297 +        asm volatile("movl %0, %%fs;  movl %0, %%gs" : : "r" (0));
298 +
299 +       /* And switch... */
300 +       co_switch();
301 +
302 +       /*
303 +        * Safely restore the registers.
304 +        */
305 +       loadsegment(fs, fs);
306 +       loadsegment(gs, gs);
307 +
308 +       kernel_fpu_end();
309 +}
310 +
311 +void co_switch_wrapper(void)
312 +{
313 +       /* taken from irq.c: debugging check for stack overflow */
314 +       long esp;
315 +       
316 +       __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (THREAD_SIZE - 1));
317 +       if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
318 +               printk("co_switch_wrapper: stack overflow: %ld\n", esp - sizeof(struct thread_info));
319 +               co_terminate(CO_TERMINATE_STACK_OVERFLOW);
320 +       }
321 +
322 +       co_switch_wrapper_protected();
323 +}
324 +
325 +void co_passage_page_acquire(unsigned long *flags)
326 +{
327 +       local_irq_save(*flags);
328 +       co_passage_page_holding_count++;
329 +}
330 +
331 +int co_passage_page_held(void)
332 +{
333 +       return co_passage_page_holding_count;
334 +}
335 +
336 +void co_passage_page_release(unsigned long flags)
337 +{
338 +       co_passage_page_holding_count--;
339 +       local_irq_restore(flags);
340 +}
341 +
342 +void co_debug(const char *fmt, ...)
343 +{
344 +}
345 +
346 +#define MAX_TRACE_POINTS 1024
347 +
348 +typedef struct {       
349 +       unsigned char *code;
350 +       unsigned char original_byte;
351 +       int off;
352 +} co_tracepoint_t;
353 +
354 +co_tracepoint_t tracepoints[MAX_TRACE_POINTS];
355 +static int active_tracepoints = 0;
356 +
357 +void co_kernel_breakpoint(struct pt_regs * regs)
358 +{
359 +       int i = 0;
360 +       unsigned char *code = (unsigned char *)regs->eip;
361 +       if (!code)
362 +               return;
363 +
364 +       for (i=0; i < active_tracepoints; i++) {
365 +               if (tracepoints[i].code == code - 1) {
366 +                       co_debug("TRACEPOINT: %x\n", code - 1);
367 +                       break;
368 +               }
369 +       }
370 +
371 +       if (i == active_tracepoints) {
372 +               /* Bad, we don't know this tracepoint */
373 +               co_terminate(CO_TERMINATE_INVALID_OPERATION);
374 +               return;
375 +       }
376 +
377 +       *tracepoints[i].code = tracepoints[i].original_byte;
378 +       regs->eflags |= (1 << 8); /* Enable TF */
379 +       regs->eip = (unsigned long)(code - 1);
380 +       tracepoints[i].off = 1;
381 +}
382 +
383 +void co_kernel_set_breakpoints(void)
384 +{
385 +       int i;
386 +
387 +       for (i=0; i < active_tracepoints; i++)
388 +               if (tracepoints[i].code  &&  tracepoints[i].off) {
389 +                       *tracepoints[i].code = 0xcc;
390 +                       tracepoints[i].off = 0;
391 +               }
392 +}
393 +
394 +int co_kernel_debug(struct pt_regs *regs, long error_code, unsigned int condition)
395 +{
396 +       /* if not a single step trap */
397 +       if (!(condition & DR_STEP))
398 +               return 0;
399 +
400 +       /* if userspace */
401 +       if (regs->xcs & 3)
402 +               return 0;
403 +
404 +       regs->eflags &= ~(1 << 8); /* Disable TF */
405 +
406 +       co_kernel_set_breakpoints();
407 +       
408 +       return 1;
409 +}
410 +
411 +void co_kernel_tracepoint_add(unsigned char *code)
412 +{
413 +       if (active_tracepoints >= MAX_TRACE_POINTS)
414 +               return;
415 +
416 +       tracepoints[active_tracepoints].code = code;
417 +       tracepoints[active_tracepoints].original_byte = *code;
418 +       tracepoints[active_tracepoints].off = 0;
419 +       active_tracepoints++;
420 +       *code = 0xcc;
421 +}
422 +
423 +co_arch_info_t co_arch_info = {
424 +       .kernel_cs = __KERNEL_CS,
425 +       .kernel_ds = __KERNEL_DS,
426 +};
427 +
428 +CO_TRACE_CONTINUE;
429 diff -urN a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
430 --- a/arch/i386/kernel/cpu/common.c
431 +++ b/arch/i386/kernel/cpu/common.c
432 @@ -4,6 +4,7 @@
433  #include <linux/smp.h>
434  #include <linux/module.h>
435  #include <linux/percpu.h>
436 +#include <linux/cooperative_internal.h>
437  #include <asm/semaphore.h>
438  #include <asm/processor.h>
439  #include <asm/i387.h>
440 @@ -570,11 +571,13 @@
441  
442         /* Clear all 6 debug registers: */
443  
444 +       if (!cooperative_mode_enabled()) {
445  #define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) );
446  
447 -       CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
448 +               CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
449  
450  #undef CD
451 +       }
452  
453         /*
454          * Force FPU initialization:
455 diff -urN a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
456 --- a/arch/i386/kernel/entry.S
457 +++ b/arch/i386/kernel/entry.S
458 @@ -158,7 +158,7 @@
459         ALIGN
460  ret_from_exception:
461         preempt_stop
462 -ret_from_intr:
463 +ENTRY(ret_from_intr)
464         GET_THREAD_INFO(%ebp)
465         movl EFLAGS(%esp), %eax         # mix EFLAGS and CS
466         movb CS(%esp), %al
467 diff -urN a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
468 --- a/arch/i386/kernel/head.S
469 +++ b/arch/i386/kernel/head.S
470 @@ -238,6 +238,7 @@
471         rep
472         movsl
473  1:
474 +ENTRY(co_startup_entry)
475  checkCPUtype:
476  
477         movl $-1,X86_CPUID              #  -1 for no CPUID initially
478 @@ -425,7 +426,7 @@
479  .data
480  
481  ENTRY(stack_start)
482 -       .long init_thread_union+THREAD_SIZE
483 +       .long init_thread_union+THREAD_SIZE-100
484         .long __BOOT_DS
485  
486  ready: .byte 0
487 diff -urN a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
488 --- a/arch/i386/kernel/i387.c
489 +++ b/arch/i386/kernel/i387.c
490 @@ -17,6 +17,7 @@
491  #include <asm/user.h>
492  #include <asm/ptrace.h>
493  #include <asm/uaccess.h>
494 +#include <linux/cooperative_internal.h>
495  
496  #ifdef CONFIG_MATH_EMULATION
497  #define HAVE_HWFP (boot_cpu_data.hard_math)
498 @@ -37,6 +38,10 @@
499                 if (mask == 0) mask = 0x0000ffbf;
500         } 
501         mxcsr_feature_mask &= mask;
502 +
503 +       if (cooperative_mode_enabled()) 
504 +               return;
505 +
506         stts();
507  }
508  
509 @@ -386,6 +391,7 @@
510         return err;
511  }
512  
513 +
514  /*
515   * ptrace request handlers.
516   */
517 diff -urN a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
518 --- a/arch/i386/kernel/i8259.c
519 +++ b/arch/i386/kernel/i8259.c
520 @@ -26,9 +26,89 @@
521  #include <asm/i8259.h>
522  
523  #include <linux/irq.h>
524 +#include <linux/cooperative_internal.h>
525  
526  #include <io_ports.h>
527  
528 +#ifdef CONFIG_COOPERATIVE
529 +
530 +CO_TRACE_STOP;
531 +
532 +void proxy_interrupt_handler(unsigned long interrupt, struct pt_regs regs)
533 +{
534 +       unsigned long flags;
535 +
536 +       co_passage_page_acquire(&flags);
537 +       co_passage_page->operation = CO_OPERATION_FORWARD_INTERRUPT;
538 +       co_passage_page->params[0] = interrupt + 0x20;
539 +       co_passage_page->params[1] = regs.eip;
540 +       co_passage_page->params[2] = (unsigned long)(&((&interrupt)[10]));
541 +       co_passage_page->host_state.flags &= ~(1 << 9); /* Turn IF off */
542 +       co_switch_wrapper();
543 +       co_callback(flags);
544 +}
545 +
546 +CO_TRACE_CONTINUE;
547 +
548 +#define IRQLIST_16(x) \
549 +       IRQ(x,0) IRQ(x,1) IRQ(x,2) IRQ(x,3) \
550 +       IRQ(x,4) IRQ(x,5) IRQ(x,6) IRQ(x,7) \
551 +       IRQ(x,8) IRQ(x,9) IRQ(x,a) IRQ(x,b) \
552 +       IRQ(x,c) IRQ(x,d) IRQ(x,e) IRQ(x,f)
553 +
554 +#define IRQLIST_224 \
555 +       IRQLIST_16(0x0) IRQLIST_16(0x1) IRQLIST_16(0x2) IRQLIST_16(0x3) \
556 +       IRQLIST_16(0x4) IRQLIST_16(0x5) IRQLIST_16(0x6) IRQLIST_16(0x7) \
557 +       IRQLIST_16(0x8) IRQLIST_16(0x9) IRQLIST_16(0xa) IRQLIST_16(0xb) \
558 +       IRQLIST_16(0xc) IRQLIST_16(0xd)
559 +
560 +#define IRQ(x,y) \
561 +       extern asmlinkage void IRQ_proxy_##x##y##_interrupt(void);
562 +IRQLIST_224;
563 +#undef IRQ
564 +
565 +#define BIRQ(id)                                               \
566 +asm(                                                           \
567 +    "\n"__ALIGN_STR"\n"                                                \
568 +    ".section .text\n"                                         \
569 +    ".globl IRQ_proxy_" #id "_interrupt\n"                     \
570 +    "IRQ_proxy_" #id "_interrupt:\n"                           \
571 +    "push %eax\n\t"                                            \
572 +    "cld;\n\t"                                                 \
573 +    "pushl %es;\n\t"                                           \
574 +    "pushl %ds;\n\t"                                           \
575 +    "pushl %eax;\n\t"                                          \
576 +    "pushl %ebp;\n\t"                                          \
577 +    "pushl %edi;\n\t"                                          \
578 +    "pushl %esi;\n\t"                                          \
579 +    "pushl %edx;\n\t"                                          \
580 +    "pushl %ecx;\n\t"                                          \
581 +    "pushl %ebx;\n\t"                                          \
582 +    "movl $123, %edx;\n\t"                                     \
583 +    "movl %edx, %ds;\n\t"                                      \
584 +    "movl %edx, %es;\n\t"                                      \
585 +    "pushl $" #id "\n\t"                                       \
586 +    "call proxy_interrupt_handler\n\t"                         \
587 +    "popl %ebx\n\t"                                            \
588 +    "jmp ret_from_intr\n"                                      \
589 +    ".previous\n"                                              \
590 +    );                                                         \
591 +
592 +#define IRQ(x,y) BIRQ(x##y)
593 +IRQLIST_224;
594 +#undef IRQ
595 +
596 +#define IRQ(x,y) &IRQ_proxy_##x##y##_interrupt,
597 +void (*proxy_interrupt[NR_IRQS])(void) = {
598 +    IRQLIST_224
599 +};
600 +#undef IRQ
601 +
602 +#undef IRQLIST_16
603 +#undef IRQLIST_224
604 +
605 +#endif 
606 +    
607  /*
608   * This is the 'legacy' 8259A Programmable Interrupt Controller,
609   * present in the majority of PC/AT boxes.
610 @@ -364,6 +444,9 @@
611  {
612         int i;
613  
614 +       if (cooperative_mode_enabled())
615 +               return;
616 +
617  #ifdef CONFIG_X86_LOCAL_APIC
618         init_bsp_APIC();
619  #endif
620 @@ -388,6 +471,65 @@
621         }
622  }
623  
624 +#ifdef CONFIG_X86_UP_COPIC
625 +
626 +/*
627 + * Not like you have any other choice other than using
628 + * COPIC in Cooperative mode.
629 + */
630 +
631 +static void end_COPIC_irq(unsigned int irq)
632 +{
633 +}
634 +
635 +#define shutdown_COPIC_irq     disable_COPIC_irq
636 +
637 +static void mask_and_ack_COPIC(unsigned int irq)
638 +{
639 +}
640 +
641 +static unsigned int startup_COPIC_irq(unsigned int irq)
642 +{
643 +       return 0;
644 +}
645 +
646 +void disable_COPIC_irq(unsigned int irq)
647 +{
648 +}
649 +
650 +void enable_COPIC_irq(unsigned int irq)
651 +{
652 +}
653 +
654 +static struct hw_interrupt_type co_pic_irq_type = {
655 +       "CO-PIC",
656 +       startup_COPIC_irq,
657 +       shutdown_COPIC_irq,
658 +       enable_COPIC_irq,
659 +       disable_COPIC_irq,
660 +       mask_and_ack_COPIC,
661 +       end_COPIC_irq,
662 +       NULL
663 +};
664 +
665 +void __init init_COPIC_irqs(void)
666 +{
667 +       int i;
668 +
669 +       for (i = 0; i < NR_IRQS; i++) {
670 +               irq_desc[i].status = IRQ_DISABLED;
671 +               irq_desc[i].action = 0;
672 +               irq_desc[i].depth = 1;
673 +
674 +               irq_desc[i].handler = &co_pic_irq_type;
675 +       }
676 +       
677 +}
678 +
679 +#else
680 +#define init_COPIC_irqs() do {} while (0);
681 +#endif
682 +
683  void __init init_IRQ(void)
684  {
685         int i;
686 @@ -395,6 +537,22 @@
687         /* all the set up before the call gates are initialised */
688         pre_intr_init_hook();
689  
690 +       if (cooperative_mode_enabled()) {
691 +               printk("Setting proxy interrupt vectors\n");
692 +
693 +               init_COPIC_irqs();
694 +
695 +               for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
696 +                       int vector = FIRST_EXTERNAL_VECTOR + i;
697 +                       if (i >= NR_IRQS)
698 +                               break;
699 +                       if (vector != SYSCALL_VECTOR)
700 +                               set_intr_gate(vector, proxy_interrupt[i]);
701 +               }
702 +               
703 +               return;
704 +       }
705 +
706         /*
707          * Cover the whole vector space, no vector can escape
708          * us. (some of these will be overridden and become
709 diff -urN a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
710 --- a/arch/i386/kernel/ioport.c
711 +++ b/arch/i386/kernel/ioport.c
712 @@ -15,6 +15,7 @@
713  #include <linux/stddef.h>
714  #include <linux/slab.h>
715  #include <linux/thread_info.h>
716 +#include <linux/cooperative_internal.h>
717  
718  /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
719  static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
720 @@ -61,6 +62,9 @@
721         struct tss_struct * tss;
722         unsigned long *bitmap;
723  
724 +       if (cooperative_mode_enabled())
725 +               return -EPERM;  
726 +
727         if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
728                 return -EINVAL;
729         if (turn_on && !capable(CAP_SYS_RAWIO))
730 @@ -133,6 +137,9 @@
731         unsigned int level = regs->ebx;
732         unsigned int old = (regs->eflags >> 12) & 3;
733  
734 +       if (cooperative_mode_enabled())
735 +               return -EPERM;  
736 +
737         if (level > 3)
738                 return -EINVAL;
739         /* Trying to gain more privileges? */
740 diff -urN a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
741 --- a/arch/i386/kernel/process.c
742 +++ b/arch/i386/kernel/process.c
743 @@ -52,6 +52,7 @@
744  
745  #include <linux/irq.h>
746  #include <linux/err.h>
747 +#include <linux/cooperative_internal.h>
748  
749  asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
750  
751 @@ -147,21 +148,24 @@
752         /* endless idle loop with no priority at all */
753         while (1) {
754                 while (!need_resched()) {
755 -                       void (*idle)(void);
756 -                       /*
757 -                        * Mark this as an RCU critical section so that
758 -                        * synchronize_kernel() in the unload path waits
759 -                        * for our completion.
760 -                        */
761 -                       rcu_read_lock();
762 -                       idle = pm_idle;
763 +                       void (*idle)(void) = pm_idle;
764 +
765 +                       /*
766 +                        * Mark this as an RCU critical section so that
767 +                        * synchronize_kernel() in the unload path waits
768 +                        * for our completion.
769 +                        */
770 +                       rcu_read_lock();
771 +
772 +                       if (cooperative_mode_enabled())
773 +                               idle = co_idle_processor;
774  
775                         if (!idle)
776                                 idle = default_idle;
777  
778                         irq_stat[smp_processor_id()].idle_timestamp = jiffies;
779                         idle();
780 -                       rcu_read_unlock();
781 +                       rcu_read_unlock();
782                 }
783                 schedule();
784         }
785 diff -urN a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
786 --- a/arch/i386/kernel/reboot.c
787 +++ b/arch/i386/kernel/reboot.c
788 @@ -13,6 +13,7 @@
789  #include <asm/uaccess.h>
790  #include <asm/apic.h>
791  #include "mach_reboot.h"
792 +#include <linux/cooperative_internal.h>
793  
794  /*
795   * Power off function, if any
796 @@ -217,6 +218,11 @@
797  {
798         unsigned long flags;
799  
800 +       if (cooperative_mode_enabled()) {
801 +               co_terminate(CO_TERMINATE_REBOOT);
802 +               return;
803 +       }
804 +
805         local_irq_disable();
806  
807         /* Write zero to CMOS register number 0x0f, which the BIOS POST
808 @@ -332,8 +338,13 @@
809          */
810         smp_send_stop();
811  #endif /* CONFIG_SMP */
812 -
813
814         lapic_shutdown();
815
816 +       if (cooperative_mode_enabled()) {
817 +               co_terminate(CO_TERMINATE_REBOOT);
818 +               return;
819 +       }
820  
821  #ifdef CONFIG_X86_IO_APIC
822         disable_IO_APIC();
823 @@ -364,12 +375,18 @@
824  
825  void machine_halt(void)
826  {
827 +       co_terminate(CO_TERMINATE_HALT);
828  }
829  
830  EXPORT_SYMBOL(machine_halt);
831  
832  void machine_power_off(void)
833  {
834 +       if (cooperative_mode_enabled()) {
835 +               co_terminate(CO_TERMINATE_POWEROFF);
836 +               return;
837 +       }
838 +
839         lapic_shutdown();
840  
841         if (efi_enabled)
842 diff -urN a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
843 --- a/arch/i386/kernel/setup.c
844 +++ b/arch/i386/kernel/setup.c
845 @@ -39,6 +39,7 @@
846  #include <linux/efi.h>
847  #include <linux/init.h>
848  #include <linux/edd.h>
849 +#include <linux/cooperative_internal.h>
850  #include <video/edid.h>
851  #include <asm/e820.h>
852  #include <asm/mpspec.h>
853 @@ -668,8 +669,17 @@
854         int len = 0;
855         int userdef = 0;
856  
857 -       /* Save unparsed command line copy for /proc/cmdline */
858 -       saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
859 +       if (cooperative_mode_enabled()) {
860 +               /*
861 +                * Better to have 'root=/dev/cobd0' here.
862 +                */
863 +               from = co_boot_parameters;
864 +               snprintf(saved_command_line, COMMAND_LINE_SIZE, "%s", 
865 +                        co_boot_parameters);
866 +       } else {
867 +               /* Save unparsed command line copy for /proc/cmdline */
868 +               saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
869 +       }
870  
871         for (;;) {
872                 /*
873 @@ -1019,6 +1029,8 @@
874  static unsigned long __init setup_memory(void)
875  {
876         unsigned long bootmap_size, start_pfn, max_low_pfn;
877 +       extern char _end;
878 +       unsigned long start_va = 0;
879  
880         /*
881          * partially used pages are not usable - thus
882 @@ -1026,9 +1038,16 @@
883          */
884         start_pfn = PFN_UP(init_pg_tables_end);
885  
886 -       find_max_pfn();
887 -
888 -       max_low_pfn = find_max_low_pfn();
889 +       if (cooperative_mode_enabled()) {
890 +            max_low_pfn = max_pfn = co_memory_size / PAGE_SIZE;
891 +            start_pfn = PFN_UP(__pa((unsigned long)&_end)) + 0x10;
892 +            start_va = (unsigned long)__va(start_pfn << PAGE_SHIFT);
893 +            co_alloc_pages(start_va, 0x20);
894 +       } else {
895 +            find_max_pfn();
896 +            
897 +            max_low_pfn = find_max_low_pfn();
898 +       }
899  
900  #ifdef CONFIG_HIGHMEM
901         highstart_pfn = highend_pfn = max_pfn;
902 @@ -1040,37 +1059,47 @@
903  #endif
904         printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
905                         pages_to_mb(max_low_pfn));
906 -       /*
907 -        * Initialize the boot-time allocator (with low memory only):
908 -        */
909 -       bootmap_size = init_bootmem(start_pfn, max_low_pfn);
910  
911 -       register_bootmem_low_pages(max_low_pfn);
912  
913         /*
914 -        * Reserve the bootmem bitmap itself as well. We do this in two
915 -        * steps (first step was init_bootmem()) because this catches
916 -        * the (very unlikely) case of us accidentally initializing the
917 -        * bootmem allocator with an invalid RAM area.
918 +        * Initialize the boot-time allocator (with low memory only):
919          */
920 -       reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
921 -                        bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
922 +       bootmap_size = init_bootmem(start_pfn, max_low_pfn);
923  
924 -       /*
925 -        * reserve physical page 0 - it's a special BIOS page on many boxes,
926 -        * enabling clean reboots, SMP operation, laptop functions.
927 -        */
928 -       reserve_bootmem(0, PAGE_SIZE);
929  
930 -       /* reserve EBDA region, it's a 4K region */
931 -       reserve_ebda_region();
932 +       if (cooperative_mode_enabled()) {
933 +               unsigned long bootmem_end = start_va + bootmap_size + (0x10 << PAGE_SHIFT);
934 +               unsigned long physical_end = __PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT);
935 +           
936 +               free_bootmem(__pa(bootmem_end), physical_end - bootmem_end);
937 +       } else {
938 +               register_bootmem_low_pages(max_low_pfn); 
939 +               
940 +               /*
941 +                * Reserve the bootmem bitmap itself as well. We do this in two
942 +                * steps (first step was init_bootmem()) because this catches
943 +                * the (very unlikely) case of us accidentally initializing the
944 +                * bootmem allocator with an invalid RAM area.
945 +                */
946 +               reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
947 +                                bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
948 +       
949 +               /*
950 +                * reserve physical page 0 - it's a special BIOS page on many boxes,
951 +                * enabling clean reboots, SMP operation, laptop functions.
952 +                */
953 +               reserve_bootmem(0, PAGE_SIZE);
954  
955 -    /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent
956 -       PCI prefetch into it (errata #56). Usually the page is reserved anyways,
957 -       unless you have no PS/2 mouse plugged in. */
958 -       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
959 -           boot_cpu_data.x86 == 6)
960 -            reserve_bootmem(0xa0000 - 4096, 4096);
961 +               /* reserve EBDA region, it's a 4K region */
962 +               reserve_ebda_region();
963 +       
964 +           /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent
965 +              PCI prefetch into it (errata #56). Usually the page is reserved anyways,
966 +              unless you have no PS/2 mouse plugged in. */
967 +               if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
968 +                   boot_cpu_data.x86 == 6)
969 +                    reserve_bootmem(0xa0000 - 4096, 4096);
970 +       }
971  
972  #ifdef CONFIG_SMP
973         /*
974 @@ -1094,6 +1123,7 @@
975  #endif
976  
977  #ifdef CONFIG_BLK_DEV_INITRD
978 +#ifndef CONFIG_COOPERATIVE
979         if (LOADER_TYPE && INITRD_START) {
980                 if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
981                         reserve_bootmem(INITRD_START, INITRD_SIZE);
982 @@ -1109,6 +1139,17 @@
983                         initrd_start = 0;
984                 }
985         }
986 +#else
987 +       if (co_initrd != NULL) {
988 +               printk(KERN_INFO "initrd enabled: start: 0x%x  size: 0x%08lx)\n",
989 +                      (unsigned int)co_initrd, (long unsigned int)co_initrd_size);
990 +               
991 +               initrd_start = (unsigned long)co_initrd;
992 +               initrd_end = (unsigned long)co_initrd + co_initrd_size;
993 +               
994 +               reserve_bootmem(virt_to_phys(co_initrd), co_initrd_size);
995 +       }
996 +#endif
997  #endif
998         return max_low_pfn;
999  }
1000 @@ -1315,6 +1356,7 @@
1001                 efi_enabled = 1;
1002  #endif
1003  
1004 +       boot_cpu_data.hard_math = 1;
1005         ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
1006         drive_info = DRIVE_INFO;
1007         screen_info = SCREEN_INFO;
1008 @@ -1338,7 +1380,7 @@
1009         ARCH_SETUP
1010         if (efi_enabled)
1011                 efi_init();
1012 -       else {
1013 +       else if (!cooperative_mode_enabled()) {
1014                 printk(KERN_INFO "BIOS-provided physical RAM map:\n");
1015                 print_memory_map(machine_specific_memory_setup());
1016         }
1017 @@ -1392,8 +1434,9 @@
1018         }
1019  #endif
1020  
1021 -
1022 -       dmi_scan_machine();
1023 +       if (!cooperative_mode_enabled()) {
1024 +            dmi_scan_machine();
1025 +       }
1026  
1027  #ifdef CONFIG_X86_GENERICARCH
1028         generic_apic_probe(*cmdline_p);
1029 @@ -1411,9 +1454,14 @@
1030                 get_smp_config();
1031  #endif
1032  
1033 -       register_memory(max_low_pfn);
1034 +       if (!cooperative_mode_enabled()) {
1035 +            register_memory(max_low_pfn);
1036 +       }
1037  
1038  #ifdef CONFIG_VT
1039 +#ifdef CONFIG_COOPERATIVE_CONSOLE
1040 +       conswitchp = &colinux_con;
1041 +#else
1042  #if defined(CONFIG_VGA_CONSOLE)
1043         if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
1044                 conswitchp = &vga_con;
1045 @@ -1421,6 +1469,7 @@
1046         conswitchp = &dummy_con;
1047  #endif
1048  #endif
1049 +#endif
1050  }
1051  
1052  #include "setup_arch_post.h"
1053 diff -urN a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
1054 --- a/arch/i386/kernel/sysenter.c
1055 +++ b/arch/i386/kernel/sysenter.c
1056 @@ -13,6 +13,7 @@
1057  #include <linux/gfp.h>
1058  #include <linux/string.h>
1059  #include <linux/elf.h>
1060 +#include <linux/cooperative_internal.h>
1061  
1062  #include <asm/cpufeature.h>
1063  #include <asm/msr.h>
1064 @@ -43,11 +44,11 @@
1065  
1066  static int __init sysenter_setup(void)
1067  {
1068 -       void *page = (void *)get_zeroed_page(GFP_ATOMIC);
1069 +       void *page = get_zeroed_page(GFP_ATOMIC);
1070  
1071         __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
1072  
1073 -       if (!boot_cpu_has(X86_FEATURE_SEP)) {
1074 +       if (cooperative_mode_enabled() || !boot_cpu_has(X86_FEATURE_SEP)) {
1075                 memcpy(page,
1076                        &vsyscall_int80_start,
1077                        &vsyscall_int80_end - &vsyscall_int80_start);
1078 @@ -59,6 +60,7 @@
1079                &vsyscall_sysenter_end - &vsyscall_sysenter_start);
1080  
1081         on_each_cpu(enable_sep_cpu, NULL, 1, 1);
1082 +
1083         return 0;
1084  }
1085  
1086 diff -urN a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
1087 --- a/arch/i386/kernel/time.c
1088 +++ b/arch/i386/kernel/time.c
1089 @@ -45,6 +45,7 @@
1090  #include <linux/sysdev.h>
1091  #include <linux/bcd.h>
1092  #include <linux/efi.h>
1093 +#include <linux/cooperative_internal.h>
1094  
1095  #include <asm/io.h>
1096  #include <asm/smp.h>
1097 @@ -94,8 +95,9 @@
1098  void do_gettimeofday(struct timeval *tv)
1099  {
1100         unsigned long seq;
1101 -       unsigned long usec, sec;
1102 -       unsigned long max_ntp_tick;
1103 +       unsigned long sec;
1104 +       long usec;
1105 +       long max_ntp_tick;
1106  
1107         do {
1108                 unsigned long lost;
1109 @@ -129,6 +131,13 @@
1110                 sec++;
1111         }
1112  
1113 +       if (cooperative_mode_enabled()) {
1114 +               while (usec < 0) {
1115 +                       usec += 1000000;
1116 +                       sec--;
1117 +               }
1118 +       }
1119 +
1120         tv->tv_sec = sec;
1121         tv->tv_usec = usec;
1122  }
1123 @@ -174,6 +183,9 @@
1124  {
1125         int retval;
1126  
1127 +       if (cooperative_mode_enabled())
1128 +               return -1;
1129 +
1130         /* gets recalled with irq locally disabled */
1131         spin_lock(&rtc_lock);
1132         if (efi_enabled)
1133 @@ -243,7 +255,8 @@
1134          * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
1135          * called as close as possible to 500 ms before the new second starts.
1136          */
1137 -       if ((time_status & STA_UNSYNC) == 0 &&
1138 +       if (!cooperative_mode_enabled() &&
1139 +           (time_status & STA_UNSYNC) == 0 &&
1140             xtime.tv_sec > last_rtc_update + 660 &&
1141             (xtime.tv_nsec / 1000)
1142                         >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
1143 @@ -307,6 +320,9 @@
1144  {
1145         unsigned long retval;
1146  
1147 +       if (cooperative_mode_enabled())
1148 +               return co_get_host_time();
1149 +
1150         spin_lock(&rtc_lock);
1151  
1152         if (efi_enabled)
1153 diff -urN a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile
1154 --- a/arch/i386/kernel/timers/Makefile
1155 +++ b/arch/i386/kernel/timers/Makefile
1156 @@ -7,3 +7,4 @@
1157  obj-$(CONFIG_X86_CYCLONE_TIMER)        += timer_cyclone.o
1158  obj-$(CONFIG_HPET_TIMER)       += timer_hpet.o
1159  obj-$(CONFIG_X86_PM_TIMER)     += timer_pm.o
1160 +obj-$(CONFIG_COOPERATIVE)      += timer_cooperative.o
1161 diff -urN a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
1162 --- a/arch/i386/kernel/timers/timer.c
1163 +++ b/arch/i386/kernel/timers/timer.c
1164 @@ -13,6 +13,9 @@
1165  #endif
1166  /* list of timers, ordered by preference, NULL terminated */
1167  static struct init_timer_opts* __initdata timers[] = {
1168 +#ifdef CONFIG_COOPERATIVE
1169 +       &timer_cooperative_init,
1170 +#endif
1171  #ifdef CONFIG_X86_CYCLONE_TIMER
1172         &timer_cyclone_init,
1173  #endif
1174 diff -urN a/arch/i386/kernel/timers/timer_cooperative.c b/arch/i386/kernel/timers/timer_cooperative.c
1175 --- a/arch/i386/kernel/timers/timer_cooperative.c
1176 +++ b/arch/i386/kernel/timers/timer_cooperative.c
1177 @@ -0,0 +1,140 @@
1178 +/*
1179 + *  Cooperative mode timer.
1180 + *
1181 + *  Dan Aloni <da-x@colinux.org>, 2003-2004 (C).
1182 + */
1183 +
1184 +#include <linux/init.h>
1185 +#include <linux/errno.h>
1186 +
1187 +#include <asm/timer.h>
1188 +#include <asm/cooperative.h>
1189 +#include <asm/div64.h>
1190 +#include <asm/param.h>
1191 +
1192 +#include <linux/cooperative.h>
1193 +#include <linux/cooperative_internal.h>
1194 +
1195 +static unsigned long long first_time;
1196 +static unsigned long frequencey;
1197 +static unsigned long long last_mark, last_mark_quotient;
1198 +static unsigned long long last_time;
1199 +
1200 +static unsigned long long query_host_highprec_time(void)
1201 +{
1202 +       unsigned long flags;
1203 +       unsigned long long this_time;
1204 +       unsigned long long diff;
1205 +
1206 +       co_passage_page_assert_valid(); 
1207 +       
1208 +       co_passage_page_acquire(&flags);
1209 +       co_passage_page->operation = CO_OPERATION_GET_HIGH_PREC_TIME;
1210 +       co_switch_wrapper();
1211 +
1212 +       this_time = *(unsigned long long *)(&co_passage_page->params[0]);
1213 +       frequencey = *(unsigned long *)(&co_passage_page->params[2]);
1214 +       diff = ((long long)this_time - (long long)last_time);
1215 +       
1216 +       /*
1217 +        * There shouldn't be any particularly large difference between
1218 +        * the current and last host timestamps. For sanity, reset the 
1219 +         * global reference variables if we encounter any difference 
1220 +        * larger than one second.
1221 +        */
1222 +
1223 +       if (diff < 0 || diff > frequencey) {
1224 +               first_time = this_time;
1225 +               last_mark_quotient = last_mark = 0;
1226 +       }
1227 +
1228 +       last_time = this_time;
1229 +       co_passage_page_release(flags);
1230 +
1231 +       return this_time;
1232 +}
1233 +
1234 +static unsigned long long monotonic_clock_cooperative(void)
1235 +{
1236 +       return 0;
1237 +}
1238 +
1239 +static long get_offset_cooperative(void)
1240 +{
1241 +       unsigned long flags;
1242 +
1243 +       local_irq_save(flags);
1244 +       
1245 +       unsigned long long this_time = query_host_highprec_time() - first_time;
1246 +       unsigned long reminder = 0, result;
1247 +       long long diff, lldiff;
1248 +       long signed_result;
1249 +
1250 +       diff = ((long long)this_time - (long long)(last_mark));
1251 +       if (diff < 0)
1252 +               lldiff = -diff;
1253 +       else
1254 +               lldiff = diff;
1255 +       
1256 +       lldiff *= 1000000;
1257 +       result = div_ll_X_l_rem(lldiff, frequencey, &reminder);
1258 +
1259 +       signed_result = result;
1260 +       if (diff < 0)
1261 +               signed_result = -signed_result;
1262 +
1263 +       local_irq_restore(flags);
1264 +       return signed_result;
1265 +}
1266 +
1267 +static void mark_offset_cooperative(void)
1268 +{
1269 +       unsigned long flags;
1270 +       local_irq_save(flags);
1271 +
1272 +       last_mark += frequencey / HZ;
1273 +       last_mark_quotient += frequencey % HZ;
1274 +       if (frequencey > HZ) {
1275 +               last_mark += 1;
1276 +               last_mark_quotient -= HZ;
1277 +       }
1278 +
1279 +       local_irq_restore(flags);
1280 +}
1281 +
1282 +static void delay_cooperative(unsigned long loops)
1283 +{
1284 +       /*
1285 +        * A bogos delay loop for creating BogoMIPS...
1286 +        */
1287 +
1288 +       loops = loops / 10000;
1289 +       while (loops) {
1290 +               query_host_highprec_time();
1291 +               loops -= 1;
1292 +       }
1293 +}
1294 +
1295 +static int __init init_cooperative_timer(char* override)
1296 +{
1297 +       first_time = query_host_highprec_time();
1298 +
1299 +       /* Always pick this timer */
1300 +       return 0;
1301 +}
1302 +
1303 +/************************************************************/
1304 +
1305 +/* tsc timer_opts struct */
1306 +struct timer_opts timer_cooperative = {
1307 +       .name =                 "cooperative",
1308 +       .mark_offset =          mark_offset_cooperative,
1309 +       .get_offset =           get_offset_cooperative,
1310 +       .monotonic_clock =      monotonic_clock_cooperative,
1311 +       .delay =                delay_cooperative,
1312 +};
1313 +
1314 +struct init_timer_opts __initdata timer_cooperative_init = {
1315 +       .init = init_cooperative_timer,
1316 +       .opts = &timer_cooperative,
1317 +};
1318 diff -urN a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c
1319 --- a/arch/i386/kernel/timers/timer_cyclone.c
1320 +++ b/arch/i386/kernel/timers/timer_cyclone.c
1321 @@ -103,7 +103,7 @@
1322                 jiffies_64++;
1323  }
1324  
1325 -static unsigned long get_offset_cyclone(void)
1326 +static long get_offset_cyclone(void)
1327  {
1328         u32 offset;
1329  
1330 diff -urN a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
1331 --- a/arch/i386/kernel/timers/timer_hpet.c
1332 +++ b/arch/i386/kernel/timers/timer_hpet.c
1333 @@ -73,7 +73,7 @@
1334         return base + cycles_2_ns(this_offset - last_offset);
1335  }
1336  
1337 -static unsigned long get_offset_hpet(void)
1338 +static long get_offset_hpet(void)
1339  {
1340         register unsigned long eax, edx;
1341  
1342 diff -urN a/arch/i386/kernel/timers/timer_none.c b/arch/i386/kernel/timers/timer_none.c
1343 --- a/arch/i386/kernel/timers/timer_none.c
1344 +++ b/arch/i386/kernel/timers/timer_none.c
1345 @@ -6,7 +6,7 @@
1346         /* nothing needed */
1347  }
1348  
1349 -static unsigned long get_offset_none(void)
1350 +static long get_offset_none(void)
1351  {
1352         return 0;
1353  }
1354 diff -urN a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
1355 --- a/arch/i386/kernel/timers/timer_pit.c
1356 +++ b/arch/i386/kernel/timers/timer_pit.c
1357 @@ -89,7 +89,7 @@
1358   * comp.protocols.time.ntp!
1359   */
1360  
1361 -static unsigned long get_offset_pit(void)
1362 +static long get_offset_pit(void)
1363  {
1364         int count;
1365         unsigned long flags;
1366 diff -urN a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
1367 --- a/arch/i386/kernel/timers/timer_pm.c
1368 +++ b/arch/i386/kernel/timers/timer_pm.c
1369 @@ -227,7 +227,7 @@
1370   * get the offset (in microseconds) from the last call to mark_offset()
1371   *     - Called holding a reader xtime_lock
1372   */
1373 -static unsigned long get_offset_pmtmr(void)
1374 +static long get_offset_pmtmr(void)
1375  {
1376         u32 now, offset, delta = 0;
1377  
1378 diff -urN a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
1379 --- a/arch/i386/kernel/timers/timer_tsc.c
1380 +++ b/arch/i386/kernel/timers/timer_tsc.c
1381 @@ -83,7 +83,7 @@
1382   */
1383  static unsigned long fast_gettimeoffset_quotient;
1384  
1385 -static unsigned long get_offset_tsc(void)
1386 +static long get_offset_tsc(void)
1387  {
1388         register unsigned long eax, edx;
1389  
1390 diff -urN a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
1391 --- a/arch/i386/kernel/traps.c
1392 +++ b/arch/i386/kernel/traps.c
1393 @@ -51,6 +51,9 @@
1394  #include <asm/arch_hooks.h>
1395  #include <asm/kdebug.h>
1396  
1397 +#include <linux/cooperative_internal.h>
1398 +#include <asm/cooperative_internal.h>
1399 +
1400  #include <linux/irq.h>
1401  #include <linux/module.h>
1402  
1403 @@ -382,6 +385,12 @@
1404         }
1405  
1406         kernel_trap: {
1407 +               if (cooperative_mode_enabled()) {
1408 +                       if (trapnr == 3) {
1409 +                               co_kernel_breakpoint(regs);
1410 +                               return;
1411 +                       }
1412 +               }
1413                 if (!fixup_exception(regs))
1414                         die(str, regs, error_code);
1415                 return;
1416 @@ -683,9 +692,15 @@
1417         unsigned int condition;
1418         struct task_struct *tsk = current;
1419         siginfo_t info;
1420 -
1421 +       
1422         __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
1423  
1424 +       if (cooperative_mode_enabled() && 
1425 +           co_kernel_debug(regs, error_code, condition))
1426 +       {
1427 +               return;
1428 +       }
1429 +
1430         if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
1431                                         SIGTRAP) == NOTIFY_STOP)
1432                 return;
1433 diff -urN a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
1434 --- a/arch/i386/kernel/vmlinux.lds.S
1435 +++ b/arch/i386/kernel/vmlinux.lds.S
1436 @@ -14,11 +14,12 @@
1437  {
1438    . = __PAGE_OFFSET + 0x100000;
1439    /* read-only */
1440 +  _kernel_start = .            ; 
1441    _text = .;                   /* Text and read-only data */
1442    .text : {
1443         *(.text)
1444         SCHED_TEXT
1445 -       LOCK_TEXT
1446 +       LOCK_TEXT
1447         *(.fixup)
1448         *(.gnu.warning)
1449         } = 0x9090
1450 diff -urN a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
1451 --- a/arch/i386/mm/fault.c
1452 +++ b/arch/i386/mm/fault.c
1453 @@ -449,7 +449,8 @@
1454         printk(KERN_ALERT " printing eip:\n");
1455         printk("%08lx\n", regs->eip);
1456         asm("movl %%cr3,%0":"=r" (page));
1457 -       page = ((unsigned long *) __va(page))[address >> 22];
1458 +       page = ((unsigned long *) __va(CO_P_TO_PP(page)))[address >> 22];
1459 +       page = CO_P_TO_PP(page);
1460         printk(KERN_ALERT "*pde = %08lx\n", page);
1461         /*
1462          * We must not directly access the pte in the highpte
1463 @@ -462,6 +463,7 @@
1464                 page &= PAGE_MASK;
1465                 address &= 0x003ff000;
1466                 page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
1467 +               page = CO_P_TO_PP(page);
1468                 printk(KERN_ALERT "*pte = %08lx\n", page);
1469         }
1470  #endif
1471 @@ -522,7 +524,7 @@
1472                 pte_t *pte_k;
1473  
1474                 asm("movl %%cr3,%0":"=r" (pgd_paddr));
1475 -               pgd = index + (pgd_t *)__va(pgd_paddr);
1476 +               pgd = index + (pgd_t *)__va(CO_P_TO_PP((unsigned long)pgd_paddr));
1477                 pgd_k = init_mm.pgd + index;
1478  
1479                 if (!pgd_present(*pgd_k))
1480 diff -urN a/arch/i386/mm/init.c b/arch/i386/mm/init.c
1481 --- a/arch/i386/mm/init.c
1482 +++ b/arch/i386/mm/init.c
1483 @@ -27,6 +27,7 @@
1484  #include <linux/slab.h>
1485  #include <linux/proc_fs.h>
1486  #include <linux/efi.h>
1487 +#include <linux/cooperative_internal.h>
1488  
1489  #include <asm/processor.h>
1490  #include <asm/system.h>
1491 @@ -76,7 +77,7 @@
1492  {
1493         if (pmd_none(*pmd)) {
1494                 pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
1495 -               set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
1496 +               set_pmd(pmd, __pmd(CO_PP_TO_P(__pa(page_table)) | _PAGE_TABLE));
1497                 if (page_table != pte_offset_kernel(pmd, 0))
1498                         BUG();  
1499  
1500 @@ -313,21 +314,23 @@
1501                 set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
1502  #endif
1503  
1504 -       /* Enable PSE if available */
1505 -       if (cpu_has_pse) {
1506 -               set_in_cr4(X86_CR4_PSE);
1507 -       }
1508 -
1509 -       /* Enable PGE if available */
1510 -       if (cpu_has_pge) {
1511 -               set_in_cr4(X86_CR4_PGE);
1512 -               __PAGE_KERNEL |= _PAGE_GLOBAL;
1513 -               __PAGE_KERNEL_EXEC |= _PAGE_GLOBAL;
1514 +       if (!cooperative_mode_enabled()) {
1515 +               /* Enable PSE if available */
1516 +               if (cpu_has_pse) {
1517 +                       set_in_cr4(X86_CR4_PSE);
1518 +               }
1519 +               
1520 +               /* Enable PGE if available */
1521 +               if (cpu_has_pge) {
1522 +                       set_in_cr4(X86_CR4_PGE);
1523 +                       __PAGE_KERNEL |= _PAGE_GLOBAL;
1524 +                       __PAGE_KERNEL_EXEC |= _PAGE_GLOBAL;
1525 +               }
1526 +               
1527 +               kernel_physical_mapping_init(pgd_base);
1528 +               remap_numa_kva();
1529         }
1530  
1531 -       kernel_physical_mapping_init(pgd_base);
1532 -       remap_numa_kva();
1533 -
1534         /*
1535          * Fixed mappings, only the page table structure has to be
1536          * created - mappings will be set by set_fixmap():
1537 @@ -394,19 +397,26 @@
1538         unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
1539         unsigned int max_dma, high, low;
1540         
1541 -       max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
1542 -       low = max_low_pfn;
1543 -       high = highend_pfn;
1544 -       
1545 -       if (low < max_dma)
1546 -               zones_size[ZONE_DMA] = low;
1547 -       else {
1548 -               zones_size[ZONE_DMA] = max_dma;
1549 -               zones_size[ZONE_NORMAL] = low - max_dma;
1550 +       if (!cooperative_mode_enabled()) {
1551 +               max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
1552 +               low = max_low_pfn;
1553 +               high = highend_pfn;
1554 +               
1555 +               if (low < max_dma)
1556 +                       zones_size[ZONE_DMA] = low;
1557 +               else {
1558 +                       zones_size[ZONE_DMA] = max_dma;
1559 +                       zones_size[ZONE_NORMAL] = low - max_dma;
1560  #ifdef CONFIG_HIGHMEM
1561 -               zones_size[ZONE_HIGHMEM] = high - low;
1562 +                       zones_size[ZONE_HIGHMEM] = high - low;
1563  #endif
1564 +               }
1565 +       } else {
1566 +               zones_size[ZONE_DMA] = 0;
1567 +               zones_size[ZONE_NORMAL] = max_low_pfn;
1568 +               zones_size[ZONE_HIGHMEM] = 0;
1569         }
1570 +
1571         free_area_init(zones_size);     
1572  }
1573  #else
1574 @@ -574,7 +584,6 @@
1575         if (!mem_map)
1576                 BUG();
1577  #endif
1578 -       
1579         bad_ppro = ppro_with_ram_bug();
1580  
1581  #ifdef CONFIG_HIGHMEM
1582 @@ -630,8 +639,10 @@
1583         if (!cpu_has_pae)
1584                 panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
1585  #endif
1586 -       if (boot_cpu_data.wp_works_ok < 0)
1587 -               test_wp_bit();
1588 +       if (!cooperative_mode_enabled()) {
1589 +               if (boot_cpu_data.wp_works_ok < 0)
1590 +                       test_wp_bit();
1591 +       }
1592  
1593         /*
1594          * Subtle. SMP is doing it's boot stuff late (because it has to
1595 diff -urN a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
1596 --- a/arch/i386/mm/ioremap.c
1597 +++ b/arch/i386/mm/ioremap.c
1598 @@ -11,6 +11,7 @@
1599  #include <linux/vmalloc.h>
1600  #include <linux/init.h>
1601  #include <linux/slab.h>
1602 +#include <linux/cooperative_internal.h>
1603  #include <asm/io.h>
1604  #include <asm/fixmap.h>
1605  #include <asm/cacheflush.h>
1606 @@ -190,7 +191,14 @@
1607  void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
1608  {
1609         unsigned long last_addr;
1610 -       void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
1611 +       void __iomem *p;
1612 +
1613 +       if (cooperative_mode_enabled()) {
1614 +               panic("ioremap_nocache %ld:%ld\n", phys_addr, size);
1615 +               return NULL;
1616 +       }
1617 +
1618 +       p = __ioremap(phys_addr, size, _PAGE_PCD);
1619         if (!p) 
1620                 return p; 
1621  
1622 diff -urN a/drivers/block/Kconfig b/drivers/block/Kconfig
1623 --- a/drivers/block/Kconfig
1624 +++ b/drivers/block/Kconfig
1625 @@ -358,6 +358,15 @@
1626           "real" root file system, etc. See <file:Documentation/initrd.txt>
1627           for details.
1628  
1629 +config BLK_DEV_COBD
1630 +       tristate 'Cooperative block device support'
1631 +       default y
1632 +       depends on COOPERATIVE=y
1633 +       help
1634 +         Virtual block device support for cooperative kernels.
1635 +
1636 +         If unsure, say Y.
1637 +
1638  config INITRAMFS_SOURCE
1639         string "Source directory of cpio_list"
1640         default ""
1641 diff -urN a/drivers/block/Makefile b/drivers/block/Makefile
1642 --- a/drivers/block/Makefile
1643 +++ b/drivers/block/Makefile
1644 @@ -29,6 +29,7 @@
1645  obj-$(CONFIG_ATARI_SLM)                += acsi_slm.o
1646  obj-$(CONFIG_AMIGA_Z2RAM)      += z2ram.o
1647  obj-$(CONFIG_BLK_DEV_RAM)      += rd.o
1648 +obj-$(CONFIG_BLK_DEV_COBD)     += cobd.o
1649  obj-$(CONFIG_BLK_DEV_LOOP)     += loop.o
1650  obj-$(CONFIG_BLK_DEV_PS2)      += ps2esdi.o
1651  obj-$(CONFIG_BLK_DEV_XD)       += xd.o
1652 diff -urN a/drivers/block/cobd.c b/drivers/block/cobd.c
1653 --- a/drivers/block/cobd.c
1654 +++ b/drivers/block/cobd.c
1655 @@ -0,0 +1,540 @@
1656 +/*
1657 + *  Copyright (C) 2003 Dan Aloni <da-x@colinux.org>
1658 + *
1659 + *  Cooperative Linux Block Device implementation
1660 + */
1661 +
1662 +#include <linux/major.h>
1663 +#include <linux/config.h>
1664 +#include <linux/module.h>
1665 +#include <linux/init.h>
1666 +#include <linux/fs.h>
1667 +#include <linux/errno.h>
1668 +#include <linux/major.h>
1669 +#include <linux/stat.h>
1670 +#include <linux/slab.h>
1671 +#include <linux/bio.h>
1672 +#include <linux/blkdev.h>
1673 +#include <linux/cooperative_internal.h>
1674 +#include <linux/file.h>
1675 +#include <linux/ioctl.h>
1676 +#include <linux/ctype.h>
1677 +
1678 +#include <asm/uaccess.h>
1679 +#include <asm/types.h>
1680 +
1681 +#include <linux/devfs_fs_kernel.h>
1682 +
1683 +#define PBD_BLOCK_SIZE  512
1684 +
1685 +static int hardsect_size = 512;
1686 +static int hardsect_size_shift = 9;
1687 +static spinlock_t cobd_lock = SPIN_LOCK_UNLOCKED;
1688 +static int cobd_max;
1689 +
1690 +struct cobd_device {
1691 +       int unit;
1692 +       int refcount;
1693 +       struct block_device *device;
1694 +};
1695 +
1696 +static int cobd_request(struct cobd_device *cobd, co_block_request_type_t type, co_block_request_t *out_request)
1697 +{
1698 +       co_block_request_t *request;
1699 +       unsigned long flags;
1700 +       long rc = 0;
1701 +
1702 +       co_passage_page_assert_valid();
1703 +
1704 +       co_passage_page_acquire(&flags);
1705 +       co_passage_page->operation = CO_OPERATION_DEVICE;
1706 +       co_passage_page->params[0] = CO_DEVICE_BLOCK;
1707 +       co_passage_page->params[1] = cobd->unit;
1708 +       request = (co_block_request_t *)&co_passage_page->params[2];
1709 +       request->type = type;
1710 +       request->rc = -1;
1711 +       co_switch_wrapper();
1712 +       rc = request->rc;
1713 +       *out_request = *request;
1714 +       co_passage_page_release(flags);
1715 +
1716 +       return rc;
1717 +}
1718 +
1719 +static int cobd_stat(struct cobd_device *cobd, co_block_request_t *out_request)
1720 +{
1721 +       return cobd_request(cobd, CO_BLOCK_STAT, out_request);
1722 +}
1723 +
1724 +static int cobd_get_alias(struct cobd_device *cobd, co_block_request_t *out_request)
1725 +{
1726 +       return cobd_request(cobd, CO_BLOCK_GET_ALIAS, out_request);
1727 +}
1728 +
1729 +static int cobd_ioctl(struct inode * inode, struct file * file,
1730 +                     unsigned int cmd, unsigned long arg)
1731 +{
1732 +       return -ENOTTY; /* unknown command */
1733 +}
1734 +
1735 +static int cobd_open(struct inode *inode, struct file *file)
1736 +{
1737 +       struct cobd_device *cobd = (struct cobd_device *)(inode->i_bdev->bd_disk->private_data);
1738 +       co_block_request_t *co_request;
1739 +       co_block_request_t stat_request;
1740 +       unsigned long flags;
1741 +       int result;
1742 +
1743 +       if (cobd->device  &&  cobd->device != inode->i_bdev)
1744 +               return -EBUSY;
1745 +
1746 +       if (cobd_stat(cobd, &stat_request))
1747 +               return -ENODEV;
1748 +
1749 +       result = 0;
1750 +
1751 +       co_passage_page_assert_valid();
1752 +
1753 +       co_passage_page_acquire(&flags);
1754 +       co_passage_page->operation = CO_OPERATION_DEVICE;
1755 +       co_passage_page->params[0] = CO_DEVICE_BLOCK;
1756 +       co_passage_page->params[1] = cobd->unit;
1757 +       co_request = (co_block_request_t *)&co_passage_page->params[2];
1758 +       co_request->type = CO_BLOCK_OPEN;
1759 +       co_switch_wrapper();
1760 +       if (co_request->rc)
1761 +               result = -EIO;
1762 +       else
1763 +               cobd->refcount++;
1764 +       co_passage_page_release(flags);
1765 +
1766 +       if (result)
1767 +               return result;
1768 +
1769 +       if (cobd->refcount == 1) {
1770 +               set_capacity(inode->i_bdev->bd_disk, stat_request.disk_size >> 9);
1771 +               cobd->device = inode->i_bdev;
1772 +       }
1773 +
1774 +       return 0;
1775 +}
1776 +
1777 +static int cobd_release(struct inode *inode, struct file *file)
1778 +{
1779 +       struct cobd_device *cobd = (struct cobd_device *)(inode->i_bdev->bd_disk->private_data);
1780 +       co_block_request_t *co_request;
1781 +       unsigned long flags;
1782 +       int ret = 0;
1783 +
1784 +       co_passage_page_assert_valid();
1785 +
1786 +       co_passage_page_acquire(&flags);
1787 +       co_passage_page->operation = CO_OPERATION_DEVICE;
1788 +       co_passage_page->params[0] = CO_DEVICE_BLOCK;
1789 +       co_passage_page->params[1] = cobd->unit;
1790 +       co_request = (co_block_request_t *)&co_passage_page->params[2];
1791 +       co_request->type = CO_BLOCK_CLOSE;
1792 +       co_switch_wrapper();
1793 +       if (co_request->rc)
1794 +               ret = -EIO;
1795 +       cobd->refcount--;
1796 +       co_passage_page_release(flags);
1797 +
1798 +       if (cobd->refcount == 0)
1799 +               cobd->device = NULL;
1800 +
1801 +       return ret;
1802 +}
1803 +
1804 +/*
1805 + * Handle an I/O request.
1806 + */
1807 +static int cobd_transfer(struct cobd_device *cobd, unsigned long sector,
1808 +                        unsigned long nsect, char *buffer, int write)
1809 +{
1810 +       co_block_request_t *co_request;
1811 +       unsigned long flags;
1812 +       int ret = 0;
1813 +
1814 +       co_passage_page_assert_valid();
1815 +
1816 +       co_passage_page_acquire(&flags);
1817 +       co_passage_page->operation = CO_OPERATION_DEVICE;
1818 +       co_passage_page->params[0] = CO_DEVICE_BLOCK;
1819 +       co_passage_page->params[1] = cobd->unit;
1820 +       co_request = (co_block_request_t *)&co_passage_page->params[2];
1821 +       if (!write)
1822 +               co_request->type = CO_BLOCK_READ;
1823 +       else
1824 +               co_request->type = CO_BLOCK_WRITE;
1825 +       co_request->offset = ((unsigned long long)sector) << hardsect_size_shift;
1826 +       co_request->size = nsect << hardsect_size_shift;
1827 +       co_request->address = buffer;
1828 +       co_request->rc = 0;
1829 +       co_switch_wrapper();
1830 +
1831 +       if (!co_request->rc)
1832 +               ret = 1;
1833 +
1834 +       co_passage_page_release(flags);
1835 +       return ret;
1836 +}
1837 +
1838 +static void do_cobd_request(request_queue_t *q)
1839 +{
1840 +        struct request *req;
1841 +       struct cobd_device *cobd;
1842 +    
1843 +        while ((req = elv_next_request(q)) != NULL) {
1844 +               int ret;
1845 +
1846 +               if (!blk_fs_request(req)) {
1847 +                       end_request(req, 0);
1848 +                       continue;
1849 +               }
1850 +               cobd = (struct cobd_device *)(req->rq_disk->private_data);
1851 +               
1852 +               ret = cobd_transfer(cobd, req->sector, req->current_nr_sectors,
1853 +                                   req->buffer, rq_data_dir(req));
1854 +               end_request(req, ret);
1855 +        }
1856 +}
1857 +
1858 +static struct block_device_operations cobd_fops = {
1859 +       .owner   = THIS_MODULE,
1860 +       .open    = cobd_open,
1861 +       .release = cobd_release,
1862 +       .ioctl   = cobd_ioctl,
1863 +};
1864 +
1865 +static struct gendisk **cobd_disks;
1866 +
1867 +static struct cobd_device cobd_devs[CO_MODULE_MAX_COBD];
1868 +
1869 +static int __init cobd_drives_init(void)
1870 +{
1871 +       int result, i;
1872 +
1873 +       if (register_blkdev(COLINUX_MAJOR, "cobd")) {
1874 +               printk(KERN_WARNING "Unable to get major number %d for cobd device\n", COLINUX_MAJOR);
1875 +               return -EIO;
1876 +       }
1877 +
1878 +       cobd_max = CO_MODULE_MAX_COBD;
1879 +
1880 +       result = -ENOMEM; /* for the possible errors */
1881 +
1882 +       cobd_disks = kmalloc(cobd_max * sizeof(struct gendisk *), GFP_KERNEL);
1883 +       if (!cobd_disks)
1884 +               goto fail_malloc;
1885 +
1886 +       for (i=0; i < cobd_max; i++) {
1887 +               cobd_disks[i] = alloc_disk(1);
1888 +               if (!cobd_disks[i])
1889 +                       goto fail_malloc3;
1890 +       }
1891 +
1892 +       for (i=0; i < cobd_max; i++) {
1893 +               struct cobd_device *cobd = &cobd_devs[i];
1894 +               struct gendisk *disk = cobd_disks[i];
1895 +
1896 +               disk->queue = blk_init_queue(do_cobd_request, &cobd_lock);
1897 +               if (!disk->queue)
1898 +                       goto fail_malloc4;
1899 +
1900 +               blk_queue_hardsect_size(disk->queue, hardsect_size);
1901 +
1902 +               cobd->unit = i;
1903 +               disk->major = COLINUX_MAJOR;
1904 +               disk->first_minor = i;
1905 +               disk->fops = &cobd_fops;
1906 +               sprintf(disk->disk_name, "cobd%d", i);
1907 +               sprintf(disk->devfs_name, "cobd/%d", i);
1908 +               disk->private_data = cobd;
1909 +       }
1910 +       
1911 +       devfs_mk_dir("cobd");
1912 +
1913 +       for (i=0; i < cobd_max; i++)
1914 +               add_disk(cobd_disks[i]);
1915 +
1916 +       printk(KERN_INFO "cobd: loaded (max %d devices)\n", cobd_max);
1917 +       return 0;
1918 +
1919 +/* error path */
1920 +fail_malloc4:
1921 +       while (i--)
1922 +               blk_cleanup_queue(cobd_disks[i]->queue);
1923 +       devfs_remove("cobd");
1924 +       i = cobd_max;
1925 +
1926 +fail_malloc3:
1927 +       while (i--) 
1928 +               if (cobd_disks[i] != NULL)
1929 +                       put_disk(cobd_disks[i]);
1930 +
1931 +       kfree(cobd_disks);
1932 +
1933 +fail_malloc:
1934 +       if (unregister_blkdev(COLINUX_MAJOR, "cobd"))
1935 +               printk(KERN_WARNING "cobd: cannot unregister blkdev\n");
1936 +
1937 +       return result;
1938 +}
1939 +
1940 +struct cobd_alias_major {
1941 +       const char *name;
1942 +       int registered;
1943 +       int number;
1944 +};
1945 +
1946 +struct cobd_alias {
1947 +       const char *name;
1948 +       struct cobd_alias_major *major;
1949 +       int minor_start;
1950 +       int minor_count;
1951 +       struct gendisk **gendisk;
1952 +};
1953 +
1954 +struct cobd_alias_major cobd_aliases_major_ide0 = {
1955 +       .name = "ide0",
1956 +       .number = IDE0_MAJOR,
1957 +};
1958 +
1959 +struct cobd_alias_major cobd_aliases_major_ide1 = {
1960 +       .name = "ide1",
1961 +       .number = IDE1_MAJOR,
1962 +};
1963 +
1964 +struct cobd_alias_major cobd_aliases_major_ide2 = {
1965 +       .name = "ide2",
1966 +       .number = IDE2_MAJOR,
1967 +};
1968 +
1969 +struct cobd_alias_major cobd_aliases_major_ide3 = {
1970 +       .name = "ide3",
1971 +       .number = IDE3_MAJOR,
1972 +};
1973 +
1974 +struct cobd_alias_major cobd_aliases_major_sd = {
1975 +       .name = "sd",
1976 +       .number = SCSI_DISK0_MAJOR,
1977 +};
1978 +
1979 +struct cobd_alias cobd_aliases[] = {
1980 +       {"hda", &cobd_aliases_major_ide0, 0x00, 21, },
1981 +       {"hdb", &cobd_aliases_major_ide0, 0x40, 21, },
1982 +       {"hdc", &cobd_aliases_major_ide1, 0x00, 21, },
1983 +       {"hdd", &cobd_aliases_major_ide1, 0x40, 21, },
1984 +       {"hde", &cobd_aliases_major_ide2, 0x00, 21, },
1985 +       {"hdf", &cobd_aliases_major_ide2, 0x40, 21, },
1986 +       {"hdg", &cobd_aliases_major_ide3, 0x00, 21, },
1987 +       {"hdh", &cobd_aliases_major_ide3, 0x40, 21, },
1988 +       {"sda", &cobd_aliases_major_sd, 0x00, 0x10, },
1989 +       {"sdb", &cobd_aliases_major_sd, 0x10, 0x10, },
1990 +       {"sdc", &cobd_aliases_major_sd, 0x20, 0x10, },
1991 +       {"sdd", &cobd_aliases_major_sd, 0x30, 0x10, },
1992 +       {"sde", &cobd_aliases_major_sd, 0x40, 0x10, },
1993 +       {"sdf", &cobd_aliases_major_sd, 0x50, 0x10, },
1994 +       {"sdg", &cobd_aliases_major_sd, 0x60, 0x10, },
1995 +       {"sdh", &cobd_aliases_major_sd, 0x70, 0x10, },
1996 +       {"sdi", &cobd_aliases_major_sd, 0x80, 0x10, },
1997 +       {"sdj", &cobd_aliases_major_sd, 0x90, 0x10, },
1998 +       {"sdk", &cobd_aliases_major_sd, 0xa0, 0x10, },
1999 +       {"sdl", &cobd_aliases_major_sd, 0xb0, 0x10, },
2000 +       {"sdm", &cobd_aliases_major_sd, 0xc0, 0x10, },
2001 +       {"sdn", &cobd_aliases_major_sd, 0xd0, 0x10, },
2002 +       {"sdp", &cobd_aliases_major_sd, 0xe0, 0x10, },
2003 +       {"sdq", &cobd_aliases_major_sd, 0xf0, 0x10, },
2004 +       {NULL, },
2005 +};
2006 +
2007 +static int __init skip_atoi(const char **s)
2008 +{
2009 +       /* lib/spprintf.h */
2010 +
2011 +        int i=0;
2012 +
2013 +        while (isdigit(**s))
2014 +                i = i*10 + *((*s)++) - '0';
2015 +
2016 +        return i;      
2017 +}
2018 +
2019 +static int __init cobd_spawn_alias(struct cobd_alias *alias, 
2020 +                                  const char *alias_name_requested,
2021 +                                  int cobd_unit)
2022 +{
2023 +       const char *index_str_start = &alias_name_requested[strlen(alias->name)];
2024 +       const char *index_str_end = index_str_start;
2025 +       struct cobd_device *cobd;
2026 +       struct gendisk *disk;
2027 +
2028 +       int index = skip_atoi(&index_str_end);
2029 +
2030 +       if (!((index >= 0) && (index <= alias->minor_count))) {
2031 +               printk(KERN_WARNING "index out of bounds for alias %s (1 - %d)\n", 
2032 +                      alias_name_requested, alias->minor_count);
2033 +               return -1;
2034 +       }
2035 +       
2036 +       if (alias->gendisk == NULL) {
2037 +               static struct gendisk **gendisks;
2038 +               gendisks = kmalloc(alias->minor_count * sizeof(struct gendisk *), GFP_KERNEL);
2039 +               memset(gendisks, 0, alias->minor_count * sizeof(struct gendisk *));
2040 +
2041 +               if (!gendisks) {
2042 +                       printk(KERN_WARNING "cannot allocate gendisk array for %s\n", alias->name);
2043 +                       return -ENOMEM;
2044 +               }
2045 +
2046 +               if (!alias->major->registered) {
2047 +                       if (register_blkdev(alias->major->number, alias->major->name)) {
2048 +                               printk(KERN_WARNING "unable to get major number %d for cobd alias device %s\n", 
2049 +                                      alias->major->number, alias_name_requested);
2050 +                               kfree(gendisks);
2051 +                               return -EIO;
2052 +                       }
2053 +
2054 +                       alias->major->registered = 1;
2055 +               }
2056 +
2057 +               alias->gendisk = gendisks;
2058 +               devfs_mk_dir(alias->name);
2059 +       }
2060 +
2061 +       if (alias->gendisk[index] != NULL) {
2062 +               printk(KERN_WARNING "alias %s already used\n", alias_name_requested);
2063 +               return -1;
2064 +       }
2065 +       
2066 +       disk = alloc_disk(1);
2067 +       if (!disk) {
2068 +               printk(KERN_WARNING "cannot allocate disk for alias %s\n", alias_name_requested);
2069 +               return -1;
2070 +       }
2071 +
2072 +       disk->queue = blk_init_queue(do_cobd_request, &cobd_lock);
2073 +       if (!disk->queue) {
2074 +               printk(KERN_WARNING "cannot allocate init queue for alias %s\n", alias_name_requested);
2075 +               put_disk(disk);
2076 +               return -1;
2077 +       }
2078 +
2079 +       cobd = &cobd_devs[cobd_unit];
2080 +       blk_queue_hardsect_size(disk->queue, hardsect_size);
2081 +       disk->major = alias->major->number;
2082 +       disk->first_minor = alias->minor_start + index;
2083 +       disk->fops = &cobd_fops;
2084 +       if (index)
2085 +               sprintf(disk->disk_name, "%s%d", alias->name, index);
2086 +       else
2087 +               sprintf(disk->disk_name, "%s", alias->name);
2088 +       sprintf(disk->devfs_name, "%s/%d", alias->name, index);
2089 +       disk->private_data = cobd;
2090 +       add_disk(disk);
2091 +       alias->gendisk[index] = disk;
2092 +
2093 +       printk("cobd alias cobd%d -> %s created\n", cobd_unit, alias_name_requested);
2094 +
2095 +       return 0;
2096 +}
2097 +
2098 +static int __init cobd_aliases_init(void)
2099 +{
2100 +       int unit;
2101 +       co_block_request_t request;
2102 +
2103 +       for (unit=0; unit < cobd_max; unit++) {
2104 +               int result = cobd_get_alias(&cobd_devs[unit], &request);
2105 +               if (result)
2106 +                       continue;
2107 +
2108 +               printk("alias for cobd%d is %s\n", unit, request.alias);
2109 +               
2110 +               struct cobd_alias *alias = &cobd_aliases[0];
2111 +               while (alias->name) {
2112 +                       const char *match = (strstr(request.alias, alias->name));
2113 +                       if (match == request.alias) {
2114 +                               cobd_spawn_alias(alias, request.alias, unit);
2115 +                               break;
2116 +                       }
2117 +                       alias++;
2118 +               }
2119 +
2120 +               if (alias->name == NULL)
2121 +                       printk("alias %s is unknown (see cobd_aliases in cobd.c)\n", request.alias);
2122 +       }
2123 +
2124 +       return 0;
2125 +}
2126 +
2127 +static void cobd_drives_exit(void) 
2128 +{
2129 +       int i;
2130 +
2131 +       for (i = 0; i < cobd_max; i++) {
2132 +               blk_cleanup_queue(cobd_disks[i]->queue);
2133 +               del_gendisk(cobd_disks[i]);
2134 +               put_disk(cobd_disks[i]);
2135 +       }
2136 +
2137 +       devfs_remove("cobd");
2138 +       if (unregister_blkdev(COLINUX_MAJOR, "cobd"))
2139 +               printk(KERN_WARNING "cobd: cannot unregister blkdev\n");
2140 +
2141 +       kfree(cobd_disks);
2142 +}
2143 +
2144 +static void cobd_aliases_exit(void) 
2145 +{
2146 +       struct cobd_alias *alias = &cobd_aliases[0];
2147 +       while (alias->name != NULL) {
2148 +               if (alias->gendisk == NULL) {
2149 +                       alias++;
2150 +                       continue;
2151 +               }
2152 +
2153 +               int index;
2154 +               for (index=0; index < alias->minor_count; index++) {
2155 +                       struct gendisk *disk = alias->gendisk[index];
2156 +                       if (!disk)
2157 +                               return;
2158 +                       
2159 +                       blk_cleanup_queue(disk->queue);
2160 +                       del_gendisk(disk);
2161 +                       put_disk(disk);
2162 +               }
2163 +
2164 +               devfs_remove(alias->name);
2165 +               if (!alias->major->registered) {
2166 +                       unregister_blkdev(alias->major->number, alias->major->name);
2167 +                       alias->major->registered = 0;
2168 +               }
2169 +               kfree(alias->gendisk);
2170 +
2171 +               alias++;
2172 +       }
2173 +}
2174 +
2175 +static int __init cobd_init(void)
2176 +{
2177 +       int result = cobd_drives_init();
2178 +       if (result)
2179 +               return result;
2180 +
2181 +       cobd_aliases_init();
2182 +       
2183 +       return result;          
2184 +}
2185 +
2186 +static void cobd_exit(void) 
2187 +{
2188 +       cobd_aliases_exit();
2189 +       cobd_drives_exit();
2190 +}
2191 +
2192 +module_init(cobd_init);
2193 +module_exit(cobd_exit);
2194 +
2195 +
2196 diff -urN a/drivers/char/Makefile b/drivers/char/Makefile
2197 --- a/drivers/char/Makefile
2198 +++ b/drivers/char/Makefile
2199 @@ -27,6 +27,7 @@
2200  obj-$(CONFIG_STALLION)         += stallion.o
2201  obj-$(CONFIG_ISTALLION)                += istallion.o
2202  obj-$(CONFIG_DIGI)             += pcxx.o
2203 +obj-$(CONFIG_COOPERATIVE)      += cocd.o
2204  obj-$(CONFIG_DIGIEPCA)         += epca.o
2205  obj-$(CONFIG_SPECIALIX)                += specialix.o
2206  obj-$(CONFIG_MOXA_INTELLIO)    += moxa.o
2207 diff -urN a/drivers/char/cocd.c b/drivers/char/cocd.c
2208 --- a/drivers/char/cocd.c
2209 +++ b/drivers/char/cocd.c
2210 @@ -0,0 +1,368 @@
2211 +/*
2212 + *  Copyright (C) 2004 Dan Aloni <da-x@colinux.org>
2213 + *
2214 + *  Cooperative Linux Serial Line implementation
2215 + * 
2216 + *  Compatible with UML, also based on some code from there.
2217 + *  Also based on The tiny_tty.c example driver by Greg Kroah-Hartman (greg@kroah.com).
2218 + */
2219 +
2220 +/*
2221 + * 20040908: Ballard, Jonathan H. <jhballard@hotmail.com>
2222 + *        : Implemented cocd_task() & throttle.
2223 + * 20041224: Used schedule() instead of shedule_work().
2224 + * 20050101: Uses interruptible_sleep_on() and wake_up() instead of schedule().
2225 + *         : Uses list_*() for dispatched data flow to each unit.
2226 + *         : Handles multiple units in seperate tasks.
2227 + *
2228 +*/
2229 +
2230 +
2231 +#include <linux/major.h>
2232 +#include <linux/config.h>
2233 +#include <linux/module.h>
2234 +#include <linux/init.h>
2235 +#include <linux/fs.h>
2236 +#include <linux/errno.h>
2237 +#include <linux/major.h>
2238 +#include <linux/stat.h>
2239 +#include <linux/file.h>
2240 +#include <linux/ioctl.h>
2241 +#include <linux/device.h>
2242 +#include <linux/console.h>
2243 +#include <linux/wait.h>
2244 +
2245 +#include <linux/workqueue.h>
2246 +#include <linux/devfs_fs_kernel.h>
2247 +#include <linux/tty.h>
2248 +#include <linux/tty_flip.h>
2249 +
2250 +#include <linux/cooperative_internal.h>
2251 +
2252 +#include <asm/uaccess.h>
2253 +
2254 +struct cocd_tty {
2255 +       struct semaphore        sem;            /* locks this structure */
2256 +       struct tty_struct       *tty;           /* tty for this device */
2257 +       unsigned                open_count;     /* open()/close() tally */
2258 +       struct work_struct      work;           /* individual unit task */
2259 +       struct list_head        inq;            /* input queue */
2260 +       wait_queue_head_t       waitq;
2261 +       int                     throttled;      /* data flow throttle bit */
2262 +};
2263 +
2264 +static struct tty_driver *cocd_driver = NULL;
2265 +DECLARE_MUTEX(cocd_sem);
2266 +
2267 +static void cocd_unit_task(void *data)
2268 +{
2269 +       co_message_node_t *input;
2270 +       struct cocd_tty *cocd = data;
2271 +       co_linux_message_t *message;
2272 +       char *p, *e, *m;
2273 +       struct tty_struct *tty;
2274 +
2275 +       tty = cocd->tty;
2276 +
2277 +       while(cocd->open_count) {
2278 +               down(&cocd->sem);
2279 +               if(list_empty(&cocd->inq)) {
2280 +                       up(&cocd->sem);
2281 +                       interruptible_sleep_on(&cocd->waitq);
2282 +                       continue;
2283 +                       }
2284 +               input = list_entry(cocd->inq.prev, co_message_node_t, node);
2285 +               up(&cocd->sem);
2286 +
2287 +               message = (co_linux_message_t *)&input->msg.data;
2288 +               e = (m = p = message->data) + message->size;
2289 +               while(p < e && cocd->open_count) {
2290 +                       if(cocd->throttled) {
2291 +                               interruptible_sleep_on(&cocd->waitq);
2292 +                               continue;
2293 +                               }
2294 +                       if(e < (m += (TTY_FLIPBUF_SIZE - tty->flip.count)))
2295 +                               m = e;
2296 +                       while(p < m) 
2297 +                               tty_insert_flip_char(tty, *(p++), 0);
2298 +                       if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
2299 +                               tty_flip_buffer_push(tty);
2300 +                       }
2301 +               }
2302 +               down(&cocd->sem);
2303 +               list_del(&input->node);
2304 +               up(&cocd->sem);
2305 +               co_free_message(input);
2306 +               if(tty->flip.count && cocd->open_count) {
2307 +                       if(cocd->throttled) {
2308 +                               interruptible_sleep_on(&cocd->waitq);
2309 +                               }
2310 +                       tty_flip_buffer_push(tty);
2311 +                       continue;
2312 +               }
2313 +       }
2314 +       down(&cocd->sem);
2315 +       while(!list_empty(&cocd->inq)) {
2316 +               input = list_entry(cocd->inq.prev, co_message_node_t, node);
2317 +               list_del(&input->node);
2318 +               co_free_message(input);
2319 +               }
2320 +       up(&cocd->sem);
2321 +       kfree(cocd);
2322 +}
2323 +
2324 +int cocd_open(struct tty_struct *tty, struct file * filp)
2325 +{
2326 +       struct cocd_tty *cocd =  NULL;
2327 +
2328 +       down(&cocd_sem);
2329 +
2330 +       /* MOD_INC_USE_COUNT; - Removed in 2.6, reference count is handled
2331 +        *   outside the module in 2.6
2332 +        */
2333 +
2334 +       if ((cocd = (struct cocd_tty *)tty->driver_data)) {
2335 +               down (&cocd->sem);
2336 +       } else {
2337 +               if(!(cocd = kmalloc(sizeof(*cocd), GFP_KERNEL))) {
2338 +                       /* MOD_DEC_USE_COUNT; - Removed in 2.6, reference count
2339 +                        *   is handled  outside the module in 2.6
2340 +                        */
2341 +
2342 +                       up(&cocd_sem);
2343 +                       return -ENOMEM;
2344 +               }
2345 +
2346 +               init_MUTEX_LOCKED(&cocd->sem);
2347 +               cocd->open_count = 0;
2348 +               cocd->tty = tty;
2349 +               cocd->throttled = 0;
2350 +               INIT_WORK(&cocd->work, cocd_unit_task, cocd);
2351 +               INIT_LIST_HEAD(&cocd->inq);
2352 +               init_waitqueue_head(&cocd->waitq);
2353 +               tty->driver_data = cocd;
2354 +               tty->low_latency = 1;
2355 +               schedule_work(&cocd->work);
2356 +       }
2357 +
2358 +       cocd->open_count++;
2359 +
2360 +       up(&cocd->sem);
2361 +       up(&cocd_sem);
2362 +       
2363 +       return 0;
2364 +}
2365 +
2366 +void cocd_close(struct tty_struct *tty, struct file * filp)
2367 +{
2368 +       struct cocd_tty *cocd =  NULL;
2369 +
2370 +       down(&cocd_sem);
2371 +
2372 +       cocd = (struct cocd_tty *)tty->driver_data;
2373 +       if (!cocd) {
2374 +               printk("cocd: no attached struct\n");
2375 +               goto out;
2376 +       }
2377 +
2378 +       down(&cocd->sem);
2379 +       if (cocd->open_count == 1) { /* last close */
2380 +               tty->driver_data = NULL;
2381 +               wake_up(&cocd->waitq);
2382 +       }
2383 +       cocd->open_count--;
2384 +       up(&cocd->sem);
2385 +
2386 +out:
2387 +       /* MOD_DEC_USE_COUNT; - Removed in 2.6, reference count is handled
2388 +        *   outside the module in 2.6
2389 +        */
2390 +
2391 +       up(&cocd_sem);
2392 +}
2393 +
2394 +void cocd_interrupt(void)
2395 +{
2396 +       if (!cocd_driver)
2397 +               return;
2398 +
2399 +       co_message_node_t *input;
2400 +       if(!co_get_message(&input, CO_DEVICE_SERIAL))
2401 +               return;
2402 +       if(!input)
2403 +               return;
2404 +
2405 +       co_linux_message_t *message;
2406 +       struct tty_struct *tty;
2407 +       struct cocd_tty *cocd;
2408 +       message = (co_linux_message_t *)&input->msg.data;
2409 +       down(&cocd_sem);
2410 +       if (message->unit < CO_MODULE_MAX_SERIAL
2411 +        && (tty = cocd_driver->ttys[message->unit])
2412 +        && (cocd = (struct cocd_tty *)tty->driver_data)) {
2413 +               up(&cocd_sem);
2414 +               down(&cocd->sem);
2415 +               list_add_tail(&input->node,&cocd->inq);
2416 +               up(&cocd->sem);
2417 +               wake_up(&cocd->waitq);
2418 +               return;
2419 +               }
2420 +       up(&cocd_sem);
2421 +       co_free_message(input);
2422 +}
2423 +
2424 +int cocd_write(struct tty_struct * tty,
2425 +              const unsigned char *buf, int count)
2426 +{
2427 +       const char *kbuf_scan = NULL;
2428 +       int count_left;
2429 +
2430 +       kbuf_scan = buf;
2431 +       count_left = count;
2432 +
2433 +       while (count_left > 0) {
2434 +               int count_partial = count_left;
2435 +               if (count_partial > 1000)
2436 +                       count_partial = 1000;
2437 +
2438 +               co_send_message(CO_MODULE_LINUX,
2439 +                               CO_MODULE_SERIAL0 + tty->index,
2440 +                               CO_PRIORITY_DISCARDABLE,
2441 +                               CO_MESSAGE_TYPE_STRING,
2442 +                               count_partial,
2443 +                               kbuf_scan);
2444 +               
2445 +               count_left -= count_partial;
2446 +               kbuf_scan += count_partial;
2447 +       }
2448 +
2449 +       return count;
2450 +}
2451 +
2452 +int cocd_write_room(struct tty_struct *tty)
2453 +{
2454 +       struct cocd_tty *cocd = NULL;
2455 +
2456 +       cocd = (struct cocd_tty *)tty->driver_data;
2457 +       if (!cocd)
2458 +               return 0;
2459 +
2460 +       down(&cocd->sem);
2461 +       if (cocd->open_count == 0) {
2462 +               /* port was not opened */
2463 +               up(&cocd->sem);
2464 +               return 0;
2465 +       }
2466 +
2467 +       up(&cocd->sem);
2468 +       return 255;
2469 +}
2470 +
2471 +void cocd_hangup(struct tty_struct *tty)
2472 +{
2473 +}
2474 +
2475 +void cocd_throttle(struct tty_struct * tty)
2476 +{
2477 +       struct cocd_tty *cocd;
2478 +       cocd = (struct cocd_tty *)tty->driver_data;
2479 +       if (!cocd)
2480 +               return;
2481 +       down(&cocd->sem);
2482 +       cocd->throttled = 1;
2483 +       up(&cocd->sem);
2484 +}
2485 +
2486 +void cocd_unthrottle(struct tty_struct * tty)
2487 +{
2488 +       struct cocd_tty *cocd;
2489 +       cocd = (struct cocd_tty *)tty->driver_data;
2490 +       if (!cocd)
2491 +               return;
2492 +       down(&cocd->sem);
2493 +       cocd->throttled = 0;
2494 +       up(&cocd->sem);
2495 +       wake_up(&cocd->waitq);
2496 +}
2497 +
2498 +void cocd_flush_buffer(struct tty_struct *tty)
2499 +{
2500 +}
2501 +
2502 +void cocd_set_termios(struct tty_struct *tty, struct termios *old_termios)
2503 +{
2504 +}
2505 +
2506 +int cocd_chars_in_buffer(struct tty_struct *tty)
2507 +{
2508 +       return 0;
2509 +}
2510 +
2511 +static struct tty_operations cocd_ops = {
2512 +       .open = cocd_open,
2513 +       .close = cocd_close,
2514 +       .write = cocd_write,
2515 +       .write_room = cocd_write_room,
2516 +       .flush_buffer = cocd_flush_buffer,
2517 +       .throttle = cocd_throttle,
2518 +       .unthrottle = cocd_unthrottle,
2519 +       .hangup = cocd_hangup, 
2520 +       .chars_in_buffer = cocd_chars_in_buffer, 
2521 +       .set_termios = cocd_set_termios,
2522 +};
2523 +
2524 +static struct tty_driver *cocd_driver;
2525 +
2526 +static void cocd_console_write(struct console *c, const char *string,  unsigned len)
2527 +{
2528 +}
2529 +
2530 +static struct tty_driver *cocd_console_device(struct console *c, int *index)
2531 +{
2532 +        *index = c->index;
2533 +        return cocd_driver;
2534 +}
2535 +
2536 +static int cocd_console_setup(struct console *co, char *options)
2537 +{
2538 +        return(0);
2539 +}
2540 +
2541 +static struct console cocd_cons = {
2542 +        name:           "ttyS",
2543 +        write:          cocd_console_write,
2544 +        device:         cocd_console_device,
2545 +        setup:          cocd_console_setup,
2546 +        flags:          CON_PRINTBUFFER,
2547 +        index:          -1,
2548 +};
2549 +
2550 +static int __init cocd_init(void)
2551 +{
2552 +       cocd_driver = alloc_tty_driver(CO_MODULE_MAX_SERIAL);
2553 +
2554 +       if (!cocd_driver)
2555 +               panic("Couldn't allocate cocd driver");
2556 +
2557 +       cocd_driver->owner = THIS_MODULE;
2558 +       cocd_driver->driver_name = "Cooperative serial lines";
2559 +       cocd_driver->name = "ttS";
2560 +       cocd_driver->devfs_name = "tts/";
2561 +       cocd_driver->major = TTY_MAJOR;
2562 +       cocd_driver->minor_start = 64;
2563 +       cocd_driver->type = TTY_DRIVER_TYPE_SERIAL;
2564 +       cocd_driver->subtype = 0;
2565 +       cocd_driver->init_termios = tty_std_termios;
2566 +       cocd_driver->flags = 0;
2567 +
2568 +       tty_set_operations(cocd_driver, &cocd_ops);
2569 +       
2570 +       if (tty_register_driver(cocd_driver))
2571 +               panic("Couldn't register cocd driver");
2572 +       
2573 +       register_console(&cocd_cons);
2574 +
2575 +       return 0;
2576 +}
2577 +
2578 +module_init(cocd_init);
2579 diff -urN a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
2580 --- a/drivers/input/keyboard/Kconfig
2581 +++ b/drivers/input/keyboard/Kconfig
2582 @@ -16,7 +16,7 @@
2583         default y
2584         depends on INPUT && INPUT_KEYBOARD
2585         select SERIO
2586 -       select SERIO_I8042 if PC
2587 +       select SERIO_I8042 if PC && !COOPERATIVE
2588         select SERIO_GSCPS2 if GSC
2589         help
2590           Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
2591 diff -urN a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
2592 --- a/drivers/input/keyboard/atkbd.c
2593 +++ b/drivers/input/keyboard/atkbd.c
2594 @@ -26,6 +26,7 @@
2595  #include <linux/input.h>
2596  #include <linux/serio.h>
2597  #include <linux/workqueue.h>
2598 +#include <linux/cooperative_internal.h>
2599  
2600  #define DRIVER_DESC    "AT and PS/2 keyboard driver"
2601  
2602 @@ -640,6 +641,9 @@
2603  {
2604         unsigned char param[2];
2605  
2606 +       if (cooperative_mode_enabled())
2607 +               return 0;
2608 +
2609  /*
2610   * Some systems, where the bit-twiddling when testing the io-lines of the
2611   * controller may confuse the keyboard need a full reset of the keyboard. On
2612 diff -urN a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
2613 --- a/drivers/input/mouse/Kconfig
2614 +++ b/drivers/input/mouse/Kconfig
2615 @@ -14,7 +14,7 @@
2616  config MOUSE_PS2
2617         tristate "PS/2 mouse"
2618         default y
2619 -       depends on INPUT && INPUT_MOUSE
2620 +       depends on INPUT && INPUT_MOUSE && !COOPERATIVE
2621         select SERIO
2622         select SERIO_I8042 if PC
2623         select SERIO_GSCPS2 if GSC
2624 @@ -36,9 +36,21 @@
2625           To compile this driver as a module, choose M here: the
2626           module will be called psmouse.
2627  
2628 +config MOUSE_COOPERATIVE
2629 +       tristate "Cooperative Mouse driver"
2630 +       default y
2631 +       depends on INPUT && INPUT_MOUSE && COOPERATIVE
2632 +       ---help---
2633 +         Virtual mouse driver for cooperative kernels.
2634 +         
2635 +         If unsure, say Y.
2636 +
2637 +         To compile this driver as a module, choose M here: the
2638 +         module will be called psmouse.
2639 +
2640  config MOUSE_SERIAL
2641         tristate "Serial mouse"
2642 -       depends on INPUT && INPUT_MOUSE
2643 +       depends on INPUT && INPUT_MOUSE && !COOPERATIVE
2644         select SERIO
2645         ---help---
2646           Say Y here if you have a serial (RS-232, COM port) mouse connected
2647 @@ -52,7 +64,7 @@
2648  
2649  config MOUSE_INPORT
2650         tristate "InPort/MS/ATIXL busmouse"
2651 -       depends on INPUT && INPUT_MOUSE && ISA
2652 +       depends on INPUT && INPUT_MOUSE && ISA && !COOPERATIVE
2653         help
2654           Say Y here if you have an InPort, Microsoft or ATI XL busmouse.
2655           They are rather rare these days.
2656 @@ -62,13 +74,13 @@
2657  
2658  config MOUSE_ATIXL
2659         bool "ATI XL variant"
2660 -       depends on MOUSE_INPORT
2661 +       depends on MOUSE_INPORT && !COOPERATIVE
2662         help
2663           Say Y here if your mouse is of the ATI XL variety.
2664  
2665  config MOUSE_LOGIBM
2666         tristate "Logitech busmouse"
2667 -       depends on INPUT && INPUT_MOUSE && ISA
2668 +       depends on INPUT && INPUT_MOUSE && ISA && !COOPERATIVE
2669         help
2670           Say Y here if you have a Logitech busmouse.
2671           They are rather rare these days.
2672 @@ -78,7 +90,7 @@
2673  
2674  config MOUSE_PC110PAD
2675         tristate "IBM PC110 touchpad"
2676 -       depends on INPUT && INPUT_MOUSE && ISA
2677 +       depends on INPUT && INPUT_MOUSE && ISA && !COOPERATIVE
2678         help
2679           Say Y if you have the IBM PC-110 micro-notebook and want its
2680           touchpad supported.
2681 @@ -88,7 +100,7 @@
2682  
2683  config MOUSE_MAPLE
2684         tristate "Maple bus mouse"
2685 -       depends on SH_DREAMCAST && INPUT && INPUT_MOUSE && MAPLE
2686 +       depends on SH_DREAMCAST && INPUT && INPUT_MOUSE && MAPLE && !COOPERATIVE
2687         help
2688           Say Y if you have a DreamCast console and a mouse attached to
2689           its Maple bus.
2690 @@ -98,7 +110,7 @@
2691  
2692  config MOUSE_AMIGA
2693         tristate "Amiga mouse"
2694 -       depends on AMIGA && INPUT && INPUT_MOUSE
2695 +       depends on AMIGA && INPUT && INPUT_MOUSE && !COOPERATIVE
2696         help
2697           Say Y here if you have an Amiga and want its native mouse
2698           supported by the kernel.
2699 @@ -108,7 +120,7 @@
2700  
2701  config MOUSE_RISCPC
2702         tristate "Acorn RiscPC mouse"
2703 -       depends on ARCH_ACORN && INPUT && INPUT_MOUSE
2704 +       depends on ARCH_ACORN && INPUT && INPUT_MOUSE && !COOPERATIVE
2705         help
2706           Say Y here if you have the Acorn RiscPC computer and want its
2707           native mouse supported.
2708 @@ -118,7 +130,7 @@
2709  
2710  config MOUSE_VSXXXAA
2711         tristate "DEC VSXXX-AA/GA mouse and VSXXX-AB tablet"
2712 -       depends on INPUT && INPUT_MOUSE
2713 +       depends on INPUT && INPUT_MOUSE && !COOPERATIVE
2714         select SERIO
2715         help
2716           Say Y (or M) if you want to use a DEC VSXXX-AA (hockey
2717 diff -urN a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
2718 --- a/drivers/input/mouse/Makefile
2719 +++ b/drivers/input/mouse/Makefile
2720 @@ -11,6 +11,7 @@
2721  obj-$(CONFIG_MOUSE_MAPLE)      += maplemouse.o
2722  obj-$(CONFIG_MOUSE_PC110PAD)   += pc110pad.o
2723  obj-$(CONFIG_MOUSE_PS2)                += psmouse.o
2724 +obj-$(CONFIG_MOUSE_COOPERATIVE)        += comouse.o
2725  obj-$(CONFIG_MOUSE_SERIAL)     += sermouse.o
2726  obj-$(CONFIG_MOUSE_VSXXXAA)    += vsxxxaa.o
2727  
2728 diff -urN a/drivers/input/mouse/comouse.c b/drivers/input/mouse/comouse.c
2729 --- a/drivers/input/mouse/comouse.c
2730 +++ b/drivers/input/mouse/comouse.c
2731 @@ -0,0 +1,74 @@
2732 +/*
2733 + * Virtual mouse driver for Linux
2734 + * 
2735 + * Skeleton based on:
2736 + *  $Id: sermouse.c,v 1.17 2002/03/13 10:03:43 vojtech Exp $
2737 + *
2738 + *  Copyright (c) 1999-2001 Vojtech Pavlik
2739 + *
2740 + * Copyright (c) 2004 Dan Aloni
2741 + */
2742 +
2743 +#include <linux/module.h>
2744 +#include <linux/slab.h>
2745 +#include <linux/interrupt.h>
2746 +#include <linux/input.h>
2747 +#include <linux/config.h>
2748 +#include <linux/serio.h>
2749 +#include <linux/init.h>
2750 +
2751 +MODULE_AUTHOR("Dan Aloni <da-x@colinux.org>");
2752 +MODULE_DESCRIPTION("Virtual mouse driver");
2753 +MODULE_LICENSE("GPL");
2754 +
2755 +/*
2756 + * comouse_interrupt() handles incoming characters, either gathering them into
2757 + * packets or passing them to the command routine as command output.
2758 + */
2759 +
2760 +static irqreturn_t comouse_interrupt(struct serio *serio,
2761 +                                    unsigned char data, unsigned int flags, struct pt_regs *regs)
2762 +{
2763 +       return IRQ_HANDLED;
2764 +}
2765 +
2766 +/*
2767 + * comouse_disconnect() cleans up after we don't want talk
2768 + * to the mouse anymore.
2769 + */
2770 +
2771 +static void comouse_disconnect(struct serio *serio)
2772 +{
2773 +}
2774 +
2775 +/*
2776 + * comouse_connect() is a callback form the serio module when
2777 + * an unhandled serio port is found.
2778 + */
2779 +
2780 +static void comouse_connect(struct serio *serio, struct serio_driver *dev)
2781 +{
2782 +}
2783 +
2784 +static struct serio_driver comouse_dev = {
2785 +       .interrupt =    comouse_interrupt,
2786 +       .connect =      comouse_connect,
2787 +       .disconnect =   comouse_disconnect,
2788 +       .driver         = {
2789 +               .name   = "comouse",
2790 +       },
2791 +};
2792 +
2793 +int __init comouse_init(void)
2794 +{
2795 +       serio_register_driver(&comouse_dev); 
2796 +       return 0;
2797 +}
2798 +
2799 +void __exit comouse_exit(void)
2800 +{
2801 +       serio_unregister_driver(&comouse_dev); 
2802 +}
2803 +
2804 +module_init(comouse_init);
2805 +module_exit(comouse_exit);
2806 diff -urN a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
2807 --- a/drivers/input/serio/Kconfig
2808 +++ b/drivers/input/serio/Kconfig
2809 @@ -20,7 +20,7 @@
2810         tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
2811         default y
2812         select SERIO
2813 -       depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K
2814 +       depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !COOPERATIVE
2815         ---help---
2816           i8042 is the chip over which the standard AT keyboard and PS/2
2817           mouse are connected to the computer. If you use these devices,
2818 @@ -132,17 +132,22 @@
2819           module will be called maceps2.
2820  
2821  config SERIO_RAW
2822 -       tristate "Raw access to serio ports"
2823 -       depends on SERIO
2824 -       help
2825 -         Say Y here if you want to have raw access to serio ports, such as
2826 -         AUX ports on i8042 keyboard controller. Each serio port that is
2827 -         bound to this driver will be accessible via a char device with
2828 -         major 10 and dynamically allocated minor. The driver will try
2829 -         allocating minor 1 (that historically corresponds to /dev/psaux)
2830 -         first. To bind this driver to a serio port use sysfs interface:
2831 -
2832 -             echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
2833 -
2834 -         To compile this driver as a module, choose M here: the
2835 -         module will be called serio_raw.
2836 +       tristate "Raw access to serio ports"
2837 +       depends on SERIO
2838 +       help
2839 +         Say Y here if you want to have raw access to serio ports, such as
2840 +         AUX ports on i8042 keyboard controller. Each serio port that is
2841 +         bound to this driver will be accessible via a char device with
2842 +         major 10 and dynamically allocated minor. The driver will try
2843 +         allocating minor 1 (that historically corresponds to /dev/psaux)
2844 +         first. To bind this driver to a serio port use sysfs interface:
2845
2846 +             echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
2847
2848 +         To compile this driver as a module, choose M here: the
2849 +         module will be called serio_raw.
2850 +
2851 +config SERIO_COKBD
2852 +       tristate "Cooperative Linux virtual keyboard controller driver"
2853 +       depends on COOPERATIVE
2854 +       default y
2855 diff -urN a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
2856 --- a/drivers/input/serio/Makefile
2857 +++ b/drivers/input/serio/Makefile
2858 @@ -18,3 +18,4 @@
2859  obj-$(CONFIG_SERIO_PCIPS2)     += pcips2.o
2860  obj-$(CONFIG_SERIO_MACEPS2)    += maceps2.o
2861  obj-$(CONFIG_SERIO_RAW)                += serio_raw.o
2862 +obj-$(CONFIG_SERIO_COKBD)      += cokbd.o
2863 \ No newline at end of file
2864 diff -urN a/drivers/input/serio/cokbd.c b/drivers/input/serio/cokbd.c
2865 --- a/drivers/input/serio/cokbd.c
2866 +++ b/drivers/input/serio/cokbd.c
2867 @@ -0,0 +1,155 @@
2868 +/*
2869 + *  Cooperative Linux virtual keyboard controller driver
2870 + *
2871 + *  Copyright (c) 1999-2002 Dan Aloni <da-x@colinux.org)
2872 + *    Based on 98kbd-io.c written by Osamu Tomita>
2873 + */
2874 +
2875 +/*
2876 + * This program is free software; you can redistribute it and/or modify it
2877 + * under the terms of the GNU General Public License version 2 as published by
2878 + * the Free Software Foundation.
2879 + */
2880 +
2881 +#include <linux/config.h>
2882 +#include <linux/delay.h>
2883 +#include <linux/module.h>
2884 +#include <linux/interrupt.h>
2885 +#include <linux/ioport.h>
2886 +#include <linux/init.h>
2887 +#include <linux/serio.h>
2888 +#include <linux/sched.h>
2889 +#include <linux/cooperative_internal.h>
2890 +
2891 +#include <asm/io.h>
2892 +
2893 +MODULE_AUTHOR("Dan Aloni <da-x@colinux.org>");
2894 +MODULE_DESCRIPTION("Cooperative Linux virtual keyboard controller driver");
2895 +MODULE_LICENSE("GPL");
2896 +
2897 +/*
2898 + * Names.
2899 + */
2900 +
2901 +#define COKBD_PHYS_DESC        "cokbd"
2902 +
2903 +static struct serio cokbd_port;
2904 +
2905 +static irqreturn_t cokbdio_interrupt(int irq, void *dev_id, struct pt_regs *regs);
2906 +
2907 +/*
2908 + * cokbd_flush() flushes all data that may be in the keyboard buffers
2909 + */
2910 +
2911 +static int cokbd_flush(void)
2912 +{
2913 +#if (0)        
2914 +       co_linux_message_t *message;
2915 +
2916 +       while (co_get_message(&message, CO_DEVICE_KEYBOARD)) {
2917 +               co_free_message(message);
2918 +       }
2919 +#endif
2920 +       return 0;
2921 +}
2922 +
2923 +/*
2924 + * cokbd_write() sends a byte out through the keyboard interface.
2925 + */
2926 +
2927 +#define ATKBD_CMD_GETID                0x02f2
2928 +
2929 +static void cokbd_receive(struct serio *port, unsigned char c)
2930 +{
2931 +       struct pt_regs regs= {0, };
2932 +
2933 +       serio_interrupt(port, c, 0, &regs);
2934 +}
2935 +
2936 +static int cokbd_write(struct serio *port, unsigned char c)
2937 +{
2938 +       return 0;
2939 +}
2940 +
2941 +/*
2942 + * cokbd_open() is called when a port is open by the higher layer.
2943 + * It allocates the interrupt and enables in in the chip.
2944 + */
2945 +
2946 +static int cokbd_open(struct serio *port)
2947 +{
2948 +       cokbd_flush();
2949 +
2950 +       if (request_irq(KEYBOARD_IRQ, cokbdio_interrupt, 0, "cokbd", NULL)) {
2951 +               printk(KERN_ERR "cobkd.c: Can't get irq %d for %s, unregistering the port.\n", KEYBOARD_IRQ, "KBD");
2952 +               serio_unregister_port(port);
2953 +               return -1;
2954 +       }
2955 +
2956 +       return 0;
2957 +}
2958 +
2959 +static void cokbd_close(struct serio *port)
2960 +{
2961 +       printk(KERN_INFO "cokbd closed\n");
2962 +
2963 +       free_irq(KEYBOARD_IRQ, NULL);
2964 +
2965 +       cokbd_flush();
2966 +}
2967 +
2968 +/*
2969 + * Structures for registering the devices in the serio.c module.
2970 + */
2971 +
2972 +static struct serio cokbd_port =
2973 +{
2974 +       .type =         SERIO_8042_XL,
2975 +       .write =        cokbd_write,
2976 +       .open =         cokbd_open,
2977 +       .close =        cokbd_close,
2978 +       .name =         "cokbd port",
2979 +       .phys =         COKBD_PHYS_DESC,
2980 +};
2981 +
2982 +/*
2983 + * cokbdio_interrupt() is the most important function in this driver -
2984 + * it handles the interrupts from keyboard, and sends incoming bytes
2985 + * to the upper layers.
2986 + */
2987 +
2988 +static irqreturn_t cokbdio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
2989 +{
2990 +       co_message_node_t *node_message;
2991 +       while (co_get_message(&node_message, CO_DEVICE_KEYBOARD)) {
2992 +               co_linux_message_t *message = (co_linux_message_t *)&node_message->msg.data;
2993 +               co_scan_code_t *sc = (co_scan_code_t *)message->data;
2994 +               unsigned long scancode = sc->code;
2995 +               
2996 +               if (!sc->down)
2997 +                       scancode |= 0x80;
2998 +               
2999 +               cokbd_receive(&cokbd_port, scancode);
3000 +               
3001 +               co_free_message(node_message);
3002 +       }
3003 +       
3004 +       return IRQ_HANDLED;
3005 +}
3006 +
3007 +int __init cokbdio_init(void)
3008 +{
3009 +       serio_register_port(&cokbd_port);
3010 +
3011 +       printk(KERN_INFO "serio: cokbd at irq %d\n", KEYBOARD_IRQ);
3012 +
3013 +       return 0;
3014 +}
3015 +
3016 +void __exit cokbdio_exit(void)
3017 +{
3018 +       serio_unregister_port(&cokbd_port);
3019 +}
3020 +
3021 +module_init(cokbdio_init);
3022 +module_exit(cokbdio_exit);
3023 diff -urN a/drivers/net/Kconfig b/drivers/net/Kconfig
3024 --- a/drivers/net/Kconfig
3025 +++ b/drivers/net/Kconfig
3026 @@ -127,6 +127,10 @@
3027  
3028           If you don't know what to use this for, you don't need it.
3029  
3030 +config COOPERATIVE_CONET
3031 +       tristate 'Cooperative Virtual Ethernet driver support'
3032 +       depends on COOPERATIVE
3033 +
3034  config NET_SB1000
3035         tristate "General Instruments Surfboard 1000"
3036         depends on NETDEVICES && PNP
3037 diff -urN a/drivers/net/Makefile b/drivers/net/Makefile
3038 --- a/drivers/net/Makefile
3039 +++ b/drivers/net/Makefile
3040 @@ -152,6 +152,7 @@
3041  
3042  # This is also a 82596 and should probably be merged
3043  obj-$(CONFIG_LP486E) += lp486e.o
3044 +obj-$(CONFIG_COOPERATIVE_CONET) += conet.o
3045  
3046  obj-$(CONFIG_ETH16I) += eth16i.o
3047  obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
3048 diff -urN a/drivers/net/conet.c b/drivers/net/conet.c
3049 --- a/drivers/net/conet.c
3050 +++ b/drivers/net/conet.c
3051 @@ -0,0 +1,305 @@
3052 +/*
3053 + *  Copyright (C) 2003-2004 Dan Aloni <da-x@gmx.net>
3054 + *  Copyright (C) 2004 Pat Erley
3055 + *  Copyright (C) 2004 George Boutwell
3056 + *
3057 + *  Cooperative Linux Network Device implementation
3058 + */
3059 +
3060 +#include <linux/config.h>
3061 +#include <linux/version.h>
3062 +#include <linux/module.h>
3063 +
3064 +#include <linux/kernel.h>
3065 +
3066 +#include <linux/netdevice.h>
3067 +#include <linux/etherdevice.h>
3068 +#include <linux/skbuff.h>
3069 +#include <linux/ethtool.h>
3070 +
3071 +#include <linux/cooperative_internal.h>
3072 +#include <asm/irq.h>
3073 +
3074 +struct conet_priv {
3075 +       struct net_device_stats stats;
3076 +       int status;
3077 +       int unit;
3078 +       int enabled;
3079 +       int handling;
3080 +};
3081 +
3082 +struct net_device *conet_dev[CO_MODULE_MAX_CONET];
3083 +
3084 +irqreturn_t conet_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr);
3085 +
3086 +static int conet_get_mac(int unit, char *address)
3087 +{
3088 +       unsigned long flags = 0;
3089 +       co_network_request_t *net_request;
3090 +       int result = 0;
3091 +
3092 +       co_passage_page_assert_valid();
3093 +
3094 +       co_passage_page_acquire(&flags);
3095 +       co_passage_page->operation = CO_OPERATION_DEVICE;
3096 +       co_passage_page->params[0] = CO_DEVICE_NETWORK;
3097 +       net_request = (typeof(net_request))&co_passage_page->params[1];
3098 +       net_request->unit = unit;
3099 +       net_request->type = CO_NETWORK_GET_MAC;
3100 +       co_switch_wrapper();
3101 +       memcpy(address, net_request->mac_address, ETH_ALEN);
3102 +       result = net_request->result;
3103 +       co_passage_page_release(flags);
3104 +
3105 +       return result;
3106 +}
3107 +
3108 +int conet_open(struct net_device *dev)
3109 +{
3110 +       struct conet_priv *priv = (struct conet_priv *)dev->priv;
3111 +
3112 +       if (priv->enabled)
3113 +               return 0;
3114 +
3115 +       conet_get_mac(priv->unit, dev->dev_addr);
3116 +
3117 +       priv->enabled = 1;
3118 +       
3119 +       netif_start_queue(dev);
3120 +
3121 +       return 0;
3122 +}
3123 +
3124 +int conet_stop(struct net_device *dev)
3125 +{
3126 +       struct conet_priv *priv = (struct conet_priv *)dev->priv;
3127 +
3128 +       priv->enabled = 0;
3129 +
3130 +       netif_stop_queue(dev); /* can't transmit any more */
3131 +
3132 +       return 0;
3133 +}
3134 +
3135 +int conet_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
3136 +{
3137 +       int len;
3138 +       char *data;
3139 +       struct conet_priv *priv = (struct conet_priv *)dev->priv;
3140 +
3141 +       len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
3142 +       data = skb->data;
3143 +
3144 +       dev->trans_start = jiffies; /* save the timestamp */
3145 +
3146 +       co_send_message(CO_MODULE_LINUX, 
3147 +                       CO_MODULE_CONET0 + priv->unit,
3148 +                       CO_PRIORITY_DISCARDABLE,
3149 +                       CO_MESSAGE_TYPE_OTHER,
3150 +                       len,
3151 +                       data);
3152 +
3153 +       priv->stats.tx_bytes+=skb->len;
3154 +       priv->stats.tx_packets++;
3155 +
3156 +       dev_kfree_skb(skb);
3157 +
3158 +       return 0;
3159 +}
3160 +
3161 +static void conet_rx(struct net_device *dev, co_linux_message_t *message)
3162 +{
3163 +       struct sk_buff *skb;
3164 +       struct conet_priv *priv = (struct conet_priv *)dev->priv;
3165 +       int len;
3166 +       unsigned char *buf;
3167 +       
3168 +       len = message->size;
3169 +       buf = message->data;
3170 +
3171 +       /*
3172 +        * The packet has been retrieved from the transmission
3173 +        * medium. Build an skb around it, so upper layers can handle it
3174 +        */
3175 +       skb = dev_alloc_skb(len+2);
3176 +       if (!skb) {
3177 +               printk("conet rx: low on mem - packet dropped\n");
3178 +               priv->stats.rx_dropped++;
3179 +               return;
3180 +       }
3181 +
3182 +       memcpy(skb_put(skb, len), buf, len);
3183 +
3184 +       /* Write metadata, and then pass to the receive level */
3185 +       skb->dev = dev;
3186 +       skb->protocol = eth_type_trans(skb, dev);
3187 +       skb->ip_summed = CHECKSUM_NONE; /* make the kernel calculate and verify
3188 +                                           the checksum */
3189 +
3190 +       priv->stats.rx_bytes += len;
3191 +       priv->stats.rx_packets++;
3192 +
3193 +       netif_rx(skb);
3194 +       return;
3195 +}
3196 +
3197 +irqreturn_t conet_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
3198 +{      
3199 +       co_message_node_t *node_message;
3200 +       while (co_get_message(&node_message, CO_DEVICE_NETWORK)) {
3201 +               struct net_device *dev;
3202 +               struct conet_priv *priv;
3203 +               co_linux_message_t *message;
3204 +
3205 +               message = (co_linux_message_t *)&node_message->msg.data;
3206 +               if (message->unit < 0  ||  message->unit >= CO_MODULE_MAX_CONET) {
3207 +                       printk("conet intrrupt: buggy network reception\n");
3208 +                       return IRQ_HANDLED;
3209 +               }
3210 +
3211 +               dev = conet_dev[message->unit];
3212 +               if (!dev) {
3213 +                       co_free_message(node_message);
3214 +                       continue;
3215 +               }
3216 +
3217 +               if (!netif_running(dev)) {
3218 +                       co_free_message(node_message);
3219 +                       continue;
3220 +               }
3221 +
3222 +               priv = (struct conet_priv *)dev->priv;
3223 +               if (priv->handling) {
3224 +                       co_free_message(node_message);
3225 +                       continue;
3226 +               }
3227 +               
3228 +               priv->handling = 1;
3229 +               conet_rx(dev, message); 
3230 +               co_free_message(node_message);
3231 +               priv->handling = 0;
3232 +       }
3233 +
3234 +       return IRQ_HANDLED;
3235 +}
3236 +
3237 +struct net_device_stats* conet_get_stats(struct net_device *dev)
3238 +{
3239 +       return (struct net_device_stats *)dev->priv;
3240 +}
3241 +
3242 +int conet_init(struct net_device *dev)
3243 +{
3244 +       struct conet_priv *priv = (struct conet_priv *)dev->priv;
3245 +
3246 +       memset(&priv->stats, 0, sizeof(priv->stats));
3247 +       
3248 +       ether_setup(dev);
3249 +
3250 +       dev->open            = conet_open;
3251 +       dev->stop            = conet_stop;
3252 +       dev->hard_start_xmit = conet_hard_start_xmit;
3253 +       dev->get_stats       = conet_get_stats;
3254 +       dev->irq             = NETWORK_IRQ;
3255 +
3256 +       SET_MODULE_OWNER(dev);
3257 +
3258 +       return 0;
3259 +}
3260 +
3261 +void conet_uninit(struct net_device *dev)
3262 +{
3263 +}
3264 +
3265 +static struct net_device *conet_create(int unit)
3266 +{
3267 +       struct net_device *dev;
3268 +       struct conet_priv *priv;
3269 +       int result = 0;
3270 +
3271 +       dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
3272 +       if (!dev) {
3273 +               return ERR_PTR(-ENOMEM);
3274 +       }
3275 +
3276 +       memset(dev, 0, sizeof(struct net_device));
3277 +
3278 +       priv = kmalloc(sizeof(struct conet_priv), GFP_KERNEL);
3279 +       if (priv == NULL) {
3280 +               kfree(dev);
3281 +               return ERR_PTR(-ENOMEM);
3282 +       }
3283 +
3284 +       memset(priv, 0, sizeof(struct conet_priv));
3285 +       priv->unit = unit;
3286 +
3287 +       dev->priv = priv;
3288 +       dev->init = conet_init;
3289 +       dev->uninit = conet_uninit;
3290 +       strcpy(dev->name, "eth%d");
3291 +
3292 +       result = register_netdev(dev);
3293 +       if (result) {
3294 +               printk("conet: error %d registering device \"%s\"\n", result, dev->name);
3295 +               kfree(dev->priv);
3296 +               kfree(dev);
3297 +               return ERR_PTR(-ENODEV);
3298 +       }
3299 +
3300 +       printk("conet%d: initialized\n", priv->unit);
3301 +
3302 +       return dev;
3303 +}
3304 +
3305 +static void conet_destroy(struct net_device *dev)
3306 +{
3307 +       struct conet_priv *priv = (struct conet_priv *) dev->priv;
3308 +
3309 +       printk("conet%d: freed\n", priv->unit);
3310 +
3311 +       unregister_netdev(dev);
3312 +       kfree(dev->priv);
3313 +       kfree(dev);
3314 +}
3315 +
3316 +static int __init conet_init_module(void)
3317 +{
3318 +       int unit = 0, result;
3319 +       struct net_device *dev;
3320 +       char mac_address[6];
3321 +
3322 +       result = request_irq(NETWORK_IRQ, &conet_interrupt, 0, "conet", NULL);
3323 +       
3324 +       printk("conet: loaded (max %d devices)\n", CO_MODULE_MAX_CONET);
3325 +
3326 +       for (unit=0; unit < CO_MODULE_MAX_CONET; unit++) {
3327 +               conet_dev[unit] = NULL;
3328 +               
3329 +               result = conet_get_mac(unit, mac_address);
3330 +               if (!result)
3331 +                       continue;
3332 +               
3333 +               dev = conet_create(unit);
3334 +               if (!IS_ERR(dev)) 
3335 +                       conet_dev[unit] = dev;
3336 +       }
3337 +
3338 +       return result;
3339 +}
3340 +
3341 +static void __exit conet_cleanup_module(void)
3342 +{
3343 +       int unit = 0;
3344 +
3345 +       free_irq(NETWORK_IRQ, NULL);
3346 +
3347 +       for (unit=0; unit < CO_MODULE_MAX_CONET; unit++) {
3348 +               if (!conet_dev[unit])
3349 +                       continue;
3350 +
3351 +               conet_destroy(conet_dev[unit]);
3352 +       }
3353 +}
3354 +
3355 +module_init(conet_init_module);
3356 +module_exit(conet_cleanup_module);
3357 diff -urN a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
3358 --- a/drivers/video/console/Kconfig
3359 +++ b/drivers/video/console/Kconfig
3360 @@ -6,7 +6,7 @@
3361  
3362  config VGA_CONSOLE
3363         bool "VGA text console" if EMBEDDED || !X86
3364 -       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC
3365 +       depends on !COOPERATIVE && !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC
3366         default y
3367         help
3368           Saying Y here will allow you to use Linux in text mode through a
3369 @@ -26,6 +26,14 @@
3370  #         fi
3371  #      fi
3372  
3373 +config COOPERATIVE_CONSOLE
3374 +       bool 'coLinux Pseudo-VGA text console' if COOPERATIVE
3375 +       depends on !VGA_CONSOLE && COOPERATIVE
3376 +       default y
3377 +       help
3378 +         You need to say Y here if you compile a Linux kernel in cooperative 
3379 +         mode.
3380 +
3381  config VIDEO_SELECT
3382         bool "Video mode selection support"
3383         depends on  (X86 || X86_64) && VGA_CONSOLE
3384 @@ -99,7 +107,7 @@
3385  
3386  config DUMMY_CONSOLE
3387         bool
3388 -       depends on PROM_CONSOLE!=y || VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y 
3389 +       depends on PROM_CONSOLE!=y || (COOPERATIVE_CONSOLE!=y && VGA_CONSOLE!=y) || SGI_NEWPORT_CONSOLE!=y 
3390         default y
3391  
3392  config FRAMEBUFFER_CONSOLE
3393 diff -urN a/drivers/video/console/Makefile b/drivers/video/console/Makefile
3394 --- a/drivers/video/console/Makefile
3395 +++ b/drivers/video/console/Makefile
3396 @@ -23,6 +23,7 @@
3397  obj-$(CONFIG_PROM_CONSOLE)        += promcon.o promcon_tbl.o
3398  obj-$(CONFIG_STI_CONSOLE)         += sticon.o sticore.o
3399  obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
3400 +obj-$(CONFIG_COOPERATIVE_CONSOLE) += cocon.o
3401  obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
3402  obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o
3403  obj-$(CONFIG_FB_TILEBLITTING)     += tileblit.o
3404 diff -urN a/drivers/video/console/cocon.c b/drivers/video/console/cocon.c
3405 --- a/drivers/video/console/cocon.c
3406 +++ b/drivers/video/console/cocon.c
3407 @@ -0,0 +1,464 @@
3408 +/*
3409 + *  linux/drivers/video/cocon.c -- Cooperative Linux console VGA driver
3410 + *
3411 + *  This file is subject to the terms and conditions of the GNU General Public
3412 + *  License.  See the file COPYING in the main directory of this archive for
3413 + *  more details.
3414 + *
3415 + *  Based on code copied from vgacon.c.
3416 + *
3417 + *  Dan Aloni <da-x@gmx.net>, 2003-2004 (c)
3418 + */
3419 +
3420 +#include <linux/config.h>
3421 +#include <linux/module.h>
3422 +#include <linux/types.h>
3423 +#include <linux/sched.h>
3424 +#include <linux/fs.h>
3425 +#include <linux/kernel.h>
3426 +#include <linux/tty.h>
3427 +#include <linux/console.h>
3428 +#include <linux/string.h>
3429 +#include <linux/kd.h>
3430 +#include <linux/slab.h>
3431 +#include <linux/vt_kern.h>
3432 +#include <linux/selection.h>
3433 +#include <linux/init.h>
3434 +
3435 +#include <linux/cooperative_internal.h>
3436 +
3437 +/*
3438 + *  Interface used by the world
3439 + */
3440 +
3441 +static const char *cocon_startup(void);
3442 +static void cocon_init(struct vc_data *c, int init);
3443 +static void cocon_deinit(struct vc_data *c);
3444 +static void cocon_clear(struct vc_data *c, int, int, int, int);
3445 +static void cocon_cursor(struct vc_data *c, int mode);
3446 +static int cocon_switch(struct vc_data *c);
3447 +static int cocon_blank(struct vc_data *c, int blank, int mode_switch);
3448 +/* static int cocon_font_op(struct vc_data *c, struct console_font_op *op); */
3449 +static int cocon_set_palette(struct vc_data *c, unsigned char *table);
3450 +static int cocon_scrolldelta(struct vc_data *c, int lines);
3451 +static int cocon_set_origin(struct vc_data *c);
3452 +static void cocon_save_screen(struct vc_data *c);
3453 +static int cocon_scroll(struct vc_data *c, int t, int b, int dir, int lines);
3454 +static u8 cocon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse);
3455 +static void cocon_invert_region(struct vc_data *c, u16 *p, int count);
3456 +
3457 +static const char __init *cocon_startup(void)
3458 +{
3459 +       unsigned long flags;
3460 +       co_console_message_t *message;
3461 +       co_message_t *co_message;
3462 +
3463 +       co_message = co_send_message_save(&flags);
3464 +       message = (co_console_message_t *)co_message->data;
3465 +       co_message->from = CO_MODULE_LINUX;
3466 +       co_message->to = CO_MODULE_CONSOLE;
3467 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3468 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3469 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3470 +       message->type = CO_OPERATION_CONSOLE_STARTUP;
3471 +       co_send_message_restore(flags);
3472 +
3473 +       return "CoCON";
3474 +}
3475 +
3476 +static void cocon_init(struct vc_data *c, int init)
3477 +{
3478 +       unsigned long flags;
3479 +       co_console_message_t *message;
3480 +       co_message_t *co_message;
3481 +
3482 +       /* We cannot be loaded as a module, therefore init is always 1 */
3483 +       c->vc_can_do_color = 1;
3484 +       c->vc_cols = 80;
3485 +       c->vc_rows = 25;
3486 +       c->vc_complement_mask = 0x7700;
3487 +       c->vc_visible_origin = 0;
3488 +       c->vc_origin = 0;
3489 +
3490 +       co_message = co_send_message_save(&flags);
3491 +       message = (co_console_message_t *)co_message->data;
3492 +       co_message->from = CO_MODULE_LINUX;
3493 +       co_message->to = CO_MODULE_CONSOLE;
3494 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3495 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3496 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3497 +       message->type = CO_OPERATION_CONSOLE_INIT;
3498 +       co_send_message_restore(flags);
3499 +}
3500 +
3501 +static void cocon_deinit(struct vc_data *c)
3502 +{
3503 +       unsigned long flags;
3504 +       co_console_message_t *message;
3505 +       co_message_t *co_message;
3506 +
3507 +       co_message = co_send_message_save(&flags);
3508 +       message = (co_console_message_t *)co_message->data;
3509 +       co_message->from = CO_MODULE_LINUX;
3510 +       co_message->to = CO_MODULE_CONSOLE;
3511 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3512 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3513 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3514 +       message->type = CO_OPERATION_CONSOLE_DEINIT;
3515 +       co_send_message_restore(flags);
3516 +
3517 +}
3518 +
3519 +static void cocon_clear(struct vc_data *c, int top, int left, int rows, int cols)
3520 +{
3521 +       unsigned long flags;
3522 +       co_console_message_t *message;
3523 +       co_message_t *co_message;
3524 +
3525 +       co_message = co_send_message_save(&flags);
3526 +       message = (co_console_message_t *)co_message->data;
3527 +       co_message->from = CO_MODULE_LINUX;
3528 +       co_message->to = CO_MODULE_CONSOLE;
3529 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3530 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3531 +       co_message->size = ((char *)(&message->clear + 1)) - ((char *)message);
3532 +       message->type = CO_OPERATION_CONSOLE_CLEAR;
3533 +       message->clear.top = top;
3534 +       message->clear.left = left;
3535 +       message->clear.bottom = top + rows - 1;
3536 +       message->clear.right = left + cols - 1;
3537 +       message->clear.charattr = c->vc_video_erase_char;
3538 +       co_send_message_restore(flags);
3539 +}
3540 +
3541 +static void cocon_putc(struct vc_data *c, int charattr, int y, int x)
3542 +{
3543 +       unsigned long flags;
3544 +       co_message_t *co_message;
3545 +       co_console_message_t *message;
3546 +
3547 +       co_message = co_send_message_save(&flags);
3548 +       message = (co_console_message_t *)co_message->data;
3549 +       co_message->from = CO_MODULE_LINUX;
3550 +       co_message->to = CO_MODULE_CONSOLE;
3551 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3552 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3553 +       co_message->size = ((char *)(&message->putc + 1)) - ((char *)message);
3554 +       message->type = CO_OPERATION_CONSOLE_PUTC;
3555 +       message->putc.x = x;
3556 +       message->putc.y = y;
3557 +       message->putc.charattr = charattr;
3558 +       co_send_message_restore(flags);
3559 +}
3560 +
3561 +
3562 +static void cocon_putcs(struct vc_data *conp, 
3563 +                       const unsigned short *s, int count, int yy, int xx)
3564 +{
3565 +       unsigned long flags;
3566 +       co_console_message_t *message;
3567 +       co_message_t *co_message;
3568 +
3569 +       if (count > CO_MAX_PARAM_SIZE/2 - 16) 
3570 +               return;
3571 +
3572 +       co_message = co_send_message_save(&flags);
3573 +       message = (co_console_message_t *)co_message->data;
3574 +       co_message->from = CO_MODULE_LINUX;
3575 +       co_message->to = CO_MODULE_CONSOLE;
3576 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3577 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3578 +       co_message->size = ((char *)(&message->putcs + 1)) - ((char *)message) + 
3579 +               count * sizeof(unsigned short);
3580 +       message->type = CO_OPERATION_CONSOLE_PUTCS;
3581 +       message->putcs.x = xx;
3582 +       message->putcs.y = yy;
3583 +       message->putcs.count = count;
3584 +       memcpy(&message->putcs.data, s, count * sizeof(unsigned short));
3585 +       co_send_message_restore(flags);
3586 +}
3587 +
3588 +static u8 cocon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse)
3589 +{
3590 +       u8 attr = color;
3591 +
3592 +       if (underline)
3593 +               attr = (attr & 0xf0) | c->vc_ulcolor;
3594 +       else if (intensity == 0)
3595 +               attr = (attr & 0xf0) | c->vc_halfcolor;
3596 +       if (reverse)
3597 +               attr = ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) & 0x77);
3598 +       if (blink)
3599 +               attr ^= 0x80;
3600 +       if (intensity == 2)
3601 +               attr ^= 0x08;
3602 +
3603 +       return attr;
3604 +}
3605 +
3606 +static void cocon_invert_region(struct vc_data *c, u16 *p, int count)
3607 +{
3608 +       unsigned long flags;
3609 +       co_message_t *co_message;
3610 +       co_console_message_t *message;
3611 +       unsigned long x = (unsigned long)(p - c->vc_origin);  // UPDATE: vc_origin = 0; but not yet
3612 +
3613 +       co_message = co_send_message_save(&flags);
3614 +       message = (co_console_message_t *)co_message->data;
3615 +       co_message->from = CO_MODULE_LINUX;
3616 +       co_message->to = CO_MODULE_CONSOLE;
3617 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3618 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3619 +       co_message->size = ((char *)(&message->invert + 1)) - ((char *)message);
3620 +       message->type = CO_OPERATION_CONSOLE_INVERT_REGION;
3621 +       message->invert.y = ((unsigned)x)/c->vc_cols;
3622 +       message->invert.x = ((unsigned)x)-(message->invert.y);
3623 +       message->invert.count = count;
3624 +       co_send_message_restore(flags);
3625 +
3626 +       while (count--) {
3627 +               u16 a = scr_readw(p);
3628 +               a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
3629 +               scr_writew(a, p++);
3630 +        }
3631 +
3632 +}
3633 +
3634 +static void cocon_cursor(struct vc_data *c, int mode)
3635 +{
3636 +       unsigned long flags;
3637 +       co_console_message_t *message;
3638 +       co_message_t *co_message;
3639 +
3640 +       co_message = co_send_message_save(&flags);
3641 +       message = (co_console_message_t *)co_message->data;
3642 +       co_message->from = CO_MODULE_LINUX;
3643 +       co_message->to = CO_MODULE_CONSOLE;
3644 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3645 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3646 +       co_message->size = ((char *)(&message->cursor + 1)) - ((char *)message);;
3647 +       if (mode==CM_ERASE) {
3648 +               message->type = CO_OPERATION_CONSOLE_CURSOR_ERASE;
3649 +               message->cursor.height = 0;
3650 +               co_send_message_restore(flags);
3651 +               return;
3652 +       }
3653 +
3654 +       if(mode==CM_MOVE) {
3655 +               message->type = CO_OPERATION_CONSOLE_CURSOR_MOVE;
3656 +       } else /*(mode==CM_DRAW)*/ {
3657 +               message->type = CO_OPERATION_CONSOLE_CURSOR_DRAW;
3658 +       }
3659 +       message->cursor.x = c->vc_x;
3660 +       message->cursor.y = c->vc_y;
3661 +
3662 +       switch (c->vc_cursor_type & CUR_HWMASK) {
3663 +       case CUR_UNDERLINE:
3664 +               message->cursor.height = 5;
3665 +               break;
3666 +       case CUR_TWO_THIRDS:
3667 +               message->cursor.height = 66;
3668 +               break;
3669 +       case CUR_LOWER_THIRD:
3670 +               message->cursor.height = 33;
3671 +               break;
3672 +       case CUR_LOWER_HALF:
3673 +               message->cursor.height = 50;
3674 +               break;
3675 +       case CUR_NONE:
3676 +               message->cursor.height = 0;
3677 +               break;
3678 +          default:
3679 +               message->cursor.height = 5;
3680 +               break;
3681 +       }
3682 +
3683 +       co_send_message_restore(flags);
3684 +}
3685 +
3686 +static int cocon_switch(struct vc_data *c)
3687 +{
3688 +       unsigned long flags;
3689 +       co_console_message_t *message;
3690 +       co_message_t *co_message;
3691 +
3692 +       co_message = co_send_message_save(&flags);
3693 +       message = (co_console_message_t *)co_message->data;
3694 +       co_message->from = CO_MODULE_LINUX;
3695 +       co_message->to = CO_MODULE_CONSOLE;
3696 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3697 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3698 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3699 +       message->type = CO_OPERATION_CONSOLE_SWITCH;
3700 +       co_send_message_restore(flags);
3701 +
3702 +       return 1;       /* Redrawing not needed */
3703 +}
3704 +
3705 +static int cocon_set_palette(struct vc_data *c, unsigned char *table)
3706 +{
3707 +       unsigned long flags;
3708 +       co_console_message_t *message;
3709 +       co_message_t *co_message;
3710 +
3711 +       co_message = co_send_message_save(&flags);
3712 +       message = (co_console_message_t *)co_message->data;
3713 +       co_message->from = CO_MODULE_LINUX;
3714 +       co_message->to = CO_MODULE_CONSOLE;
3715 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3716 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3717 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3718 +       message->type = CO_OPERATION_CONSOLE_SET_PALETTE;
3719 +       co_send_message_restore(flags);
3720 +
3721 +       return 1;
3722 +}
3723 +
3724 +static int cocon_blank(struct vc_data *c, int blank, int mode_switchg)
3725 +{
3726 +       unsigned long flags;
3727 +       co_console_message_t *message;
3728 +       co_message_t *co_message;
3729 +
3730 +       co_message = co_send_message_save(&flags);
3731 +       message = (co_console_message_t *)co_message->data;
3732 +       co_message->from = CO_MODULE_LINUX;
3733 +       co_message->to = CO_MODULE_CONSOLE;
3734 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3735 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3736 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3737 +       message->type = CO_OPERATION_CONSOLE_BLANK;
3738 +       co_send_message_restore(flags);
3739 +
3740 +       return 1;
3741 +}
3742 +
3743 +
3744 +static int cocon_scrolldelta(struct vc_data *c, int lines)
3745 +{
3746 +       unsigned long flags;
3747 +       co_console_message_t *message;
3748 +       co_message_t *co_message;
3749 +
3750 +       co_message = co_send_message_save(&flags);
3751 +       message = (co_console_message_t *)co_message->data;
3752 +       co_message->from = CO_MODULE_LINUX;
3753 +       co_message->to = CO_MODULE_CONSOLE;
3754 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3755 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3756 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3757 +       message->type = CO_OPERATION_CONSOLE_SCROLLDELTA;
3758 +       co_send_message_restore(flags);
3759 +
3760 +       return 1;
3761 +}
3762 +
3763 +static int cocon_set_origin(struct vc_data *c)
3764 +{
3765 +       unsigned long flags;
3766 +       co_console_message_t *message;
3767 +       co_message_t *co_message;
3768 +
3769 +       co_message = co_send_message_save(&flags);
3770 +       message = (co_console_message_t *)co_message->data;
3771 +       co_message->from = CO_MODULE_LINUX;
3772 +       co_message->to = CO_MODULE_CONSOLE;
3773 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3774 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3775 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3776 +       message->type = CO_OPERATION_CONSOLE_SET_ORIGIN;
3777 +       co_send_message_restore(flags);
3778 +
3779 +       return 1;
3780 +}
3781 +
3782 +static void cocon_save_screen(struct vc_data *c)
3783 +{
3784 +       unsigned long flags;
3785 +       co_console_message_t *message;
3786 +       co_message_t *co_message;
3787 +
3788 +       co_message = co_send_message_save(&flags);
3789 +       message = (co_console_message_t *)co_message->data;
3790 +       co_message->from = CO_MODULE_LINUX;
3791 +       co_message->to = CO_MODULE_CONSOLE;
3792 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3793 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3794 +       co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
3795 +       message->type = CO_OPERATION_CONSOLE_SAVE_SCREEN;
3796 +       co_send_message_restore(flags);
3797 +}
3798 +
3799 +static int cocon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
3800 +{
3801 +       unsigned long flags;
3802 +       co_console_message_t *message;
3803 +       co_message_t *co_message;
3804 +
3805 +       co_message = co_send_message_save(&flags);
3806 +       message = (co_console_message_t *)co_message->data;
3807 +       co_message->from = CO_MODULE_LINUX;
3808 +       co_message->to = CO_MODULE_CONSOLE;
3809 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3810 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3811 +       co_message->size = ((char *)(&message->scroll + 1)) - ((char *)message);
3812 +       if (dir == SM_UP)
3813 +               message->type = CO_OPERATION_CONSOLE_SCROLL_UP;
3814 +       else
3815 +               message->type = CO_OPERATION_CONSOLE_SCROLL_DOWN;
3816 +       message->scroll.top = t;
3817 +       message->scroll.bottom = b-1;
3818 +       message->scroll.lines = lines;
3819 +       co_send_message_restore(flags);
3820 +
3821 +       return 0;
3822 +}
3823 +
3824 +static void cocon_bmove(struct vc_data *c, int sy, int sx, int dy, int dx, int h, int w)
3825 +{
3826 +       unsigned long flags;
3827 +       co_console_message_t *message;
3828 +       co_message_t *co_message;
3829 +
3830 +       co_message = co_send_message_save(&flags);
3831 +       message = (co_console_message_t *)co_message->data;
3832 +       co_message->from = CO_MODULE_LINUX;
3833 +       co_message->to = CO_MODULE_CONSOLE;
3834 +       co_message->priority = CO_PRIORITY_DISCARDABLE;
3835 +       co_message->type = CO_MESSAGE_TYPE_STRING;
3836 +       co_message->size = ((char *)(&message->bmove + 1)) - ((char *)message);
3837 +       message->type = CO_OPERATION_CONSOLE_BMOVE;
3838 +       message->bmove.row = dy;
3839 +       message->bmove.column = dx;
3840 +       message->bmove.top = sy;
3841 +       message->bmove.left = sx;
3842 +       message->bmove.bottom = sy + h - 1;
3843 +       message->bmove.right = sx + w - 1;
3844 +       co_send_message_restore(flags);
3845 +}
3846 +
3847 +/*
3848 + *  The console `switch' structure for the VGA based console
3849 + */
3850 +
3851 +const struct consw colinux_con = {
3852 +       con_startup:            cocon_startup,
3853 +       con_init:               cocon_init,
3854 +       con_deinit:             cocon_deinit,
3855 +       con_clear:              cocon_clear,
3856 +       con_putc:               cocon_putc,
3857 +       con_putcs:              cocon_putcs,
3858 +       con_cursor:             cocon_cursor,
3859 +       con_scroll:             cocon_scroll,
3860 +       con_bmove:              cocon_bmove,
3861 +       con_switch:             cocon_switch,
3862 +       con_blank:              cocon_blank,
3863 +       con_set_palette:        cocon_set_palette,
3864 +       con_scrolldelta:        cocon_scrolldelta,
3865 +       con_set_origin:         cocon_set_origin,
3866 +       con_save_screen:        cocon_save_screen,
3867 +       con_build_attr:         cocon_build_attr,
3868 +       con_invert_region:      cocon_invert_region,
3869 +};
3870 +
3871 +MODULE_LICENSE("GPL");
3872 diff -urN a/fs/Kconfig b/fs/Kconfig
3873 --- a/fs/Kconfig
3874 +++ b/fs/Kconfig
3875 @@ -1098,6 +1098,19 @@
3876           containing the directory /) cannot be compiled as a module.
3877  
3878  
3879 +config COFUSE_FS
3880 +       tristate "Cooperative Host file system support (COFUSE)"
3881 +       depends on COOPERATIVE
3882 +       default y
3883 +       help
3884 +         In Cooperative mode, this file system allows you to mount an host 
3885 +         directory structure to a local mountpoint. 
3886 +         COFUSE (Cooperative FUSE) is based on the original FUSE 
3887 +         (File System in User Space). 
3888 +
3889 +         To compile the cofuse support as a module, choose M here: the
3890 +         module will be called cofusefs.
3891 +
3892  
3893  config EFS_FS
3894         tristate "EFS file system support (read only) (EXPERIMENTAL)"
3895 diff -urN a/fs/Makefile b/fs/Makefile
3896 --- a/fs/Makefile
3897 +++ b/fs/Makefile
3898 @@ -94,3 +94,5 @@
3899  obj-$(CONFIG_BEFS_FS)          += befs/
3900  obj-$(CONFIG_HOSTFS)           += hostfs/
3901  obj-$(CONFIG_HPPFS)            += hppfs/
3902 +obj-$(CONFIG_COFUSE_FS)                += cofusefs/
3903 +
3904 diff -urN a/fs/cofusefs/Makefile b/fs/cofusefs/Makefile
3905 --- a/fs/cofusefs/Makefile
3906 +++ b/fs/cofusefs/Makefile
3907 @@ -0,0 +1,8 @@
3908 +#
3909 +# Makefile for the Linux cofuse filesystem routines.
3910 +#
3911 +
3912 +obj-$(CONFIG_COFUSE_FS) += cofusefs.o
3913 +
3914 +cofusefs-objs := inode.o dir.o file.o util.o dev.o
3915 +
3916 diff -urN a/fs/cofusefs/dev.c b/fs/cofusefs/dev.c
3917 --- a/fs/cofusefs/dev.c
3918 +++ b/fs/cofusefs/dev.c
3919 @@ -0,0 +1,889 @@
3920 +/*
3921 +    FUSE: Filesystem in Userspace
3922 +    Copyright (C) 2001-2004  Miklos Szeredi <miklos@szeredi.hu>
3923 +
3924 +    This program can be distributed under the terms of the GNU GPL.
3925 +    See the file COPYING.
3926 +*/
3927 +
3928 +#include "fuse_i.h"
3929 +
3930 +#include <linux/poll.h>
3931 +#include <linux/proc_fs.h>
3932 +#include <linux/file.h>
3933 +
3934 +#ifndef CONFIG_COOPERATIVE
3935 +
3936 +/* If more requests are outstanding, then the operation will block */
3937 +#define MAX_OUTSTANDING 10
3938 +
3939 +static struct proc_dir_entry *proc_fs_fuse;
3940 +struct proc_dir_entry *proc_fuse_dev;
3941 +static kmem_cache_t *fuse_req_cachep;
3942 +
3943 +static struct fuse_req *request_new(void)
3944 +{
3945 +       struct fuse_req *req;
3946 +
3947 +       req = (struct fuse_req *) kmem_cache_alloc(fuse_req_cachep, SLAB_NOFS);
3948 +       if(req) {
3949 +               INIT_LIST_HEAD(&req->list);
3950 +               req->issync = 0;
3951 +               req->locked = 0;
3952 +               req->interrupted = 0;
3953 +               req->sent = 0;
3954 +               req->finished = 0;
3955 +               req->in = NULL;
3956 +               req->out = NULL;
3957 +               init_waitqueue_head(&req->waitq);
3958 +       }
3959 +
3960 +       return req;
3961 +}
3962 +
3963 +static void request_free(struct fuse_req *req)
3964 +{
3965 +       kmem_cache_free(fuse_req_cachep, req);
3966 +}
3967 +
3968 +static int request_restartable(enum fuse_opcode opcode)
3969 +{
3970 +       switch(opcode) {
3971 +       case FUSE_LOOKUP:
3972 +       case FUSE_GETATTR:
3973 +       case FUSE_READLINK:
3974 +       case FUSE_GETDIR:
3975 +       case FUSE_OPEN:
3976 +       case FUSE_READ:
3977 +       case FUSE_WRITE:
3978 +               return 1;
3979 +
3980 +       default:
3981 +               return 0;
3982 +       }
3983 +}
3984 +
3985 +/* Called with fuse_lock held.  Releases, and then reaquires it. */
3986 +static void request_wait_answer(struct fuse_req *req)
3987 +{
3988 +       int intr;
3989 +       
3990 +       spin_unlock(&fuse_lock);
3991 +       intr = wait_event_interruptible(req->waitq, req->finished);
3992 +       spin_lock(&fuse_lock);
3993 +       if(!intr)
3994 +               return;
3995 +
3996 +       /* Request interrupted... Wait for it to be unlocked */
3997 +       if(req->locked) {
3998 +               req->interrupted = 1;
3999 +               spin_unlock(&fuse_lock);
4000 +               wait_event(req->waitq, !req->locked);
4001 +               spin_lock(&fuse_lock);
4002 +       }
4003 +       
4004 +       /* Operations which modify the filesystem cannot safely be
4005 +          restarted, because it is uncertain whether the operation has
4006 +          completed or not... */
4007 +       if(req->sent && !request_restartable(req->in->h.opcode))
4008 +               req->out->h.error = -EINTR;
4009 +       else
4010 +               req->out->h.error = -ERESTARTSYS;
4011 +}
4012 +
4013 +static int get_unique(struct fuse_conn *fc)
4014 +{
4015 +       do fc->reqctr++;
4016 +       while(!fc->reqctr);
4017 +       return fc->reqctr;
4018 +}
4019 +
4020 +/* Must be called with fuse_lock held, and unlocks it */
4021 +static void request_end(struct fuse_conn *fc, struct fuse_req *req)
4022 +{
4023 +       fuse_reqend_t endfunc = req->end;
4024 +
4025 +       if(!endfunc) {
4026 +               wake_up(&req->waitq);
4027 +               spin_unlock(&fuse_lock);
4028 +       } else {
4029 +               spin_unlock(&fuse_lock);
4030 +               endfunc(fc, req->in, req->out, req->data);
4031 +               request_free(req);
4032 +               up(&fc->outstanding);
4033 +       }
4034 +}
4035 +
4036 +void request_send(struct fuse_conn *fc, struct fuse_in *in,
4037 +                 struct fuse_out *out)
4038 +{
4039 +       struct fuse_req *req;
4040 +
4041 +       out->h.error = -ERESTARTSYS;
4042 +       if(down_interruptible(&fc->outstanding))
4043 +               return;
4044 +
4045 +       out->h.error = -ENOMEM;
4046 +       req = request_new();
4047 +       if(req) {
4048 +               req->in = in;
4049 +               req->out = out;
4050 +               req->issync = 1;
4051 +               req->end = NULL;
4052 +               
4053 +               spin_lock(&fuse_lock);
4054 +               out->h.error = -ENOTCONN;
4055 +               if(fc->file) {
4056 +                       in->h.unique = get_unique(fc);          
4057 +                       list_add_tail(&req->list, &fc->pending);
4058 +                       wake_up(&fc->waitq);
4059 +                       request_wait_answer(req);
4060 +                       list_del(&req->list);
4061 +               }
4062 +               spin_unlock(&fuse_lock);
4063 +               request_free(req);
4064 +       }
4065 +
4066 +       up(&fc->outstanding);
4067 +}
4068 +
4069 +
4070 +static inline void destroy_request(struct fuse_req *req)
4071 +{
4072 +       if(req) {
4073 +               kfree(req->in);
4074 +               request_free(req);
4075 +       }
4076 +}
4077 +
4078 +/* This one is currently only used for sending FORGET and RELEASE,
4079 +   which are kernel initiated request.  So the outstanding semaphore
4080 +   is not used.  */
4081 +int request_send_noreply(struct fuse_conn *fc, struct fuse_in *in)
4082 +{
4083 +       struct fuse_req *req;
4084 +
4085 +       req = request_new();
4086 +       if(!req)
4087 +               return -ENOMEM;
4088 +
4089 +       req->in = in;
4090 +       req->issync = 0;
4091 +
4092 +       spin_lock(&fuse_lock);
4093 +       if(!fc->file) {
4094 +               spin_unlock(&fuse_lock);
4095 +               request_free(req);
4096 +               return -ENOTCONN;
4097 +       }
4098 +
4099 +       list_add_tail(&req->list, &fc->pending);
4100 +       wake_up(&fc->waitq);
4101 +       spin_unlock(&fuse_lock);
4102 +       return 0;
4103 +}
4104 +
4105 +int request_send_nonblock(struct fuse_conn *fc, struct fuse_in *in,
4106 +                         struct fuse_out *out, fuse_reqend_t end, void *data)
4107 +{
4108 +       int err;
4109 +       struct fuse_req *req;
4110 +
4111 +       BUG_ON(!end);
4112 +
4113 +       if(down_trylock(&fc->outstanding))
4114 +               return -EWOULDBLOCK;
4115 +
4116 +       err = -ENOMEM;
4117 +       req = request_new();
4118 +       if(req) {
4119 +               req->in = in;
4120 +               req->out = out;
4121 +               req->issync = 1;
4122 +               req->end = end;
4123 +               req->data = data;
4124 +
4125 +               spin_lock(&fuse_lock);
4126 +               err = -ENOTCONN;
4127 +               if(fc->file) {
4128 +                       in->h.unique = get_unique(fc);          
4129 +                       list_add_tail(&req->list, &fc->pending);
4130 +                       wake_up(&fc->waitq);
4131 +                       spin_unlock(&fuse_lock);
4132 +                       return 0;
4133 +               }
4134 +               spin_unlock(&fuse_lock);
4135 +               request_free(req);
4136 +       }
4137 +       up(&fc->outstanding);
4138 +       return err;
4139 +}
4140 +
4141 +static void request_wait(struct fuse_conn *fc)
4142 +{
4143 +       DECLARE_WAITQUEUE(wait, current);
4144 +
4145 +       add_wait_queue_exclusive(&fc->waitq, &wait);
4146 +       while(fc->sb != NULL && list_empty(&fc->pending)) {
4147 +               set_current_state(TASK_INTERRUPTIBLE);
4148 +               if(signal_pending(current))
4149 +                       break;
4150 +
4151 +               spin_unlock(&fuse_lock);
4152 +               schedule();
4153 +               spin_lock(&fuse_lock);
4154 +       }
4155 +       set_current_state(TASK_RUNNING);
4156 +       remove_wait_queue(&fc->waitq, &wait);
4157 +}
4158 +
4159 +static inline int copy_in_one(const void *src, size_t srclen, char **dstp,
4160 +                             size_t *dstlenp)
4161 +{
4162 +       if(*dstlenp < srclen) {
4163 +               printk("fuse_dev_read: buffer too small\n");
4164 +               return -EINVAL;
4165 +       }
4166 +                       
4167 +       if(copy_to_user(*dstp, src, srclen))
4168 +               return -EFAULT;
4169 +
4170 +       *dstp += srclen;
4171 +       *dstlenp -= srclen;
4172 +
4173 +       return 0;
4174 +}
4175 +
4176 +static inline int copy_in_args(struct fuse_in *in, char *buf, size_t nbytes)
4177 +{
4178 +       int err;
4179 +       int i;
4180 +       size_t orignbytes = nbytes;
4181 +               
4182 +       err = copy_in_one(&in->h, sizeof(in->h), &buf, &nbytes);
4183 +       if(err)
4184 +               return err;
4185 +
4186 +       for(i = 0; i < in->numargs; i++) {
4187 +               struct fuse_in_arg *arg = &in->args[i];
4188 +               err = copy_in_one(arg->value, arg->size, &buf, &nbytes);
4189 +               if(err)
4190 +                       return err;
4191 +       }
4192 +
4193 +       return orignbytes - nbytes;
4194 +}
4195 +
4196 +static ssize_t fuse_dev_read(struct file *file, char *buf, size_t nbytes,
4197 +                            loff_t *off)
4198 +{
4199 +       ssize_t ret;
4200 +       struct fuse_conn *fc = DEV_FC(file);
4201 +       struct fuse_req *req = NULL;
4202 +
4203 +       spin_lock(&fuse_lock);
4204 +       request_wait(fc);
4205 +       if(fc->sb != NULL && !list_empty(&fc->pending)) {
4206 +               req = list_entry(fc->pending.next, struct fuse_req, list);
4207 +               list_del_init(&req->list);
4208 +               req->locked = 1;
4209 +       }
4210 +       spin_unlock(&fuse_lock);
4211 +       if(fc->sb == NULL)
4212 +               return -ENODEV;
4213 +       if(req == NULL)
4214 +               return -EINTR;
4215 +
4216 +       ret = copy_in_args(req->in, buf, nbytes);
4217 +       spin_lock(&fuse_lock);
4218 +       if(req->issync) {
4219 +               if(ret < 0) {
4220 +                       req->out->h.error = -EPROTO;
4221 +                       req->finished = 1;
4222 +               } else {
4223 +                       list_add_tail(&req->list, &fc->processing);
4224 +                       req->sent = 1;
4225 +               }
4226 +               req->locked = 0;
4227 +               if(ret < 0 || req->interrupted)
4228 +                       /* Unlocks fuse_lock: */
4229 +                       request_end(fc, req);
4230 +               else
4231 +                       spin_unlock(&fuse_lock);
4232 +       } else {
4233 +               spin_unlock(&fuse_lock);
4234 +               destroy_request(req);
4235 +       }
4236 +       return ret;
4237 +}
4238 +
4239 +static struct fuse_req *request_find(struct fuse_conn *fc, unsigned int unique)
4240 +{
4241 +       struct list_head *entry;
4242 +       struct fuse_req *req = NULL;
4243 +
4244 +       list_for_each(entry, &fc->processing) {
4245 +               struct fuse_req *tmp;
4246 +               tmp = list_entry(entry, struct fuse_req, list);
4247 +               if(tmp->in->h.unique == unique) {
4248 +                       req = tmp;
4249 +                       break;
4250 +               }
4251 +       }
4252 +
4253 +       return req;
4254 +}
4255 +
4256 +static void process_getdir(struct fuse_req *req)
4257 +{
4258 +       struct fuse_getdir_out *arg;
4259 +       arg = (struct fuse_getdir_out *) req->out->args[0].value;
4260 +       arg->file = fget(arg->fd);
4261 +}
4262 +
4263 +static inline int copy_out_one(struct fuse_out_arg *arg, const char **srcp,
4264 +                              size_t *srclenp, int allowvar)
4265 +{
4266 +       size_t dstlen = arg->size;
4267 +       if(*srclenp < dstlen) {
4268 +               if(!allowvar) {
4269 +                       printk("fuse_dev_write: write is short\n");
4270 +                       return -EINVAL;
4271 +               }
4272 +               dstlen = *srclenp;
4273 +       }
4274 +
4275 +       if(dstlen) {
4276 +               if(copy_from_user(arg->value, *srcp, dstlen))
4277 +                       return -EFAULT;
4278 +       }
4279 +
4280 +       *srcp += dstlen;
4281 +       *srclenp -= dstlen;
4282 +       arg->size = dstlen;
4283 +
4284 +       return 0;
4285 +}
4286 +
4287 +static inline int copy_out_args(struct fuse_out *out, const char *buf,
4288 +                               size_t nbytes)
4289 +{
4290 +       int err;
4291 +       int i;
4292 +
4293 +       buf += sizeof(struct fuse_out_header);
4294 +       nbytes -= sizeof(struct fuse_out_header);
4295 +               
4296 +       if(!out->h.error) {
4297 +               for(i = 0; i < out->numargs; i++) {
4298 +                       struct fuse_out_arg *arg = &out->args[i];
4299 +                       int allowvar;
4300 +
4301 +                       if(out->argvar && i == out->numargs - 1)
4302 +                               allowvar = 1;
4303 +                       else
4304 +                               allowvar = 0;
4305 +
4306 +                       err = copy_out_one(arg, &buf, &nbytes, allowvar);
4307 +                       if(err)
4308 +                               return err;
4309 +               }
4310 +       }
4311 +
4312 +       if(nbytes != 0) {
4313 +               printk("fuse_dev_write: write is long\n");
4314 +               return -EINVAL;
4315 +       }
4316 +
4317 +       return 0;
4318 +}
4319 +
4320 +static inline int copy_out_header(struct fuse_out_header *oh, const char *buf,
4321 +                                 size_t nbytes)
4322 +{
4323 +       if(nbytes < sizeof(struct fuse_out_header)) {
4324 +               printk("fuse_dev_write: write is short\n");
4325 +               return -EINVAL;
4326 +       }
4327 +       
4328 +       if(copy_from_user(oh, buf, sizeof(struct fuse_out_header)))
4329 +               return -EFAULT;
4330 +
4331 +       return 0;
4332 +}
4333 +
4334 +#ifdef KERNEL_2_6
4335 +static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh)
4336 +{
4337 +       struct inode *inode = ilookup(fc->sb, uh->ino);
4338 +       if (!inode)
4339 +               return -ENOENT;
4340 +       invalidate_inode_pages(inode->i_mapping);
4341 +       iput(inode);
4342 +       return 0;
4343 +}
4344 +#else 
4345 +static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh)
4346 +{
4347 +       struct inode *inode = iget(fc->sb, uh->ino);
4348 +       int err = -ENOENT;
4349 +       if(inode) {
4350 +               if(inode->u.generic_ip) {
4351 +                       invalidate_inode_pages(inode);
4352 +                       err = 0;
4353 +               }
4354 +               iput(inode);
4355 +       }
4356 +       return err;
4357 +}
4358 +#endif
4359 +
4360 +static int fuse_user_request(struct fuse_conn *fc, const char *buf,
4361 +                            size_t nbytes)
4362 +{
4363 +       struct fuse_user_header uh;
4364 +       int err;
4365 +
4366 +       if (nbytes < sizeof(struct fuse_user_header)) {
4367 +               printk("fuse_dev_write: write is short\n");
4368 +               return -EINVAL;
4369 +       }
4370 +
4371 +       if(copy_from_user(&uh, buf, sizeof(struct fuse_out_header)))
4372 +               return -EFAULT;
4373 +       
4374 +       switch(uh.opcode) {
4375 +       case FUSE_INVALIDATE:
4376 +               err = fuse_invalidate(fc, &uh);
4377 +               break;
4378 +
4379 +       default:
4380 +               err = -ENOSYS;
4381 +       }
4382 +       return err;
4383 +}
4384 +    
4385 +
4386 +static ssize_t fuse_dev_write(struct file *file, const char *buf,
4387 +                             size_t nbytes, loff_t *off)
4388 +{
4389 +       int err;
4390 +       struct fuse_conn *fc = DEV_FC(file);
4391 +       struct fuse_req *req;
4392 +       struct fuse_out_header oh;
4393 +
4394 +       if(!fc->sb)
4395 +               return -EPERM;
4396 +
4397 +       err = copy_out_header(&oh, buf, nbytes);
4398 +       if(err)
4399 +               return err;
4400 +
4401 +       if (!oh.unique) {
4402 +               err = fuse_user_request(fc, buf, nbytes);
4403 +               goto out;
4404 +       }     
4405 +
4406 +        if (oh.error <= -512 || oh.error > 0) {
4407 +                printk("fuse_dev_write: bad error value\n");
4408 +                return -EINVAL;
4409 +        }
4410 +
4411 +       spin_lock(&fuse_lock);
4412 +       req = request_find(fc, oh.unique);
4413 +       if(req != NULL) {
4414 +               list_del_init(&req->list);
4415 +               req->locked = 1;
4416 +       }
4417 +       spin_unlock(&fuse_lock);
4418 +       if(!req)
4419 +               return -ENOENT;
4420 +
4421 +       req->out->h = oh;
4422 +       err = copy_out_args(req->out, buf, nbytes);
4423 +
4424 +       spin_lock(&fuse_lock);
4425 +       if(err)
4426 +               req->out->h.error = -EPROTO;
4427 +       else {
4428 +               /* fget() needs to be done in this context */
4429 +               if(req->in->h.opcode == FUSE_GETDIR && !oh.error)
4430 +                       process_getdir(req);
4431 +       }       
4432 +       req->finished = 1;
4433 +       req->locked = 0;
4434 +       /* Unlocks fuse_lock: */
4435 +       request_end(fc, req);
4436 +
4437 +  out:
4438 +       if(!err)
4439 +               return nbytes;
4440 +       else
4441 +               return err;
4442 +}
4443 +
4444 +
4445 +static unsigned int fuse_dev_poll(struct file *file, poll_table *wait)
4446 +{
4447 +       struct fuse_conn *fc = DEV_FC(file);
4448 +       unsigned int mask = POLLOUT | POLLWRNORM;
4449 +
4450 +       if(!fc->sb)
4451 +               return -EPERM;
4452 +
4453 +       poll_wait(file, &fc->waitq, wait);
4454 +
4455 +       spin_lock(&fuse_lock);
4456 +       if (!list_empty(&fc->pending))
4457 +                mask |= POLLIN | POLLRDNORM;
4458 +       spin_unlock(&fuse_lock);
4459 +
4460 +       return mask;
4461 +}
4462 +
4463 +static struct fuse_conn *new_conn(void)
4464 +{
4465 +       struct fuse_conn *fc;
4466 +
4467 +       fc = kmalloc(sizeof(*fc), GFP_KERNEL);
4468 +       if(fc != NULL) {
4469 +               fc->sb = NULL;
4470 +               fc->file = NULL;
4471 +               fc->flags = 0;
4472 +               fc->uid = 0;
4473 +               fc->oldrelease = 0;
4474 +               init_waitqueue_head(&fc->waitq);
4475 +               INIT_LIST_HEAD(&fc->pending);
4476 +               INIT_LIST_HEAD(&fc->processing);
4477 +               sema_init(&fc->outstanding, MAX_OUTSTANDING);
4478 +               fc->reqctr = 1;
4479 +       }
4480 +       return fc;
4481 +}
4482 +
4483 +static int fuse_dev_open(struct inode *inode, struct file *file)
4484 +{
4485 +       struct fuse_conn *fc;
4486 +
4487 +       fc = new_conn();
4488 +       if(!fc)
4489 +               return -ENOMEM;
4490 +
4491 +       fc->file = file;
4492 +       file->private_data = fc;
4493 +
4494 +       return 0;
4495 +}
4496 +
4497 +static void end_requests(struct fuse_conn *fc, struct list_head *head)
4498 +{
4499 +       while(!list_empty(head)) {
4500 +               struct fuse_req *req;
4501 +               req = list_entry(head->next, struct fuse_req, list);
4502 +               list_del_init(&req->list);
4503 +               if(req->issync) {
4504 +                       req->out->h.error = -ECONNABORTED;
4505 +                       req->finished = 1;
4506 +                       /* Unlocks fuse_lock: */
4507 +                       request_end(fc, req);
4508 +                       spin_lock(&fuse_lock);
4509 +               } else
4510 +                       destroy_request(req);
4511 +       }
4512 +}
4513 +
4514 +static int fuse_dev_release(struct inode *inode, struct file *file)
4515 +{
4516 +       struct fuse_conn *fc = DEV_FC(file);
4517 +
4518 +       spin_lock(&fuse_lock);
4519 +       fc->file = NULL;
4520 +       end_requests(fc, &fc->pending);
4521 +       end_requests(fc, &fc->processing);
4522 +       release_conn(fc);
4523 +       spin_unlock(&fuse_lock);
4524 +       return 0;
4525 +}
4526 +
4527 +static struct file_operations fuse_dev_operations = {
4528 +       .owner          = THIS_MODULE,
4529 +       .read           = fuse_dev_read,
4530 +       .write          = fuse_dev_write,
4531 +       .poll           = fuse_dev_poll,
4532 +       .open           = fuse_dev_open,
4533 +       .release        = fuse_dev_release,
4534 +};
4535 +
4536 +int fuse_dev_init()
4537 +{
4538 +       int ret;
4539 +
4540 +       proc_fs_fuse = NULL;
4541 +       proc_fuse_dev = NULL;
4542 +
4543 +       fuse_req_cachep = kmem_cache_create("cofuser_request",
4544 +                                            sizeof(struct fuse_req),
4545 +                                            0, 0, NULL, NULL);
4546 +       if(!fuse_req_cachep)
4547 +               return -ENOMEM;
4548 +
4549 +       ret = -ENOMEM;
4550 +       proc_fs_fuse = proc_mkdir("fuse", proc_root_fs);
4551 +       if(!proc_fs_fuse) {
4552 +               printk("fuse: failed to create directory in /proc/fs\n");
4553 +               goto err;
4554 +       }
4555 +
4556 +       proc_fs_fuse->owner = THIS_MODULE;
4557 +       proc_fuse_dev = create_proc_entry("dev", S_IFSOCK | 0600, proc_fs_fuse);
4558 +       if(!proc_fuse_dev) {
4559 +               printk("fuse: failed to create entry in /proc/fs/fuse\n");
4560 +               goto err;
4561 +       }
4562 +
4563 +       proc_fuse_dev->proc_fops = &fuse_dev_operations;
4564 +
4565 +       return 0;
4566 +
4567 +  err:
4568 +       fuse_dev_cleanup();
4569 +       return ret;
4570 +}
4571 +
4572 +void fuse_dev_cleanup()
4573 +{
4574 +       if (cooperative_mode_enabled()) {
4575 +               kmem_cache_destroy(fuse_req_cachep);
4576 +               return;
4577 +       }
4578 +
4579 +       if(proc_fs_fuse) {
4580 +               remove_proc_entry("dev", proc_fs_fuse);
4581 +               remove_proc_entry("fuse", proc_root_fs);
4582 +       }
4583 +       
4584 +       kmem_cache_destroy(fuse_req_cachep);
4585 +}
4586 +
4587 +#else
4588 +
4589 +struct fuse_conn *cofs_volumes[CO_MODULE_MAX_COFS] = {NULL, };
4590 +
4591 +static void cofuse_request_start(unsigned long *flags, struct fuse_conn *fc, struct fuse_in *in)
4592 +{
4593 +       co_passage_page_assert_valid();
4594 +       
4595 +       co_passage_page_acquire(flags);
4596 +       co_passage_page->operation = CO_OPERATION_DEVICE;
4597 +       co_passage_page->params[0] = CO_DEVICE_FILESYSTEM;
4598 +       co_passage_page->params[1] = fc->cofs_unit;
4599 +       co_passage_page->params[2] = in->h.opcode;
4600 +       co_passage_page->params[3] = in->h.ino;
4601 +       co_passage_page->params[4] = 0;
4602 +}
4603 +
4604 +static void cofuse_request_end(unsigned long flags, struct fuse_out *out)
4605 +{
4606 +       unsigned long ret;
4607 +       ret = co_passage_page->params[4];
4608 +       co_passage_page_release(flags);
4609 +       out->h.error = ret;
4610 +}
4611 +
4612 +void request_send(struct fuse_conn *fc, struct fuse_in *in,
4613 +                 struct fuse_out *out)
4614 +{
4615 +       unsigned long flags;
4616 +       char *str;
4617 +
4618 +       switch ((unsigned long)in->h.opcode) {
4619 +       case FUSE_STATFS: {
4620 +               struct fuse_statfs_out *arg;
4621 +
4622 +               arg = (struct fuse_statfs_out *)out->args[0].value;
4623 +
4624 +               cofuse_request_start(&flags, fc, in);
4625 +               co_switch_wrapper();
4626 +               *arg = *(struct fuse_statfs_out *)&co_passage_page->params[5];
4627 +               cofuse_request_end(flags, out);
4628 +               return;
4629 +       }
4630 +
4631 +       case FUSE_OPEN: {
4632 +               struct fuse_open_in *opin = (struct fuse_open_in *)in->args[0].value;
4633 +
4634 +               cofuse_request_start(&flags, fc, in);
4635 +               co_passage_page->params[5] = opin->flags;
4636 +               co_switch_wrapper();
4637 +               cofuse_request_end(flags, out);
4638 +               return;
4639 +       }
4640 +
4641 +       case FUSE_WRITE: {
4642 +               struct fuse_write_in *write_in = (struct fuse_write_in *)in->args[0].value;
4643 +               unsigned long long *offset_passage = (unsigned long long *)&co_passage_page->params[5];
4644 +
4645 +               cofuse_request_start(&flags, fc, in);
4646 +               *offset_passage = write_in->offset;
4647 +               co_passage_page->params[7] = write_in->size;
4648 +               co_passage_page->params[8] = (unsigned long)in->args[1].value;
4649 +               co_switch_wrapper();
4650 +               cofuse_request_end(flags, out);
4651 +               return;
4652 +       }
4653 +
4654 +       case FUSE_READ: {
4655 +               struct fuse_read_in *read_in = (struct fuse_read_in *)in->args[0].value;
4656 +               unsigned long long *offset_passage = (unsigned long long *)&co_passage_page->params[5];
4657 +
4658 +               cofuse_request_start(&flags, fc, in);
4659 +               *offset_passage = read_in->offset;
4660 +               co_passage_page->params[7] = read_in->size;
4661 +               co_passage_page->params[8] = (unsigned long)out->args[0].value;
4662 +               co_switch_wrapper();
4663 +               cofuse_request_end(flags, out);
4664 +               return;
4665 +       }
4666 +
4667 +       case FUSE_LOOKUP: {
4668 +               struct fuse_lookup_out *arg;
4669 +
4670 +               arg = (struct fuse_lookup_out *)out->args[0].value;
4671 +               str = (char *)&co_passage_page->params[30];
4672 +
4673 +               cofuse_request_start(&flags, fc, in);
4674 +               memcpy(str, (char *)in->args[0].value, in->args[0].size);
4675 +               co_switch_wrapper();
4676 +               *arg = *(struct fuse_lookup_out *)&co_passage_page->params[5];
4677 +               cofuse_request_end(flags, out);
4678 +               return;
4679 +       }
4680 +
4681 +       case FUSE_RENAME: {
4682 +               struct fuse_rename_in *arg;
4683 +               char *str2;
4684 +
4685 +               arg = (struct fuse_rename_in *)in->args[0].value;
4686 +               str = (char *)(&co_passage_page->params[30]);
4687 +               str2 = str + in->args[1].size;
4688 +
4689 +               cofuse_request_start(&flags, fc, in);
4690 +               co_passage_page->params[5] = arg->newdir;
4691 +               memcpy(str, (char *)in->args[1].value, in->args[1].size);
4692 +               memcpy(str2, (char *)in->args[2].value, in->args[2].size);
4693 +               co_switch_wrapper();
4694 +               cofuse_request_end(flags, out);
4695 +               return;
4696 +       }
4697 +
4698 +       case FUSE_MKNOD: {
4699 +               struct fuse_mknod_in *inarg;
4700 +               struct fuse_mknod_out *outarg;
4701 +               char *str;
4702 +
4703 +               inarg = (struct fuse_mknod_in *)(in->args[0].value);
4704 +               outarg = (struct fuse_mknod_out *)(out->args[0].value);
4705 +
4706 +               cofuse_request_start(&flags, fc, in);
4707 +               co_passage_page->params[5] = inarg->mode;
4708 +               co_passage_page->params[6] = inarg->rdev;
4709 +               str = (char *)&co_passage_page->params[30];
4710 +               memcpy(str, (char *)in->args[1].value, in->args[1].size);
4711 +               co_switch_wrapper();
4712 +               outarg->ino = co_passage_page->params[7];
4713 +               outarg->attr = *(struct fuse_attr *)(&co_passage_page->params[8]);
4714 +               cofuse_request_end(flags, out);
4715 +               return;
4716 +       }
4717 +
4718 +       case FUSE_SETATTR: {
4719 +               struct fuse_setattr_in *inarg;
4720 +               struct fuse_setattr_out *outarg;
4721 +               struct fuse_attr *attr;
4722 +
4723 +               inarg = (struct fuse_setattr_in *)(in->args[0].value);
4724 +               outarg = (struct fuse_setattr_out *)(out->args[0].value);
4725 +               attr = (struct fuse_attr *)(&co_passage_page->params[6]);
4726 +
4727 +               cofuse_request_start(&flags, fc, in);
4728 +               co_passage_page->params[5] = inarg->valid;
4729 +               *attr = inarg->attr;
4730 +               co_switch_wrapper();
4731 +               outarg->attr = *attr;
4732 +               cofuse_request_end(flags, out);
4733 +               return;
4734 +       }
4735 +
4736 +       case FUSE_MKDIR: {
4737 +               struct fuse_mkdir_in *arg;
4738 +
4739 +               arg = (struct fuse_mkdir_in *)(in->args[0].value);
4740 +               str = (char *)&co_passage_page->params[30];
4741 +
4742 +               cofuse_request_start(&flags, fc, in);
4743 +               co_passage_page->params[5] = arg->mode;
4744 +               memcpy(str, (char *)in->args[1].value, in->args[1].size);
4745 +               co_switch_wrapper();
4746 +               cofuse_request_end(flags, out);
4747 +               return;
4748 +       }
4749 +
4750 +       case FUSE_UNLINK: 
4751 +       case FUSE_RMDIR: {
4752 +               str = (char *)&co_passage_page->params[30];
4753 +
4754 +               cofuse_request_start(&flags, fc, in);
4755 +               memcpy(str, (char *)in->args[0].value, in->args[0].size);
4756 +               co_switch_wrapper();
4757 +               cofuse_request_end(flags, out);
4758 +               return;
4759 +       }
4760 +               
4761 +       case FUSE_GETATTR: {
4762 +               struct fuse_getattr_out *arg;
4763 +               arg = (struct fuse_getattr_out *)out->args[0].value;
4764 +
4765 +               co_passage_page_assert_valid();
4766 +               cofuse_request_start(&flags, fc, in);
4767 +               co_switch_wrapper();
4768 +               *arg = *(struct fuse_getattr_out *)&co_passage_page->params[5];
4769 +               cofuse_request_end(flags, out);
4770 +               return;
4771 +       }
4772 +       }
4773 +
4774 +       /* printk("cofuse: request_send %d\n", in->h.opcode); */
4775 +       out->h.error = -EIO;
4776 +}
4777 +
4778 +int request_send_noreply(struct fuse_conn *fc, struct fuse_in *in)
4779 +{
4780 +       return -EIO;
4781 +}
4782 +
4783 +int request_send_nonblock(struct fuse_conn *fc, struct fuse_in *in,
4784 +                         struct fuse_out *out, fuse_reqend_t end, void *data)
4785 +{
4786 +       /* printk("cofuse: request_send_nonblock %d\n", in->h.opcode); */
4787 +       request_send(fc, in, out);
4788 +       end(fc, in, out, data);
4789 +       return 0;
4790 +}
4791 +
4792 +int fuse_dev_init()
4793 +{
4794 +       return 0;
4795 +}
4796 +
4797 +void fuse_dev_cleanup()
4798 +{
4799 +}
4800 +
4801 +#endif
4802 +
4803 +/* 
4804 + * Local Variables:
4805 + * indent-tabs-mode: t
4806 + * c-basic-offset: 8
4807 + * End:
4808 + */
4809 diff -urN a/fs/cofusefs/dir.c b/fs/cofusefs/dir.c
4810 --- a/fs/cofusefs/dir.c
4811 +++ b/fs/cofusefs/dir.c
4812 @@ -0,0 +1,961 @@
4813 +/*
4814 +    FUSE: Filesystem in Userspace
4815 +    Copyright (C) 2001-2004  Miklos Szeredi <miklos@szeredi.hu>
4816 +
4817 +    This program can be distributed under the terms of the GNU GPL.
4818 +    See the file COPYING.
4819 +*/
4820 +
4821 +#include "fuse_i.h"
4822 +
4823 +#include <linux/pagemap.h>
4824 +#include <linux/slab.h>
4825 +#include <linux/file.h>
4826 +
4827 +static struct inode_operations fuse_dir_inode_operations;
4828 +static struct inode_operations fuse_file_inode_operations;
4829 +static struct inode_operations fuse_symlink_inode_operations;
4830 +
4831 +static struct file_operations fuse_dir_operations;
4832 +
4833 +static struct dentry_operations fuse_dentry_operations;
4834 +
4835 +/* FIXME: This should be user configurable */
4836 +#define FUSE_REVALIDATE_TIME (1 * HZ)
4837 +
4838 +#ifndef KERNEL_2_6
4839 +#define new_decode_dev(x) (x)
4840 +#define new_encode_dev(x) (x)
4841 +#endif
4842 +
4843 +static void change_attributes(struct inode *inode, struct fuse_attr *attr)
4844 +{
4845 +       if(S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) {
4846 +#ifdef KERNEL_2_6
4847 +               invalidate_inode_pages(inode->i_mapping);
4848 +#else
4849 +               invalidate_inode_pages(inode);
4850 +#endif
4851 +       }
4852 +
4853 +       inode->i_mode    = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
4854 +       inode->i_nlink   = attr->nlink;
4855 +       inode->i_uid     = attr->uid;
4856 +       inode->i_gid     = attr->gid;
4857 +       i_size_write(inode, attr->size);
4858 +       inode->i_blksize = PAGE_CACHE_SIZE;
4859 +       inode->i_blocks  = attr->blocks;
4860 +#ifdef KERNEL_2_6
4861 +       inode->i_atime.tv_sec   = attr->atime;
4862 +       inode->i_atime.tv_nsec  = 0;
4863 +       inode->i_mtime.tv_sec   = attr->mtime;
4864 +       inode->i_mtime.tv_nsec  = 0;
4865 +       inode->i_ctime.tv_sec   = attr->ctime;
4866 +       inode->i_ctime.tv_nsec  = 0;
4867 +#else
4868 +       inode->i_atime   = attr->atime;
4869 +       inode->i_mtime   = attr->mtime;
4870 +       inode->i_ctime   = attr->ctime;
4871 +#endif
4872 +}
4873 +
4874 +static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
4875 +{
4876 +       inode->i_mode = attr->mode & S_IFMT;
4877 +       i_size_write(inode, attr->size);
4878 +       if(S_ISREG(inode->i_mode)) {
4879 +               inode->i_op = &fuse_file_inode_operations;
4880 +               fuse_init_file_inode(inode);
4881 +       }
4882 +       else if(S_ISDIR(inode->i_mode)) {
4883 +               inode->i_op = &fuse_dir_inode_operations;
4884 +               inode->i_fop = &fuse_dir_operations;
4885 +       }
4886 +       else if(S_ISLNK(inode->i_mode)) {
4887 +               inode->i_op = &fuse_symlink_inode_operations;
4888 +       }
4889 +       else {
4890 +               inode->i_op = &fuse_file_inode_operations;
4891 +               init_special_inode(inode, inode->i_mode,
4892 +                                  new_decode_dev(attr->rdev));
4893 +       }
4894 +       inode->u.generic_ip = inode;
4895 +}
4896 +
4897 +struct inode *fuse_iget(struct super_block *sb, ino_t ino,
4898 +                       struct fuse_attr *attr, int version)
4899 +{
4900 +       struct inode *inode;
4901 +
4902 +       inode = iget(sb, ino);
4903 +       if(inode) {
4904 +               if(!inode->u.generic_ip)
4905 +                       fuse_init_inode(inode, attr);
4906 +
4907 +               change_attributes(inode, attr);
4908 +               inode->i_version = version;
4909 +       }
4910 +
4911 +       return inode;
4912 +}
4913 +
4914 +static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
4915 +                         struct fuse_lookup_out *outarg, int *version)
4916 +{
4917 +       struct fuse_conn *fc = INO_FC(dir);
4918 +       struct fuse_in in = FUSE_IN_INIT;
4919 +       struct fuse_out out = FUSE_OUT_INIT;
4920 +
4921 +       if (entry->d_name.len > FUSE_NAME_MAX)
4922 +               return -ENAMETOOLONG;
4923 +
4924 +       in.h.opcode = FUSE_LOOKUP;
4925 +       in.h.ino = dir->i_ino;
4926 +       in.numargs = 1;
4927 +       in.args[0].size = entry->d_name.len + 1;
4928 +       in.args[0].value = entry->d_name.name;
4929 +       out.numargs = 1;
4930 +       out.args[0].size = sizeof(struct fuse_lookup_out);
4931 +       out.args[0].value = outarg;
4932 +       request_send(fc, &in, &out);
4933 +
4934 +       *version = out.h.unique;
4935 +       return out.h.error;
4936 +}
4937 +
4938 +static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
4939 +                           struct inode **inodep)
4940 +{
4941 +       int err;
4942 +       struct fuse_lookup_out outarg;
4943 +       int version;
4944 +       struct inode *inode = NULL;
4945 +
4946 +       err = fuse_do_lookup(dir, entry, &outarg, &version);
4947 +       if(!err) {
4948 +               inode = fuse_iget(dir->i_sb, outarg.ino, &outarg.attr, version);
4949 +               if(!inode)
4950 +                       return -ENOMEM;
4951 +       } else if(err != -ENOENT)
4952 +               return err;
4953 +
4954 +       entry->d_time = jiffies;
4955 +       entry->d_op = &fuse_dentry_operations;
4956 +       *inodep = inode;
4957 +       return 0;
4958 +}
4959 +
4960 +static void uncache_dir(struct inode *dir)
4961 +{
4962 +       struct dentry *entry = d_find_alias(dir);
4963 +       if (!entry)
4964 +               dir->i_nlink = 0;
4965 +       else {
4966 +               entry->d_time = jiffies - FUSE_REVALIDATE_TIME - 1;
4967 +               dput(entry);
4968 +       }
4969 +}
4970 +
4971 +/* create needs to return a positive entry, so this is actually an
4972 +   mknod+lookup */
4973 +static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
4974 +                     dev_t rdev)
4975 +{
4976 +       struct fuse_conn *fc = INO_FC(dir);
4977 +       struct fuse_in in = FUSE_IN_INIT;
4978 +       struct fuse_out out = FUSE_OUT_INIT;
4979 +       struct fuse_mknod_in inarg;
4980 +       struct fuse_mknod_out outarg;
4981 +       struct inode *inode;
4982 +
4983 +       memset(&inarg, 0, sizeof(inarg));
4984 +       inarg.mode = mode;
4985 +       inarg.rdev = new_encode_dev(rdev);
4986 +
4987 +       in.h.opcode = FUSE_MKNOD;
4988 +       in.h.ino = dir->i_ino;
4989 +       in.numargs = 2;
4990 +       in.args[0].size = sizeof(inarg);
4991 +       in.args[0].value = &inarg;
4992 +       in.args[1].size = entry->d_name.len + 1;
4993 +       in.args[1].value = entry->d_name.name;
4994 +       out.numargs = 1;
4995 +       out.args[0].size = sizeof(outarg);
4996 +       out.args[0].value = &outarg;
4997 +       request_send(fc, &in, &out);
4998 +
4999 +       if(out.h.error) 
5000 +               return out.h.error;
5001 +
5002 +       inode = fuse_iget(dir->i_sb, outarg.ino, &outarg.attr, out.h.unique);
5003 +       if(!inode) 
5004 +               return -ENOMEM;
5005 +
5006 +       /* Don't allow userspace to do really stupid things... */
5007 +       if((inode->i_mode ^ mode) & S_IFMT) {
5008 +               iput(inode);
5009 +               printk("fuse_mknod: inode has wrong type\n");
5010 +               return -EPROTO;
5011 +       }
5012 +
5013 +       d_instantiate(entry, inode);
5014 +       uncache_dir(dir);
5015 +       return 0;
5016 +}
5017 +
5018 +static int _fuse_create(struct inode *dir, struct dentry *entry, int mode)
5019 +{
5020 +       return _fuse_mknod(dir, entry, mode, 0);
5021 +}
5022 +
5023 +/* knfsd needs the new entry instantiated in mkdir/symlink/link. this
5024 +   should rather be done like mknod: attributes returned in out arg to
5025 +   save a call to userspace */
5026 +static int lookup_new_entry(struct inode *dir, struct dentry *entry)
5027 +{
5028 +       struct inode *inode;
5029 +       int err = fuse_lookup_iget(dir, entry, &inode);
5030 +       if(err || !inode) {
5031 +               printk("fuse_mkdir: failed to look up new entry\n");
5032 +               return err ? err : -ENOENT;
5033 +       }
5034 +       d_instantiate(entry, inode);
5035 +       uncache_dir(dir);
5036 +       return 0;
5037 +}
5038 +
5039 +static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
5040 +{
5041 +       struct fuse_conn *fc = INO_FC(dir);
5042 +       struct fuse_in in = FUSE_IN_INIT;
5043 +       struct fuse_out out = FUSE_OUT_INIT;
5044 +       struct fuse_mkdir_in inarg;
5045 +
5046 +       memset(&inarg, 0, sizeof(inarg));
5047 +       inarg.mode = mode;
5048 +
5049 +       in.h.opcode = FUSE_MKDIR;
5050 +       in.h.ino = dir->i_ino;
5051 +       in.numargs = 2;
5052 +       in.args[0].size = sizeof(inarg);
5053 +       in.args[0].value = &inarg;
5054 +       in.args[1].size = entry->d_name.len + 1;
5055 +       in.args[1].value = entry->d_name.name;
5056 +       request_send(fc, &in, &out);
5057 +       if(out.h.error)
5058 +               return out.h.error;
5059 +
5060 +       return lookup_new_entry(dir, entry);
5061 +}
5062 +
5063 +static int fuse_symlink(struct inode *dir, struct dentry *entry,
5064 +                       const char *link)
5065 +{
5066 +       struct fuse_conn *fc = INO_FC(dir);
5067 +       struct fuse_in in = FUSE_IN_INIT;
5068 +       struct fuse_out out = FUSE_OUT_INIT;
5069 +       unsigned int len = strlen(link) + 1;
5070 +       
5071 +       if (len > FUSE_SYMLINK_MAX)
5072 +               return -ENAMETOOLONG;
5073 +
5074 +       in.h.opcode = FUSE_SYMLINK;
5075 +       in.h.ino = dir->i_ino;
5076 +       in.numargs = 2;
5077 +       in.args[0].size = entry->d_name.len + 1;
5078 +       in.args[0].value = entry->d_name.name;
5079 +       in.args[1].size = len;
5080 +       in.args[1].value = link;
5081 +       request_send(fc, &in, &out);
5082 +       if(out.h.error)
5083 +               return out.h.error;
5084 +
5085 +       return lookup_new_entry(dir, entry);
5086 +}
5087 +
5088 +static int fuse_remove(struct inode *dir, struct dentry *entry, 
5089 +                      enum fuse_opcode op)
5090 +{
5091 +       struct fuse_conn *fc = INO_FC(dir);
5092 +       struct fuse_in in = FUSE_IN_INIT;
5093 +       struct fuse_out out = FUSE_OUT_INIT;
5094 +
5095 +       in.h.opcode = op;
5096 +       in.h.ino = dir->i_ino;
5097 +       in.numargs = 1;
5098 +       in.args[0].size = entry->d_name.len + 1;
5099 +       in.args[0].value = entry->d_name.name;
5100 +       request_send(fc, &in, &out);
5101 +
5102 +       return out.h.error;
5103 +}
5104 +
5105 +static int fuse_unlink(struct inode *dir, struct dentry *entry)
5106 +{
5107 +       int err = fuse_remove(dir, entry, FUSE_UNLINK);
5108 +       if(!err) {
5109 +               /* FIXME: the new i_nlink could be returned by the
5110 +                   unlink operation */
5111 +               err = fuse_do_getattr(entry->d_inode);
5112 +               if(err == -ENOENT)
5113 +                       entry->d_inode->i_nlink = 0;
5114 +
5115 +               uncache_dir(dir);
5116 +               return 0;
5117 +       }
5118 +       return err;
5119 +}
5120 +
5121 +static int fuse_rmdir(struct inode *dir, struct dentry *entry)
5122 +{
5123 +       int err = fuse_remove(dir, entry, FUSE_RMDIR);
5124 +       if(!err) {
5125 +               entry->d_inode->i_nlink = 0;
5126 +               uncache_dir(dir);
5127 +       }
5128 +       return err;
5129 +}
5130 +
5131 +static int fuse_rename(struct inode *olddir, struct dentry *oldent,
5132 +                      struct inode *newdir, struct dentry *newent)
5133 +{
5134 +       struct fuse_conn *fc = INO_FC(olddir);
5135 +       struct fuse_in in = FUSE_IN_INIT;
5136 +       struct fuse_out out = FUSE_OUT_INIT;
5137 +       struct fuse_rename_in inarg;
5138 +       
5139 +       memset(&inarg, 0, sizeof(inarg));
5140 +       inarg.newdir = newdir->i_ino;
5141 +
5142 +       in.h.opcode = FUSE_RENAME;
5143 +       in.h.ino = olddir->i_ino;
5144 +       in.numargs = 3;
5145 +       in.args[0].size = sizeof(inarg);
5146 +       in.args[0].value = &inarg;
5147 +       in.args[1].size = oldent->d_name.len + 1;
5148 +       in.args[1].value = oldent->d_name.name;
5149 +       in.args[2].size = newent->d_name.len + 1;
5150 +       in.args[2].value = newent->d_name.name;
5151 +       request_send(fc, &in, &out);
5152 +
5153 +       if (!out.h.error) {
5154 +               uncache_dir(olddir);
5155 +               if (olddir != newdir)
5156 +                       uncache_dir(newdir);
5157 +       }
5158 +
5159 +       return out.h.error;
5160 +}
5161 +
5162 +static int fuse_link(struct dentry *entry, struct inode *newdir,
5163 +                    struct dentry *newent)
5164 +{
5165 +       struct inode *inode = entry->d_inode;
5166 +       struct fuse_conn *fc = INO_FC(inode);
5167 +       struct fuse_in in = FUSE_IN_INIT;
5168 +       struct fuse_out out = FUSE_OUT_INIT;
5169 +       struct fuse_link_in inarg;
5170 +       
5171 +       memset(&inarg, 0, sizeof(inarg));
5172 +       inarg.newdir = newdir->i_ino;
5173 +
5174 +       in.h.opcode = FUSE_LINK;
5175 +       in.h.ino = inode->i_ino;
5176 +       in.numargs = 2;
5177 +       in.args[0].size = sizeof(inarg);
5178 +       in.args[0].value = &inarg;
5179 +       in.args[1].size = newent->d_name.len + 1;
5180 +       in.args[1].value = newent->d_name.name;
5181 +       request_send(fc, &in, &out);
5182 +       if(out.h.error)
5183 +               return out.h.error;
5184 +
5185 +       /* Invalidate old entry, so attributes are refreshed */
5186 +       d_invalidate(entry);
5187 +       return lookup_new_entry(newdir, newent);
5188 +}
5189 +
5190 +int fuse_do_getattr(struct inode *inode)
5191 +{
5192 +       struct fuse_conn *fc = INO_FC(inode);
5193 +       struct fuse_in in = FUSE_IN_INIT;
5194 +       struct fuse_out out = FUSE_OUT_INIT;
5195 +       struct fuse_getattr_out arg;
5196 +       
5197 +       in.h.opcode = FUSE_GETATTR;
5198 +       in.h.ino = inode->i_ino;
5199 +       out.numargs = 1;
5200 +       out.args[0].size = sizeof(arg);
5201 +       out.args[0].value = &arg;
5202 +       request_send(fc, &in, &out);
5203 +       
5204 +       if(!out.h.error)
5205 +               change_attributes(inode, &arg.attr);
5206 +       
5207 +       return out.h.error;
5208 +}
5209 +
5210 +static int fuse_revalidate(struct dentry *entry)
5211 +{
5212 +       struct inode *inode = entry->d_inode;
5213 +       struct fuse_conn *fc = INO_FC(inode);
5214 +
5215 +       if(inode->i_ino == FUSE_ROOT_INO) {
5216 +               if(!(fc->flags & FUSE_ALLOW_OTHER) &&
5217 +                  current->fsuid != fc->uid)
5218 +                       return -EACCES;
5219 +       } else if(time_before_eq(jiffies, entry->d_time + FUSE_REVALIDATE_TIME))
5220 +               return 0;
5221 +
5222 +       return fuse_do_getattr(inode);
5223 +}
5224 +
5225 +static int _fuse_permission(struct inode *inode, int mask)
5226 +{
5227 +       struct fuse_conn *fc = INO_FC(inode);
5228 +
5229 +       if(!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid)
5230 +               return -EACCES;
5231 +       else if(fc->flags & FUSE_DEFAULT_PERMISSIONS) {
5232 +               int err = generic_permission(inode, mask, NULL);
5233 +
5234 +               /* If permission is denied, try to refresh file
5235 +                  attributes.  This is also needed, because the root
5236 +                  node will at first have no permissions */
5237 +
5238 +               if(err == -EACCES) {
5239 +                       err = fuse_do_getattr(inode);
5240 +                       if(!err)
5241 +                               err = generic_permission(inode, mask, NULL);
5242 +               }
5243 +
5244 +               /* FIXME: Need some mechanism to revoke permissions:
5245 +                  currently if the filesystem suddenly changes the
5246 +                  file mode, we will not be informed abot that, and
5247 +                  continue to allow access to the file/directory.
5248 +                  
5249 +                  This is actually not so grave, since the user can
5250 +                  simply keep access to the file/directory anyway by
5251 +                  keeping it open... */
5252 +
5253 +               return err;
5254 +       }
5255 +       else
5256 +               return 0;
5257 +}
5258 +
5259 +static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
5260 +                        void *dstbuf, filldir_t filldir)
5261 +{
5262 +       while(nbytes >= FUSE_NAME_OFFSET) {
5263 +               struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
5264 +               size_t reclen = FUSE_DIRENT_SIZE(dirent);
5265 +               int over;
5266 +
5267 +               if(dirent->namelen > NAME_MAX) {
5268 +                       printk("fuse_readdir: name too long\n");
5269 +                       return -EPROTO;
5270 +               }
5271 +               if(reclen > nbytes)
5272 +                       break;
5273 +
5274 +               over = filldir(dstbuf, dirent->name, dirent->namelen,
5275 +                             file->f_pos, dirent->ino, dirent->type);
5276 +               if(over)
5277 +                       break;
5278 +
5279 +               buf += reclen;
5280 +               file->f_pos += reclen;
5281 +               nbytes -= reclen;
5282 +       }
5283 +
5284 +       return 0;
5285 +}
5286 +
5287 +#ifndef CONFIG_COOPERATIVE
5288 +
5289 +#define DIR_BUFSIZE 2048
5290 +static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
5291 +{
5292 +       struct file *cfile = file->private_data;
5293 +       char *buf;
5294 +       int ret;
5295 +
5296 +       if(!cfile)
5297 +               return -EISDIR;
5298 +
5299 +       buf = kmalloc(DIR_BUFSIZE, GFP_KERNEL);
5300 +       if(!buf)
5301 +               return -ENOMEM;
5302 +       
5303 +       ret = kernel_read(cfile, file->f_pos, buf, DIR_BUFSIZE);
5304 +       if(ret < 0)
5305 +               printk("fuse_readdir: failed to read container file\n");
5306 +       else 
5307 +               ret = parse_dirfile(buf, ret, file, dstbuf, filldir);
5308 +
5309 +       kfree(buf);     
5310 +       return ret;
5311 +}
5312 +
5313 +#else
5314 +
5315 +#define DIR_BUFSIZE 4096
5316 +
5317 +typedef struct {
5318 +       struct fuse_conn *fc;
5319 +       int inode;
5320 +} readdir_data_t;
5321 +
5322 +static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
5323 +{
5324 +       readdir_data_t *rd = file->private_data;
5325 +       unsigned long flags;
5326 +       int ret, size;
5327 +       char *buf;
5328 +
5329 +       buf = kmalloc(DIR_BUFSIZE, GFP_KERNEL);
5330 +       if (!buf)
5331 +               return -ENOMEM;
5332 +
5333 +       co_passage_page_assert_valid();
5334 +               
5335 +       co_passage_page_acquire(&flags);
5336 +       co_passage_page->operation = CO_OPERATION_DEVICE;
5337 +       co_passage_page->params[0] = CO_DEVICE_FILESYSTEM;
5338 +       co_passage_page->params[1] = rd->fc->cofs_unit;
5339 +       co_passage_page->params[2] = FUSE_DIR_READ;
5340 +       co_passage_page->params[3] = rd->inode;
5341 +       co_passage_page->params[5] = DIR_BUFSIZE;
5342 +       co_passage_page->params[6] = (unsigned long)buf;
5343 +       co_passage_page->params[8] = file->f_pos;
5344 +       
5345 +       co_switch_wrapper();
5346 +       
5347 +       ret = co_passage_page->params[4];
5348 +       size = co_passage_page->params[7];
5349 +       
5350 +       co_passage_page_release(flags);
5351 +       
5352 +       if (ret) {
5353 +               printk("fuse_readdir: host returned error: %x\n", ret);
5354 +               kfree(buf);     
5355 +               return ret;
5356 +       }
5357 +       
5358 +       parse_dirfile(buf, size, file, dstbuf, filldir);
5359 +               
5360 +       ret = 0;
5361 +       kfree(buf);     
5362 +       return ret;
5363 +}
5364 +
5365 +#endif
5366 +
5367 +static char *read_link(struct dentry *dentry)
5368 +{
5369 +       struct inode *inode = dentry->d_inode;
5370 +       struct fuse_conn *fc = INO_FC(inode);
5371 +       struct fuse_in in = FUSE_IN_INIT;
5372 +       struct fuse_out out = FUSE_OUT_INIT;
5373 +       char *link;
5374 +
5375 +       link = (char *) __get_free_page(GFP_KERNEL);
5376 +       if(!link)
5377 +               return ERR_PTR(-ENOMEM);
5378 +
5379 +       in.h.opcode = FUSE_READLINK;
5380 +       in.h.ino = inode->i_ino;
5381 +       out.argvar = 1;
5382 +       out.numargs = 1;
5383 +       out.args[0].size = PAGE_SIZE - 1;
5384 +       out.args[0].value = link;
5385 +       request_send(fc, &in, &out);
5386 +       if(out.h.error) {
5387 +               free_page((unsigned long) link);
5388 +               return ERR_PTR(out.h.error);
5389 +       }
5390 +
5391 +       link[out.args[0].size] = '\0';
5392 +       return link;
5393 +}
5394 +
5395 +static void free_link(char *link)
5396 +{
5397 +       if(!IS_ERR(link))
5398 +               free_page((unsigned long) link);
5399 +}
5400 +
5401 +static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
5402 +{
5403 +       int ret;
5404 +       char *link;
5405 +
5406 +       link = read_link(dentry);
5407 +       ret = vfs_readlink(dentry, buffer, buflen, link);
5408 +       free_link(link);
5409 +       return ret;
5410 +}
5411 +
5412 +static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
5413 +{
5414 +       int ret;
5415 +       char *link;
5416 +
5417 +       link = read_link(dentry);
5418 +       ret = vfs_follow_link(nd, link);
5419 +       free_link(link);
5420 +       return ret;
5421 +}
5422 +
5423 +#ifndef CONFIG_COOPERATIVE
5424 +
5425 +static int fuse_dir_open(struct inode *inode, struct file *file)
5426 +{
5427 +       struct fuse_conn *fc = INO_FC(inode);
5428 +       struct fuse_in in = FUSE_IN_INIT;
5429 +       struct fuse_out out = FUSE_OUT_INIT;
5430 +       struct fuse_getdir_out outarg;
5431 +
5432 +       in.h.opcode = FUSE_GETDIR;
5433 +       in.h.ino = inode->i_ino;
5434 +       out.numargs = 1;
5435 +       out.args[0].size = sizeof(outarg);
5436 +       out.args[0].value = &outarg;
5437 +       request_send(fc, &in, &out);
5438 +       if(!out.h.error) {
5439 +               struct file *cfile = outarg.file;
5440 +               struct inode *inode;
5441 +               if(!cfile) {
5442 +                       printk("fuse_getdir: invalid file\n");
5443 +                       return -EPROTO;
5444 +               }
5445 +               inode = cfile->f_dentry->d_inode;
5446 +               if(!S_ISREG(inode->i_mode)) {
5447 +                       printk("fuse_getdir: not a regular file\n");
5448 +                       fput(cfile);
5449 +                       return -EPROTO;
5450 +               }
5451 +
5452 +               file->private_data = cfile;
5453 +       }
5454 +
5455 +       return out.h.error;
5456 +}
5457 +
5458 +static int fuse_dir_release(struct inode *inode, struct file *file)
5459 +{
5460 +       struct file *cfile = file->private_data;
5461 +
5462 +       if(cfile)
5463 +               fput(cfile);
5464 +
5465 +       return 0;
5466 +}
5467 +
5468 +#else
5469 +
5470 +static int fuse_dir_open(struct inode *inode, struct file *file)
5471 +{
5472 +       struct fuse_conn *fc = INO_FC(inode);
5473 +       unsigned long flags;
5474 +       readdir_data_t *rd;
5475 +       int ret;
5476 +
5477 +       rd = kmalloc(sizeof(*rd), GFP_KERNEL);
5478 +       if (!rd)
5479 +               return -ENOMEM;
5480 +
5481 +       rd->fc = fc;
5482 +       rd->inode = inode->i_ino;
5483 +
5484 +       co_passage_page_assert_valid();
5485 +
5486 +       co_passage_page_acquire(&flags);
5487 +       co_passage_page->operation = CO_OPERATION_DEVICE;
5488 +       co_passage_page->params[0] = CO_DEVICE_FILESYSTEM;
5489 +       co_passage_page->params[1] = fc->cofs_unit;
5490 +       co_passage_page->params[2] = FUSE_DIR_OPEN;
5491 +       co_passage_page->params[3] = inode->i_ino;
5492 +       co_passage_page->params[4] = 0;
5493 +
5494 +       co_switch_wrapper();
5495 +
5496 +       ret = co_passage_page->params[4];
5497 +
5498 +       co_passage_page_release(flags);
5499 +
5500 +       if (ret) {
5501 +               printk("fuse_readdir: host returned error: %x\n", ret);
5502 +               kfree(rd);
5503 +       } else {
5504 +               file->private_data = (void *)rd;
5505 +       }
5506 +
5507 +       return ret;
5508 +}
5509 +
5510 +static int fuse_dir_release(struct inode *inode, struct file *file)
5511 +{
5512 +       readdir_data_t *rd = file->private_data;
5513 +       unsigned long flags;
5514 +       int ret;
5515 +
5516 +       co_passage_page_assert_valid();
5517 +
5518 +       co_passage_page_acquire(&flags);
5519 +       co_passage_page->operation = CO_OPERATION_DEVICE;
5520 +       co_passage_page->params[0] = CO_DEVICE_FILESYSTEM;
5521 +       co_passage_page->params[1] = rd->fc->cofs_unit;
5522 +       co_passage_page->params[2] = FUSE_DIR_RELEASE;
5523 +       co_passage_page->params[3] = rd->inode;
5524 +       co_passage_page->params[4] = 0;
5525 +
5526 +       co_switch_wrapper();
5527 +
5528 +       ret = co_passage_page->params[4];
5529 +
5530 +       co_passage_page_release(flags);
5531 +
5532 +       if (ret) {
5533 +               printk("fuse_readdir: host returned error: %x\n", ret);
5534 +       } 
5535 +
5536 +       kfree(rd);
5537 +
5538 +       return ret;
5539 +}
5540 +
5541 +#endif
5542 +
5543 +static unsigned int iattr_to_fattr(struct iattr *iattr,
5544 +                                  struct fuse_attr *fattr)
5545 +{
5546 +       unsigned int ivalid = iattr->ia_valid;
5547 +       unsigned int fvalid = 0;
5548 +       
5549 +       memset(fattr, 0, sizeof(*fattr));
5550 +       
5551 +       if(ivalid & ATTR_MODE)
5552 +               fvalid |= FATTR_MODE,   fattr->mode = iattr->ia_mode;
5553 +       if(ivalid & ATTR_UID)
5554 +               fvalid |= FATTR_UID,    fattr->uid = iattr->ia_uid;
5555 +       if(ivalid & ATTR_GID)
5556 +               fvalid |= FATTR_GID,    fattr->gid = iattr->ia_gid;
5557 +       if(ivalid & ATTR_SIZE)
5558 +               fvalid |= FATTR_SIZE,   fattr->size = iattr->ia_size;
5559 +       /* You can only _set_ these together (they may change by themselves) */
5560 +       if((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
5561 +               fvalid |= FATTR_UTIME;
5562 +#ifdef KERNEL_2_6
5563 +               fattr->atime = iattr->ia_atime.tv_sec;
5564 +               fattr->mtime = iattr->ia_mtime.tv_sec;
5565 +#else
5566 +               fattr->atime = iattr->ia_atime;
5567 +               fattr->mtime = iattr->ia_mtime;
5568 +#endif
5569 +       }
5570 +
5571 +       return fvalid;
5572 +}
5573 +
5574 +static int fuse_setattr(struct dentry *entry, struct iattr *attr)
5575 +{
5576 +       struct inode *inode = entry->d_inode;
5577 +       struct fuse_conn *fc = INO_FC(inode);
5578 +       struct fuse_in in = FUSE_IN_INIT;
5579 +       struct fuse_out out = FUSE_OUT_INIT;
5580 +       struct fuse_setattr_in inarg;
5581 +       struct fuse_setattr_out outarg;
5582 +
5583 +       /* FIXME: need to fix race between truncate and writepage */
5584 +       if (attr->ia_valid & ATTR_SIZE) 
5585 +               fuse_sync_inode(inode);
5586 +
5587 +       memset(&inarg, 0, sizeof(inarg));
5588 +       inarg.valid = iattr_to_fattr(attr, &inarg.attr);
5589 +       
5590 +       in.h.opcode = FUSE_SETATTR;
5591 +       in.h.ino = inode->i_ino;
5592 +       in.numargs = 1;
5593 +       in.args[0].size = sizeof(inarg);
5594 +       in.args[0].value = &inarg;
5595 +       out.numargs = 1;
5596 +       out.args[0].size = sizeof(outarg);
5597 +       out.args[0].value = &outarg;
5598 +       request_send(fc, &in, &out);
5599 +
5600 +       if(!out.h.error) {
5601 +               if(attr->ia_valid & ATTR_SIZE &&
5602 +                  outarg.attr.size < i_size_read(inode))
5603 +                       vmtruncate(inode, outarg.attr.size);
5604 +
5605 +               change_attributes(inode, &outarg.attr);
5606 +       } 
5607 +       return out.h.error;
5608 +}
5609 +
5610 +static int _fuse_dentry_revalidate(struct dentry *entry)
5611 +{
5612 +       if(!entry->d_inode)
5613 +               return 0;
5614 +       else if(time_after(jiffies, entry->d_time + FUSE_REVALIDATE_TIME)) {
5615 +               struct inode *inode = entry->d_inode;
5616 +               struct fuse_lookup_out outarg;
5617 +               int version;
5618 +               int ret;
5619 +               
5620 +               ret = fuse_do_lookup(entry->d_parent->d_inode, entry, &outarg,
5621 +                                    &version);
5622 +               if(ret)
5623 +                       return 0;
5624 +               
5625 +               if(outarg.ino != inode->i_ino)
5626 +                       return 0;
5627 +               
5628 +               change_attributes(inode, &outarg.attr);
5629 +               inode->i_version = version;
5630 +               entry->d_time = jiffies;
5631 +       }
5632 +       return 1;
5633 +}
5634 +
5635 +#ifdef KERNEL_2_6
5636 +
5637 +#define fuse_mknod _fuse_mknod
5638 +
5639 +static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
5640 +                       struct kstat *stat)
5641 +{
5642 +       struct inode *inode = entry->d_inode;
5643 +       int err = fuse_revalidate(entry);
5644 +       if(!err)
5645 +               generic_fillattr(inode, stat);
5646 +       
5647 +       return err;
5648 +}
5649 +
5650 +static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
5651 +                                  struct nameidata *nd)
5652 +{
5653 +       struct inode *inode;
5654 +       int err = fuse_lookup_iget(dir, entry, &inode);
5655 +       if (err)
5656 +               return ERR_PTR(err);
5657 +       return d_splice_alias(inode, entry);
5658 +}
5659 +
5660 +static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
5661 +                      struct nameidata *nd)
5662 +{
5663 +       return _fuse_create(dir, entry, mode);
5664 +}
5665 +
5666 +static int fuse_permission(struct inode *inode, int mask,
5667 +                           struct nameidata *nd)
5668 +{
5669 +       return _fuse_permission(inode, mask);
5670 +}
5671 +
5672 +static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
5673 +{
5674 +       return _fuse_dentry_revalidate(entry);
5675 +}
5676 +#else /* KERNEL_2_6 */
5677 +
5678 +#define fuse_create _fuse_create
5679 +#define fuse_permission _fuse_permission
5680 +
5681 +static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
5682 +{
5683 +       struct inode *inode;
5684 +       struct dentry *alias;
5685 +
5686 +       int err = fuse_lookup_iget(dir, entry, &inode);
5687 +       if(err)
5688 +               return ERR_PTR(err);
5689 +
5690 +       if(inode && S_ISDIR(inode->i_mode) &&
5691 +          (alias = d_find_alias(inode)) != NULL) {
5692 +               dput(alias);
5693 +               iput(inode);
5694 +               printk("fuse: cannot assign an existing directory\n");
5695 +               return ERR_PTR(-EPROTO);
5696 +       }
5697 +
5698 +       d_add(entry, inode);
5699 +       return NULL;
5700 +}
5701 +
5702 +static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
5703 +                     int rdev)
5704 +{
5705 +       return _fuse_mknod(dir, entry, mode, rdev);
5706 +}
5707 +
5708 +static int fuse_dentry_revalidate(struct dentry *entry, int flags)
5709 +{
5710 +       return _fuse_dentry_revalidate(entry);
5711 +}
5712 +#endif /* KERNEL_2_6 */
5713 +
5714 +
5715 +static struct inode_operations fuse_dir_inode_operations =
5716 +{
5717 +       .lookup         = fuse_lookup,
5718 +       .create         = fuse_create,
5719 +       .mknod          = fuse_mknod,
5720 +       .mkdir          = fuse_mkdir,
5721 +       .symlink        = fuse_symlink,
5722 +       .unlink         = fuse_unlink,
5723 +       .rmdir          = fuse_rmdir,
5724 +       .rename         = fuse_rename,
5725 +       .link           = fuse_link,
5726 +       .setattr        = fuse_setattr,
5727 +       .permission     = fuse_permission,
5728 +#ifdef KERNEL_2_6
5729 +       .getattr        = fuse_getattr,
5730 +#else
5731 +       .revalidate     = fuse_revalidate,
5732 +#endif
5733 +};
5734 +
5735 +static struct file_operations fuse_dir_operations = {
5736 +       .read           = generic_read_dir,
5737 +       .readdir        = fuse_readdir,
5738 +       .open           = fuse_dir_open,
5739 +       .release        = fuse_dir_release,
5740 +};
5741 +
5742 +static struct inode_operations fuse_file_inode_operations = {
5743 +       .setattr        = fuse_setattr,
5744 +       .permission     = fuse_permission,
5745 +#ifdef KERNEL_2_6
5746 +       .getattr        = fuse_getattr,
5747 +#else
5748 +       .revalidate     = fuse_revalidate,
5749 +#endif
5750 +};
5751 +
5752 +static struct inode_operations fuse_symlink_inode_operations =
5753 +{
5754 +       .setattr        = fuse_setattr,
5755 +       .readlink       = fuse_readlink,
5756 +       .follow_link    = fuse_follow_link,
5757 +#ifdef KERNEL_2_6
5758 +       .getattr        = fuse_getattr,
5759 +#else
5760 +       .revalidate     = fuse_revalidate,
5761 +#endif
5762 +};
5763 +
5764 +static struct dentry_operations fuse_dentry_operations = {
5765 +       .d_revalidate   = fuse_dentry_revalidate,
5766 +};
5767 +
5768 +/* 
5769 + * Local Variables:
5770 + * indent-tabs-mode: t
5771 + * c-basic-offset: 8
5772 + * End:
5773 + */
5774 diff -urN a/fs/cofusefs/file.c b/fs/cofusefs/file.c
5775 --- a/fs/cofusefs/file.c
5776 +++ b/fs/cofusefs/file.c
5777 @@ -0,0 +1,542 @@
5778 +/*
5779 +    FUSE: Filesystem in Userspace
5780 +    Copyright (C) 2001-2004  Miklos Szeredi <miklos@szeredi.hu>
5781 +
5782 +    This program can be distributed under the terms of the GNU GPL.
5783 +    See the file COPYING.
5784 +*/
5785 +#include "fuse_i.h"
5786 +
5787 +#include <linux/pagemap.h>
5788 +#include <linux/slab.h>
5789 +#ifdef KERNEL_2_6
5790 +#include <linux/backing-dev.h>
5791 +#include <linux/writeback.h>
5792 +#endif
5793 +
5794 +#ifndef KERNEL_2_6
5795 +#define PageUptodate(page) Page_Uptodate(page)
5796 +#endif
5797 +
5798 +static int fuse_open(struct inode *inode, struct file *file)
5799 +{
5800 +       struct fuse_conn *fc = INO_FC(inode);
5801 +       struct fuse_in in = FUSE_IN_INIT;
5802 +       struct fuse_out out = FUSE_OUT_INIT;
5803 +       struct fuse_open_in inarg;
5804 +       int err;
5805 +
5806 +       err = generic_file_open(inode, file);
5807 +       if(err)
5808 +               return err;
5809 +
5810 +       /* If opening the root node, no lookup has been performed on
5811 +          it, so the attributes must be refreshed */
5812 +       if(inode->i_ino == FUSE_ROOT_INO) {
5813 +               int err = fuse_do_getattr(inode);
5814 +               if(err)
5815 +                       return err;
5816 +       }
5817 +
5818 +       memset(&inarg, 0, sizeof(inarg));
5819 +       inarg.flags = file->f_flags & ~O_EXCL;
5820 +
5821 +       in.h.opcode = FUSE_OPEN;
5822 +       in.h.ino = inode->i_ino;
5823 +       in.numargs = 1;
5824 +       in.args[0].size = sizeof(inarg);
5825 +       in.args[0].value = &inarg;
5826 +       request_send(fc, &in, &out);
5827 +       if(!out.h.error && !(fc->flags & FUSE_KERNEL_CACHE)) {
5828 +#ifdef KERNEL_2_6
5829 +               invalidate_inode_pages(inode->i_mapping);
5830 +#else
5831 +               invalidate_inode_pages(inode);
5832 +#endif
5833 +       }
5834 +
5835 +       return out.h.error;
5836 +}
5837 +
5838 +void fuse_sync_inode(struct inode *inode)
5839 +{
5840 +#ifdef KERNEL_2_6
5841 +       filemap_fdatawrite(inode->i_mapping);
5842 +       filemap_fdatawait(inode->i_mapping);
5843 +#else
5844 +#ifndef NO_MM
5845 +       filemap_fdatasync(inode->i_mapping);
5846 +       filemap_fdatawait(inode->i_mapping);
5847 +#endif
5848 +#endif
5849 +}
5850 +
5851 +static int fuse_release_old(struct inode *inode, struct file *file)
5852 +{
5853 +       struct fuse_conn *fc = INO_FC(inode);
5854 +       struct fuse_in *in = NULL;
5855 +       struct fuse_open_in *inarg = NULL;
5856 +       unsigned int s = sizeof(struct fuse_in) + sizeof(struct fuse_open_in);
5857 +
5858 +       in = kmalloc(s, GFP_NOFS);
5859 +       if(!in)
5860 +               return -ENOMEM;
5861 +       memset(in, 0, s);
5862 +       inarg = (struct fuse_open_in *) (in + 1);
5863 +       inarg->flags = file->f_flags & ~O_EXCL;
5864 +
5865 +       in->h.opcode = FUSE_RELEASE;
5866 +       in->h.ino = inode->i_ino;
5867 +       in->numargs = 1;
5868 +       in->args[0].size = sizeof(struct fuse_open_in);
5869 +       in->args[0].value = inarg;
5870 +       if(!request_send_noreply(fc, in))
5871 +               return 0;
5872 +
5873 +       kfree(in);
5874 +       return 0;
5875 +}
5876 +
5877 +static int fuse_release(struct inode *inode, struct file *file)
5878 +{
5879 +       struct fuse_conn *fc = INO_FC(inode);
5880 +       struct fuse_in in = FUSE_IN_INIT;
5881 +       struct fuse_out out = FUSE_OUT_INIT;
5882 +       struct fuse_open_in inarg;
5883 +
5884 +       if(file->f_mode & FMODE_WRITE)
5885 +               fuse_sync_inode(inode);
5886 +
5887 +       if (fc->oldrelease)
5888 +               return fuse_release_old(inode, file);
5889 +
5890 +       memset(&inarg, 0, sizeof(inarg));
5891 +       inarg.flags = file->f_flags & ~O_EXCL;
5892 +
5893 +       in.h.opcode = FUSE_RELEASE2;
5894 +       in.h.ino = inode->i_ino;
5895 +       in.numargs = 1;
5896 +       in.args[0].size = sizeof(inarg);
5897 +       in.args[0].value = &inarg;
5898 +       request_send(fc, &in, &out);
5899 +       if (out.h.error == -ENOSYS) {
5900 +               fc->oldrelease = 1;
5901 +               return fuse_release_old(inode, file);
5902 +       }
5903 +       return 0;
5904 +}
5905 +
5906 +static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
5907 +{
5908 +       struct inode *inode = de->d_inode;
5909 +       struct fuse_conn *fc = INO_FC(inode);
5910 +       struct fuse_in in = FUSE_IN_INIT;
5911 +       struct fuse_out out = FUSE_OUT_INIT;
5912 +       struct fuse_fsync_in inarg;
5913 +       
5914 +       memset(&inarg, 0, sizeof(inarg));
5915 +       inarg.datasync = datasync;
5916 +
5917 +       in.h.opcode = FUSE_FSYNC;
5918 +       in.h.ino = inode->i_ino;
5919 +       in.numargs = 1;
5920 +       in.args[0].size = sizeof(inarg);
5921 +       in.args[0].value = &inarg;
5922 +       request_send(fc, &in, &out);
5923 +       return out.h.error;
5924 +
5925 +       /* FIXME: need to ensure, that all write requests issued
5926 +           before this request are completed.  Should userspace take
5927 +           care of this? */
5928 +}
5929 +
5930 +static int fuse_readpage(struct file *file, struct page *page)
5931 +{
5932 +       struct inode *inode = page->mapping->host;
5933 +       struct fuse_conn *fc = INO_FC(inode);
5934 +       struct fuse_in in = FUSE_IN_INIT;
5935 +       struct fuse_out out = FUSE_OUT_INIT;
5936 +       struct fuse_read_in inarg;
5937 +       char *buffer;
5938 +
5939 +       buffer = kmap(page);
5940 +       
5941 +       memset(&inarg, 0, sizeof(inarg));
5942 +       inarg.offset = (unsigned long long) page->index << PAGE_CACHE_SHIFT;
5943 +       inarg.size = PAGE_CACHE_SIZE;
5944 +
5945 +       in.h.opcode = FUSE_READ;
5946 +       in.h.ino = inode->i_ino;
5947 +       in.numargs = 1;
5948 +       in.args[0].size = sizeof(inarg);
5949 +       in.args[0].value = &inarg;
5950 +       out.argvar = 1;
5951 +       out.numargs = 1;
5952 +       out.args[0].size = PAGE_CACHE_SIZE;
5953 +       out.args[0].value = buffer;
5954 +
5955 +       request_send(fc, &in, &out);
5956 +       if(!out.h.error) {
5957 +               size_t outsize = out.args[0].size;
5958 +               if(outsize < PAGE_CACHE_SIZE) 
5959 +                       memset(buffer + outsize, 0, PAGE_CACHE_SIZE - outsize);
5960 +               flush_dcache_page(page);
5961 +               SetPageUptodate(page);
5962 +       }
5963 +
5964 +       kunmap(page);
5965 +       unlock_page(page);
5966 +
5967 +       return out.h.error;
5968 +}
5969 +
5970 +static int fuse_is_block_uptodate(struct address_space *mapping,
5971 +               struct inode *inode, size_t bl_index)
5972 +{
5973 +       size_t index = bl_index << FUSE_BLOCK_PAGE_SHIFT;
5974 +       size_t end_index = ((bl_index + 1) << FUSE_BLOCK_PAGE_SHIFT) - 1;
5975 +       size_t file_end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
5976 +
5977 +       if (end_index > file_end_index)
5978 +               end_index = file_end_index;
5979 +
5980 +       for (; index <= end_index; index++) {
5981 +               struct page *page = find_get_page(mapping, index);
5982 +
5983 +               if (!page)
5984 +                       return 0;
5985 +
5986 +               if (!PageUptodate(page)) {
5987 +                       page_cache_release(page);
5988 +                       return 0;
5989 +               }
5990 +
5991 +               page_cache_release(page);
5992 +       }
5993 +
5994 +       return 1;
5995 +}
5996 +
5997 +
5998 +static int fuse_cache_block(struct address_space *mapping,
5999 +               struct inode *inode, char *bl_buf,
6000 +               size_t bl_index)
6001 +{
6002 +       size_t start_index = bl_index << FUSE_BLOCK_PAGE_SHIFT;
6003 +       size_t end_index = ((bl_index + 1) << FUSE_BLOCK_PAGE_SHIFT) - 1;
6004 +       size_t file_end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
6005 +
6006 +       int i;
6007 +
6008 +       if (end_index > file_end_index)
6009 +               end_index = file_end_index;
6010 +
6011 +       for (i = 0; start_index + i <= end_index; i++) {
6012 +               size_t index = start_index + i;
6013 +               struct page *page;
6014 +               char *buffer;
6015 +
6016 +               page = grab_cache_page(mapping, index);
6017 +               if (!page)
6018 +                       return -1;
6019 +
6020 +               if (!PageUptodate(page)) {
6021 +                       buffer = kmap(page);
6022 +                       memcpy(buffer, bl_buf + i * PAGE_CACHE_SIZE,
6023 +                                       PAGE_CACHE_SIZE);
6024 +                       flush_dcache_page(page);
6025 +                       SetPageUptodate(page);
6026 +                       kunmap(page);
6027 +               }
6028 +
6029 +               unlock_page(page);
6030 +               page_cache_release(page);
6031 +       }
6032 +
6033 +       return 0;
6034 +} 
6035 +
6036 +static int fuse_file_read_block(struct inode *inode, char *bl_buf,
6037 +               size_t bl_index)
6038 +{
6039 +       struct fuse_conn *fc = INO_FC(inode);
6040 +       struct fuse_in in = FUSE_IN_INIT;
6041 +       struct fuse_out out = FUSE_OUT_INIT;
6042 +       struct fuse_read_in inarg;
6043 +
6044 +       memset(&inarg, 0, sizeof(inarg));
6045 +       inarg.offset = (unsigned long long) bl_index << FUSE_BLOCK_SHIFT;
6046 +       inarg.size = FUSE_BLOCK_SIZE;
6047 +
6048 +       in.h.opcode = FUSE_READ;
6049 +       in.h.ino = inode->i_ino;
6050 +       in.numargs = 1;
6051 +       in.args[0].size = sizeof(inarg);
6052 +       in.args[0].value = &inarg;
6053 +       out.argvar = 1;
6054 +       out.numargs = 1;
6055 +       out.args[0].size = FUSE_BLOCK_SIZE;
6056 +       out.args[0].value = bl_buf;
6057 +
6058 +       request_send(fc, &in, &out);
6059 +
6060 +       if (!out.h.error) {
6061 +               size_t outsize = out.args[0].size;
6062 +               if (outsize < FUSE_BLOCK_SIZE)
6063 +                       memset(bl_buf + outsize, 0, FUSE_BLOCK_SIZE - outsize);
6064 +       }
6065 +
6066 +       return out.h.error;
6067 +}   
6068 +
6069 +static void fuse_file_bigread(struct address_space *mapping,
6070 +                             struct inode *inode, loff_t pos, size_t count)
6071 +{
6072 +       size_t bl_index = pos >> FUSE_BLOCK_SHIFT;
6073 +       size_t bl_end_index = (pos + count) >> FUSE_BLOCK_SHIFT;
6074 +       size_t bl_file_end_index = i_size_read(inode) >> FUSE_BLOCK_SHIFT;
6075 +       
6076 +       if (bl_end_index > bl_file_end_index)
6077 +               bl_end_index = bl_file_end_index;
6078 +       
6079 +       while (bl_index <= bl_end_index) {
6080 +               int res;
6081 +               char *bl_buf = kmalloc(FUSE_BLOCK_SIZE, GFP_NOFS);
6082 +               if (!bl_buf)
6083 +                       break;
6084 +               res = fuse_is_block_uptodate(mapping, inode, bl_index);
6085 +               if (!res)
6086 +                       res = fuse_file_read_block(inode, bl_buf, bl_index);
6087 +               if (!res)
6088 +                       fuse_cache_block(mapping, inode, bl_buf, bl_index);
6089 +               kfree(bl_buf);
6090 +               bl_index++;
6091 +       }
6092 +}
6093 +
6094 +static ssize_t fuse_file_read(struct file *filp, char *buf,
6095 +               size_t count, loff_t * ppos)
6096 +{
6097 +       struct address_space *mapping = filp->f_dentry->d_inode->i_mapping;
6098 +       struct inode *inode = mapping->host;
6099 +       struct fuse_conn *fc = INO_FC(inode);
6100 +
6101 +       if(fc->flags & FUSE_LARGE_READ) {
6102 +               /* Don't allow this to get mixed up with writes */
6103 +               down(&inode->i_sem);
6104 +               fuse_file_bigread(mapping, inode, *ppos, count);
6105 +               up(&inode->i_sem);
6106 +       }
6107 +
6108 +       return generic_file_read(filp, buf, count, ppos);
6109 +}  
6110 +
6111 +static int write_buffer(struct inode *inode, struct page *page,
6112 +                       unsigned offset, size_t count)
6113 +{
6114 +       struct fuse_conn *fc = INO_FC(inode);
6115 +       struct fuse_in in = FUSE_IN_INIT;
6116 +       struct fuse_out out = FUSE_OUT_INIT;
6117 +       struct fuse_write_in inarg;
6118 +       char *buffer;
6119 +
6120 +       buffer = kmap(page);
6121 +
6122 +       memset(&inarg, 0, sizeof(inarg));
6123 +       inarg.offset = ((unsigned long long) page->index << PAGE_CACHE_SHIFT) +
6124 +               offset;
6125 +       inarg.size = count;
6126 +       
6127 +       in.h.opcode = FUSE_WRITE;
6128 +       in.h.ino = inode->i_ino;
6129 +       in.numargs = 2;
6130 +       in.args[0].size = sizeof(inarg);
6131 +       in.args[0].value = &inarg;
6132 +       in.args[1].size = count;
6133 +       in.args[1].value = buffer + offset;
6134 +       request_send(fc, &in, &out);
6135 +       kunmap(page);
6136 +       if(out.h.error)
6137 +               SetPageError(page);
6138 +
6139 +       return out.h.error;
6140 +}
6141 +
6142 +static int get_write_count(struct inode *inode, struct page *page)
6143 +{
6144 +       unsigned long end_index;
6145 +       loff_t size = i_size_read(inode);
6146 +       int count;
6147 +       
6148 +       end_index = size >> PAGE_CACHE_SHIFT;
6149 +       if(page->index < end_index)
6150 +               count = PAGE_CACHE_SIZE;
6151 +       else {
6152 +               count = size & (PAGE_CACHE_SIZE - 1);
6153 +               if(page->index > end_index || count == 0)
6154 +                       return 0;
6155 +       }
6156 +       return count;
6157 +}
6158 +
6159 +#ifdef KERNEL_2_6
6160 +
6161 +static void write_buffer_end(struct fuse_conn *fc, struct fuse_in *in,
6162 +                            struct fuse_out *out, void *_page)
6163 +{
6164 +       struct page *page = (struct page *) _page;
6165 +       
6166 +       if(out->h.error) {
6167 +               SetPageError(page);
6168 +               if(out->h.error == -ENOSPC)
6169 +                       set_bit(AS_ENOSPC, &page->mapping->flags);
6170 +               else
6171 +                       set_bit(AS_EIO, &page->mapping->flags);
6172 +       }
6173 +       end_page_writeback(page);
6174 +       kunmap(page);
6175 +       kfree(in);      
6176 +}
6177 +
6178 +static int write_buffer_nonblock(struct inode *inode, struct page *page,
6179 +                                unsigned offset, size_t count)
6180 +{
6181 +       int err;
6182 +       struct fuse_conn *fc = INO_FC(inode);
6183 +       struct fuse_in *in = NULL;
6184 +       struct fuse_out *out = NULL;
6185 +       struct fuse_write_in *inarg = NULL;
6186 +       char *buffer;
6187 +       unsigned int s = sizeof(struct fuse_in) + sizeof(struct fuse_out) +
6188 +               sizeof(struct fuse_write_in);
6189 +
6190 +       in = kmalloc(s, GFP_NOFS);
6191 +       if(!in)
6192 +               return -ENOMEM;
6193 +       memset(in, 0, s);
6194 +       out = (struct fuse_out *)(in + 1);
6195 +       inarg = (struct fuse_write_in *)(out + 1);
6196 +       
6197 +       buffer = kmap(page);
6198 +
6199 +       inarg->offset = ((unsigned long long) page->index << PAGE_CACHE_SHIFT) + offset;
6200 +       inarg->size = count;
6201 +       
6202 +       in->h.opcode = FUSE_WRITE;
6203 +       in->h.ino = inode->i_ino;
6204 +       in->numargs = 2;
6205 +       in->args[0].size = sizeof(struct fuse_write_in);
6206 +       in->args[0].value = inarg;
6207 +       in->args[1].size = count;
6208 +       in->args[1].value = buffer + offset;
6209 +       err = request_send_nonblock(fc, in, out, write_buffer_end, page);
6210 +       if(err) {
6211 +               if(err != -EWOULDBLOCK)
6212 +                       SetPageError(page);
6213 +               kunmap(page);
6214 +               kfree(in);
6215 +       }
6216 +       return err;
6217 +}
6218 +
6219 +static int fuse_writepage(struct page *page, struct writeback_control *wbc)
6220 +{
6221 +       int err;
6222 +       struct inode *inode = page->mapping->host;
6223 +       unsigned count = get_write_count(inode, page);
6224 +
6225 +       err = -EINVAL;
6226 +       if(count) {
6227 +               /* FIXME: check sync_mode, and wait for previous writes (or
6228 +                  signal userspace to do this) */
6229 +               if(wbc->nonblocking) {
6230 +                       SetPageWriteback(page);
6231 +                       err = write_buffer_nonblock(inode, page, 0, count);
6232 +                       if (err)
6233 +                               ClearPageWriteback(page);
6234 +                       if(err == -EWOULDBLOCK) {
6235 +                               __set_page_dirty_nobuffers(page);
6236 +                               err = 0;
6237 +                       }
6238 +               } else
6239 +                       err = write_buffer(inode, page, 0, count);
6240 +       }
6241 +
6242 +       unlock_page(page);
6243 +       return err;
6244 +}
6245 +#else
6246 +static int fuse_writepage(struct page *page)
6247 +{
6248 +       int err;
6249 +       struct inode *inode = page->mapping->host;
6250 +       int count = get_write_count(inode, page);
6251 +       err = -EINVAL;
6252 +       if(count)
6253 +               err = write_buffer(inode, page, 0, count);
6254 +
6255 +       unlock_page(page);
6256 +       return err;
6257 +}
6258 +#endif
6259 +
6260 +static int fuse_prepare_write(struct file *file, struct page *page,
6261 +                             unsigned offset, unsigned to)
6262 +{
6263 +       /* No op */
6264 +       return 0;
6265 +}
6266 +
6267 +static int fuse_commit_write(struct file *file, struct page *page,
6268 +                            unsigned offset, unsigned to)
6269 +{
6270 +       int err;
6271 +       struct inode *inode = page->mapping->host;
6272 +
6273 +       err = write_buffer(inode, page, offset, to - offset);
6274 +       if(!err) {
6275 +               loff_t pos = (page->index << PAGE_CACHE_SHIFT) + to;
6276 +               if(pos > i_size_read(inode))
6277 +                       i_size_write(inode, pos);
6278 +       }
6279 +       return err;
6280 +}
6281 +
6282 +static struct file_operations fuse_file_operations = {
6283 +       .read           = fuse_file_read,
6284 +       .write          = generic_file_write,
6285 +       .mmap           = generic_file_mmap,
6286 +       .open           = fuse_open,
6287 +       .release        = fuse_release,
6288 +       .fsync          = fuse_fsync,
6289 +#ifdef KERNEL_2_6
6290 +       .sendfile       = generic_file_sendfile,
6291 +#endif
6292 +};
6293 +
6294 +static struct address_space_operations fuse_file_aops  = {
6295 +       .readpage =             fuse_readpage,
6296 +       .writepage =            fuse_writepage,
6297 +       .prepare_write =        fuse_prepare_write,
6298 +       .commit_write =         fuse_commit_write,
6299 +};
6300 +
6301 +void fuse_init_file_inode(struct inode *inode)
6302 +{
6303 +#ifdef KERNEL_2_6
6304 +       struct fuse_conn *fc = INO_FC(inode);
6305 +       /* Readahead somehow defeats big reads on 2.6 (says Michael
6306 +           Grigoriev) */
6307 +       if(fc->flags & FUSE_LARGE_READ)
6308 +               inode->i_mapping->backing_dev_info->ra_pages = 0;
6309 +#endif
6310 +       inode->i_fop = &fuse_file_operations;
6311 +       inode->i_data.a_ops = &fuse_file_aops;
6312 +}
6313 +
6314 +/* 
6315 + * Local Variables:
6316 + * indent-tabs-mode: t
6317 + * c-basic-offset: 8
6318 + * End:
6319 + */
6320 diff -urN a/fs/cofusefs/fuse_i.h b/fs/cofusefs/fuse_i.h
6321 --- a/fs/cofusefs/fuse_i.h
6322 +++ b/fs/cofusefs/fuse_i.h
6323 @@ -0,0 +1,297 @@
6324 +/*
6325 +    COFUSE: Filesystem in an host of Cooperative Linux
6326 +    Copyright (C) 2004 Dan Aloni <da-x@colinux.org>
6327 +
6328 +    based on FUSE: Filesystem in Userspace
6329 +    Copyright (C) 2001-2004  Miklos Szeredi <miklos@szeredi.hu>
6330 +
6331 +    This program can be distributed under the terms of the GNU GPL.
6332 +    See the file COPYING.
6333 +*/
6334 +
6335 +
6336 +#include <linux/version.h>
6337 +#include <linux/config.h>
6338 +
6339 +#ifndef CONFIG_COOPERATIVE
6340 +#include <linux/cofuse.h>
6341 +#else
6342 +#include <linux/cooperative_internal.h>
6343 +#endif
6344 +
6345 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
6346 +#error Kernel version 2.5.* not supported
6347 +#endif
6348 +
6349 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
6350 +#define KERNEL_2_6
6351 +#endif
6352 +
6353 +#ifndef KERNEL_2_6
6354 +#include <linux/config.h>
6355 +#ifdef CONFIG_MODVERSIONS
6356 +#define MODVERSIONS
6357 +#include <linux/modversions.h>
6358 +#endif
6359 +#include <config.h>
6360 +#ifndef HAVE_I_SIZE_FUNC
6361 +#define i_size_read(inode) ((inode)->i_size)
6362 +#define i_size_write(inode, size) do { (inode)->i_size = size; } while(0)
6363 +#endif
6364 +#endif 
6365 +#include <linux/kernel.h>
6366 +#include <linux/module.h>
6367 +#include <linux/fs.h>
6368 +#include <linux/list.h>
6369 +#include <linux/spinlock.h>
6370 +
6371 +/** Read combining parameters */
6372 +#define FUSE_BLOCK_SHIFT 16
6373 +#define FUSE_BLOCK_SIZE 65536
6374 +#define FUSE_BLOCK_MASK 0xffff0000
6375 +
6376 +#define FUSE_BLOCK_PAGE_SHIFT (FUSE_BLOCK_SHIFT - PAGE_CACHE_SHIFT)
6377 +
6378 +/**
6379 + * A Fuse connection.
6380 + *
6381 + * This structure is created, when the client device is opened, and is
6382 + * destroyed, when the client device is closed _and_ the filesystem is
6383 + * unmounted.
6384 + */
6385 +struct fuse_conn {
6386 +       /** The superblock of the mounted filesystem */
6387 +       struct super_block *sb;
6388 +
6389 +#ifndef CONFIG_COOPERATIVE     
6390 +       /** The opened client device */
6391 +       struct file *file;
6392 +#else
6393 +       int cofs_unit;
6394 +#endif
6395 +       /** The user id for this mount */
6396 +       uid_t uid;
6397 +
6398 +       /** The fuse mount flags for this mount */
6399 +       unsigned int flags;
6400 +
6401 +       /** Is the new (synchronous) release not supported by
6402 +           userspace? */
6403 +       unsigned int oldrelease;
6404 +
6405 +       char opt_pathname[0x80];
6406 +
6407 +#ifndef CONFIG_COOPERATIVE     
6408 +       /** Readers of the connection are waiting on this */
6409 +       wait_queue_head_t waitq;
6410 +
6411 +       /** The list of pending requests */
6412 +       struct list_head pending;
6413 +
6414 +       /** The list of requests being processed */
6415 +       struct list_head processing;
6416 +
6417 +       /** Controls the maximum number of outstanding requests */
6418 +       struct semaphore outstanding;
6419 +       
6420 +       /** The next unique request id */
6421 +       int reqctr;
6422 +#endif
6423 +};
6424 +
6425 +/** One input argument of a request */
6426 +struct fuse_in_arg {
6427 +       unsigned int size;
6428 +       const void *value;
6429 +};
6430 +
6431 +/** The request input */
6432 +struct fuse_in {
6433 +       struct fuse_in_header h;
6434 +       unsigned int numargs;
6435 +       struct fuse_in_arg args[3];
6436 +};
6437 +
6438 +/** One output argument of a request */
6439 +struct fuse_out_arg {
6440 +       unsigned int size;
6441 +       void *value;
6442 +};
6443 +
6444 +/** The request output */
6445 +struct fuse_out {
6446 +       struct fuse_out_header h;
6447 +       unsigned int argvar;
6448 +       unsigned int numargs;
6449 +       struct fuse_out_arg args[3];
6450 +};
6451 +
6452 +#define FUSE_IN_INIT { {0, 0, 0, current->fsuid, current->fsgid}, 0}
6453 +#define FUSE_OUT_INIT { {0, 0}, 0, 0}
6454 +
6455 +struct fuse_req;
6456 +typedef void (*fuse_reqend_t)(struct fuse_conn *, struct fuse_in *,
6457 +                             struct fuse_out *, void *data);
6458 +
6459 +/**
6460 + * A request to the client
6461 + */
6462 +struct fuse_req {
6463 +       /** The request list */
6464 +       struct list_head list;
6465 +
6466 +       /** True if the request is synchronous */
6467 +       unsigned int issync:1;
6468 +
6469 +       /** The request is locked */
6470 +       unsigned int locked:1;
6471 +
6472 +       /** The request has been interrupted while it was locked */
6473 +       unsigned int interrupted:1;
6474 +
6475 +       /* The request has been sent to the client */
6476 +       unsigned int sent:1;
6477 +
6478 +       /* The request is finished */
6479 +       unsigned int finished:1;
6480 +
6481 +       /** The request input */
6482 +       struct fuse_in *in;
6483 +
6484 +       /** The request output */
6485 +       struct fuse_out *out;
6486 +
6487 +       /** Used to wake up the task waiting for completion of request*/
6488 +       wait_queue_head_t waitq;
6489 +
6490 +       /** Request completion callback */
6491 +       fuse_reqend_t end;
6492 +
6493 +       /** User data */
6494 +       void *data;
6495 +};
6496 +
6497 +#ifdef KERNEL_2_6
6498 +#define SB_FC(sb) ((sb)->s_fs_info)
6499 +#else
6500 +#define SB_FC(sb) ((sb)->u.generic_sbp)
6501 +#endif
6502 +#define INO_FC(inode) SB_FC((inode)->i_sb)
6503 +#define DEV_FC(file) ((struct fuse_conn *) (file)->private_data)
6504 +
6505 +
6506 +/**
6507 + * The proc entry for the client device ("/proc/fs/fuse/dev")
6508 + */
6509 +extern struct proc_dir_entry *proc_fuse_dev;
6510 +
6511 +/**
6512 + * The lock to protect fuses structures
6513 + */
6514 +extern spinlock_t cofuse_lock;
6515 +
6516 +
6517 +/**
6518 + * Get a filled in inode
6519 + */
6520 +struct inode *cofuse_iget(struct super_block *sb, ino_t ino,
6521 +                         struct fuse_attr *attr, int version);
6522 +
6523 +
6524 +/**
6525 + * Initialise operations on regular file
6526 + */
6527 +void cofuse_init_file_inode(struct inode *inode);
6528 +
6529 +/**
6530 + * Check if the connection can be released, and if yes, then free the
6531 + * connection structure
6532 + */
6533 +void cofuse_release_conn(struct fuse_conn *fc);
6534 +
6535 +/**
6536 + * Initialize the client device
6537 + */
6538 +int cofuse_dev_init(void);
6539 +
6540 +/**
6541 + * Cleanup the client device
6542 + */
6543 +void cofuse_dev_cleanup(void);
6544 +
6545 +/**
6546 + * Initialize the fuse filesystem 
6547 + */
6548 +int cofuse_fs_init(void);
6549 +
6550 +/**
6551 + * Cleanup the fuse filesystem
6552 + */
6553 +void cofuse_fs_cleanup(void);
6554 +
6555 +/**
6556 + * Send a request
6557 + *
6558 + */
6559 +void cofuse_request_send(struct fuse_conn *fc, struct fuse_in *in,
6560 +                        struct fuse_out *out);
6561 +
6562 +/**
6563 + * Send a request for which a reply is not expected
6564 + */
6565 +int cofuse_request_send_noreply(struct fuse_conn *fc, struct fuse_in *in);
6566 +
6567 +
6568 +/**
6569 + * Send a synchronous request without blocking
6570 + */
6571 +int cofuse_request_send_nonblock(struct fuse_conn *fc, struct fuse_in *in,
6572 +                                struct fuse_out *out, fuse_reqend_t end, void *data);
6573 +
6574 +/**
6575 + * Get the attributes of a file
6576 + */
6577 +int cofuse_do_getattr(struct inode *inode);
6578 +
6579 +/**
6580 + * Write dirty pages
6581 + */
6582 +void cofuse_sync_inode(struct inode *inode);
6583 +
6584 +/*
6585 + * Local Variables:
6586 + * indent-tabs-mode: t
6587 + * c-basic-offset: 8
6588 + * End:
6589 + */
6590 +
6591 +#define COFUSE_VERSION "0.1"
6592 +#define FUSE_VERSION COFUSE_VERSION
6593 +
6594 +#define fuse_init_file_inode cofuse_init_file_inode
6595 +#define fuse_do_getattr cofuse_do_getattr
6596 +#define fuse_sync_inode cofuse_sync_inode
6597 +#define fuse_lock cofuse_lock
6598 +
6599 +#define request_send cofuse_request_send
6600 +#define request_send_noreply cofuse_request_send_noreply
6601 +#define request_send_nonblock cofuse_request_send_nonblock
6602 +#define release_conn cofuse_release_conn
6603 +#define fuse_iget cofuse_iget 
6604 +#define fuse_dev_init cofuse_dev_init
6605 +#define fuse_dev_cleanup cofuse_dev_cleanup
6606 +#define fuse_fs_init cofuse_fs_init
6607 +#define fuse_fs_cleanup cofuse_fs_cleanup
6608 +
6609 +extern struct fuse_conn *cofs_volumes[CO_MODULE_MAX_COFS];
6610 +
6611 +/** Data passed to mount */
6612 +struct cofuse_mount_data {
6613 +       struct fuse_mount_data *fuse;
6614 +       int uid;
6615 +       int gid;
6616 +       unsigned long file_mode;
6617 +       unsigned long dir_mode;
6618 +       unsigned long flags;
6619 +       char name[0x80];
6620 +};
6621 diff -urN a/fs/cofusefs/inode.c b/fs/cofusefs/inode.c
6622 --- a/fs/cofusefs/inode.c
6623 +++ b/fs/cofusefs/inode.c
6624 @@ -0,0 +1,545 @@
6625 +/*
6626 +    FUSE: Filesystem in Userspace
6627 +    Copyright (C) 2001 Miklos Szeredi (miklos@szeredi.hu)
6628 +
6629 +    This program can be distributed under the terms of the GNU GPL.
6630 +    See the file COPYING.
6631 +*/
6632 +
6633 +#include "fuse_i.h"
6634 +
6635 +#include <linux/pagemap.h>
6636 +#include <linux/sched.h>
6637 +#include <linux/slab.h>
6638 +#include <linux/file.h>
6639 +#include <linux/ctype.h>
6640 +#include <linux/proc_fs.h>
6641 +#ifdef KERNEL_2_6
6642 +#include <linux/statfs.h>
6643 +#endif
6644 +
6645 +#define FUSE_SUPER_MAGIC 0x65735546
6646 +
6647 +#ifndef KERNEL_2_6
6648 +#define kstatfs statfs
6649 +#endif
6650 +
6651 +#ifndef FS_BINARY_MOUNTDATA
6652 +#define FS_BINARY_MOUNTDATA 0
6653 +#endif
6654 +
6655 +static void fuse_read_inode(struct inode *inode)
6656 +{
6657 +       /* No op */
6658 +}
6659 +
6660 +static void fuse_clear_inode(struct inode *inode)
6661 +{
6662 +       unsigned long flags;
6663 +       struct fuse_conn *fc = INO_FC(inode);
6664 +
6665 +#ifndef CONFIG_COOPERATIVE
6666 +       struct fuse_in *in = NULL;
6667 +       struct fuse_forget_in *inarg = NULL;
6668 +       unsigned int s = sizeof(struct fuse_in) + sizeof(struct fuse_forget_in);
6669 +
6670 +       if(fc == NULL)
6671 +               return;
6672 +
6673 +       in = kmalloc(s, GFP_NOFS);
6674 +       if(!in)
6675 +               return;
6676 +       memset(in, 0, s);
6677 +       inarg = (struct fuse_forget_in *) (in + 1);
6678 +       inarg->version = inode->i_version;
6679 +               
6680 +       in->h.opcode = FUSE_FORGET;
6681 +       in->h.ino = inode->i_ino;
6682 +       in->numargs = 1;
6683 +       in->args[0].size = sizeof(struct fuse_forget_in);
6684 +       in->args[0].value = inarg;
6685 +               
6686 +       if(!request_send_noreply(fc, in))
6687 +               return;
6688 +
6689 +       kfree(in);
6690 +#else
6691 +       if (FUSE_ROOT_INO == inode->i_ino)
6692 +               return;
6693 +
6694 +       co_passage_page_assert_valid();
6695 +       co_passage_page_acquire(&flags);
6696 +       co_passage_page->operation = CO_OPERATION_DEVICE;
6697 +       co_passage_page->params[0] = CO_DEVICE_FILESYSTEM;
6698 +       co_passage_page->params[1] = fc->cofs_unit;
6699 +       co_passage_page->params[2] = FUSE_FORGET;
6700 +       co_passage_page->params[3] = inode->i_ino;
6701 +       co_switch_wrapper();
6702 +       co_passage_page_release(flags);
6703 +#endif
6704 +}
6705 +
6706 +static void fuse_put_super(struct super_block *sb)
6707 +{
6708 +       struct fuse_conn *fc = SB_FC(sb);
6709 +
6710 +       spin_lock(&fuse_lock);
6711 +       fc->sb = NULL;
6712 +       fc->uid = 0;
6713 +       fc->flags = 0;
6714 +       /* Flush all readers on this fs */
6715 +#ifndef CONFIG_COOPERATIVE
6716 +       wake_up_all(&fc->waitq);
6717 +#endif
6718 +       release_conn(fc);
6719 +       SB_FC(sb) = NULL;
6720 +       spin_unlock(&fuse_lock);
6721 +}
6722 +
6723 +static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
6724 +{
6725 +       stbuf->f_type    = FUSE_SUPER_MAGIC;
6726 +       stbuf->f_bsize   = attr->block_size;
6727 +       stbuf->f_blocks  = attr->blocks;
6728 +       stbuf->f_bfree   = stbuf->f_bavail = attr->blocks_free;
6729 +       stbuf->f_files   = attr->files;
6730 +       stbuf->f_ffree   = attr->files_free;
6731 +       /* Is this field necessary?  Most filesystems ignore it...
6732 +       stbuf->f_fsid.val[0] = (FUSE_SUPER_MAGIC>>16)&0xffff;
6733 +       stbuf->f_fsid.val[1] =  FUSE_SUPER_MAGIC     &0xffff; */
6734 +       stbuf->f_namelen = attr->namelen;
6735 +}
6736 +
6737 +static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
6738 +{
6739 +       struct fuse_conn *fc = SB_FC(sb);
6740 +       struct fuse_in in = FUSE_IN_INIT;
6741 +       struct fuse_out out = FUSE_OUT_INIT;
6742 +       struct fuse_statfs_out outarg;
6743 +       
6744 +       in.numargs = 0;
6745 +       in.h.opcode = FUSE_STATFS;
6746 +       out.numargs = 1;
6747 +       out.args[0].size = sizeof(outarg);
6748 +       out.args[0].value = &outarg;
6749 +       request_send(fc, &in, &out);
6750 +       if(!out.h.error)
6751 +               convert_fuse_statfs(buf, &outarg.st);
6752 +       
6753 +       return out.h.error;
6754 +}
6755 +
6756 +#ifndef CONFIG_COOPERATIVE
6757 +
6758 +static struct fuse_conn *get_conn(struct fuse_mount_data *d)
6759 +{
6760 +       struct fuse_conn *fc = NULL;
6761 +       struct file *file;
6762 +       struct inode *ino;
6763 +
6764 +       if(d == NULL) {
6765 +               printk("fuse_read_super: Bad mount data\n");
6766 +               return NULL;
6767 +       }
6768 +
6769 +       if(d->version != FUSE_KERNEL_VERSION) {
6770 +               printk("fuse_read_super: Bad version: %i\n", d->version);
6771 +               return NULL;
6772 +       }
6773 +
6774 +       file = fget(d->fd);
6775 +       ino = NULL;
6776 +       if(file)
6777 +               ino = file->f_dentry->d_inode;
6778 +       
6779 +       if(!ino || !proc_fuse_dev || proc_fuse_dev->low_ino != ino->i_ino) {
6780 +               printk("fuse_read_super: Bad file: %i\n", d->fd);
6781 +               goto out;
6782 +       }
6783 +
6784 +       fc = file->private_data;
6785 +
6786 +  out:
6787 +       fput(file);
6788 +       return fc;
6789 +}
6790 +
6791 +#else
6792 +
6793 +static int _atoi(const char *s, const char **out)
6794 +{
6795 +       /* lib/spprintf.h */
6796 +
6797 +        int i=0;
6798 +
6799 +        while (isdigit(*s))
6800 +                i = i*10 + *(s++) - '0';
6801 +
6802 +       *out = s;
6803 +
6804 +        return i;      
6805 +}
6806 +
6807 +static struct fuse_conn *co_get_conn(struct cofuse_mount_data *d)
6808 +{
6809 +       int index;
6810 +       int ret;
6811 +       unsigned long flags;
6812 +       struct fuse_conn *conn = NULL;
6813 +       const char *name, *next;
6814 +
6815 +       if (d == NULL) {
6816 +               printk("cofuse_read_super: Bad mount data\n");
6817 +               return NULL;
6818 +       }
6819 +
6820 +       name = d->name;
6821 +
6822 +       if (strncmp("cofs", name, 4) == 0)
6823 +               name += 4;
6824 +
6825 +       index = _atoi(name, &next);
6826 +       if (index < 0  || index >= CO_MODULE_MAX_COFS) {
6827 +               printk("cofuse_read_super: Invalid index %d\n", index);
6828 +               return NULL;
6829 +       }
6830 +       
6831 +       if (cofs_volumes[index])
6832 +               return cofs_volumes[index];
6833 +
6834 +       conn = kmalloc(sizeof(struct fuse_conn), GFP_KERNEL);
6835 +       if (!conn)
6836 +               return NULL;
6837 +
6838 +       memset(conn, 0, sizeof(*conn));
6839 +
6840 +       if (*next == ':') {
6841 +               snprintf(conn->opt_pathname, sizeof(conn->opt_pathname), "%s", next+1);
6842 +       }
6843 +
6844 +       conn->cofs_unit = index;
6845 +
6846 +       co_passage_page_assert_valid();
6847 +       co_passage_page_acquire(&flags);
6848 +       co_passage_page->operation = CO_OPERATION_DEVICE;
6849 +       co_passage_page->params[0] = CO_DEVICE_FILESYSTEM;
6850 +       co_passage_page->params[1] = conn->cofs_unit;
6851 +       co_passage_page->params[2] = FUSE_MOUNT;
6852 +       co_passage_page->params[5] = d->uid;
6853 +       co_passage_page->params[6] = d->gid;
6854 +       co_passage_page->params[7] = d->dir_mode;
6855 +       co_passage_page->params[8] = d->file_mode;
6856 +       memcpy(&co_passage_page->params[30], conn->opt_pathname, strlen(conn->opt_pathname) + 1);
6857 +       co_switch_wrapper();
6858 +       ret = co_passage_page->params[4];
6859 +       co_passage_page_release(flags);
6860 +       
6861 +       if (ret) {
6862 +               kfree(conn);
6863 +               conn = NULL;
6864 +       }
6865 +
6866 +       return conn; 
6867 +}
6868 +
6869 +#endif
6870 +
6871 +static struct inode *get_root_inode(struct super_block *sb, unsigned int mode)
6872 +{
6873 +       struct fuse_attr attr;
6874 +       memset(&attr, 0, sizeof(attr));
6875 +
6876 +       attr.mode = mode;
6877 +       return fuse_iget(sb, 1, &attr, 0);
6878 +}
6879 +
6880 +
6881 +#ifdef KERNEL_2_6
6882 +
6883 +static struct dentry *fuse_get_dentry(struct super_block *sb, void *vobjp)
6884 +{
6885 +       __u32 *objp = vobjp;
6886 +       unsigned long ino = objp[0];
6887 +       /* __u32 generation = objp[1]; */
6888 +       struct inode *inode;
6889 +       struct dentry *entry;
6890 +
6891 +       if(ino == 0)
6892 +               return ERR_PTR(-ESTALE);
6893 +
6894 +       inode = ilookup(sb, ino);
6895 +       if(!inode)
6896 +               return ERR_PTR(-ESTALE);
6897 +
6898 +       entry = d_alloc_anon(inode);
6899 +       if(!entry) {
6900 +               iput(inode);
6901 +               return ERR_PTR(-ENOMEM);
6902 +       }
6903 +
6904 +       return entry;
6905 +}
6906 +
6907 +static struct export_operations fuse_export_operations = {
6908 +       .get_dentry     = fuse_get_dentry,
6909 +};
6910 +#endif
6911 +
6912 +static struct super_operations fuse_super_operations = {
6913 +       .read_inode     = fuse_read_inode,
6914 +       .clear_inode    = fuse_clear_inode,
6915 +       .put_super      = fuse_put_super,
6916 +       .statfs         = fuse_statfs,
6917 +};
6918 +
6919 +static int fuse_read_super(struct super_block *sb, void *data, int silent)
6920 +{      
6921 +       struct fuse_conn *fc;
6922 +       struct inode *root;
6923 +#ifndef CONFIG_COOPERATIVE
6924 +       struct fuse_mount_data *d = data;
6925 +#else
6926 +       struct cofuse_mount_data *co_d = data;
6927 +       struct fuse_mount_data *d = co_d->fuse;
6928 +#endif
6929 +       sb->s_blocksize = PAGE_CACHE_SIZE;
6930 +       sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
6931 +       sb->s_magic = FUSE_SUPER_MAGIC;
6932 +       sb->s_op = &fuse_super_operations;
6933 +       sb->s_maxbytes = MAX_LFS_FILESIZE;
6934 +#ifdef KERNEL_2_6
6935 +       sb->s_export_op = &fuse_export_operations;
6936 +#endif
6937 +
6938 +#ifndef CONFIG_COOPERATIVE
6939 +       fc = get_conn(d);
6940 +#else
6941 +       fc = co_get_conn(co_d);
6942 +#endif
6943 +       if(fc == NULL)
6944 +               return -EINVAL;
6945 +       spin_lock(&fuse_lock);
6946 +       if(fc->sb != NULL) {
6947 +               printk("fuse_read_super: connection already mounted\n");
6948 +               spin_unlock(&fuse_lock);
6949 +               return -EINVAL;
6950 +       }
6951 +       fc->sb = sb;
6952 +       fc->flags = d->flags;
6953 +       fc->uid = d->uid;
6954 +       spin_unlock(&fuse_lock);
6955 +       
6956 +       /* fc is needed in fuse_init_file_inode which could be called
6957 +          from get_root_inode */
6958 +       SB_FC(sb) = fc;
6959 +
6960 +       root = get_root_inode(sb, d->rootmode);
6961 +       if(root == NULL) {
6962 +               printk("fuse_read_super: failed to get root inode\n");
6963 +               return -EINVAL;
6964 +       }
6965 +
6966 +       sb->s_root = d_alloc_root(root);
6967 +       if(!sb->s_root) {
6968 +               printk("fuse_read_super: failed to allocate root\n");
6969 +               return -EINVAL;
6970 +       }
6971 +
6972 +       return 0;
6973 +}
6974 +
6975 +#ifdef CONFIG_COOPERATIVE
6976 +/*
6977 + * cofuse_getopt and cofuse_parse_options were
6978 + * addopted from smb
6979 + */ 
6980 +
6981 +struct option {
6982 +       const char *name;
6983 +       unsigned long flag;
6984 +       int val;
6985 +};
6986 +
6987 +/**
6988 + *      cofuse_getopt - option parser
6989 + *      based on smb_getopt from fs/smbfs
6990 + *
6991 + *      @caller: name of the caller, for error messages
6992 + *      @options: the options string
6993 + *      @opts: an array of &struct option entries controlling parser operations
6994 + *      @optopt: output; will contain the current option
6995 + *      @optarg: output; will contain the value (if one exists)
6996 + *      @flag: output; may be NULL; should point to a long for or'ing flags
6997 + *      @value: output; may be NULL; will be overwritten with the integer value
6998 + *              of the current argument.
6999 + *
7000 + *      Helper to parse options on the format used by mount ("a=b,c=d,e,f").
7001 + *      Returns opts->val if a matching entry in the 'opts' array is found,
7002 + *      0 when no more tokens are found, -1 if an error is encountered.
7003 + */
7004 +static int cofuse_getopt(char *caller, char **options, struct option *opts,
7005 +                        char **optopt, char **optarg, unsigned long *flag,
7006 +                        unsigned long *value)
7007 +{
7008 +        char *token;
7009 +        char *val;
7010 +        int i;
7011 +
7012 +        do {
7013 +                if ((token = strsep(options, ",")) == NULL)
7014 +                        return 0;
7015 +        } while (*token == '\0');
7016 +        *optopt = token;
7017 +
7018 +        *optarg = NULL;
7019 +        if ((val = strchr (token, '=')) != NULL) {
7020 +                *val++ = 0;
7021 +                if (value)
7022 +                        *value = simple_strtoul(val, NULL, 0);
7023 +                *optarg = val;
7024 +        }
7025 +
7026 +        for (i = 0; opts[i].name != NULL; i++) {
7027 +                if (!strcmp(opts[i].name, token)) {
7028 +                        if (!opts[i].flag && (!val || !*val)) {
7029 +                                printk("%s: the %s option requires an argument\n",
7030 +                                       caller, token);
7031 +                                return -1;
7032 +                        }
7033 +
7034 +                        if (flag && opts[i].flag)
7035 +                                *flag |= opts[i].flag;
7036 +
7037 +                        return opts[i].val;
7038 +                }
7039 +        }
7040 +        printk("%s: Unrecognized mount option %s\n", caller, token);
7041 +        return -1;
7042 +}
7043 +
7044 +static struct option opts[] = {
7045 +       { "uid",        0, 'u' },
7046 +       { "gid",        0, 'g' },
7047 +       { "fmask",      0, 'f' },
7048 +       { "dmask",      0, 'd' },
7049 +       { NULL,         0, 0}
7050 +};
7051 +
7052 +/*
7053 + * parse_options - based on parse_options from fs/smbfs
7054 + */
7055 +static int parse_options(struct cofuse_mount_data *mnt, char *options)
7056 +{
7057 +        int c;
7058 +        unsigned long flags;
7059 +        unsigned long value;
7060 +        char *optarg;
7061 +        char *optopt;
7062 +
7063 +        flags = 0;
7064 +        while ((c = cofuse_getopt("cofuse", &options, opts,
7065 +                                 &optopt, &optarg, &flags, &value)) > 0)
7066 +       {
7067 +                switch (c) {
7068 +                case 1:
7069 +                        /* got a "flag" option */
7070 +                        break;
7071 +                case 'u':
7072 +                        mnt->uid = value;
7073 +                        break;
7074 +                case 'g':
7075 +                        mnt->gid = value;
7076 +                        break;
7077 +                case 'f':
7078 +                        mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
7079 +                        break;
7080 +                case 'd':
7081 +                        mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
7082 +                        break;
7083 +                default:
7084 +                        printk("cofs: Unrecognized mount option %s\n", optopt);
7085 +                        return -1;
7086 +                }
7087 +        }
7088 +
7089 +        mnt->flags = flags;
7090 +        return c;
7091 +}
7092 +#endif
7093 +
7094 +#ifdef KERNEL_2_6
7095 +static struct super_block *fuse_get_sb(struct file_system_type *fs_type,
7096 +                                      int flags, const char *dev_name,
7097 +                                      void *raw_data)
7098 +{
7099 +#ifdef CONFIG_COOPERATIVE
7100 +       struct cofuse_mount_data co_md = {0, };
7101 +       struct fuse_mount_data md = {0, };
7102 +       int ret;
7103 +
7104 +       co_md.uid = current->uid;
7105 +       co_md.gid = current->gid;
7106 +       co_md.dir_mode = FUSE_S_IRWXU | FUSE_S_IRGRP | FUSE_S_IXGRP | 
7107 +               FUSE_S_IROTH | FUSE_S_IXOTH | S_IFDIR;
7108 +       co_md.file_mode = FUSE_S_IRWXU | FUSE_S_IRGRP | FUSE_S_IXGRP | 
7109 +               FUSE_S_IROTH | FUSE_S_IXOTH | S_IFREG;
7110 +
7111 +       ret = parse_options(&co_md, raw_data);
7112 +       if (ret == -1)
7113 +               return ERR_PTR(-EINVAL);
7114 +
7115 +       md.rootmode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
7116 +       md.flags = FUSE_ALLOW_OTHER | FUSE_DEFAULT_PERMISSIONS;
7117 +
7118 +       co_md.fuse = &md;
7119 +       snprintf(co_md.name, sizeof(co_md.name), "%s", dev_name);
7120 +
7121 +       return get_sb_nodev(fs_type, flags, &co_md, fuse_read_super);
7122 +#else
7123 +       return get_sb_nodev(fs_type, flags, raw_data, fuse_read_super);
7124 +#endif
7125 +}
7126 +
7127 +static struct file_system_type fuse_fs_type = {
7128 +       .owner          = THIS_MODULE,
7129 +       .name           = "cofs",
7130 +       .get_sb         = fuse_get_sb,
7131 +       .kill_sb        = kill_anon_super,
7132 +       .fs_flags       = FS_BINARY_MOUNTDATA,
7133 +};
7134 +#else
7135 +static struct super_block *fuse_read_super_compat(struct super_block *sb,
7136 +                                                 void *data, int silent)
7137 +{
7138 +       int err = fuse_read_super(sb, data, silent);
7139 +       if(err)
7140 +               return NULL;
7141 +       else
7142 +               return sb;
7143 +}
7144 +
7145 +static DECLARE_FSTYPE(fuse_fs_type, "cofs", fuse_read_super_compat, 0);
7146 +#endif
7147 +
7148 +int fuse_fs_init()
7149 +{
7150 +       int res;
7151 +
7152 +       res = register_filesystem(&fuse_fs_type);
7153 +       if(res)
7154 +               printk("fuse: failed to register filesystem\n");
7155 +
7156 +       return res;
7157 +}
7158 +
7159 +void fuse_fs_cleanup()
7160 +{
7161 +       unregister_filesystem(&fuse_fs_type);
7162 +}
7163 +
7164 +/* 
7165 + * Local Variables:
7166 + * indent-tabs-mode: t
7167 + * c-basic-offset: 8
7168 + * End:
7169 + */
7170 diff -urN a/fs/cofusefs/util.c b/fs/cofusefs/util.c
7171 --- a/fs/cofusefs/util.c
7172 +++ b/fs/cofusefs/util.c
7173 @@ -0,0 +1,78 @@
7174 +/*
7175 +    FUSE: Filesystem in Userspace
7176 +    Copyright (C) 2001-2004  Miklos Szeredi <miklos@szeredi.hu>
7177 +
7178 +    This program can be distributed under the terms of the GNU GPL.
7179 +    See the file COPYING.
7180 +*/
7181 +
7182 +#include "fuse_i.h"
7183 +
7184 +#include <linux/init.h>
7185 +#include <linux/slab.h>
7186 +
7187 +MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
7188 +MODULE_DESCRIPTION("Filesystem in Userspace");
7189 +#ifdef MODULE_LICENSE
7190 +MODULE_LICENSE("GPL");
7191 +#endif
7192 +
7193 +spinlock_t fuse_lock = SPIN_LOCK_UNLOCKED;
7194 +
7195 +/* Must be called with the fuse lock held */
7196 +void release_conn(struct fuse_conn *fc)
7197 +{
7198 +#ifdef CONFIG_COOPERATIVE
7199 +       if (cooperative_mode_enabled()) {
7200 +               cofs_volumes[fc->cofs_unit] = NULL;
7201 +               kfree(fc);
7202 +               return;
7203 +       }
7204 +#else
7205 +       if(fc->sb == NULL && fc->file == NULL) {
7206 +               kfree(fc);
7207 +       }
7208 +#endif
7209 +}
7210 +
7211 +int __init cofuse_init(void)
7212 +{
7213 +       int res;
7214 +
7215 +       printk(KERN_DEBUG "cofuse init %s (API version %i.%i)\n",
7216 +              FUSE_VERSION,
7217 +              FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
7218 +
7219 +       res = fuse_fs_init();
7220 +       if(res)
7221 +               goto err;
7222 +       
7223 +       res = fuse_dev_init();
7224 +       if(res)
7225 +               goto err_fs_cleanup;
7226 +       
7227 +       return 0;
7228 +
7229 +  err_fs_cleanup:
7230 +       fuse_fs_cleanup();
7231 +  err:
7232 +       return res;
7233 +}
7234 +
7235 +void __exit cofuse_exit(void)
7236 +{
7237 +       printk(KERN_DEBUG "cofuse exit\n");
7238 +       
7239 +       fuse_fs_cleanup();
7240 +       fuse_dev_cleanup();
7241 +}
7242 +
7243 +module_init(cofuse_init);
7244 +module_exit(cofuse_exit);
7245 +
7246 +/*
7247 + * Local Variables:
7248 + * indent-tabs-mode: t
7249 + * c-basic-offset: 8
7250 + * End:
7251 + */
7252 diff -urN a/fs/namespace.c b/fs/namespace.c
7253 --- a/fs/namespace.c
7254 +++ b/fs/namespace.c
7255 @@ -1015,7 +1015,7 @@
7256         /* Discard magic */
7257         if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
7258                 flags &= ~MS_MGC_MSK;
7259 -
7260 +       
7261         /* Basic sanity checks */
7262  
7263         if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
7264 diff -urN a/include/asm-i386/bug.h b/include/asm-i386/bug.h
7265 --- a/include/asm-i386/bug.h
7266 +++ b/include/asm-i386/bug.h
7267 @@ -10,11 +10,17 @@
7268   */
7269  
7270  #if 1  /* Set to zero for a slightly smaller kernel */
7271 +#ifdef CONFIG_COOPERATIVE
7272 +#include <linux/cooperative.h>
7273 +extern void co_terminate(co_termination_reason_t reason);
7274 +#define BUG() do { co_terminate(CO_TERMINATE_BUG); } while(0)
7275 +#else
7276  #define BUG()                          \
7277   __asm__ __volatile__( "ud2\n"         \
7278                         "\t.word %c0\n" \
7279                         "\t.long %c1\n" \
7280                          : : "i" (__LINE__), "i" (__FILE__))
7281 +#endif
7282  #else
7283  #define BUG() __asm__ __volatile__("ud2\n")
7284  #endif
7285 diff -urN a/include/asm-i386/cooperative.h b/include/asm-i386/cooperative.h
7286 --- a/include/asm-i386/cooperative.h
7287 +++ b/include/asm-i386/cooperative.h
7288 @@ -0,0 +1,184 @@
7289 +/*
7290 + *  linux/include/asm/cooperative.h
7291 + *
7292 + *  Copyright (C) 2004 Dan Aloni
7293 + *
7294 + *  This file defines the lower level interfaces between the Cooperative Linux 
7295 + *  kernel and the host OS driver. It's for both external inclusion from the 
7296 + *  and internal inclusion in the kernel sources.
7297 + */
7298 +
7299 +#ifndef __LINUX_ASM_COOPERATIVE_H__
7300 +#define __LINUX_ASM_COOPERATIVE_H__
7301 +
7302 +typedef struct {
7303 +       unsigned short size;
7304 +       struct x86_idt_entry *table;
7305 +} __attribute__((packed)) x86_idt_t;
7306 +
7307 +typedef struct {
7308 +       unsigned short limit;
7309 +       struct x86_dt_entry *base;
7310 +} __attribute__((packed)) x86_gdt_t;
7311 +
7312 +typedef struct {
7313 +       unsigned char border2[0x4];
7314 +
7315 +       unsigned long cs;
7316 +        #define CO_ARCH_STATE_STACK_CS "0x04"
7317 +
7318 +       unsigned long ds;
7319 +        #define CO_ARCH_STATE_STACK_DS "0x08"
7320 +
7321 +       unsigned long es;
7322 +        #define CO_ARCH_STATE_STACK_ES "0x0C"
7323 +
7324 +       unsigned long cr3;   
7325 +        #define CO_ARCH_STATE_STACK_CR3 "0x10"
7326 +
7327 +       unsigned long cr4;  
7328 +        #define CO_ARCH_STATE_STACK_CR4 "0x14"
7329 +
7330 +       unsigned long cr2;
7331 +        #define CO_ARCH_STATE_STACK_CR2 "0x18"
7332 +
7333 +       unsigned long cr0;
7334 +        #define CO_ARCH_STATE_STACK_CR0 "0x1C"
7335 +
7336 +       x86_gdt_t gdt;
7337 +        #define CO_ARCH_STATE_STACK_GDT "0x20"
7338 +
7339 +       unsigned long fs;    
7340 +        #define CO_ARCH_STATE_STACK_FS  "0x26"
7341 +
7342 +       unsigned long gs;
7343 +        #define CO_ARCH_STATE_STACK_GS  "0x2A"
7344 +
7345 +       unsigned short ldt;
7346 +        #define CO_ARCH_STATE_STACK_LDT "0x2E"
7347 +
7348 +       x86_idt_t idt;
7349 +        #define CO_ARCH_STATE_STACK_IDT "0x30"
7350 +
7351 +       unsigned short tr;   
7352 +        #define CO_ARCH_STATE_STACK_TR  "0x36"
7353 +
7354 +       unsigned long return_eip; 
7355 +        #define CO_ARCH_STATE_STACK_RETURN_EIP  "0x38"
7356 +
7357 +       unsigned long flags;     
7358 +        #define CO_ARCH_STATE_STACK_FLAGS "0x3C"
7359 +
7360 +       unsigned long esp;        
7361 +        #define CO_ARCH_STATE_STACK_ESP "0x40"
7362 +
7363 +       unsigned long ss;    
7364 +        #define CO_ARCH_STATE_STACK_SS "0x44"
7365 +
7366 +       unsigned long dr0;        
7367 +        #define CO_ARCH_STATE_STACK_DR0 "0x48"
7368 +
7369 +       unsigned long dr1;      
7370 +        #define CO_ARCH_STATE_STACK_DR1 "0x4C"
7371 +
7372 +       unsigned long dr2;       
7373 +        #define CO_ARCH_STATE_STACK_DR2 "0x50"
7374 +
7375 +       unsigned long dr3;
7376 +        #define CO_ARCH_STATE_STACK_DR3 "0x54"
7377 +
7378 +       unsigned long dr6;
7379 +        #define CO_ARCH_STATE_STACK_DR6 "0x58"
7380 +
7381 +       unsigned long dr7;
7382 +        #define CO_ARCH_STATE_STACK_DR7 "0x5C"
7383 +
7384 +       unsigned long temp_cr3;
7385 +        #define CO_ARCH_STATE_STACK_TEMP_CR3 "0x60"
7386 +
7387 +       unsigned long relocate_eip; 
7388 +        #define CO_ARCH_STATE_STACK_RELOCATE_EIP "0x64"
7389 +
7390 +       unsigned long pad1;
7391 +        #define CO_ARCH_STATE_STACK_RELOCATE_EIP_AFTER "0x68"
7392 +
7393 +       unsigned long va;
7394 +        #define CO_ARCH_STATE_STACK_VA "0x6C"
7395 +
7396 +       unsigned char fxstate[0x200];
7397 +        #define CO_ARCH_STATE_STACK_FXSTATE "0x70"
7398 +} __attribute__((packed)) co_arch_state_stack_t;
7399 +
7400 +#define CO_MAX_PARAM_SIZE 0x400
7401 +
7402 +typedef struct co_arch_passage_page_normal_address_space {
7403 +       unsigned long pgd[0x400];
7404 +       unsigned long pte[2][0x400];
7405 +} co_arch_passage_page_normal_address_space_t;
7406 +
7407 +typedef struct co_arch_passage_page_pae_address_space {
7408 +       unsigned long long main[0x200];
7409 +       unsigned long long pgd[2][0x200];
7410 +       unsigned long long pte[2][0x200];
7411 +} co_arch_passage_page_pae_address_space_t;
7412 +
7413 +typedef struct co_arch_passage_page {
7414 +       union {
7415 +               struct {
7416 +                       union {
7417 +                               struct {
7418 +                                       unsigned long self_physical_address;
7419 +                                       unsigned long dr0;
7420 +                                       unsigned long dr1;
7421 +                                       unsigned long dr2;
7422 +                                       unsigned long dr3;
7423 +                                       unsigned long dr6;
7424 +                                       unsigned long dr7; 
7425 +                                       unsigned char code[0x230];
7426 +                               } __attribute__((packed));
7427 +                               unsigned char pad[0x250]; /* Be careful! see NOTE below */
7428 +                       } __attribute__((packed));
7429 +                       
7430 +                       /* Machine states */
7431 +
7432 +                       /* 
7433 +                        * NOTE: *_state fields must be aligned at 16 bytes boundary since
7434 +                        * the fxsave/fxload instructions expect an aligned arugment.
7435 +                        */
7436 +
7437 +                       co_arch_state_stack_t host_state; 
7438 +                       co_arch_state_stack_t linuxvm_state;
7439 +                       
7440 +                       /* Control parameters */
7441 +                       unsigned long operation;
7442 +                       unsigned long params[];
7443 +               } __attribute__((packed));
7444 +               unsigned char first_page[0x1000];
7445 +       };
7446 +
7447 +       /* page tables for passage address spaces */
7448 +       co_arch_passage_page_normal_address_space_t guest_normal;
7449 +       union {
7450 +               co_arch_passage_page_normal_address_space_t host_normal;
7451 +               co_arch_passage_page_pae_address_space_t host_pae;
7452 +       } __attribute__((packed));
7453 +} co_arch_passage_page_t;
7454 +
7455 +/*
7456 + * Address space layout:
7457 + */
7458 +
7459 +#define CO_VPTR_BASE                         (0xffc00000)
7460 +#define CO_VPTR_PHYSICAL_TO_PSEUDO_PFN_MAP   (CO_VPTR_BASE - 0x1000000)
7461 +#define CO_VPTR_PSEUDO_RAM_PAGE_TABLES       (CO_VPTR_BASE - 0x1100000)
7462 +#define CO_VPTR_PASSAGE_PAGE                 (CO_VPTR_BASE - 0x1101000)
7463 +#define CO_VPTR_IO_AREA_SIZE                 (0x10000)
7464 +#define CO_VPTR_IO_AREA_START                (CO_VPTR_BASE - 0x1200000)
7465 +#define CO_VPTR_SELF_MAP                     (CO_VPTR_BASE - 0x1400000)
7466 +
7467 +typedef struct {
7468 +       unsigned long kernel_cs;
7469 +       unsigned long kernel_ds;
7470 +} __attribute__((packed)) co_arch_info_t;
7471 +
7472 +#endif
7473 diff -urN a/include/asm-i386/cooperative_internal.h b/include/asm-i386/cooperative_internal.h
7474 --- a/include/asm-i386/cooperative_internal.h
7475 +++ b/include/asm-i386/cooperative_internal.h
7476 @@ -0,0 +1,33 @@
7477 +/*
7478 + *  linux/include/asm/cooperative_internal.h
7479 + *
7480 + *  Copyright (C) 2004 Dan Aloni
7481 + */
7482 +
7483 +#ifndef __LINUX_ASM_COOPERATIVE_INTERNAL_H__
7484 +#define __LINUX_ASM_COOPERATIVE_INTERNAL_H__
7485 +
7486 +#include <linux/config.h>
7487 +#include <asm/ptrace.h>
7488 +
7489 +#ifdef CONFIG_COOPERATIVE
7490 +
7491 +extern void co_kernel_breakpoint(struct pt_regs * regs);
7492 +extern int co_kernel_debug(struct pt_regs * regs, long error_code, unsigned int condition);
7493 +
7494 +fastcall unsigned int do_IRQ(struct pt_regs *regs);
7495 +
7496 +#else
7497 +
7498 +static inline void co_kernel_breakpoint(struct pt_regs * regs)
7499 +{
7500 +}
7501 +
7502 +static inline int co_kernel_debug(struct pt_regs * regs, long error_code, unsigned int condition)
7503 +{
7504 +       return 0;
7505 +}
7506 +
7507 +#endif
7508 +
7509 +#endif
7510 diff -urN a/include/asm-i386/dma.h b/include/asm-i386/dma.h
7511 --- a/include/asm-i386/dma.h
7512 +++ b/include/asm-i386/dma.h
7513 @@ -268,6 +268,7 @@
7514   *
7515   * Assumes DMA flip-flop is clear.
7516   */
7517 +#ifndef CONFIG_COOPERATIVE
7518  static __inline__ int get_dma_residue(unsigned int dmanr)
7519  {
7520         unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
7521 @@ -281,6 +282,7 @@
7522         
7523         return (dmanr<=3)? count : (count<<1);
7524  }
7525 +#endif
7526  
7527  
7528  /* These are in kernel/dma.c: */
7529 diff -urN a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
7530 --- a/include/asm-i386/fixmap.h
7531 +++ b/include/asm-i386/fixmap.h
7532 @@ -31,6 +31,7 @@
7533  #include <linux/threads.h>
7534  #include <asm/kmap_types.h>
7535  #endif
7536 +#include <asm/cooperative.h>
7537  
7538  /*
7539   * Here we define all the compile-time 'special' virtual
7540 diff -urN a/include/asm-i386/io.h b/include/asm-i386/io.h
7541 --- a/include/asm-i386/io.h
7542 +++ b/include/asm-i386/io.h
7543 @@ -104,12 +104,15 @@
7544   * address. 
7545   */
7546  
7547 -static inline void __iomem * ioremap(unsigned long offset, unsigned long size)
7548 +static inline void * __iomem ioremap (unsigned long offset, unsigned long size)
7549  {
7550 +#ifdef CONFIG_COOPERATIVE
7551 +       panic("ioremap %ld:%ld\n", offset, size);
7552 +#endif
7553         return __ioremap(offset, size, 0);
7554  }
7555  
7556 -extern void __iomem * ioremap_nocache(unsigned long offset, unsigned long size);
7557 +extern void * __iomem ioremap_nocache (unsigned long offset, unsigned long size);
7558  extern void iounmap(volatile void __iomem *addr);
7559  
7560  /*
7561 @@ -280,7 +283,7 @@
7562  
7563  #endif /* __KERNEL__ */
7564  
7565 -#ifdef SLOW_IO_BY_JUMPING
7566 +#if SLOW_IO_BY_JUMPING || CONFIG_COOPERATIVE
7567  #define __SLOW_DOWN_IO "jmp 1f; 1: jmp 1f; 1:"
7568  #else
7569  #define __SLOW_DOWN_IO "outb %%al,$0x80;"
7570 diff -urN a/include/asm-i386/mach-default/irq_vectors.h b/include/asm-i386/mach-default/irq_vectors.h
7571 --- a/include/asm-i386/mach-default/irq_vectors.h
7572 +++ b/include/asm-i386/mach-default/irq_vectors.h
7573 @@ -67,6 +67,11 @@
7574  
7575  #define TIMER_IRQ 0
7576  
7577 +#ifdef CONFIG_COOPERATIVE
7578 +#define KEYBOARD_IRQ 1
7579 +#define NETWORK_IRQ 2
7580 +#endif
7581 +
7582  /*
7583   * 16 8259A IRQ's, 208 potential APIC interrupt sources.
7584   * Right now the APIC is mostly only used for SMP.
7585 diff -urN a/include/asm-i386/mach-default/irq_vectors_limits.h b/include/asm-i386/mach-default/irq_vectors_limits.h
7586 --- a/include/asm-i386/mach-default/irq_vectors_limits.h
7587 +++ b/include/asm-i386/mach-default/irq_vectors_limits.h
7588 @@ -5,7 +5,7 @@
7589  #define NR_IRQS FIRST_SYSTEM_VECTOR
7590  #define NR_IRQ_VECTORS NR_IRQS
7591  #else
7592 -#ifdef CONFIG_X86_IO_APIC
7593 +#if defined(CONFIG_X86_IO_APIC) || defined(CONFIG_X86_UP_COPIC)
7594  #define NR_IRQS 224
7595  # if (224 >= 32 * NR_CPUS)
7596  # define NR_IRQ_VECTORS NR_IRQS
7597 diff -urN a/include/asm-i386/mc146818rtc.h b/include/asm-i386/mc146818rtc.h
7598 --- a/include/asm-i386/mc146818rtc.h
7599 +++ b/include/asm-i386/mc146818rtc.h
7600 @@ -4,6 +4,7 @@
7601  #ifndef _ASM_MC146818RTC_H
7602  #define _ASM_MC146818RTC_H
7603  
7604 +#include <linux/config.h>
7605  #include <asm/io.h>
7606  
7607  #ifndef RTC_PORT
7608 @@ -11,6 +12,8 @@
7609  #define RTC_ALWAYS_BCD 1       /* RTC operates in binary mode */
7610  #endif
7611  
7612 +#ifndef CONFIG_COOPERATIVE
7613 +
7614  /*
7615   * The yet supported machines all access the RTC index register via
7616   * an ISA port access but the way to access the date register differs ...
7617 @@ -24,6 +27,11 @@
7618  outb_p((val),RTC_PORT(1)); \
7619  })
7620  
7621 +#else
7622 +#define CMOS_READ(addr) (0)
7623 +#define CMOS_WRITE(val, addr) do {} while(0)
7624 +#endif
7625 +
7626  #define RTC_IRQ 8
7627  
7628  #endif /* _ASM_MC146818RTC_H */
7629 diff -urN a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
7630 --- a/include/asm-i386/mmzone.h
7631 +++ b/include/asm-i386/mmzone.h
7632 @@ -6,7 +6,9 @@
7633  #ifndef _ASM_MMZONE_H_
7634  #define _ASM_MMZONE_H_
7635  
7636 +#include <linux/config.h>
7637  #include <asm/smp.h>
7638 +#include <asm/cooperative.h>
7639  
7640  #ifdef CONFIG_DISCONTIGMEM
7641  
7642 @@ -116,7 +118,8 @@
7643         (unsigned long)(__page - __zone->zone_mem_map)                  \
7644                 + __zone->zone_start_pfn;                               \
7645  })
7646 -#define pmd_page(pmd)          (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
7647 +
7648 +#define pmd_page(pmd)          (pfn_to_page(CO_P_TO_PP(pmd_val(pmd)) >> PAGE_SHIFT))
7649  
7650  #ifdef CONFIG_X86_NUMAQ            /* we have contiguous memory on NUMA-Q */
7651  #define pfn_valid(pfn)          ((pfn) < num_physpages)
7652 diff -urN a/include/asm-i386/page.h b/include/asm-i386/page.h
7653 --- a/include/asm-i386/page.h
7654 +++ b/include/asm-i386/page.h
7655 @@ -13,6 +13,7 @@
7656  #ifndef __ASSEMBLY__
7657  
7658  #include <linux/config.h>
7659 +#include <asm/cooperative.h>
7660  
7661  #ifdef CONFIG_X86_USE_3DNOW
7662  
7663 @@ -126,6 +127,19 @@
7664  #define __PAGE_OFFSET          (0xC0000000UL)
7665  #endif
7666  
7667 +#ifdef CONFIG_COOPERATIVE
7668 +#define CO_PA(pfn)             (((unsigned long *)CO_VPTR_PSEUDO_RAM_PAGE_TABLES)[pfn])
7669 +#define CO_VA_PFN(pa)          (((unsigned long *)CO_VPTR_PHYSICAL_TO_PSEUDO_PFN_MAP)[((pa) >> PAGE_SHIFT)])
7670 +#define CO_PFN_PP_TO_P(pfn)    (CO_PA(pfn) >> PAGE_SHIFT)
7671 +#define CO_PFN_P_TO_PP(pfn)    (CO_VA_PFN(pfn << PAGE_SHIFT))
7672 +#define CO_PP_TO_P(pa)         ((CO_PFN_PP_TO_P(pa >> PAGE_SHIFT) << PAGE_SHIFT) | (pa & ~PAGE_MASK))
7673 +#define CO_P_TO_PP(pa)         ((CO_PFN_P_TO_PP(pa >> PAGE_SHIFT) << PAGE_SHIFT) | (pa & ~PAGE_MASK))
7674 +#else
7675 +#define CO_PFN_P_TO_PP(pfn)    pfn
7676 +#define CO_PFN_PP_TO_P(pfn)    pfn
7677 +#define CO_PP_TO_P(pa)         pa
7678 +#define CO_P_TO_PP(pa)         pa
7679 +#endif
7680  
7681  #define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
7682  #define VMALLOC_RESERVE                ((unsigned long)__VMALLOC_RESERVE)
7683 diff -urN a/include/asm-i386/param.h b/include/asm-i386/param.h
7684 --- a/include/asm-i386/param.h
7685 +++ b/include/asm-i386/param.h
7686 @@ -2,8 +2,12 @@
7687  #define _ASMi386_PARAM_H
7688  
7689  #ifdef __KERNEL__
7690 +# include <linux/config.h>
7691 +# ifndef CONFIG_COOPERATIVE
7692  # define HZ            1000            /* Internal kernel timer frequency */
7693 +# else
7694  # define USER_HZ       100             /* .. some user interfaces are in "ticks" */
7695 +# endif
7696  # define CLOCKS_PER_SEC                (USER_HZ)       /* like times() */
7697  #endif
7698  
7699 diff -urN a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h
7700 --- a/include/asm-i386/pgalloc.h
7701 +++ b/include/asm-i386/pgalloc.h
7702 @@ -6,15 +6,16 @@
7703  #include <asm/fixmap.h>
7704  #include <linux/threads.h>
7705  #include <linux/mm.h>          /* for struct page */
7706 +#include <asm/cooperative.h>
7707  
7708  #define pmd_populate_kernel(mm, pmd, pte) \
7709 -               set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
7710 +               set_pmd(pmd, __pmd(_PAGE_TABLE + CO_PP_TO_P(__pa(pte))))
7711  
7712  static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
7713  {
7714         set_pmd(pmd, __pmd(_PAGE_TABLE +
7715 -               ((unsigned long long)page_to_pfn(pte) <<
7716 -                       (unsigned long long) PAGE_SHIFT)));
7717 +                          ((CO_PFN_PP_TO_P((unsigned long long)page_to_pfn(pte))) <<
7718 +                           (unsigned long long) PAGE_SHIFT)));
7719  }
7720  /*
7721   * Allocate and free page tables.
7722 diff -urN a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
7723 --- a/include/asm-i386/pgtable-2level.h
7724 +++ b/include/asm-i386/pgtable-2level.h
7725 @@ -8,6 +8,9 @@
7726  #define pgd_ERROR(e) \
7727         printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
7728  
7729 +#include <linux/config.h>
7730 +#include <asm/cooperative.h>
7731 +
7732  /*
7733   * The "pgd_xxx()" functions here are trivial for a folded two-level
7734   * setup: the pgd is never bad, and a pmd always exists (as it's folded
7735 @@ -33,19 +36,21 @@
7736  #define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
7737  
7738  #define pgd_page(pgd) \
7739 -((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
7740 +       ((unsigned long) __va(CO_P_TO_PP(pgd_val(pgd)) & PAGE_MASK))
7741  
7742  static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
7743  {
7744         return (pmd_t *) dir;
7745  }
7746 +
7747  #define ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte_low, 0))
7748  #define pte_same(a, b)         ((a).pte_low == (b).pte_low)
7749 +
7750  #define pte_page(x)            pfn_to_page(pte_pfn(x))
7751 +#define pte_pfn(x)             CO_PFN_P_TO_PP((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
7752 +#define pfn_pte(pfn, prot)     __pte((CO_PFN_PP_TO_P(pfn) << PAGE_SHIFT) | pgprot_val(prot))
7753 +#define pfn_pmd(pfn, prot)     __pmd((CO_PFN_PP_TO_P(pfn) << PAGE_SHIFT) | pgprot_val(prot))
7754  #define pte_none(x)            (!(x).pte_low)
7755 -#define pte_pfn(x)             ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
7756 -#define pfn_pte(pfn, prot)     __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
7757 -#define pfn_pmd(pfn, prot)     __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
7758  
7759  /*
7760   * All present user pages are user-executable:
7761 diff -urN a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
7762 --- a/include/asm-i386/pgtable.h
7763 +++ b/include/asm-i386/pgtable.h
7764 @@ -25,6 +25,8 @@
7765  #include <linux/list.h>
7766  #include <linux/spinlock.h>
7767  
7768 +#include <asm/cooperative.h>
7769 +
7770  /*
7771   * ZERO_PAGE is a global shared page that is always zero: used
7772   * for zero-mapped memory areas etc..
7773 @@ -294,10 +296,10 @@
7774  #define page_pte(page) page_pte_prot(page, __pgprot(0))
7775  
7776  #define pmd_page_kernel(pmd) \
7777 -((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
7778 +((unsigned long) __va(CO_P_TO_PP(pmd_val(pmd)) & PAGE_MASK))
7779  
7780  #ifndef CONFIG_DISCONTIGMEM
7781 -#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
7782 +#define pmd_page(pmd) (pfn_to_page(CO_PFN_P_TO_PP(pmd_val(pmd) >> PAGE_SHIFT)))
7783  #endif /* !CONFIG_DISCONTIGMEM */
7784  
7785  #define pmd_large(pmd) \
7786 diff -urN a/include/asm-i386/processor.h b/include/asm-i386/processor.h
7787 --- a/include/asm-i386/processor.h
7788 +++ b/include/asm-i386/processor.h
7789 @@ -182,8 +182,7 @@
7790  }
7791  
7792  #define load_cr3(pgdir) \
7793 -       asm volatile("movl %0,%%cr3": :"r" (__pa(pgdir)))
7794 -
7795 +       asm volatile("movl %0,%%cr3": :"r" (CO_PP_TO_P(__pa(pgdir))))
7796  
7797  /*
7798   * Intel CPU features in CR4
7799 diff -urN a/include/asm-i386/timer.h b/include/asm-i386/timer.h
7800 --- a/include/asm-i386/timer.h
7801 +++ b/include/asm-i386/timer.h
7802 @@ -19,7 +19,7 @@
7803  struct timer_opts {
7804         char* name;
7805         void (*mark_offset)(void);
7806 -       unsigned long (*get_offset)(void);
7807 +       long (*get_offset)(void);
7808         unsigned long long (*monotonic_clock)(void);
7809         void (*delay)(unsigned long);
7810  };
7811 @@ -50,6 +50,9 @@
7812  #ifdef CONFIG_X86_CYCLONE_TIMER
7813  extern struct init_timer_opts timer_cyclone_init;
7814  #endif
7815 +#ifdef CONFIG_COOPERATIVE
7816 +extern struct init_timer_opts timer_cooperative_init;
7817 +#endif
7818  
7819  extern unsigned long calibrate_tsc(void);
7820  extern void init_cpu_khz(void);
7821 diff -urN a/include/linux/console.h b/include/linux/console.h
7822 --- a/include/linux/console.h
7823 +++ b/include/linux/console.h
7824 @@ -61,6 +61,7 @@
7825  extern const struct consw dummy_con;   /* dummy console buffer */
7826  extern const struct consw fb_con;      /* frame buffer based console */
7827  extern const struct consw vga_con;     /* VGA text console */
7828 +extern const struct consw colinux_con; /* coLinux Mode text console */
7829  extern const struct consw newport_con; /* SGI Newport console  */
7830  extern const struct consw prom_con;    /* SPARC PROM console */
7831  
7832 diff -urN a/include/linux/cooperative.h b/include/linux/cooperative.h
7833 --- a/include/linux/cooperative.h
7834 +++ b/include/linux/cooperative.h
7835 @@ -0,0 +1,322 @@
7836 +/*
7837 + *  linux/include/linux/cooperative.h
7838 + *
7839 + *  Copyright (C) 2004 Dan Aloni
7840 + *
7841 + *  This file defines the interfaces between the Cooperative Linux kernel
7842 + *  and the host OS driver. It's for both external inclusion from the 
7843 + *  and internal inclusion in the kernel sources.
7844 + */
7845 +
7846 +#ifndef __LINUX_COOPERATIVE_H__
7847 +#define __LINUX_COOPERATIVE_H__
7848 +
7849 +#ifdef __KERNEL__
7850 +#ifndef CO_KERNEL
7851 +#define CO_COLINUX_KERNEL
7852 +#define CO_KERNEL
7853 +#endif
7854 +#endif
7855 +
7856 +#include <asm/cooperative.h>
7857 +
7858 +#define CO_LINUX_API_VERSION    8
7859 +
7860 +#pragma pack(0)
7861 +
7862 +#define CO_BOOTPARAM_STRING_LENGTH 0x100
7863 +
7864 +typedef enum {
7865 +       CO_OPERATION_EMPTY=0,
7866 +       CO_OPERATION_START,
7867 +       CO_OPERATION_IDLE,
7868 +       CO_OPERATION_TERMINATE,
7869 +       CO_OPERATION_MESSAGE_TO_MONITOR,
7870 +       CO_OPERATION_MESSAGE_FROM_MONITOR,
7871 +       CO_OPERATION_FORWARD_INTERRUPT,
7872 +       CO_OPERATION_DEVICE,
7873 +       CO_OPERATION_GET_TIME,
7874 +       CO_OPERATION_DEBUG_LINE,
7875 +       CO_OPERATION_GET_HIGH_PREC_TIME,
7876 +       CO_OPERATION_TRACE_POINT,
7877 +       CO_OPERATION_FREE_PAGES,
7878 +       CO_OPERATION_ALLOC_PAGES,
7879 +} co_operation_t;
7880 +
7881 +#define CO_MODULE_MAX_CONET    16
7882 +#define CO_MODULE_MAX_COBD     32
7883 +#define CO_MODULE_MAX_COFS     32
7884 +#define CO_MODULE_MAX_SERIAL   64
7885 +
7886 +typedef enum {
7887 +       CO_MODULE_LINUX,
7888 +       CO_MODULE_MONITOR,
7889 +       CO_MODULE_DAEMON,
7890 +       CO_MODULE_IDLE,
7891 +       CO_MODULE_KERNEL_SWITCH,
7892 +       CO_MODULE_USER_SWITCH,
7893 +       CO_MODULE_CONSOLE,
7894 +       CO_MODULE_PRINTK,
7895 +
7896 +       CO_MODULE_CONET0,
7897 +       CO_MODULE_CONET_END=CO_MODULE_CONET0+CO_MODULE_MAX_CONET-1,
7898 +
7899 +       CO_MODULE_COBD0,
7900 +       CO_MODULE_COBD_END=CO_MODULE_COBD0+CO_MODULE_MAX_COBD-1,
7901 +
7902 +       CO_MODULE_COFS0,
7903 +       CO_MODULE_COFS_END=CO_MODULE_COFS0+CO_MODULE_MAX_COFS-1,
7904 +       
7905 +       CO_MODULE_SERIAL0,
7906 +       CO_MODULE_SERIAL_END=CO_MODULE_SERIAL0+CO_MODULE_MAX_SERIAL-1,
7907 +} co_module_t;
7908 +
7909 +typedef enum {
7910 +       CO_PRIORITY_DISCARDABLE=0,
7911 +       CO_PRIORITY_IMPORTANT,
7912 +} co_priority_t;
7913 +
7914 +typedef enum {
7915 +       CO_MESSAGE_TYPE_STRING=0,
7916 +       CO_MESSAGE_TYPE_OTHER=1,
7917 +} co_message_type_t;
7918 +
7919 +typedef struct {
7920 +       co_module_t from;
7921 +       co_module_t to;
7922 +       co_priority_t priority;
7923 +       co_message_type_t type;
7924 +       unsigned long size;
7925 +       char data[0];
7926 +} __attribute__((packed)) co_message_t;
7927 +
7928 +typedef enum {
7929 +       CO_DEVICE_BLOCK=0,
7930 +       CO_DEVICE_CONSOLE,
7931 +       CO_DEVICE_KEYBOARD,
7932 +       CO_DEVICE_NETWORK,
7933 +       CO_DEVICE_TIMER,
7934 +       CO_DEVICE_POWER,
7935 +       CO_DEVICE_SERIAL,
7936 +       CO_DEVICE_FILESYSTEM,
7937 +
7938 +       CO_DEVICES_TOTAL,
7939 +} co_device_t;
7940 +
7941 +typedef struct {
7942 +       unsigned char code;
7943 +       int down;
7944 +} co_scan_code_t;
7945 +
7946 +typedef enum {
7947 +       CO_LINUX_MESSAGE_POWER_ALT_CTRL_DEL=0,
7948 +} co_linux_message_power_type_t;
7949 +
7950 +typedef struct {
7951 +       co_linux_message_power_type_t type;
7952 +} __attribute__((packed)) co_linux_message_power_t;
7953 +
7954 +typedef struct {
7955 +       unsigned long tick_count;
7956 +} __attribute__((packed)) co_linux_message_idle_t;
7957 +
7958 +typedef struct {
7959 +       co_device_t device;
7960 +       unsigned long unit;
7961 +       unsigned long size;
7962 +       char data[];
7963 +} __attribute__((packed)) co_linux_message_t;
7964 +
7965 +typedef enum {
7966 +       CO_TERMINATE_END=0,
7967 +       CO_TERMINATE_REBOOT,
7968 +       CO_TERMINATE_POWEROFF,
7969 +       CO_TERMINATE_PANIC,
7970 +       CO_TERMINATE_HALT,
7971 +       CO_TERMINATE_FORCED_OFF,
7972 +       CO_TERMINATE_FORCED_END,
7973 +       CO_TERMINATE_INVALID_OPERATION,
7974 +       CO_TERMINATE_STACK_OVERFLOW,
7975 +       CO_TERMINATE_BUG,
7976 +} co_termination_reason_t;
7977 +
7978 +typedef void (*co_switcher_t)(co_arch_passage_page_t *page, 
7979 +                             unsigned char *from,
7980 +                             unsigned char *to);
7981 +
7982 +#define co_passage_page_func_low(_from_,_to_)  \
7983 +       (((co_switcher_t)(co_passage_page->code))       \
7984 +        (co_passage_page,                              \
7985 +         (char *)&_from_.border2,                      \
7986 +         (char *)&_to_.border2))
7987 +
7988 +#define co_passage_page_func(_from_,_to_)                              \
7989 +       co_passage_page_func_low(co_passage_page->_from_, co_passage_page->_to_)
7990 +
7991 +#ifdef CO_KERNEL
7992 +# ifdef CO_COLINUX_KERNEL
7993 +#  define co_passage_page  ((co_arch_passage_page_t *)(CO_VPTR_PASSAGE_PAGE))
7994 +#  define co_current (co_passage_page->linuxvm_state)
7995 +#  define co_other (co_passage_page->host_state)
7996 +# else
7997 +#  define co_passage_page  (cmon->passage_page)
7998 +#  define co_other (co_passage_page->linuxvm_state)
7999 +#  define co_current (co_passage_page->host_state)
8000 +# endif
8001 +
8002 +# define co_switch() co_passage_page_func_low(co_current, co_other)
8003 +#endif
8004 +
8005 +/*
8006 + * Defines operations on various virtual devices.
8007 + */
8008 +
8009 +typedef enum {
8010 +       CO_OPERATION_CONSOLE_STARTUP=0,
8011 +       CO_OPERATION_CONSOLE_INIT=1,
8012 +       CO_OPERATION_CONSOLE_DEINIT,
8013 +       CO_OPERATION_CONSOLE_CLEAR,
8014 +       CO_OPERATION_CONSOLE_PUTC,
8015 +       CO_OPERATION_CONSOLE_PUTCS,
8016 +       CO_OPERATION_CONSOLE_CURSOR_DRAW,
8017 +       CO_OPERATION_CONSOLE_CURSOR_ERASE,
8018 +       CO_OPERATION_CONSOLE_CURSOR_MOVE,
8019 +       CO_OPERATION_CONSOLE_SCROLL_UP,
8020 +       CO_OPERATION_CONSOLE_SCROLL_DOWN,
8021 +       CO_OPERATION_CONSOLE_BMOVE,
8022 +       CO_OPERATION_CONSOLE_SWITCH,
8023 +       CO_OPERATION_CONSOLE_BLANK,
8024 +       CO_OPERATION_CONSOLE_FONT_OP,
8025 +       CO_OPERATION_CONSOLE_SET_PALETTE,
8026 +       CO_OPERATION_CONSOLE_SCROLLDELTA,
8027 +       CO_OPERATION_CONSOLE_SET_ORIGIN,
8028 +       CO_OPERATION_CONSOLE_SAVE_SCREEN,
8029 +       CO_OPERATION_CONSOLE_INVERT_REGION,
8030 +} co_operation_console_t;
8031 +
8032 +
8033 +typedef char co_console_code;
8034 +typedef unsigned short co_console_character;
8035 +typedef unsigned short co_console_unit;
8036 +
8037 +typedef struct {
8038 +       co_console_unit x;
8039 +       co_console_unit y;
8040 +       co_console_unit height;
8041 +} __attribute__((packed)) co_cursor_pos_t;
8042 +
8043 +typedef struct {
8044 +       co_operation_console_t type;
8045 +       union {
8046 +               struct {
8047 +                       co_console_unit top;  
8048 +                       co_console_unit bottom;
8049 +                       co_console_unit lines;
8050 +               } scroll;
8051 +               struct {
8052 +                       co_console_unit y;
8053 +                       co_console_unit x;
8054 +                       co_console_unit count;
8055 +                       co_console_character data[];
8056 +               } putcs;
8057 +               struct {
8058 +                       co_console_unit x;
8059 +                       co_console_unit y;
8060 +                       co_console_character charattr;
8061 +               } putc;
8062 +               struct {
8063 +                       co_console_unit top;
8064 +                       co_console_unit left;
8065 +                       co_console_unit bottom;
8066 +                       co_console_unit right;
8067 +                       co_console_character charattr;
8068 +               } clear;
8069 +               struct {
8070 +                       co_console_unit y;
8071 +                       co_console_unit x;
8072 +                       co_console_unit count;
8073 +               } invert;
8074 +               struct {
8075 +                       co_console_unit row;
8076 +                       co_console_unit column;
8077 +                       co_console_unit top;
8078 +                       co_console_unit left;
8079 +                       co_console_unit bottom;
8080 +                       co_console_unit right;
8081 +               } bmove;
8082 +               co_cursor_pos_t cursor;
8083 +       };
8084 +} __attribute__((packed)) co_console_message_t;
8085 +
8086 +typedef struct {       
8087 +       unsigned long index;
8088 +       unsigned long flags;
8089 +       unsigned long func;
8090 +       unsigned long pid;
8091 +} __attribute__((packed)) co_trace_point_info_t;
8092 +
8093 +typedef enum {
8094 +       CO_BLOCK_OPEN=0,
8095 +       CO_BLOCK_STAT,
8096 +       CO_BLOCK_READ,
8097 +       CO_BLOCK_WRITE,
8098 +       CO_BLOCK_CLOSE,
8099 +       CO_BLOCK_GET_ALIAS,
8100 +} co_block_request_type_t;
8101 +
8102 +typedef enum {
8103 +       CO_NETWORK_GET_MAC=0,
8104 +} co_network_request_type_t;
8105 +
8106 +#ifdef CO_KERNEL
8107 +/* If we are compiling kernel code (Linux or Host Driver) */
8108 +# ifdef CO_COLINUX_KERNEL
8109 +/* Inside Linux, vm_ptr_t considered a valid pointer in its virtual address space */
8110 +typedef void *vm_ptr_t;
8111 +#  else
8112 +/* But inside the host, the type is considered not to be a pointer in its own address space */
8113 +typedef unsigned long vm_ptr_t;
8114 +# endif
8115 +
8116 +typedef struct {
8117 +       co_block_request_type_t type;
8118 +       long rc;
8119 +       union {
8120 +               struct {
8121 +                       unsigned long long offset;
8122 +                       unsigned long long size;
8123 +                       unsigned long long disk_size;
8124 +                       vm_ptr_t address;
8125 +               };
8126 +               struct {
8127 +                       char alias[20];
8128 +               };
8129 +       };
8130 +} __attribute__((packed)) co_block_request_t;
8131 +
8132 +typedef struct {
8133 +       co_network_request_type_t type;
8134 +       unsigned long unit;
8135 +       char mac_address[6];
8136 +       char _pad[2];
8137 +       int result;
8138 +} __attribute__((packed)) co_network_request_t;
8139 +
8140 +#endif
8141 +
8142 +typedef struct {
8143 +       unsigned long api_version;
8144 +       unsigned long compiler_major;
8145 +       unsigned long compiler_minor;
8146 +} __attribute__((packed)) co_info_t;
8147 +
8148 +#ifndef COLINUX_TRACE
8149 +#define CO_TRACE_STOP
8150 +#define CO_TRACE_CONTINUE
8151 +#endif
8152 +
8153 +#pragma pack()
8154 +
8155 +#include "cooperative_fs.h"
8156 +
8157 +#endif
8158 diff -urN a/include/linux/cooperative_fs.h b/include/linux/cooperative_fs.h
8159 --- a/include/linux/cooperative_fs.h
8160 +++ b/include/linux/cooperative_fs.h
8161 @@ -0,0 +1,267 @@
8162 +/*
8163 +    FUSE: Filesystem in Userspace
8164 +    Copyright (C) 2001-2004  Miklos Szeredi <miklos@szeredi.hu>
8165 +
8166 +    This program can be distributed under the terms of the GNU GPL.
8167 +    See the file COPYING.
8168 +*/
8169 +
8170 +/* This file defines the kernel interface of FUSE */
8171 +
8172 +#pragma pack(0)
8173 +
8174 +/** Version number of this interface */
8175 +#define FUSE_KERNEL_VERSION 2
8176 +
8177 +/** Minor version number of this interface */
8178 +#define FUSE_KERNEL_MINOR_VERSION 2
8179 +
8180 +/** The inode number of the root inode */
8181 +#define FUSE_ROOT_INO 1
8182 +
8183 +/** Data passed to mount */
8184 +struct fuse_mount_data {
8185 +       /** The file type of the root inode */
8186 +       unsigned int rootmode;
8187 +
8188 +       /** The user ID of the user initiating this mount */
8189 +       unsigned int uid;
8190 +       
8191 +       /** FUSE specific mount flags */
8192 +       unsigned int flags;
8193 +};
8194 +
8195 +/* FUSE mount flags: */
8196 +
8197 +/** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem
8198 +module will check permissions based on the file mode.  Otherwise no
8199 +permission checking is done in the kernel */
8200 +#define FUSE_DEFAULT_PERMISSIONS (1 << 0)
8201 +
8202 +/** If the FUSE_ALLOW_OTHER flag is given, then not only the user
8203 +    doing the mount will be allowed to access the filesystem */
8204 +#define FUSE_ALLOW_OTHER         (1 << 1)
8205 +
8206 +/** If the FUSE_KERNEL_CACHE flag is given, then files will be cached
8207 +    until the INVALIDATE operation is invoked */
8208 +#define FUSE_KERNEL_CACHE        (1 << 2)
8209 +
8210 +/** Allow FUSE to combine reads into 64k chunks.  This is useful if
8211 +    the filesystem is better at handling large chunks.  NOTE: in
8212 +    current implementation the raw throughput is worse for large reads
8213 +    than for small. */
8214 +#define FUSE_LARGE_READ          (1 << 3)
8215 +
8216 +struct fuse_attr {
8217 +       unsigned long long  size;
8218 +       unsigned int        mode;
8219 +       unsigned int        nlink;
8220 +       unsigned int        uid;
8221 +       unsigned int        gid;
8222 +       unsigned int        rdev;
8223 +       unsigned long       _dummy;
8224 +       unsigned long       blocks;
8225 +       unsigned long       atime;
8226 +       unsigned long       mtime;
8227 +       unsigned long       ctime;
8228 +};
8229 +
8230 +struct fuse_kstatfs {
8231 +    long block_size;
8232 +    long blocks;
8233 +    long blocks_free;
8234 +    long files;
8235 +    long files_free;
8236 +    long namelen;
8237 +};
8238 +
8239 +#define FATTR_MODE     (1 << 0)
8240 +#define FATTR_UID      (1 << 1)
8241 +#define FATTR_GID      (1 << 2)
8242 +#define FATTR_SIZE     (1 << 3)
8243 +#define FATTR_UTIME    (1 << 4)
8244 +
8245 +enum fuse_opcode {
8246 +       FUSE_LOOKUP     = 1,
8247 +       FUSE_FORGET     = 2,  /* no reply */
8248 +       FUSE_GETATTR    = 3,
8249 +       FUSE_SETATTR    = 4,
8250 +       FUSE_READLINK   = 5,
8251 +       FUSE_SYMLINK    = 6,
8252 +       FUSE_GETDIR     = 7,
8253 +       FUSE_MKNOD      = 8,
8254 +       FUSE_MKDIR      = 9,
8255 +       FUSE_UNLINK     = 10,
8256 +       FUSE_RMDIR      = 11,
8257 +       FUSE_RENAME     = 12,
8258 +       FUSE_LINK       = 13,
8259 +       FUSE_OPEN       = 14,
8260 +       FUSE_READ       = 15,
8261 +       FUSE_WRITE      = 16,
8262 +       FUSE_STATFS     = 17,
8263 +       FUSE_RELEASE    = 18, /* no reply */
8264 +       FUSE_INVALIDATE = 19, /* user initiated */
8265 +       FUSE_FSYNC      = 20,
8266 +       FUSE_RELEASE2   = 21,  /* reply needed after all */
8267 +
8268 +       /* Cooperative Linux does things a little differently: */
8269 +       FUSE_DIR_OPEN    = 22, 
8270 +       FUSE_DIR_READ    = 23, 
8271 +       FUSE_DIR_RELEASE = 24, 
8272 +
8273 +       FUSE_MOUNT       = 25,
8274 +};
8275 +
8276 +/* Conservative buffer size for the client */
8277 +#define FUSE_MAX_IN 8192
8278 +
8279 +#define FUSE_NAME_MAX 1024
8280 +#define FUSE_SYMLINK_MAX 4096
8281 +
8282 +struct fuse_lookup_out {
8283 +       struct fuse_attr attr;
8284 +       unsigned long ino;
8285 +};
8286 +
8287 +struct fuse_forget_in {
8288 +       int version;
8289 +};
8290 +
8291 +struct fuse_getattr_out {
8292 +       struct fuse_attr attr;
8293 +};
8294 +
8295 +struct fuse_getdir_out {
8296 +       int fd;
8297 +       void *file; /* Used by kernel only */
8298 +};
8299 +
8300 +/* FIXME: 2.6 needs 32 bit rdev */
8301 +struct fuse_mknod_in {
8302 +       unsigned short mode;
8303 +       unsigned short rdev;
8304 +};
8305 +
8306 +struct fuse_mknod_out {
8307 +       struct fuse_attr attr;
8308 +       unsigned long ino;
8309 +};
8310 +
8311 +struct fuse_mkdir_in {
8312 +       unsigned short mode;
8313 +};
8314 +
8315 +struct fuse_rename_in {
8316 +       unsigned long newdir;
8317 +};
8318 +
8319 +struct fuse_link_in {
8320 +       unsigned long newdir;
8321 +};
8322 +
8323 +struct fuse_setattr_in {
8324 +       struct fuse_attr attr;
8325 +       unsigned int valid;
8326 +};
8327 +
8328 +struct fuse_setattr_out {
8329 +       struct fuse_attr attr;
8330 +};
8331 +
8332 +struct fuse_open_in {
8333 +       unsigned int flags;
8334 +};
8335 +
8336 +struct fuse_read_in {
8337 +       unsigned long long offset;
8338 +       unsigned int size;
8339 +};
8340 +
8341 +struct fuse_write_in {
8342 +       unsigned long long offset;
8343 +       unsigned int size;
8344 +};
8345 +
8346 +struct fuse_statfs_out {
8347 +       struct fuse_kstatfs st;
8348 +};
8349 +
8350 +struct fuse_fsync_in {
8351 +       int datasync;
8352 +};
8353 +
8354 +struct fuse_in_header {
8355 +       int unique;
8356 +       enum fuse_opcode opcode;
8357 +       unsigned long ino;
8358 +       unsigned int uid;
8359 +       unsigned int gid;
8360 +};
8361 +
8362 +struct fuse_out_header {
8363 +       int unique;
8364 +       int error;
8365 +};
8366 +
8367 +struct fuse_user_header {
8368 +       int unique; /* zero */
8369 +       enum fuse_opcode opcode;
8370 +       unsigned long ino;
8371 +};
8372 +
8373 +struct fuse_dirent {
8374 +       unsigned long ino;
8375 +       unsigned short namelen;
8376 +       unsigned char type;
8377 +       char name[256];
8378 +};
8379 +
8380 +#define FUSE_S_IFMT   00170000
8381 +#define FUSE_S_IFSOCK 0140000
8382 +#define FUSE_S_IFLNK  0120000
8383 +#define FUSE_S_IFREG  0100000
8384 +#define FUSE_S_IFBLK  0060000
8385 +#define FUSE_S_IFDIR  0040000
8386 +#define FUSE_S_IFCHR  0020000
8387 +#define FUSE_S_IFIFO  0010000
8388 +#define FUSE_S_ISUID  0004000
8389 +#define FUSE_S_ISGID  0002000
8390 +#define FUSE_S_ISVTX  0001000
8391 +
8392 +#define FUSE_S_IRWXU 00700
8393 +#define FUSE_S_IRUSR 00400
8394 +#define FUSE_S_IWUSR 00200
8395 +#define FUSE_S_IXUSR 00100
8396 +
8397 +#define FUSE_S_IRWXG 00070
8398 +#define FUSE_S_IRGRP 00040
8399 +#define FUSE_S_IWGRP 00020
8400 +#define FUSE_S_IXGRP 00010
8401 +
8402 +#define FUSE_S_IRWXO 00007
8403 +#define FUSE_S_IROTH 00004
8404 +#define FUSE_S_IWOTH 00002
8405 +#define FUSE_S_IXOTH 00001
8406 +
8407 +#define FUSE_DT_UNKNOWN                0
8408 +#define FUSE_DT_FIFO           1
8409 +#define FUSE_DT_CHR            2
8410 +#define FUSE_DT_DIR            4
8411 +#define FUSE_DT_BLK            6
8412 +#define FUSE_DT_REG            8
8413 +#define FUSE_DT_LNK            10
8414 +#define FUSE_DT_SOCK           12
8415 +#define FUSE_DT_WHT            14
8416 +
8417 +#define FUSE_NAME_OFFSET ((unsigned int) ((struct fuse_dirent *) 0)->name)
8418 +#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(long) - 1) & ~(sizeof(long) - 1))
8419 +#define FUSE_DIRENT_SIZE(d) \
8420 +       FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
8421 +#pragma pack()
8422 +
8423 +/* 
8424 + * Local Variables:
8425 + * indent-tabs-mode: t
8426 + * c-basic-offset: 8
8427 + * End:
8428 + */
8429 diff -urN a/include/linux/cooperative_internal.h b/include/linux/cooperative_internal.h
8430 --- a/include/linux/cooperative_internal.h
8431 +++ b/include/linux/cooperative_internal.h
8432 @@ -0,0 +1,80 @@
8433 +/*
8434 + *  linux/include/linux/cooperative.h
8435 + *
8436 + *  Copyright (C) 2004 Dan Aloni
8437 + *
8438 + *  This header gathers the functions and variables in Cooperative Mode 
8439 + *  when CONFIG_COOPERATIVE is defined.
8440 + */
8441 +#ifndef __LINUX_COOPERATIVE_LINUX_H__
8442 +#define __LINUX_COOPERATIVE_LINUX_H__
8443 +
8444 +#include <linux/config.h>
8445 +#include <linux/cooperative.h>
8446 +#include <linux/list.h>
8447 +
8448 +#ifdef CONFIG_COOPERATIVE
8449 +
8450 +typedef struct {
8451 +       struct list_head node;
8452 +       co_message_t msg;
8453 +} co_message_node_t;
8454 +
8455 +extern void co_debug(const char *fmt, ...);
8456 +extern void co_printk(const char *line);
8457 +
8458 +extern void co_callback(unsigned long flags);
8459 +extern void co_switch_wrapper(void);
8460 +extern void co_idle_processor(void);
8461 +extern void co_terminate(co_termination_reason_t reason);
8462 +extern void co_free_pages(unsigned long vaddr, int order);
8463 +extern int co_alloc_pages(unsigned long vaddr, int order);
8464 +extern void co_start_kernel(void);
8465 +extern void co_arch_start_kernel(void);
8466 +extern void co_handle_jiffies(long count);
8467 +
8468 +extern void co_send_message(co_module_t from, 
8469 +                           co_module_t to,
8470 +                           co_priority_t priority,
8471 +                           co_message_type_t type,
8472 +                           unsigned long size,
8473 +                           const char *data);
8474 +extern unsigned long co_get_host_time(void);
8475 +extern co_message_t *co_send_message_save(unsigned long *flags);
8476 +extern co_message_t *co_get_message_save(unsigned long *flags);
8477 +extern void co_send_message_restore(unsigned long flags);
8478 +
8479 +extern void cocd_interrupt(void);
8480 +
8481 +extern void co_handle_incoming_messages(void);
8482 +extern void co_handle_incoming_message(co_message_node_t *message);
8483 +extern void co_queue_incoming_message(co_message_node_t *message);
8484 +extern int co_get_message(co_message_node_t **message, co_device_t device);
8485 +extern void co_free_message(co_message_node_t *message);
8486 +
8487 +extern int co_passage_page_held(void);
8488 +extern void co_passage_page_acquire(unsigned long *flags);
8489 +extern void co_passage_page_release(unsigned long flags);
8490 +
8491 +#define co_passage_page_assert_valid() do {    \
8492 +       if (co_passage_page_held())             \
8493 +            BUG();                             \
8494 +} while (0);
8495 +
8496 +extern char co_boot_parameters[CO_BOOTPARAM_STRING_LENGTH];
8497 +extern unsigned long co_core_end;
8498 +extern unsigned long co_memory_size;
8499 +extern void *co_initrd;
8500 +extern unsigned long co_initrd_size;
8501 +
8502 +#define cooperative_mode_enabled()     1
8503 +
8504 +#else
8505 +
8506 +#define co_printk(line)                do {} while (0)
8507 +#define co_terminate(reason)           do {} while (0)
8508 +#define cooperative_mode_enabled()     0
8509 +
8510 +#endif
8511 +
8512 +#endif
8513 diff -urN a/include/linux/major.h b/include/linux/major.h
8514 --- a/include/linux/major.h
8515 +++ b/include/linux/major.h
8516 @@ -130,6 +130,7 @@
8517  #define VIOCD_MAJOR            113
8518  
8519  #define ATARAID_MAJOR          114
8520 +#define COLINUX_MAJOR          117
8521  
8522  #define SCSI_DISK8_MAJOR       128
8523  #define SCSI_DISK9_MAJOR       129
8524 diff -urN a/init/do_mounts.c b/init/do_mounts.c
8525 --- a/init/do_mounts.c
8526 +++ b/init/do_mounts.c
8527 @@ -175,6 +175,7 @@
8528         for (p = s; *p; p++)
8529                 if (*p == '/')
8530                         *p = '!';
8531 +
8532         res = try_name(s, 0);
8533         if (res)
8534                 goto done;
8535 diff -urN a/init/main.c b/init/main.c
8536 --- a/init/main.c
8537 +++ b/init/main.c
8538 @@ -537,6 +537,7 @@
8539                 panic(panic_later, panic_param);
8540         profile_init();
8541         local_irq_enable();
8542 +
8543  #ifdef CONFIG_BLK_DEV_INITRD
8544         if (initrd_start && !initrd_below_start_ok &&
8545                         initrd_start < min_low_pfn << PAGE_SHIFT) {
8546 diff -urN a/kernel/Makefile b/kernel/Makefile
8547 --- a/kernel/Makefile
8548 +++ b/kernel/Makefile
8549 @@ -26,6 +26,7 @@
8550  obj-$(CONFIG_KPROBES) += kprobes.o
8551  obj-$(CONFIG_SYSFS) += ksysfs.o
8552  obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
8553 +obj-$(CONFIG_COOPERATIVE) += cooperative.o
8554  
8555  ifneq ($(CONFIG_IA64),y)
8556  # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
8557 diff -urN a/kernel/cooperative.c b/kernel/cooperative.c
8558 --- a/kernel/cooperative.c
8559 +++ b/kernel/cooperative.c
8560 @@ -0,0 +1,354 @@
8561 +/*
8562 + *  linux/kernel/cooperative.c
8563 + *
8564 + *  Cooperative mode (coLinux) support routines.
8565 + *
8566 + *  Dan Aloni <da-x@colinux.org>, 2003-2004 (C).
8567 + *
8568 + */
8569 +
8570 +#include <linux/kernel.h>
8571 +#include <linux/module.h>
8572 +#include <linux/string.h>
8573 +#include <linux/interrupt.h>
8574 +#include <linux/mm.h>
8575 +#include <linux/slab.h>
8576 +#include <linux/cooperative_internal.h>
8577 +
8578 +CO_TRACE_STOP;
8579 +
8580 +void start_kernel(void);
8581 +extern char _kernel_start, _end;
8582 +
8583 +
8584 +unsigned long co_core_end = 0;
8585 +unsigned long co_memory_size = 0;
8586 +void *co_initrd = NULL;
8587 +unsigned long co_initrd_size = 0;
8588 +char co_boot_parameters[CO_BOOTPARAM_STRING_LENGTH];
8589 +
8590 +
8591 +typedef struct {
8592 +       struct list_head list;
8593 +       int num_messages;
8594 +} co_message_queue_t;
8595 +
8596 +int co_messages_active = 0;
8597 +co_message_queue_t co_outgoing_messages;
8598 +co_message_queue_t co_incoming_messages;
8599 +co_message_queue_t *co_incoming_queued_messages;
8600 +
8601 +void co_start_kernel(void)
8602 +{
8603 +        co_core_end = co_passage_page->params[0];
8604 +        co_memory_size = co_passage_page->params[1];
8605 +        co_initrd = (void *)co_passage_page->params[2];
8606 +        co_initrd_size = co_passage_page->params[3];
8607 +
8608 +        memcpy(co_boot_parameters, &co_passage_page->params[10], 
8609 +               sizeof(co_boot_parameters));
8610 +
8611 +       co_arch_start_kernel();
8612 +
8613 +       /* should never be reached */
8614 +       co_terminate(CO_TERMINATE_END);
8615 +}
8616 +
8617 +co_message_t *co_send_message_save(unsigned long *flags)
8618 +{
8619 +       co_passage_page_assert_valid(); 
8620 +       co_passage_page_acquire(flags);
8621 +       co_passage_page->operation = CO_OPERATION_MESSAGE_TO_MONITOR;
8622 +       return ((co_message_t *)CO_VPTR_IO_AREA_START);
8623 +}
8624 +
8625 +void co_send_message_restore(unsigned long flags)
8626 +{
8627 +       co_switch_wrapper();
8628 +       co_passage_page_release(flags);
8629 +}
8630 +
8631 +void co_send_message_s(co_message_t *message, const char *data)
8632 +{
8633 +       if ((sizeof(co_message_t) + message->size) > CO_VPTR_IO_AREA_SIZE)
8634 +               return;
8635 +       
8636 +       if (co_passage_page_held())
8637 +               return;
8638 +       
8639 +       unsigned long flags;
8640 +       co_message_t *buffer = ((co_message_t *)CO_VPTR_IO_AREA_START);
8641 +       
8642 +       co_passage_page_acquire(&flags);
8643 +       co_passage_page->operation = CO_OPERATION_MESSAGE_TO_MONITOR;
8644 +       *buffer = *message;
8645 +       memcpy(buffer->data, data, message->size);
8646 +       co_switch_wrapper();
8647 +       co_passage_page_release(flags);
8648 +}
8649 +
8650 +void co_send_message(co_module_t from, 
8651 +                    co_module_t to,
8652 +                    co_priority_t priority,
8653 +                    co_message_type_t type,
8654 +                    unsigned long size,
8655 +                    const char *data)
8656 +{
8657 +       co_message_t params;
8658 +
8659 +       params.from = from;
8660 +       params.to = to;
8661 +       params.priority = priority;
8662 +       params.type = type;
8663 +       params.size = size;
8664 +
8665 +       co_send_message_s(&params, data);
8666 +}
8667 +
8668 +static void co_message_add_to_incoming(co_message_t *message, unsigned long size)
8669 +{
8670 +       co_message_node_t *message_copy;
8671 +
8672 +       message_copy = kmalloc(size + sizeof(co_message_node_t) - sizeof(co_message_t), 
8673 +                              GFP_ATOMIC);
8674 +       if (!message_copy)
8675 +               return;
8676 +       
8677 +       memcpy(&message_copy->msg, message, size);
8678 +       list_add_tail(&message_copy->node, &co_incoming_messages.list);
8679 +}
8680 +
8681 +void co_callback(unsigned long flags)
8682 +{
8683 +       if (co_passage_page->operation != CO_OPERATION_MESSAGE_FROM_MONITOR) {
8684 +               co_passage_page_release(flags);
8685 +               return;
8686 +       }
8687 +
8688 +       long io_size = co_passage_page->params[0];
8689 +       unsigned long new_jiffies = co_passage_page->params[1];
8690 +
8691 +       if (co_messages_active  &&  io_size > 0) {
8692 +               unsigned char *io_buffer = (char *)CO_VPTR_IO_AREA_START;
8693 +               unsigned char *io_buffer_end = io_buffer + io_size;
8694 +               if (!(io_size > CO_VPTR_IO_AREA_SIZE)) {
8695 +                       while (io_buffer < io_buffer_end) {
8696 +                               co_message_t *message = (co_message_t *)io_buffer;
8697 +                               unsigned long size = message->size + sizeof(*message);
8698 +                               
8699 +                               co_message_add_to_incoming(message, size);
8700 +                               io_buffer += size;
8701 +                       }
8702 +               }
8703 +       }
8704 +
8705 +       co_passage_page_release(flags);
8706 +
8707 +       co_handle_jiffies(new_jiffies);
8708 +       co_handle_incoming_messages();
8709 +}
8710 +
8711 +void co_handle_incoming_messages(void)
8712 +{
8713 +       if (!co_messages_active)
8714 +               return;
8715 +
8716 +       if (list_empty(&co_incoming_messages.list))
8717 +               return;
8718 +
8719 +       for (;;) {
8720 +               unsigned long flags;
8721 +               co_message_node_t *message = NULL;
8722 +
8723 +               /*
8724 +                * Pop a message from the incoming queue.
8725 +                */
8726 +               local_irq_save(flags);
8727 +               if (!list_empty(&co_incoming_messages.list)) {
8728 +                       message = list_entry(co_incoming_messages.list.next, 
8729 +                                            co_message_node_t, node);
8730 +                       list_del(&message->node);
8731 +               }
8732 +               local_irq_restore(flags);
8733 +
8734 +               if (!message)
8735 +                       break;
8736 +               
8737 +               /*
8738 +                * Let the interrupt routine of the arch dependant code
8739 +                * handle the message, and be responsible to free it.
8740 +                */
8741 +               co_handle_incoming_message(message);
8742 +       }
8743 +}
8744 +
8745 +void co_idle_processor(void)
8746 +{
8747 +       unsigned long flags;
8748 +
8749 +       co_passage_page_assert_valid(); 
8750 +
8751 +       co_passage_page_acquire(&flags);
8752 +       co_passage_page->operation = CO_OPERATION_IDLE;
8753 +       co_switch_wrapper();
8754 +       co_callback(flags);
8755 +}
8756 +
8757 +void co_printk(const char *line)
8758 +{
8759 +       co_send_message(CO_MODULE_LINUX, 
8760 +                       CO_MODULE_PRINTK,
8761 +                       CO_PRIORITY_DISCARDABLE,
8762 +                       CO_MESSAGE_TYPE_STRING,
8763 +                       strlen(line)+1,
8764 +                       line);
8765 +}
8766 +
8767 +void co_debug_line(char *line)
8768 +{
8769 +}
8770 +
8771 +void co_terminate(co_termination_reason_t reason)
8772 +{
8773 +       unsigned long flags;
8774 +
8775 +       co_passage_page_acquire(&flags);
8776 +       co_passage_page->operation = CO_OPERATION_TERMINATE;
8777 +       co_passage_page->params[0] = reason;
8778 +       co_switch_wrapper();
8779 +       /* This doesn't really return. This code shouldn't be running. */
8780 +       co_passage_page_release(flags);
8781 +}
8782 +
8783 +unsigned long co_get_host_time(void)
8784 +{
8785 +       unsigned long flags;
8786 +       unsigned long time;
8787 +
8788 +       co_passage_page_assert_valid();
8789 +
8790 +       co_passage_page_acquire(&flags);
8791 +       co_passage_page->operation = CO_OPERATION_GET_TIME;
8792 +       co_switch_wrapper();
8793 +       time = co_passage_page->params[0];
8794 +       co_passage_page_release(flags);
8795 +
8796 +       return time;
8797 +}
8798 +
8799 +void co_queue_incoming_message(co_message_node_t *node_message)
8800 +{
8801 +       if (!co_messages_active)
8802 +               return;
8803 +       
8804 +       co_linux_message_t *message = (co_linux_message_t *)&node_message->msg.data;
8805 +       if (message->device < 0 || (message->device >= CO_DEVICES_TOTAL))
8806 +               return;
8807 +       
8808 +       co_message_queue_t *queue;
8809 +       queue = &co_incoming_queued_messages[message->device];
8810 +
8811 +       /* Add to the queue */
8812 +       unsigned long flags;
8813 +       local_irq_save(flags);
8814 +       list_add(&node_message->node, &queue->list);
8815 +       queue->num_messages++;
8816 +       local_irq_restore(flags);
8817 +}
8818 +
8819 +int co_get_message(co_message_node_t **message, co_device_t device)
8820 +{
8821 +       co_message_queue_t *queue;
8822 +       co_message_node_t *node;
8823 +       unsigned long flags;
8824 +
8825 +       if (!co_messages_active)
8826 +               return 0;
8827 +
8828 +       local_irq_save(flags);
8829 +       queue = &co_incoming_queued_messages[device];
8830 +       if (list_empty(&queue->list)) {
8831 +               local_irq_restore(flags);
8832 +               return 0;
8833 +       }
8834 +
8835 +       node = list_entry(queue->list.prev, co_message_node_t, node);
8836 +       list_del(&node->node);
8837 +       queue->num_messages--;
8838 +       local_irq_restore(flags);
8839 +
8840 +       *message = node;
8841 +       return 1;
8842 +}
8843 +
8844 +void co_free_message(co_message_node_t *message)
8845 +{
8846 +       kfree(message);
8847 +}
8848 +
8849 +co_info_t co_info = {
8850 +       .api_version = CO_LINUX_API_VERSION,
8851 +       .compiler_major = __GNUC__,
8852 +       .compiler_minor = __GNUC_MINOR__,
8853 +};
8854 +
8855 +static int __init initcall_message_queues(void)
8856 +{
8857 +       int queue_index;
8858 +
8859 +       INIT_LIST_HEAD(&co_outgoing_messages.list);
8860 +       INIT_LIST_HEAD(&co_incoming_messages.list);
8861 +
8862 +       co_incoming_queued_messages = kmalloc(sizeof(co_message_queue_t) * CO_DEVICES_TOTAL, 
8863 +                                             GFP_KERNEL);
8864 +       if (!co_incoming_queued_messages)
8865 +               panic("unable to allocate message queues\n");
8866 +
8867 +       for (queue_index=0; queue_index < CO_DEVICES_TOTAL; queue_index++) {
8868 +               co_message_queue_t *queue = &co_incoming_queued_messages[queue_index];
8869 +               queue->num_messages = 0;
8870 +               INIT_LIST_HEAD(&queue->list);
8871 +       }
8872 +
8873 +       co_messages_active = 1;
8874 +
8875 +       return 0;
8876 +}
8877 +
8878 +
8879 +void co_free_pages(unsigned long vaddr, int order)
8880 +{
8881 +       unsigned long flags;
8882 +       
8883 +       co_passage_page_acquire(&flags);
8884 +       co_passage_page->operation = CO_OPERATION_FREE_PAGES;
8885 +       co_passage_page->params[0] = vaddr;
8886 +       co_passage_page->params[1] = order;
8887 +       co_switch_wrapper();
8888 +       co_passage_page_release(flags);
8889 +}
8890 +
8891 +int co_alloc_pages(unsigned long vaddr, int order)
8892 +{
8893 +       unsigned long flags;
8894 +       long result;
8895 +
8896 +       co_passage_page_acquire(&flags);
8897 +       co_passage_page->operation = CO_OPERATION_ALLOC_PAGES;
8898 +       co_passage_page->params[0] = vaddr;
8899 +       co_passage_page->params[1] = order;
8900 +       co_switch_wrapper();
8901 +       result = (long)co_passage_page->params[4];
8902 +       co_passage_page_release(flags);
8903 +
8904 +       if (result < 0)
8905 +               return -ENOMEM;
8906 +
8907 +       return 0;
8908 +}
8909 +
8910 +__initcall(initcall_message_queues);
8911 +
8912 +EXPORT_SYMBOL(co_terminate);
8913 +
8914 +CO_TRACE_CONTINUE;
8915 diff -urN a/kernel/panic.c b/kernel/panic.c
8916 --- a/kernel/panic.c
8917 +++ b/kernel/panic.c
8918 @@ -18,6 +18,7 @@
8919  #include <linux/sysrq.h>
8920  #include <linux/interrupt.h>
8921  #include <linux/nmi.h>
8922 +#include <linux/cooperative_internal.h>
8923  
8924  int panic_timeout;
8925  int panic_on_oops;
8926 @@ -71,6 +72,10 @@
8927         printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
8928         bust_spinlocks(0);
8929  
8930 +       if (cooperative_mode_enabled()) {
8931 +               co_terminate(CO_TERMINATE_PANIC);
8932 +       }
8933 +
8934  #ifdef CONFIG_SMP
8935         smp_send_stop();
8936  #endif
8937 diff -urN a/kernel/printk.c b/kernel/printk.c
8938 --- a/kernel/printk.c
8939 +++ b/kernel/printk.c
8940 @@ -34,6 +34,8 @@
8941  
8942  #include <asm/uaccess.h>
8943  
8944 +#include <linux/cooperative_internal.h>
8945 +
8946  #define __LOG_BUF_LEN  (1 << CONFIG_LOG_BUF_SHIFT)
8947  
8948  /* printk's without a loglevel use this.. */
8949 @@ -538,6 +540,8 @@
8950         /* Emit the output into the temporary buffer */
8951         printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
8952  
8953 +       co_printk(printk_buf);
8954 +
8955         /*
8956          * Copy the output into log_buf.  If the caller didn't provide
8957          * appropriate log level tags, we insert them here
8958 diff -urN a/localversion-cooperative b/localversion-cooperative
8959 --- a/localversion-cooperative
8960 +++ b/localversion-cooperative
8961 @@ -0,0 +1 @@
8962 +-co-
8963 diff -urN a/mm/bootmem.c b/mm/bootmem.c
8964 --- a/mm/bootmem.c
8965 +++ b/mm/bootmem.c
8966 @@ -17,6 +17,7 @@
8967  #include <linux/bootmem.h>
8968  #include <linux/mmzone.h>
8969  #include <linux/module.h>
8970 +#include <linux/cooperative_internal.h>
8971  #include <asm/dma.h>
8972  #include <asm/io.h>
8973  
8974 @@ -248,6 +249,23 @@
8975         for (i = start; i < start+areasize; i++)
8976                 if (unlikely(test_and_set_bit(i, bdata->node_bootmem_map)))
8977                         BUG();
8978 +
8979 +       if (cooperative_mode_enabled()) {
8980 +               unsigned long alloc_address = (unsigned long)ret;
8981 +               unsigned long alloc_size = size;
8982 +               int result;
8983 +
8984 +               alloc_size += (alloc_address & (~PAGE_MASK));
8985 +               alloc_address &= PAGE_MASK;
8986 +               alloc_size = (alloc_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
8987 +
8988 +               result = co_alloc_pages(alloc_address, alloc_size);
8989 +               if (result) {
8990 +                       free_bootmem((unsigned long)ret, size);
8991 +                       return NULL;
8992 +               }
8993 +       }
8994 +
8995         memset(ret, 0, size);
8996         return ret;
8997  }
8998 diff -urN a/mm/page_alloc.c b/mm/page_alloc.c
8999 --- a/mm/page_alloc.c
9000 +++ b/mm/page_alloc.c
9001 @@ -32,7 +32,7 @@
9002  #include <linux/sysctl.h>
9003  #include <linux/cpu.h>
9004  #include <linux/nodemask.h>
9005 -
9006 +#include <linux/cooperative_internal.h>
9007  #include <asm/tlbflush.h>
9008  
9009  nodemask_t node_online_map = NODE_MASK_NONE;
9010 @@ -184,6 +184,9 @@
9011  {
9012         unsigned long page_idx, index, mask;
9013  
9014 +       if (cooperative_mode_enabled())
9015 +               co_free_pages((unsigned long)page_address(page), 1 << order);
9016 +
9017         if (order)
9018                 destroy_compound_page(page, order);
9019         mask = (~0UL) << order;
9020 @@ -738,6 +741,37 @@
9021  got_pg:
9022         zone_statistics(zonelist, z);
9023         kernel_map_pages(page, 1 << order, 1);
9024 +
9025 +       if (cooperative_mode_enabled()) {
9026 +               int result, retries_left;
9027 +
9028 +               retries_left = 10;
9029 +
9030 +               while (retries_left > 0) {
9031 +                       result = co_alloc_pages((unsigned long)page_address(page), 1 << order);
9032 +                       if (result) {
9033 +                               unsigned long cache_size;
9034 +                               /* 
9035 +                                * Whoops, we have allocated too much of the
9036 +                                * host OS's memory, time to free some cache.
9037 +                                * cache.
9038 +                                */
9039 +                               cache_size = get_page_cache_size()-total_swapcache_pages;
9040 +                               cache_size /= 2;
9041 +                               if (cache_size < ((1 << order)*2))
9042 +                                       cache_size = (1 << order)*2;
9043 +                               shrink_all_memory(cache_size);
9044 +                       } else
9045 +                               break;
9046 +                       retries_left--;
9047 +               }
9048 +
9049 +               if (result) {
9050 +                       __free_pages(page, order);
9051 +                       return NULL;
9052 +               }
9053 +       }
9054 +
9055         return page;
9056  }
9057  
9058 diff -urN a/mm/vmscan.c b/mm/vmscan.c
9059 --- a/mm/vmscan.c
9060 +++ b/mm/vmscan.c
9061 @@ -1180,7 +1180,7 @@
9062         wake_up_interruptible(&zone->zone_pgdat->kswapd_wait);
9063  }
9064  
9065 -#ifdef CONFIG_PM
9066 +#if defined(CONFIG_PM) || defined(CONFIG_COOPERATIVE)
9067  /*
9068   * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
9069   * pages.