diff -Naur linux-2.6.11.8/arch/arm/Kconfig linux-2.6.x/arch/arm/Kconfig
--- linux-2.6.11.8/arch/arm/Kconfig	2009-09-06 22:49:56.000000000 +0100
+++ linux-2.6.x/arch/arm/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -289,6 +289,14 @@
 	  
 	  refer to  <http://www.espd-inc.com/prod01-arm-samsung4510.htm>
 
+config ARCH_ACTELM7
+	bool "Actel M7"
+	help
+	  Actel M7 series are based on ARM7TDMI-S core,
+	  equipped with 20kb on-chip RAM and 1KB of on-chip Flash, 
+	  operating at up to 28MHz together with 
+	  a wide range of peripherals and external bus options.
+
 config ARCH_S3C44B0
 	bool "Samsung S3C44B0"
 	help
@@ -348,6 +356,8 @@
 
 source "arch/arm/mach-espd_4510b/Kconfig"
 
+source "arch/arm/mach-actelm7/Kconfig"
+
 source "arch/arm/mach-s3c24a0/Kconfig" 
 
 source "arch/arm/mach-p2001/Kconfig"
@@ -835,9 +845,9 @@
 
 source "drivers/parport/Kconfig"
 
-if ALIGNMENT_TRAP
+#if ALIGNMENT_TRAP
 source "drivers/mtd/Kconfig"
-endif
+#endif
 
 source "drivers/pnp/Kconfig"
 
diff -Naur linux-2.6.11.8/arch/arm/Kconfig-nommu linux-2.6.x/arch/arm/Kconfig-nommu
--- linux-2.6.11.8/arch/arm/Kconfig-nommu	2009-09-06 22:49:56.000000000 +0100
+++ linux-2.6.x/arch/arm/Kconfig-nommu	2009-09-06 22:42:40.000000000 +0100
@@ -16,6 +16,7 @@
 	default 0x0C000000 if ARCH_S3C44B0
 	default 0x00000000 if ARCH_S5C7375
 	default 0x00000000 if ARCH_ESPD_4510B
+	default 0x10000000 if ARCH_ACTELM7
 	default 0x10000000 if ARCH_S3C24A0 
 	default 0x40000000 if ARCH_P2001
 	default 0x00000000 if ARCH_INTEGRATOR
@@ -28,6 +29,7 @@
 	default 0x01000000 if ARCH_S3C44B0
 	default 0x00400000 if ARCH_S5C7375
 	default 0x00800000 if ARCH_ESPD_4510B
+	default 0x00100000 if ARCH_ACTELM7
 	default 0x04000000 if ARCH_S3C24A0 
 	default 0x04000000 if ARCH_P2001
 	default 0x08000000 if ARCH_INTEGRATOR
@@ -40,6 +42,7 @@
 	default 0x00000000 if ARCH_S3C44B0
 	default 0x08000000 if ARCH_S5C7375
 	default 0x01000000 if ARCH_ESPD_4510B
+	default 0x00000000 if ARCH_ACTELM7
 	default 0x02000000 if ARCH_P2001
 	default 0x24000000 if ARCH_INTEGRATOR
 	default 0x00400000
@@ -51,6 +54,7 @@
 	default 0x00200000 if ARCH_S3C44B0
 	default 0x00200000 if ARCH_S5C7375
 	default 0x00200000 if ARCH_ESPD_4510B
+	default 0x01000000 if ARCH_ACTELM7
 	default 0x00400000 if ARCH_P2001
 	default 0x01000000 if ARCH_INTEGRATOR
 	default 0x00400000
diff -Naur linux-2.6.11.8/arch/arm/kernel/vmlinux.lds.S linux-2.6.x/arch/arm/kernel/vmlinux.lds.S
--- linux-2.6.11.8/arch/arm/kernel/vmlinux.lds.S	2005-04-30 02:26:22.000000000 +0100
+++ linux-2.6.x/arch/arm/kernel/vmlinux.lds.S	2009-09-06 22:42:40.000000000 +0100
@@ -150,6 +150,7 @@
 		*(.bss)
 		*(COMMON)
 		_end = .;
+		_ebss = .;
 	}
 					/* Stabs debugging sections.	*/
 	.stab 0 : { *(.stab) }
diff -Naur linux-2.6.11.8/arch/arm/mach-actelm7/arch.c linux-2.6.x/arch/arm/mach-actelm7/arch.c
--- linux-2.6.11.8/arch/arm/mach-actelm7/arch.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/arch/arm/mach-actelm7/arch.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,45 @@
+/*
+ *  linux/arch/arm/mach-actelm7/arch.c
+ *
+ *  Architecture specific fixups.  This is where any
+ *  parameters in the params struct are fixed up, or
+ *  any additional architecture specific information
+ *  is pulled from the params struct.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+#include <linux/tty.h>
+#include <asm/elf.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+
+extern void __init actelm7_init_irq(void);
+
+extern struct sys_timer actelm7_timer;
+
+MACHINE_START(ACTELM7, "Actel M7, Actel Corporation")
+	MAINTAINER("Steven taffs <steventaffs@yahoo.com>")
+	INITIRQ(actelm7_init_irq)
+	.timer	= &actelm7_timer,
+MACHINE_END
diff -Naur linux-2.6.11.8/arch/arm/mach-actelm7/head.S linux-2.6.x/arch/arm/mach-actelm7/head.S
--- linux-2.6.11.8/arch/arm/mach-actelm7/head.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/arch/arm/mach-actelm7/head.S	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,110 @@
+/*
+ *  linux/arch/arm/mach-actelm7/head.S
+ *
+ *  uClinux kernel startup code for actelm7
+ *  which has no proper bootloader for linux startup
+ *  because of XIP.
+ */
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/assembler.h>
+#include <asm/mach-types.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/hardware.h>
+/*
+ * Kernel startup entry point.
+ */
+	__INIT
+	.type	stext, #function			/*type stext is a function symbol*/
+ENTRY(stext)						/*tell the compiler that stext section is function */
+
+	mov	r12, r0						
+	mov	r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC	/* make sure svc mode */
+	msr	cpsr_c, r0				/* and all irqs disabled */ 
+
+/* Do basic initialization */
+
+	adr	r3, __LC0_init_data
+	ldmia	r3!, {r4, r5, r6, r7}
+
+    	cmp	r4, r5					@ Copy data segment if needed
+1:	cmpne	r5, r6
+	ldrne	fp, [r4], #4
+	strne	fp, [r5], #4
+	bne	1b
+
+	mov	fp, #0					@ Clear BSS (and zero fp)
+1:	cmp	r6, r7
+	strcc	fp, [r6],#4
+	bcc	1b
+
+  /*  Pretend we know what our processor code is (for arm_id)   */
+
+	ldmia	r3, {r6, r9, sp}
+	ldr	r2, ACTELM7_PROCESSOR_TYPE
+
+	str     r2, [r6]				/* store processor_type in processor_id address */
+	ldr     r2, ACTELM7_MACH_TYPE				
+	str     r2, [r9]				/* store MACH_TYPE in __machine_arch_type address */
+
+        mov fp, #0					/*clear frame reg (r11 it looks like)*/
+	
+	
+/*	ldr	r4, UART0_LCR	
+	mov	r5, #0x83
+	str	r5,[r4]
+		
+	ldr	r4, UART0_DLR
+	mov	r5, #0x09
+	str	r5,[r4]
+	
+	ldr	r4, UART0_DMR
+	mov	r5, #0x00
+	str	r5,[r4]	
+
+	ldr	r4, UART0_LCR
+	mov	r5, #0x03
+	str	r5,[r4]
+	
+	ldr	r4, UART0_REC
+	mov	r5, #0x31
+	str	r5,[r4]			*/
+	
+	
+  	b	start_kernel				/*jump to start of kernel */
+        
+
+.type	__LC0_init_data, %object
+__LC0_init_data:
+	.long	__data_loc		@ r4
+	.long	__data_start		@ r5
+	.long	__bss_start		@ r6
+	.long	_end			@ r7
+	.long	processor_id		@ r4
+	.long   __machine_arch_type	@ r5
+	.long	init_thread_union+8192	@ sp
+
+	.align	8
+	
+ACTELM7_PROCESSOR_TYPE:
+	.long	0x22000000
+ACTELM7_MACH_TYPE:
+	.long	MACH_TYPE_ACTELM7
+
+/*UART0_DLR:
+	.long  0x22000000
+UART0_DMR:
+	.long  0x22000004
+UART0_LCR:
+	.long  0x2200000C
+UART0_REC:
+	.long  0x22000000 */
+
+#include "../kernel/head-common.S"
+
+
+
diff -Naur linux-2.6.11.8/arch/arm/mach-actelm7/irq.c linux-2.6.x/arch/arm/mach-actelm7/irq.c
--- linux-2.6.11.8/arch/arm/mach-actelm7/irq.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/arch/arm/mach-actelm7/irq.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,122 @@
+/*
+ *  linux/arch/arm/mach-actelm7/irq.c
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+void __inline__ actelm7_mask_irq(unsigned int irq)
+{
+	IRQEnableClear = 1 << irq;
+}
+
+void __inline__ actelm7_unmask_irq(unsigned int irq)
+{
+	IRQEnable |= 1 << irq;
+}
+
+/* Clear pending bit */
+void __inline__ actelm7_clear_pb(unsigned int irq)
+{
+	/* we dont have external interupts at the moment*/
+	return;
+}
+
+void __inline__ actelm7_mask_ack_irq(unsigned int irq)
+{
+
+	actelm7_clear_pb(irq);
+	actelm7_mask_irq(irq);
+}
+
+
+/* YOU CAN CHANGE THIS ROUTINE FOR SPEED UP */
+__inline__ unsigned int fixup_irq (int irq )
+{
+	actelm7_clear_pb(irq);
+	return(irq);
+}
+
+static struct irqchip actelm7_chip = {
+	//set the pointers so ack, mask & unmask functions can be used
+	.ack	= actelm7_mask_ack_irq,
+	.mask	= actelm7_mask_irq,
+	.unmask = actelm7_unmask_irq,
+};
+
+#ifdef CONFIG_PM
+static unsigned long ic_irq_enable;
+
+static int irq_suspend(struct sys_device *dev, u32 state)
+{
+	return 0;
+}
+
+static int irq_resume(struct sys_device *dev)
+{
+	/* disable all irq sources */
+	return 0;
+}
+#else
+#define irq_suspend NULL
+#define irq_resume NULL
+#endif
+
+static struct sysdev_class irq_class = {
+	set_kset_name("irq"),
+	.suspend	= irq_suspend,
+	.resume		= irq_resume,
+};
+
+static struct sys_device irq_device = {
+	.id	= 0,
+	.cls	= &irq_class,
+};
+
+static int __init irq_init_sysfs(void)
+{
+	int ret = sysdev_class_register(&irq_class);
+	if (ret == 0)
+		ret = sysdev_register(&irq_device);
+	return ret;
+}
+
+device_initcall(irq_init_sysfs);
+
+void __init actelm7_init_irq(void)
+{
+        int irq;
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		//register each irq in turn with the kernel
+		set_irq_chip(irq, &actelm7_chip);
+		//get a handle for each irq
+		set_irq_handler(irq, do_level_IRQ);
+		
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* mask and disable all further interrupts */
+	IRQEnableClear = 0xFF;
+}
+
diff -Naur linux-2.6.11.8/arch/arm/mach-actelm7/Kconfig linux-2.6.x/arch/arm/mach-actelm7/Kconfig
--- linux-2.6.11.8/arch/arm/mach-actelm7/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/arch/arm/mach-actelm7/Kconfig	2009-09-12 17:40:58.000000000 +0100
@@ -0,0 +1,42 @@
+#       linux/arch/arm/mach-actelm7/Kconfig	
+#
+
+
+menu "Actel M7 Options"
+	depends on ARCH_ACTELM7
+
+config ARCH_SUPPORTS_BIG_ENDIAN
+    bool "Default Big Endian mode"
+    default n
+	help
+	Actel M7 core supports LITTLE-ENDIAN only,
+	both for CPU core and the external memory access.
+
+config ActelM7_Fosc
+    int	"Oscillator Frequency"
+    default 20000000
+    help
+	Oscillator frequency. The default is 20MHz. 
+	Change it according to your board.
+	
+config ARM_CLK
+	int 'Arm Core Clock'
+	default 20000000
+	help
+	CPU core clock frequency. The default is 20MHz.
+	Change it according to your application needs.
+
+config SKIP_DUMP_CPU_INFO
+	bool
+	default	y 
+	help
+	Actel M7 (ARM7TDMI) core has no cache and does not support cache size
+	recognition instructions which uses MMU features.
+
+config REMAP_VECTORS_TO_RAM
+	bool "Remap Vectors to ram"
+	default y
+	help
+	Actel M7 suppports ROM and RAM remap function. 
+
+endmenu
diff -Naur linux-2.6.11.8/arch/arm/mach-actelm7/Makefile linux-2.6.x/arch/arm/mach-actelm7/Makefile
--- linux-2.6.11.8/arch/arm/mach-actelm7/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/arch/arm/mach-actelm7/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y		+= arch.o irq.o time.o
diff -Naur linux-2.6.11.8/arch/arm/mach-actelm7/time.c linux-2.6.x/arch/arm/mach-actelm7/time.c
--- linux-2.6.11.8/arch/arm/mach-actelm7/time.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/arch/arm/mach-actelm7/time.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,80 @@
+/*
+ *  linux/arch/arm/mach-actelm7/time.c
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/system.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach/time.h>
+#include <asm/arch/time.h>
+
+extern void	actelm7_unmask_irq(unsigned int);
+
+unsigned long actelm7_gettimeoffset (void)
+{
+    return ((INIT_VALUE - T0_VALUE) / CLOCKS_PER_USEC);
+}
+
+static irqreturn_t
+actelm7_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+    if (!(T0_MIS & 0x01)) return IRQ_NONE;
+
+    timer_tick(regs);
+
+    T0_INT_CLR = 0x01;	/* reset interrupt */
+    return IRQ_HANDLED;
+}
+
+static struct irqaction actelm7_timer_irq = {
+        .name           = "actelm7 Timer Tick",
+        .flags          = SA_INTERRUPT,
+        .handler        = actelm7_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+
+void __init  actelm7_time_init (void)
+{
+	
+	// disable timer 0 
+	T0_TCR = 0x00;
+	
+	/* initialize the timer period to interrupt every 10ms*/
+	T0_TLR = INIT_VALUE;
+
+	//set the prescale to its lowest value which is divide by 2
+	T0_PR = PRESCALE_COUNTER_INIT_VALUE;
+
+	/*
+	 * @todo do those really need to be function pointers ?
+	 */
+	actelm7_timer_irq.handler = actelm7_timer_interrupt;
+
+	/* set up the interrupt vevtor for timer 0 match */
+	setup_irq(ACTELM7_INTERRUPT_TIMER0, &actelm7_timer_irq);
+	
+	/* enable the timer IRQ */
+	actelm7_unmask_irq(ACTELM7_INTERRUPT_TIMER0);
+
+	/* let timer 0 run... */
+	T0_INT_CLR = 0x01;    /* reset timer0 interrupts*/
+	T0_TCR = 0x03;	      /* enable timer counter and timer interrupt */
+}
+
+struct sys_timer actelm7_timer = {
+	.init		= actelm7_time_init,
+	.offset		= actelm7_gettimeoffset,
+};
diff -Naur linux-2.6.11.8/arch/arm/Makefile linux-2.6.x/arch/arm/Makefile
--- linux-2.6.11.8/arch/arm/Makefile	2009-09-06 22:49:56.000000000 +0100
+++ linux-2.6.x/arch/arm/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -1,278 +1,281 @@
-#
-# arch/arm/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1995-2001 by Russell King
-# Copyright (C) 2004 by Hyok S. Choi (for uClinux/ARM 2.6)
-
-LDFLAGS_vmlinux	:=-p --no-undefined -X
-CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
-OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
-GZFLAGS		:=-9
-#CFLAGS		+=-pipe
-ifeq ($(CONFIG_MMU),)
-CFLAGS		+=-fno-builtin -D__linux__
-endif
-
-# Do not use arch/arm/defconfig - it's always outdated.
-# Select a platform tht is kept up-to-date
-KBUILD_DEFCONFIG := versatile_defconfig
-
-# defines filename extension for mmu type, if any.
-ifeq ($(CONFIG_MMU),)
-MMUEXT		:= -nommu
-endif
-
-ifeq ($(CONFIG_FRAME_POINTER),y)
-CFLAGS		+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
-endif
-
-ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
-CFLAGS		+= -mbig-endian
-AS		+= -EB
-LD		+= -EB
-AFLAGS		+= -mbig-endian
-else
-CFLAGS		+= -mlittle-endian
-AS		+= -EL
-LD		+= -EL
-AFLAGS		+= -mlittle-endian
-endif
-
-comma = ,
-
-# This selects which instruction set is used.
-# Note that GCC does not numerically define an architecture version
-# macro, but instead defines a whole series of macros which makes
-# testing for a specific architecture or later rather impossible.
-arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
-arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
-arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
-arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
-
-# This selects how we optimise for the processor.
-tune-$(CONFIG_CPU_ARM7V3)	:=-mtune=arm610
-tune-$(CONFIG_CPU_ARM610)	:=-mtune=arm610
-tune-$(CONFIG_CPU_ARM710)	:=-mtune=arm710
-tune-$(CONFIG_CPU_ARM7TDMI)	:=-mtune=arm7tdmi
-tune-$(CONFIG_CPU_S3C4510B)	:=-mtune=arm7tdmi
-tune-$(CONFIG_CPU_ARM720T)	:=-mtune=arm7tdmi
-tune-$(CONFIG_CPU_ARM740T)	:=-mtune=arm7tdmi
-tune-$(CONFIG_CPU_ARM9TDMI)	:=-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM920T)	:=-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM922T)	:=-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM925T)	:=-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM940T)	:=-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM946T)	:=-mtune=arm9tdmi
-tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
-tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
-tune-$(CONFIG_CPU_XSCALE)	:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
-tune-$(CONFIG_CPU_V6)		:=-mtune=strongarm
-
-# Need -Uarm for gcc < 3.x
-CFLAGS_ABI	:=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)
-CFLAGS		+=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-AFLAGS		+=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
-
-CHECKFLAGS	+= -D__arm__
-
-#Default value
-head-y		:= arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
-ifeq ($(CONFIG_MMU),y)
-textaddr-y	:= 0xC0008000
-else
-textaddr-y	:= 0x00008000
-endif
-
- machine-$(CONFIG_ARCH_RPC)	   := rpc
- machine-$(CONFIG_ARCH_EBSA110)	   := ebsa110
- machine-$(CONFIG_ARCH_CLPS7500)   := clps7500
-  incdir-$(CONFIG_ARCH_CLPS7500)   := cl7500
- machine-$(CONFIG_FOOTBRIDGE)	   := footbridge
-  incdir-$(CONFIG_FOOTBRIDGE)	   := ebsa285
-textaddr-$(CONFIG_ARCH_CO285)	   := 0x60008000
- machine-$(CONFIG_ARCH_CO285)	   := footbridge
-  incdir-$(CONFIG_ARCH_CO285)	   := ebsa285
- machine-$(CONFIG_ARCH_SHARK)	   := shark
- machine-$(CONFIG_ARCH_SA1100)	   := sa1100
-ifeq ($(CONFIG_ARCH_SA1100),y)
-# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
-textaddr-$(CONFIG_SA1111)	   := 0xc0208000
-endif
- machine-$(CONFIG_ARCH_PXA)	   := pxa
- machine-$(CONFIG_ARCH_L7200)	   := l7200
- machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
- machine-$(CONFIG_ARCH_CAMELOT)	   := epxa10db
-textaddr-$(CONFIG_ARCH_CLPS711X)   := 0xc0028000
- machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
-textaddr-$(CONFIG_ARCH_FORTUNET)   := 0xc0008000
- machine-$(CONFIG_ARCH_IOP3XX)	   := iop3xx
- machine-$(CONFIG_ARCH_IXP4XX)	   := ixp4xx
- machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
- machine-$(CONFIG_ARCH_OMAP)	   := omap
- machine-$(CONFIG_ARCH_S3C2410)	   := s3c2410
- machine-$(CONFIG_ARCH_LH7A40X)	   := lh7a40x
- machine-$(CONFIG_ARCH_VERSATILE)  := versatile
- machine-$(CONFIG_ARCH_IMX)	   := imx
- machine-$(CONFIG_ARCH_H720X)	   := h720x
- machine-$(CONFIG_ARCH_ATMEL)	   := atmel
-textaddr-$(CONFIG_ARCH_ATMEL)	   := 0x01000000
- machine-$(CONFIG_ARCH_ESPD_4510B) := espd_4510b
-textaddr-$(CONFIG_ARCH_ESPD_4510B) := 0x00008000
- machine-$(CONFIG_ARCH_S3C3410)	   := s3c3410
-textaddr-$(CONFIG_ARCH_S3C3410)	   := 0x01020000
- machine-$(CONFIG_ARCH_S3C44B0)	   := s3c44b0x
-textaddr-$(CONFIG_ARCH_S3C44B0)	   := 0x0c008000
- machine-$(CONFIG_ARCH_S5C7375)	   := s5c7375
-textaddr-$(CONFIG_ARCH_S5C7375)	   := 0x00008000
- machine-$(CONFIG_ARCH_S3C24A0)	   := s3c24a0
-ifeq ($(CONFIG_MMU),)
-textaddr-$(CONFIG_ARCH_S3C24A0)	   := 0x10008000
-endif
-  incdir-$(CONFIG_ARCH_P2001)	   := p2001
- machine-$(CONFIG_ARCH_P2001)	   := p2001
-textaddr-$(CONFIG_ARCH_P2001)	   := 0x40100000
-
-
-ifeq ($(CONFIG_ARCH_EBSA110),y)
-# This is what happens if you forget the IOCS16 line.
-# PCMCIA cards stop working.
-CFLAGS_3c589_cs.o :=-DISA_SIXTEEN_BIT_PERIPHERAL
-export CFLAGS_3c589_cs.o
-endif
-
-TEXTADDR := $(textaddr-y)
-ifeq ($(CONFIG_XIP_KERNEL),y)
-  DATAADDR := $(TEXTADDR)
-  xipaddr-$(CONFIG_ARCH_CO285) := 0x5f000000
-  xipaddr-y ?= 0xbf000000
-  # Replace phys addr with virt addr while keeping offset from base.
-  TEXTADDR := $(shell echo $(CONFIG_XIP_PHYS_ADDR) $(xipaddr-y) | \
-                      awk --non-decimal-data '/[:xdigit:]/ \
-                          { printf("0x%x\n", and($$1, 0x000fffff) + $$2) }' )
-endif
-
-ifeq ($(incdir-y),)
-incdir-y := $(machine-y)
-endif
-INCDIR   := arch-$(incdir-y)
-ifneq ($(machine-y),)
-MACHINE  := arch/arm/mach-$(machine-y)/
-else
-MACHINE  :=
-endif
-
-# set HEAD as default (kernel/head.o)
-HEAD		:= head$(MMUEXT).o
-# Check if an overriding head.S exist for non-paged kernel
-ifeq ($(CONFIG_MMU),)
-ifeq ($(MACHINE)head.S, $(wildcard $(MACHINE)head.S))
-head-y		:= $(MACHINE)head.o  arch/arm/kernel/init_task.o
-HEAD		:= ../mach-$(machine-y)/head.o
-endif
-endif
-  
-export	MACHINE HEAD MMUEXT TEXTADDR DATAADDR GZFLAGS
-
-# Do we have FASTFPE?
-FASTFPE		:=arch/arm/fastfpe
-ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
-FASTFPE_OBJ	:=$(FASTFPE)/
-endif
-
-# If we have a machine-specific directory, then include it in the build.
-core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
-core-y				+= $(MACHINE)
-core-$(CONFIG_FPE_NWFPE)	+= arch/arm/nwfpe/
-core-$(CONFIG_FPE_FASTFPE)	+= $(FASTFPE_OBJ)
-core-$(CONFIG_VFP)		+= arch/arm/vfp/
-
-drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
-drivers-$(CONFIG_ARCH_CLPS7500)	+= drivers/acorn/char/
-drivers-$(CONFIG_ARCH_L7200)	+= drivers/acorn/char/
-
-libs-y				+= arch/arm/lib/
-
-# Default target when executing plain make
-ifeq ($(CONFIG_MMU),y)
-  ifeq ($(CONFIG_XIP_KERNEL),y)
-  all: xipImage
-  else
-  all: zImage
-  endif
-else
-  all: uCImage
-endif
-
-boot := arch/arm/boot
-
-#	Update machine arch and proc symlinks if something which affects
-#	them changed.  We use .arch to indicate when they were updated
-#	last, otherwise make uses the target directory mtime.
-
-include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/MARKER
-	@echo '  SYMLINK include/asm-arm/arch -> include/asm-arm/$(INCDIR)'
-ifneq ($(KBUILD_SRC),)
-	$(Q)mkdir -p include/asm-arm
-	$(Q)ln -fsn $(srctree)/include/asm-arm/$(INCDIR) include/asm-arm/arch
-else
-	$(Q)ln -fsn $(INCDIR) include/asm-arm/arch
-endif
-	@touch $@
-
-prepare: maketools include/asm-arm/.arch
-
-.PHONY: maketools FORCE
-maketools: include/asm-arm/constants.h include/linux/version.h FORCE
-	$(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
-
-# Convert bzImage to zImage
-bzImage: zImage
-
-zImage Image xipImage bootpImage uImage: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
-
-uCImage: vmlinux linux.bin
-
-linux.bin: vmlinux FORCE
-	@$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux $@
-	@echo '  Kernel: $@ is ready'
-
-zinstall install: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) $@
-
-CLEAN_FILES += include/asm-arm/constants.h* include/asm-arm/mach-types.h \
-	       include/asm-arm/arch include/asm-arm/.arch \
-	       linux.bin linux arch/arm/kernel/entry-macro.S
-
-# We use MRPROPER_FILES and CLEAN_FILES now
-archclean:
-	$(Q)$(MAKE) $(clean)=$(boot)
-
-# My testing targets (bypasses dependencies)
-bp:;	$(Q)$(MAKE) $(build)=$(boot) $(boot)/bootpImage
-i zi:;	$(Q)$(MAKE) $(build)=$(boot) $@
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-				   include/asm-arm/.arch
-
-include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
-	$(call filechk,gen-asm-offsets)
-
-define archhelp
-  echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
-  echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
-  echo  '  uCImage	 - Uncompressed kernel and the stripped binary (linux.bin)'
-  echo  '* xipImage      - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)'
-  echo  '  bootpImage    - Combined zImage and initial RAM disk' 
-  echo  '                  (supply initrd image via make variable INITRD=<path>)'
-  echo  '  install       - Install uncompressed kernel'
-  echo  '  zinstall      - Install compressed kernel'
-  echo  '                  Install using (your) ~/bin/installkernel or'
-  echo  '                  (distribution) /sbin/installkernel or'
-  echo  '                  install to $$(INSTALL_PATH) and run lilo'
-endef
+#
+# arch/arm/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995-2001 by Russell King
+# Copyright (C) 2004 by Hyok S. Choi (for uClinux/ARM 2.6)
+
+LDFLAGS_vmlinux	:=-p --no-undefined -X
+CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
+OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
+GZFLAGS		:=-9
+#CFLAGS		+=-pipe
+ifeq ($(CONFIG_MMU),)
+CFLAGS		+=-fno-builtin -D__linux__
+endif
+
+# Do not use arch/arm/defconfig - it's always outdated.
+# Select a platform tht is kept up-to-date
+KBUILD_DEFCONFIG := versatile_defconfig
+
+# defines filename extension for mmu type, if any.
+ifeq ($(CONFIG_MMU),)
+MMUEXT		:= -nommu
+endif
+
+ifeq ($(CONFIG_FRAME_POINTER),y)
+CFLAGS		+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
+endif
+
+ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+CFLAGS		+= -mbig-endian
+AS		+= -EB
+LD		+= -EB
+AFLAGS		+= -mbig-endian
+else
+CFLAGS		+= -mlittle-endian
+AS		+= -EL
+LD		+= -EL
+AFLAGS		+= -mlittle-endian
+endif
+
+comma = ,
+
+# This selects which instruction set is used.
+# Note that GCC does not numerically define an architecture version
+# macro, but instead defines a whole series of macros which makes
+# testing for a specific architecture or later rather impossible.
+arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
+arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
+arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
+arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
+
+# This selects how we optimise for the processor.
+tune-$(CONFIG_CPU_ARM7V3)	:=-mtune=arm610
+tune-$(CONFIG_CPU_ARM610)	:=-mtune=arm610
+tune-$(CONFIG_CPU_ARM710)	:=-mtune=arm710
+tune-$(CONFIG_CPU_ARM7TDMI)	:=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_S3C4510B)	:=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ACTELM7)	:=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM720T)	:=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM740T)	:=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM9TDMI)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM920T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM922T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM925T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM940T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM946T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
+tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
+tune-$(CONFIG_CPU_XSCALE)	:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
+tune-$(CONFIG_CPU_V6)		:=-mtune=strongarm
+
+# Need -Uarm for gcc < 3.x
+CFLAGS_ABI	:=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)
+CFLAGS		+=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
+AFLAGS		+=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
+
+CHECKFLAGS	+= -D__arm__
+
+#Default value
+head-y		:= arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
+ifeq ($(CONFIG_MMU),y)
+textaddr-y	:= 0xC0008000
+else
+textaddr-y	:= 0x00008000
+endif
+
+ machine-$(CONFIG_ARCH_RPC)	   := rpc
+ machine-$(CONFIG_ARCH_EBSA110)	   := ebsa110
+ machine-$(CONFIG_ARCH_CLPS7500)   := clps7500
+  incdir-$(CONFIG_ARCH_CLPS7500)   := cl7500
+ machine-$(CONFIG_FOOTBRIDGE)	   := footbridge
+  incdir-$(CONFIG_FOOTBRIDGE)	   := ebsa285
+textaddr-$(CONFIG_ARCH_CO285)	   := 0x60008000
+ machine-$(CONFIG_ARCH_CO285)	   := footbridge
+  incdir-$(CONFIG_ARCH_CO285)	   := ebsa285
+ machine-$(CONFIG_ARCH_SHARK)	   := shark
+ machine-$(CONFIG_ARCH_SA1100)	   := sa1100
+ifeq ($(CONFIG_ARCH_SA1100),y)
+# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
+textaddr-$(CONFIG_SA1111)	   := 0xc0208000
+endif
+ machine-$(CONFIG_ARCH_PXA)	   := pxa
+ machine-$(CONFIG_ARCH_L7200)	   := l7200
+ machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
+ machine-$(CONFIG_ARCH_CAMELOT)	   := epxa10db
+textaddr-$(CONFIG_ARCH_CLPS711X)   := 0xc0028000
+ machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
+textaddr-$(CONFIG_ARCH_FORTUNET)   := 0xc0008000
+ machine-$(CONFIG_ARCH_IOP3XX)	   := iop3xx
+ machine-$(CONFIG_ARCH_IXP4XX)	   := ixp4xx
+ machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
+ machine-$(CONFIG_ARCH_OMAP)	   := omap
+ machine-$(CONFIG_ARCH_S3C2410)	   := s3c2410
+ machine-$(CONFIG_ARCH_LH7A40X)	   := lh7a40x
+ machine-$(CONFIG_ARCH_VERSATILE)  := versatile
+ machine-$(CONFIG_ARCH_IMX)	   := imx
+ machine-$(CONFIG_ARCH_H720X)	   := h720x
+ machine-$(CONFIG_ARCH_ATMEL)	   := atmel
+textaddr-$(CONFIG_ARCH_ATMEL)	   := 0x01000000
+ machine-$(CONFIG_ARCH_ESPD_4510B) := espd_4510b
+textaddr-$(CONFIG_ARCH_ESPD_4510B) := 0x00008000
+ machine-$(CONFIG_ARCH_ACTELM7)	   := actelm7
+textaddr-$(CONFIG_ARCH_ACTELM7)	   := 0x10008000
+ machine-$(CONFIG_ARCH_S3C3410)	   := s3c3410
+textaddr-$(CONFIG_ARCH_S3C3410)	   := 0x01020000
+ machine-$(CONFIG_ARCH_S3C44B0)	   := s3c44b0x
+textaddr-$(CONFIG_ARCH_S3C44B0)	   := 0x0c008000
+ machine-$(CONFIG_ARCH_S5C7375)	   := s5c7375
+textaddr-$(CONFIG_ARCH_S5C7375)	   := 0x00008000
+ machine-$(CONFIG_ARCH_S3C24A0)	   := s3c24a0
+ifeq ($(CONFIG_MMU),)
+textaddr-$(CONFIG_ARCH_S3C24A0)	   := 0x10008000
+endif
+  incdir-$(CONFIG_ARCH_P2001)	   := p2001
+ machine-$(CONFIG_ARCH_P2001)	   := p2001
+textaddr-$(CONFIG_ARCH_P2001)	   := 0x40100000
+
+
+ifeq ($(CONFIG_ARCH_EBSA110),y)
+# This is what happens if you forget the IOCS16 line.
+# PCMCIA cards stop working.
+CFLAGS_3c589_cs.o :=-DISA_SIXTEEN_BIT_PERIPHERAL
+export CFLAGS_3c589_cs.o
+endif
+
+TEXTADDR := $(textaddr-y)
+ifeq ($(CONFIG_XIP_KERNEL),y)
+  DATAADDR := $(TEXTADDR)
+  xipaddr-$(CONFIG_ARCH_CO285) := 0x5f000000
+  xipaddr-y ?= 0x00080000
+  # Replace phys addr with virt addr while keeping offset from base.
+  TEXTADDR := $(shell echo $(CONFIG_XIP_PHYS_ADDR) $(xipaddr-y) | \
+                      awk --non-decimal-data '/[:xdigit:]/ \
+                          { printf("0x%x\n", and($$1, 0x000fffff) + $$2) }' )
+endif
+
+ifeq ($(incdir-y),)
+incdir-y := $(machine-y)
+endif
+INCDIR   := arch-$(incdir-y)
+ifneq ($(machine-y),)
+MACHINE  := arch/arm/mach-$(machine-y)/
+else
+MACHINE  :=
+endif
+
+# set HEAD as default (kernel/head.o)
+HEAD		:= head$(MMUEXT).o
+# Check if an overriding head.S exist for non-paged kernel
+ifeq ($(CONFIG_MMU),)
+ifeq ($(MACHINE)head.S, $(wildcard $(MACHINE)head.S))
+head-y		:= $(MACHINE)head.o  arch/arm/kernel/init_task.o
+HEAD		:= ../mach-$(machine-y)/head.o
+endif
+endif
+  
+export	MACHINE HEAD MMUEXT TEXTADDR DATAADDR GZFLAGS
+
+# Do we have FASTFPE?
+FASTFPE		:=arch/arm/fastfpe
+ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
+FASTFPE_OBJ	:=$(FASTFPE)/
+endif
+
+# If we have a machine-specific directory, then include it in the build.
+core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
+core-y				+= $(MACHINE)
+core-$(CONFIG_FPE_NWFPE)	+= arch/arm/nwfpe/
+core-$(CONFIG_FPE_FASTFPE)	+= $(FASTFPE_OBJ)
+core-$(CONFIG_VFP)		+= arch/arm/vfp/
+
+drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
+drivers-$(CONFIG_ARCH_CLPS7500)	+= drivers/acorn/char/
+drivers-$(CONFIG_ARCH_L7200)	+= drivers/acorn/char/
+
+libs-y				+= arch/arm/lib/
+
+# Default target when executing plain make
+ifeq ($(CONFIG_MMU),y)
+  ifeq ($(CONFIG_XIP_KERNEL),y)
+  all: xipImage
+  else
+  all: zImage
+  endif
+else
+  all: uCImage
+endif
+
+boot := arch/arm/boot
+
+#	Update machine arch and proc symlinks if something which affects
+#	them changed.  We use .arch to indicate when they were updated
+#	last, otherwise make uses the target directory mtime.
+
+include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/MARKER
+	@echo '  SYMLINK include/asm-arm/arch -> include/asm-arm/$(INCDIR)'
+ifneq ($(KBUILD_SRC),)
+	$(Q)mkdir -p include/asm-arm
+	$(Q)ln -fsn $(srctree)/include/asm-arm/$(INCDIR) include/asm-arm/arch
+else
+	$(Q)ln -fsn $(INCDIR) include/asm-arm/arch
+endif
+	@touch $@
+
+prepare: maketools include/asm-arm/.arch
+
+.PHONY: maketools FORCE
+maketools: include/asm-arm/constants.h include/linux/version.h FORCE
+	$(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
+
+# Convert bzImage to zImage
+bzImage: zImage
+
+zImage Image xipImage bootpImage uImage: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+uCImage: vmlinux linux.bin
+
+linux.bin: vmlinux FORCE
+	@$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux $@
+	@echo '  Kernel: $@ is ready'
+
+zinstall install: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $@
+
+CLEAN_FILES += include/asm-arm/constants.h* include/asm-arm/mach-types.h \
+	       include/asm-arm/arch include/asm-arm/.arch \
+	       linux.bin linux arch/arm/kernel/entry-macro.S
+
+# We use MRPROPER_FILES and CLEAN_FILES now
+archclean:
+	$(Q)$(MAKE) $(clean)=$(boot)
+
+# My testing targets (bypasses dependencies)
+bp:;	$(Q)$(MAKE) $(build)=$(boot) $(boot)/bootpImage
+i zi:;	$(Q)$(MAKE) $(build)=$(boot) $@
+
+arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
+				   include/asm-arm/.arch
+
+include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
+	$(call filechk,gen-asm-offsets)
+
+define archhelp
+  echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+  echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+  echo  '  uCImage	 - Uncompressed kernel and the stripped binary (linux.bin)'
+  echo  '* xipImage      - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)'
+  echo  '  bootpImage    - Combined zImage and initial RAM disk' 
+  echo  '                  (supply initrd image via make variable INITRD=<path>)'
+  echo  '  install       - Install uncompressed kernel'
+  echo  '  zinstall      - Install compressed kernel'
+  echo  '                  Install using (your) ~/bin/installkernel or'
+  echo  '                  (distribution) /sbin/installkernel or'
+  echo  '                  install to $$(INSTALL_PATH) and run lilo'
+endef
diff -Naur linux-2.6.11.8/arch/arm/mm/Kconfig linux-2.6.x/arch/arm/mm/Kconfig
--- linux-2.6.11.8/arch/arm/mm/Kconfig	2009-09-06 22:49:57.000000000 +0100
+++ linux-2.6.x/arch/arm/mm/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -72,6 +72,16 @@
 	  Say Y if you want support for the S3C4510B/ARM7TDMI processor.
 	  Otherwise, say N.
 
+# ActelM7
+config CPU_ACTELM7
+	bool "Support Actel M7/ARM7TDMI processor" if !ARCH_ACTELM7
+	depends on ARCH_ACTELM7
+	default y if ARCH_ACTELM7
+	select CPU_32v4
+	select CPU_HAS_NO_CP15
+	help
+	  A Actel M7 32-bit RISC microprocessor based on ARM7TDMI-S core.
+
 # ARM720T
 config CPU_ARM720T
 	bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR
diff -Naur linux-2.6.11.8/arch/arm/mm/Makefile linux-2.6.x/arch/arm/mm/Makefile
--- linux-2.6.11.8/arch/arm/mm/Makefile	2009-09-06 22:49:57.000000000 +0100
+++ linux-2.6.x/arch/arm/mm/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -42,6 +42,7 @@
 obj-$(CONFIG_CPU_TLB_V6)	+= tlb-v6.o
 
 obj-$(CONFIG_CPU_S3C4510B)	+= proc-s3c4510b.o
+obj-$(CONFIG_CPU_ACTELM7)	+= proc-actelm7.o
 obj-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o
 obj-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o
 obj-$(CONFIG_CPU_ARM7TDMI)	+= proc-arm6_7.o
diff -Naur linux-2.6.11.8/arch/arm/mm/proc-actelm7.S linux-2.6.x/arch/arm/mm/proc-actelm7.S
--- linux-2.6.11.8/arch/arm/mm/proc-actelm7.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/arch/arm/mm/proc-actelm7.S	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,288 @@
+/*
+ *  linux/arch/armnommu/mm/proc-actelm7.S
+ *
+ *  Copyright (C) 1997-2000 Russell King
+ *
+ *  Copyright (c) 2004	Cucy Systems (http://www.cucy.com)
+ *  Curt Brune <curt@cucy.com>
+ *  Modified for actelm7 cache
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/constants.h>
+#include <asm/pgtable.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+#include <asm/errno.h>
+#include <asm/hardware.h>
+	
+ENTRY(actelm7_flush_user_cache_all)
+ENTRY(actelm7_flush_kern_cache_all)
+ENTRY(actelm7_flush_user_cache_range)
+ENTRY(actelm7_coherent_kern_range)
+ENTRY(actelm7_coherent_user_range)
+ENTRY(actelm7_flush_kern_dcache_page)
+ENTRY(actelm7_dma_inv_range)
+ENTRY(actelm7_dma_flush_range)
+ENTRY(actelm7_dma_clean_range)
+	mov	pc, lr
+
+ENTRY(cpu_arm7_dcache_clean_area)
+	mov	pc, lr  
+
+/*
+ * Function: arm6_7_data_abort ()
+ *
+ * Params  : r2 = address of aborted instruction
+ *	   : sp = pointer to registers
+ *
+ * Purpose : obtain information about current aborted instruction
+ *
+ * Returns : r0 = address of abort
+ *	   : r1 = FSR
+ */
+
+ENTRY(cpu_arm7_data_abort)
+@FIXME
+	ldr     r8, [r2]                        @ read arm instruction
+	tst     r8, #1 << 20                    @ L = 1 -> write?
+	and	r7, r8, #15 << 24
+	orr	r1, r7, #1
+	orreq   r1, r1, #1 << 8                 @ yes.
+	add	pc, pc, r7, lsr #22		@ Now branch to the relevant processing routine
+	nop
+
+/* 0 */	b	.data_unknown
+/* 1 */	mov	pc, lr				@ swp
+/* 2 */	b	.data_unknown
+/* 3 */	b	.data_unknown
+/* 4 */	b	.data_arm_lateldrpostconst	@ ldr	rd, [rn], #m
+/* 5 */	b	.data_arm_lateldrpreconst	@ ldr	rd, [rn, #m]
+/* 6 */	b	.data_arm_lateldrpostreg	@ ldr	rd, [rn], rm
+/* 7 */	b	.data_arm_lateldrprereg		@ ldr	rd, [rn, rm]
+/* 8 */	b	.data_arm_ldmstm		@ ldm*a	rn, <rlist>
+/* 9 */	b	.data_arm_ldmstm		@ ldm*b	rn, <rlist>
+/* a */	b	.data_unknown
+/* b */	b	.data_unknown
+/* c */	mov	pc, lr				@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m
+/* d */	mov	pc, lr				@ ldc	rd, [rn, #m]
+/* e */	b	.data_unknown
+/* f */
+.data_unknown:	@ Part of jumptable
+	mov	r0, r2
+	mov	r1, r8
+	mov	r2, sp
+	bl	baddataabort
+	b	ret_from_exception
+
+ENTRY(cpu_arm6_data_abort)
+@FIXME
+	ldr	r8, [r2]			@ read arm instruction
+	tst	r8, #1 << 20			@ L = 1 -> write?
+	orreq	r1, r1, #1 << 8			@ yes.
+	and	r7, r8, #14 << 24
+	teq	r7, #8 << 24			@ was it ldm/stm
+	movne	pc, lr
+
+.data_arm_ldmstm:
+	tst	r8, #1 << 21			@ check writeback bit
+	moveq	pc, lr				@ no writeback -> no fixup
+	mov	r7, #0x11
+	orr	r7, r7, #0x1100
+	and	r6, r8, r7
+	and	r2, r8, r7, lsl #1
+	add	r6, r6, r2, lsr #1
+	and	r2, r8, r7, lsl #2
+	add	r6, r6, r2, lsr #2
+	and	r2, r8, r7, lsl #3
+	add	r6, r6, r2, lsr #3
+	add	r6, r6, r6, lsr #8
+	add	r6, r6, r6, lsr #4
+	and	r6, r6, #15			@ r6 = no. of registers to transfer.
+	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	tst	r8, #1 << 23			@ Check U bit
+	subne	r7, r7, r6, lsl #2		@ Undo increment
+	addeq	r7, r7, r6, lsl #2		@ Undo decrement
+	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
+	mov	pc, lr
+
+.data_arm_apply_r6_and_rn:
+	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	tst	r8, #1 << 23			@ Check U bit
+	subne	r7, r7, r6			@ Undo incrmenet
+	addeq	r7, r7, r6			@ Undo decrement
+	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
+	mov	pc, lr
+
+.data_arm_lateldrpreconst:
+	tst	r8, #1 << 21			@ check writeback bit
+	moveq	pc, lr				@ no writeback -> no fixup
+.data_arm_lateldrpostconst:
+	movs	r2, r8, lsl #20			@ Get offset
+	moveq	pc, lr				@ zero -> no fixup
+	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	tst	r8, #1 << 23			@ Check U bit
+	subne	r7, r7, r2, lsr #20		@ Undo increment
+	addeq	r7, r7, r2, lsr #20		@ Undo decrement
+	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
+	mov	pc, lr
+
+.data_arm_lateldrprereg:
+	tst	r8, #1 << 21			@ check writeback bit
+	moveq	pc, lr				@ no writeback -> no fixup
+.data_arm_lateldrpostreg:
+	and	r7, r8, #15			@ Extract 'm' from instruction
+	ldr	r6, [sp, r7, lsl #2]		@ Get register 'Rm'
+	mov	r5, r8, lsr #7			@ get shift count
+	ands	r5, r5, #31
+	and	r7, r8, #0x70			@ get shift type
+	orreq	r7, r7, #8			@ shift count = 0
+	add	pc, pc, r7
+	nop
+
+	mov	r6, r6, lsl r5			@ 0: LSL #!0
+	b	.data_arm_apply_r6_and_rn
+	b	.data_arm_apply_r6_and_rn	@ 1: LSL #0
+	nop
+	b	.data_unknown			@ 2: MUL?
+	nop
+	b	.data_unknown			@ 3: MUL?
+	nop
+	mov	r6, r6, lsr r5			@ 4: LSR #!0
+	b	.data_arm_apply_r6_and_rn
+	mov	r6, r6, lsr #32			@ 5: LSR #32
+	b	.data_arm_apply_r6_and_rn
+	b	.data_unknown			@ 6: MUL?
+	nop
+	b	.data_unknown			@ 7: MUL?
+	nop
+	mov	r6, r6, asr r5			@ 8: ASR #!0
+	b	.data_arm_apply_r6_and_rn
+	mov	r6, r6, asr #32			@ 9: ASR #32
+	b	.data_arm_apply_r6_and_rn
+	b	.data_unknown			@ A: MUL?
+	nop
+	b	.data_unknown			@ B: MUL?
+	nop
+	mov	r6, r6, ror r5			@ C: ROR #!0
+	b	.data_arm_apply_r6_and_rn
+	mov	r6, r6, rrx			@ D: RRX
+	b	.data_arm_apply_r6_and_rn
+	b	.data_unknown			@ E: MUL?
+	nop
+	b	.data_unknown			@ F: MUL?
+
+/*
+ * Function: arm6_7_proc_init (void)
+ *	   : arm6_7_proc_fin (void)
+ *
+ * Notes   : This processor does not require these
+ */
+ENTRY(cpu_arm7_proc_init)
+		mov	pc, lr
+
+ENTRY(cpu_arm7_proc_fin)
+		mov	r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+		msr	cpsr_c, r0
+		mov	pc, lr
+
+ENTRY(cpu_arm7_do_idle)
+		mov	r0, #-EINVAL
+		mov	pc, lr
+
+/*
+ * Function: arm6_7_switch_mm(unsigned long pgd_phys)
+ * Params  : pgd_phys	Physical address of page table
+ * Purpose : Perform a task switch, saving the old processes state, and restoring
+ *	     the new.
+ */
+ENTRY(cpu_arm7_switch_mm)
+		mov	pc, lr
+
+/*
+ * Function: _arm6_7_reset
+ * Params  : r0 = address to jump to
+ * Notes   : This sets up everything for a reset
+ */
+ENTRY(cpu_arm7_reset)
+		mov	pc, r0
+
+
+		__INIT
+
+		.type	__arm7_setup, #function
+__arm7_setup:
+		mov	pc, lr
+		.size	__arm7_setup, . - __arm7_setup
+	
+		__INITDATA
+
+		.type	actelm7_cache_fns, #object
+ENTRY(actelm7_cache_fns)
+		.long	actelm7_flush_kern_cache_all
+		.long	actelm7_flush_user_cache_all
+		.long	actelm7_flush_user_cache_range
+		.long	actelm7_coherent_kern_range
+		.long	actelm7_coherent_user_range
+		.long	actelm7_flush_kern_dcache_page
+		.long	actelm7_dma_inv_range
+		.long	actelm7_dma_clean_range
+		.long	actelm7_dma_flush_range
+		.size	actelm7_cache_fns, . - actelm7_cache_fns
+	
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+		.type	arm7_processor_functions, #object
+ENTRY(arm7_processor_functions)
+		.word	cpu_arm7_data_abort
+		.word	cpu_arm7_proc_init
+		.word	cpu_arm7_proc_fin
+		.word	cpu_arm7_reset
+		.word	cpu_arm7_do_idle
+		.word	cpu_arm7_dcache_clean_area
+		.word	cpu_arm7_switch_mm
+		.size	arm7_processor_functions, . - arm7_processor_functions
+
+		.section ".rodata"
+
+		.type	cpu_arch_name, #object
+cpu_arch_name:	.asciz	"armv4t"
+		.size	cpu_arch_name, . - cpu_arch_name
+
+		.type	cpu_elf_name, #object
+cpu_elf_name:	.asciz	"v4"
+		.size	cpu_elf_name, . - cpu_elf_name
+
+		.type	cpu_actelm7, #object
+cpu_actelm7_name:
+		.asciz	"Actel-M7"
+		.size	cpu_actelm7_name, . - cpu_actelm7_name
+
+		.align
+
+		.section ".proc.info", #alloc, #execinstr
+
+		.type	__actelm7_proc_info, #object
+__actelm7_proc_info:
+		.long	0x22000000
+		.long	0xffff0000
+		b	__arm7_setup
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_26BIT
+		.long	cpu_actelm7_name
+		.long	arm7_processor_functions
+		.long	actelm7_cache_fns
+		.size	__actelm7_proc_info, . - __actelm7_proc_info
+
diff -Naur linux-2.6.11.8/arch/arm/tools/mach-types linux-2.6.x/arch/arm/tools/mach-types
--- linux-2.6.11.8/arch/arm/tools/mach-types	2005-04-30 02:27:24.000000000 +0100
+++ linux-2.6.x/arch/arm/tools/mach-types	2009-09-06 22:42:40.000000000 +0100
@@ -667,3 +667,4 @@
 manga_ks8695		MACH_MANGA_KS8695	MANGA_KS8695		657
 ajax			MACH_AJAX		AJAX			658
 nec_mp900		MACH_NEC_MP900		NEC_MP900		659
+actelm7			MACH_ACTELM7		ACTELM7			715
diff -Naur linux-2.6.11.8/drivers/char/hello.c linux-2.6.x/drivers/char/hello.c
--- linux-2.6.11.8/drivers/char/hello.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/drivers/char/hello.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,33 @@
+/*****************************************************************************/
+/*
+ * Example module for external inclusion in the uClinux-dist
+ * davidm@snapgear.com
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+/*****************************************************************************/
+
+MODULE_LICENSE("GPL");
+
+static int __init
+mymodule_init(void)
+{
+	printk("My Module init\n");
+	return(0);
+}
+
+void mymodule_fini(void)
+{
+	printk("My Module fini\n");
+}
+
+/*****************************************************************************/
+
+module_init(mymodule_init);
+module_exit(mymodule_fini);
+
+/*****************************************************************************/
diff -Naur linux-2.6.11.8/drivers/char/Kconfig linux-2.6.x/drivers/char/Kconfig
--- linux-2.6.11.8/drivers/char/Kconfig	2005-04-30 02:23:15.000000000 +0100
+++ linux-2.6.x/drivers/char/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -990,6 +990,5 @@
 	help
 	  The mmtimer device allows direct userspace access to the
 	  Altix system timer.
-
 endmenu
 
diff -Naur linux-2.6.11.8/drivers/i2c/busses/i2c-actelm7.c linux-2.6.x/drivers/i2c/busses/i2c-actelm7.c
--- linux-2.6.11.8/drivers/i2c/busses/i2c-actelm7.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/drivers/i2c/busses/i2c-actelm7.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,451 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-actelm7.c i2c bus driver algorithms for Actel m7 board                */
+/* ------------------------------------------------------------------------- */
+/* Created by steven taffs steventaffs@yahoo.com code based on work by
+ * Peter Milne, D-TACQ Solutions Ltd
+ *
+ * With acknowledgements to i2c-algo-ibm_ocp.c by 
+ * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
+ *
+ * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
+ *
+ * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
+ *  
+ * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
+ *
+ * Initial release 0.01
+ *
+ * This driver contains the i2c algorithm and bus driver for the actelm7 board
+ * this release don't use interrupt it polls the on-board i2c unit
+ *
+ * TODO:
+ *
+ * Convert driver from a polling to an interrupt driven drivers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ */
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <asm/arch/hardware.h>
+
+#include "i2c-actelm7.h"
+
+//define prototypes
+static inline unsigned char i2c_cook_addr(struct i2c_msg *msg);
+uint8_t i2c_send_start_bit(void);
+uint8_t i2c_wait_event(void);
+static void m7_i2c_transaction_cleanup(struct i2c_algo_m7_data *m7_adap);
+static int m7_i2c_send_target_addr(struct i2c_algo_m7_data *m7_adap, struct i2c_msg* msg);
+static int m7_i2c_write_byte(struct i2c_algo_m7_data *m7_adap, char byte);
+static int m7_i2c_read_byte(struct i2c_algo_m7_data *m7_adap, char* byte);
+static int m7_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count);
+static int m7_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count);
+static int m7_i2c_unit_init(void);
+static u32 m7_i2c_func(struct i2c_adapter *adap);
+
+/* global unit counter */
+static int i2c_id = 0;
+
+static inline unsigned char 
+i2c_cook_addr(struct i2c_msg *msg) 
+{
+	unsigned char addr;
+
+	addr = (msg->addr << 1);
+
+	if (msg->flags & I2C_M_RD){
+		addr |= 1;
+		
+	}
+
+	/*
+	 * read or Write?
+	 */
+	if (msg->flags & I2C_M_REV_DIR_ADDR){
+		addr ^= 1;
+
+	}
+
+	return addr;   
+}
+
+uint8_t i2c_send_start_bit(void)
+{	
+	//send a start bit
+    I2C_CNTR |= M7_I2C_CR_SET_START;
+
+	//clear interrupt
+    I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    
+	if(i2c_wait_event() != 0){
+		printk("i2c timeout error when sending start bit.\n");
+		return -ETIMEDOUT;		//report error
+	} else {
+		 //clear start bit
+    	I2C_CNTR &= M7_I2C_CR_CLEAR_START;
+		return 0;	
+	}
+}
+
+uint8_t i2c_wait_event(void)
+{
+	int timeout;
+
+	timeout = TIMEOUT_VALUE;
+    //wait for interrupt flag
+  	while (timeout-- && ((I2C_CNTR & M7_I2C_CR_SET_SI) != 1)) 
+  	{
+		//add small 100us delay
+	}
+	
+	//check for errors
+	if(timeout == 0){
+			return -ETIMEDOUT; //report if we have one
+	} else {
+			return 0; 
+	} 
+}
+
+static void 
+m7_i2c_transaction_cleanup(struct i2c_algo_m7_data *m7_adap)
+{
+	
+	//make sure I2C unit is off
+  	I2C_CNTR = M7_I2C_CR_DISABLE_ENS1;  
+    //set units clock speed
+    I2C_CNTR |= M7_I2C_CR_PCLK_DIVIDE_160;  
+    //enable I2C unit
+    I2C_CNTR |= M7_I2C_CR_ENABLE_ENS1;
+}
+
+static int 
+m7_i2c_send_target_addr(struct i2c_algo_m7_data *m7_adap, 
+				struct i2c_msg* msg)
+{
+
+	//load device address and direction into data reg
+	I2C_DATA = i2c_cook_addr(msg);
+
+	//clear interrupt
+    I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    	
+    if(i2c_wait_event() != 0){
+		//set stop bit in control reg
+		I2C_CNTR |= M7_I2C_CR_STO;
+		//clear interrupt 
+    	I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    	//wait until stop bit is sent
+		i2c_wait_event();
+		printk("i2c timeout error sending target address.\n");
+		return -ETIMEDOUT;		//report error
+	}	
+    	
+	//check for ack
+	if(I2C_STATUS == M7_I2C_SR_SLA_TRANS_ACKED || I2C_STATUS == M7_I2C_SR_SLA_REC_ACKED){
+			return 0;	
+	} else {
+			//set stop bit in control reg
+			I2C_CNTR |= M7_I2C_CR_STO;
+			//clear interrupt 
+    		I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    		//wait until stop bit is sent
+			i2c_wait_event();
+			printk("i2c nack received when sending target address \n");
+			return -EREMOTEIO;	//report error
+	}
+}
+
+static int 
+m7_i2c_write_byte(struct i2c_algo_m7_data *m7_adap, char byte)
+{		
+	unsigned char i2c_status = 0x00;
+
+	I2C_DATA = byte;
+    	//clear interrupt
+    	I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    	
+    	if(i2c_wait_event() != 0){
+			//set stop bit in control reg
+			I2C_CNTR |= M7_I2C_CR_STO;
+			//clear interrupt 
+    		I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    		//wait until stop bit is sent
+			i2c_wait_event();
+			printk("i2c timeout error writing byte.\n");
+			return -ETIMEDOUT;	//report error
+		}		
+    	
+		//check for nack
+		if(I2C_STATUS != M7_I2C_SR_DATA_TRANS_ACKED){
+			i2c_status = I2C_STATUS;
+			//set stop bit in control reg
+			I2C_CNTR |= M7_I2C_CR_STO;
+			//clear interrupt 
+    		I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    		//wait until stop bit is sent
+			i2c_wait_event();
+			printk("i2c nack error writing byte status=%02x \n", i2c_status);
+			return -EREMOTEIO; //report error
+		}
+
+		return 0;
+
+}
+
+static int 
+m7_i2c_read_byte(struct i2c_algo_m7_data *m7_adap, char* byte)
+{
+		unsigned char i2c_status = 0x00;
+
+		//get the next byte and ack response
+    	I2C_CNTR |= M7_I2C_CR_SET_AA_BIT;
+    	//clear interrupt
+    	I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+
+		//wait for data to be sent
+    	if(i2c_wait_event() != 0){
+    		//set stop bit in control reg
+			I2C_CNTR |= M7_I2C_CR_STO;
+			//clear interrupt 
+    		I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    		//wait until stop bit is sent
+			i2c_wait_event();
+			printk("i2c timeout error reading byte. \n");
+			return -ETIMEDOUT;	//report error
+		}
+
+		//check for ack
+		if(I2C_STATUS == M7_I2C_SR_DATA_REC_ACKED){
+			//save data
+			*byte = I2C_DATA;
+		} else {
+			//set stop bit in control reg
+			I2C_CNTR |= M7_I2C_CR_STO;
+			//clear interrupt 
+    		I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    		//wait until stop bit is sent
+			i2c_wait_event();
+			printk("i2c nack error reading byte status=%02x \n", i2c_status);
+			return -EREMOTEIO;	//report error
+		}
+
+		return 0;
+}
+
+static int 
+m7_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)
+{
+	struct i2c_algo_m7_data *m7_adap = i2c_adap->algo_data;
+	int ii;
+	int rc = 0;
+
+	for (ii = 0; rc == 0 && ii < count; ++ii) 
+		rc = m7_i2c_write_byte(m7_adap, buf[ii]);
+	return rc;
+
+}
+
+static int 
+m7_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
+{
+	struct i2c_algo_m7_data *m7_adap = i2c_adap->algo_data;
+	int ii;
+	int rc = 0;
+
+	for (ii = 0; rc == 0 && ii < count; ++ii) {
+		rc = m7_i2c_read_byte(m7_adap, &buf[ii]);
+	}
+	return rc;
+}
+
+/*
+ * master_xfer() - main read/write entry
+ */
+static int 
+m7_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], 
+				int num)
+{
+	struct i2c_algo_m7_data *m7_adap = i2c_adap->algo_data;
+	struct i2c_msg* pmsg;
+	int im = 0;
+	int rc = 0;
+
+	for (im = 0; im < num; im++) {
+
+		pmsg = &msgs[im];
+
+		/*printk("i2c-actelm7.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n",
+		     pmsg->flags & I2C_M_RD ? "read" : "write",
+                     pmsg->len, pmsg->addr, im + 1, num);*/
+	
+		//first message to be transmitted so send first start bit
+		if(im == 0){
+			/* printk("i2c sending first start bit \n"); */
+			if(i2c_send_start_bit() != 0){
+				printk("i2c timeout error after sending first start bit\n");
+				return -ETIMEDOUT;
+			}
+		}
+
+		//after every start or repeated start the devices address needs to be sent
+		/* printk("i2c sending target address.\n"); */
+		rc = m7_i2c_send_target_addr(m7_adap, pmsg);
+		if (rc < 0) {
+			return rc;
+		}
+
+		//check for read
+		if ((pmsg->flags&I2C_M_RD)) {
+			/* printk("i2c reading byte.\n"); */
+			rc = m7_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
+			if (rc < 0) {
+				return rc;
+			}
+		} else {
+			//must be a write
+			/* printk("i2c writing byte.\n"); */
+			rc =  m7_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
+			if (rc < 0) {
+				return rc;
+			}
+		}
+
+		//do we need to send a stop bit ?	
+		if ((im + 1) == num) {
+			/* printk("sending stop bit\n"); */
+			//yes so set stop bit in control reg
+			I2C_CNTR |= M7_I2C_CR_STO;
+			//clear interrupt 
+    		I2C_CNTR &= M7_I2C_CR_CLEAR_SI;
+    	
+    		if(i2c_wait_event() != 0){
+				printk("i2c timeout error sending stop bit. \n");
+				return -ETIMEDOUT; 
+			}		//report error
+    	
+			//make sure line is idle
+			if(I2C_STATUS != M7_I2C_SR_IDLE_STATE){
+				printk("i2c error line not idle after sending stop bit\n");
+				return -EREMOTEIO; //report error
+			} else {
+				//clear interrupt 
+    			I2C_CNTR &= M7_I2C_CR_CLEAR_SI; 
+			}
+		}else {				//send repeated start bit
+			/* printk("sending repeated start bit\n"); */
+			if(i2c_send_start_bit() != 0){
+				printk("i2c timeout error after sending repeated start\n");
+				return -ETIMEDOUT;
+			}
+		}
+	}
+
+	/* printk("i2c transaction completed ok.\n"); */
+
+	//put i2c unit into its idle state
+	m7_i2c_transaction_cleanup(m7_adap);
+
+	return im;   
+}
+
+static struct i2c_algorithm m7_i2c_algo = {
+	.name			= "m7 I2C algorithm",
+	.id			= I2C_ALGO_EXP,			
+	.master_xfer		= m7_i2c_master_xfer,
+	.functionality		= m7_i2c_func,
+};
+
+static struct i2c_adapter m7_adapter = {
+	.owner		= THIS_MODULE,
+	.algo		= &m7_i2c_algo,
+	.name		= "m7 adapter",
+	.id		= I2C_HW_M7,
+};
+
+static int m7_i2c_unit_init(void)
+{
+	//init adapter data struct
+	int ret;
+
+	struct i2c_algo_m7_data *adapter_data;
+	adapter_data = kmalloc(sizeof(struct i2c_algo_m7_data), GFP_KERNEL);
+	if (!adapter_data) {
+		ret = -ENOMEM;
+		goto free_adapter;
+	}
+	
+	memset((void*)adapter_data, 0, sizeof(*adapter_data));
+	
+	/* set the adapter enumeration # */
+	adapter_data->id = i2c_id++;
+	
+	m7_adapter.algo_data = adapter_data;
+
+	//make sure I2C unit is off
+  	I2C_CNTR = M7_I2C_CR_DISABLE_ENS1; 
+  	//load units slave address
+  	I2C_ADDR0 = MY_SLAVE_ADDR;
+    //set units clock speed
+    I2C_CNTR |= M7_I2C_CR_PCLK_DIVIDE_160;  
+     //enable I2C unit
+    I2C_CNTR |= M7_I2C_CR_ENABLE_ENS1;
+
+	if(I2C_STATUS == M7_I2C_SR_IDLE_STATE)
+	{
+		printk("i2c-actelm7.o: detected and initialized i2c unit.\n");
+		return 0;
+	}
+	else
+	{
+		return -ENXIO;	
+	}
+	
+free_adapter:
+	kfree(adapter_data);
+
+	return ret;
+}
+
+static u32 
+m7_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static int __init i2c_m7_init(void)
+{
+	int rval;
+	rval = m7_i2c_unit_init();
+	if (!rval) {
+		i2c_add_adapter(&m7_adapter); 
+	}
+	return rval;
+	
+}
+
+static void __exit i2c_m7_exit(void)
+{
+	struct i2c_algo_m7_data *m7_adap = m7_adapter.algo_data;
+	kfree(m7_adap);
+	i2c_del_adapter(&m7_adapter);
+}
+
+module_init (i2c_m7_init);
+module_exit (i2c_m7_exit);
+
+MODULE_AUTHOR("steven taffs" steventaffs@yahoo.com);
+MODULE_DESCRIPTION("actelm7 i2c algorithm and adapter");
+MODULE_LICENSE("GPL");
diff -Naur linux-2.6.11.8/drivers/i2c/busses/i2c-actelm7.h linux-2.6.x/drivers/i2c/busses/i2c-actelm7.h
--- linux-2.6.11.8/drivers/i2c/busses/i2c-actelm7.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/drivers/i2c/busses/i2c-actelm7.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,95 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-actelm7.h algorithm driver definitions private to i2c-actelm7.c       */
+/* ------------------------------------------------------------------------- */
+/*  Created by steven taffs based on code by Peter Milne, D-TACQ Solutions Ltd
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, version 2.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
+/* ------------------------------------------------------------------------- */
+
+
+#ifndef I2C_ACTELM7_H
+#define I2C_ACTELM7_H 1
+
+/*
+ * actel m7 hardware bit definitions
+ */
+
+/* I2C control reg */
+
+
+#define M7_I2C_CR_PCLK_DIVIDE_256		0x00
+#define M7_I2C_CR_PCLK_DIVIDE_224		0x01
+#define M7_I2C_CR_PCLK_DIVIDE_192		0x02
+#define M7_I2C_CR_PCLK_DIVIDE_160		0x03
+#define M7_I2C_CR_PCLK_DIVIDE_960		0x80
+#define M7_I2C_CR_PCLK_DIVIDE_120		0x81
+#define M7_I2C_CR_PCLK_DIVIDE_60		0x82
+#define M7_I2C_CR_BCLK_DIVIDE_8			0x83
+#define M7_I2C_CR_CLEAR_SI				0xf7	/* Clear interrupts */
+#define M7_I2C_CR_SET_SI				0x08
+#define M7_I2C_CR_ENABLE_ENS1			0x40	/* 1=Unit Enable */
+#define M7_I2C_CR_DISABLE_ENS1			0x00
+#define M7_I2C_CR_NACK					0x00	/* 0=reply with NACK */
+#define M7_I2C_CR_ACK					0x04	/* 1=reply with ACK */
+#define M7_I2C_CR_STO					0x10	/* 1=send a STOP */
+#define M7_I2C_CR_SET_START				0x20	/* 1=initiate a START */
+#define M7_I2C_CR_CLEAR_START			0xDF
+#define M7_I2C_CR_SET_AA_BIT			0x04
+
+
+/* I2C status reg (master transmit mode) */
+
+#define M7_I2C_SR_SLA_TRANS_ACKED				0x18
+#define M7_I2C_SR_SLA_TRANS_NACKED				0x20
+#define M7_I2C_SR_DATA_TRANS_ACKED				0x28
+#define M7_I2C_SR_DATA_TRANS_NACKED				0x30
+#define M7_I2C_SR_ARBITRATION_LOST				0x38
+
+/* I2C status reg (master receive mode) */
+
+#define M7_I2C_SR_SLA_REC_ACKED					0x40
+#define M7_I2C_SR_SLA_REC_NACKED				0x48
+#define M7_I2C_SR_DATA_REC_ACKED				0x50
+#define M7_I2C_SR_DATA_REC_NACKED				0x58
+
+/* I2C status reg (Miscellaneous States) */
+
+#define M7_I2C_SR_START							0x08
+#define M7_I2C_SR_REP_START						0x10
+#define M7_I2C_SR_IDLE_STATE					0xF8
+#define M7_I2C_SR_BUS_ERROR						0x00
+
+/* I2C data reg */
+
+#define M7_I2C_DR_WRITE_BIT						0x00
+#define M7_I2C_DR_READ_BIT						0x01
+
+
+#define MY_SLAVE_ADDR			0x02	/* SWAG a suitable slave address */
+
+#define TIMEOUT_VALUE 0xFF
+
+
+#define	CR_OFFSET		0
+#define	SR_OFFSET		0x4
+#define	DBR_OFFSET		0x8
+#define	SAR_OFFSET		0xc
+
+#define I2C_HW_M7		0x00
+
+struct i2c_algo_m7_data {
+	int id;
+};
+
+#endif /* I2C_ACTELM7_H */
diff -Naur linux-2.6.11.8/drivers/i2c/busses/Kconfig linux-2.6.x/drivers/i2c/busses/Kconfig
--- linux-2.6.11.8/drivers/i2c/busses/Kconfig	2005-04-30 02:31:03.000000000 +0100
+++ linux-2.6.x/drivers/i2c/busses/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -5,6 +5,13 @@
 menu "I2C Hardware Bus support"
 	depends on I2C
 
+config I2C_ACTELM7
+	tristate "i2c Actelm7"
+	depends on I2C
+	help
+	  if you say yes to this option, support will be included for the
+	  actelm7 i2c core.
+
 config I2C_ALI1535
 	tristate "ALI 1535"
 	depends on I2C && PCI && EXPERIMENTAL
diff -Naur linux-2.6.11.8/drivers/i2c/busses/Makefile linux-2.6.x/drivers/i2c/busses/Makefile
--- linux-2.6.11.8/drivers/i2c/busses/Makefile	2005-04-30 02:33:23.000000000 +0100
+++ linux-2.6.x/drivers/i2c/busses/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -2,6 +2,7 @@
 # Makefile for the i2c bus drivers.
 #
 
+obj-$(CONFIG_I2C_ACTELM7)	+= i2c-actelm7.o
 obj-$(CONFIG_I2C_ALI1535)	+= i2c-ali1535.o
 obj-$(CONFIG_I2C_ALI1563)	+= i2c-ali1563.o
 obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
diff -Naur linux-2.6.11.8/drivers/i2c/chips/rtc8564.c linux-2.6.x/drivers/i2c/chips/rtc8564.c
--- linux-2.6.11.8/drivers/i2c/chips/rtc8564.c	2005-04-30 02:23:00.000000000 +0100
+++ linux-2.6.x/drivers/i2c/chips/rtc8564.c	2009-09-06 22:42:40.000000000 +0100
@@ -1,396 +1,547 @@
-/*
- *  linux/drivers/i2c/chips/rtc8564.c
- *
- *  Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- *	based on linux/drivers/acron/char/pcf8583.c
- *  Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Driver for system3's EPSON RTC 8564 chip
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/rtc.h>		/* get the user-level API */
-#include <linux/init.h>
-#include <linux/init.h>
-
-#include "rtc8564.h"
-
-#ifdef DEBUG
-# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
-#else
-# define _DBG(x, fmt, args...) do { } while(0);
-#endif
-
-#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \
-			"mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \
-			(rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \
-			(rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl);
-
-struct rtc8564_data {
-	struct i2c_client client;
-	u16 ctrl;
-};
-
-static inline u8 _rtc8564_ctrl1(struct i2c_client *client)
-{
-	struct rtc8564_data *data = i2c_get_clientdata(client);
-	return data->ctrl & 0xff;
-}
-static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
-{
-	struct rtc8564_data *data = i2c_get_clientdata(client);
-	return (data->ctrl & 0xff00) >> 8;
-}
-
-#define CTRL1(c) _rtc8564_ctrl1(c)
-#define CTRL2(c) _rtc8564_ctrl2(c)
-
-#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-
-static int debug;;
-module_param(debug, int, S_IRUGO | S_IWUSR);
-
-static struct i2c_driver rtc8564_driver;
-
-static unsigned short ignore[] = { I2C_CLIENT_END };
-static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
-
-static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_addr,
-	.normal_i2c_range	= ignore,
-	.probe			= ignore,
-	.probe_range		= ignore,
-	.ignore			= ignore,
-	.ignore_range		= ignore,
-	.force			= ignore,
-};
-
-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem);
-
-static int rtc8564_read(struct i2c_client *client, unsigned char adr,
-			unsigned char *buf, unsigned char len)
-{
-	int ret = -EIO;
-	unsigned char addr[1] = { adr };
-	struct i2c_msg msgs[2] = {
-		{client->addr, 0, 1, addr},
-		{client->addr, I2C_M_RD, len, buf}
-	};
-
-	_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
-
-	if (!buf || !client) {
-		ret = -EINVAL;
-		goto done;
-	}
-
-	ret = i2c_transfer(client->adapter, msgs, 2);
-	if (ret == 2) {
-		ret = 0;
-	}
-
-done:
-	return ret;
-}
-
-static int rtc8564_write(struct i2c_client *client, unsigned char adr,
-			 unsigned char *data, unsigned char len)
-{
-	int ret = 0;
-	unsigned char _data[16];
-	struct i2c_msg wr;
-	int i;
-
-	if (!client || !data || len > 15) {
-		ret = -EINVAL;
-		goto done;
-	}
-
-	_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len);
-
-	_data[0] = adr;
-	for (i = 0; i < len; i++) {
-		_data[i + 1] = data[i];
-		_DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]);
-	}
-
-	wr.addr = client->addr;
-	wr.flags = 0;
-	wr.len = len + 1;
-	wr.buf = _data;
-
-	ret = i2c_transfer(client->adapter, &wr, 1);
-	if (ret == 1) {
-		ret = 0;
-	}
-
-done:
-	return ret;
-}
-
-static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
-{
-	int ret;
-	struct i2c_client *new_client;
-	struct rtc8564_data *d;
-	unsigned char data[10];
-	unsigned char ad[1] = { 0 };
-	struct i2c_msg ctrl_wr[1] = {
-		{addr, 0, 2, data}
-	};
-	struct i2c_msg ctrl_rd[2] = {
-		{addr, 0, 1, ad},
-		{addr, I2C_M_RD, 2, data}
-	};
-
-	d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
-	if (!d) {
-		ret = -ENOMEM;
-		goto done;
-	}
-	memset(d, 0, sizeof(struct rtc8564_data));
-	new_client = &d->client;
-
-	strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
-	i2c_set_clientdata(new_client, d);
-	new_client->id = rtc8564_driver.id;
-	new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
-	new_client->addr = addr;
-	new_client->adapter = adap;
-	new_client->driver = &rtc8564_driver;
-
-	_DBG(1, "client=%p", new_client);
-	_DBG(1, "client.id=%d", new_client->id);
-
-	/* init ctrl1 reg */
-	data[0] = 0;
-	data[1] = 0;
-	ret = i2c_transfer(new_client->adapter, ctrl_wr, 1);
-	if (ret != 1) {
-		printk(KERN_INFO "rtc8564: cant init ctrl1\n");
-		ret = -ENODEV;
-		goto done;
-	}
-
-	/* read back ctrl1 and ctrl2 */
-	ret = i2c_transfer(new_client->adapter, ctrl_rd, 2);
-	if (ret != 2) {
-		printk(KERN_INFO "rtc8564: cant read ctrl\n");
-		ret = -ENODEV;
-		goto done;
-	}
-
-	d->ctrl = data[0] | (data[1] << 8);
-
-	_DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x",
-	     data[0], data[1]);
-
-	ret = i2c_attach_client(new_client);
-done:
-	if (ret) {
-		kfree(d);
-	}
-	return ret;
-}
-
-static int rtc8564_probe(struct i2c_adapter *adap)
-{
-	return i2c_probe(adap, &addr_data, rtc8564_attach);
-}
-
-static int rtc8564_detach(struct i2c_client *client)
-{
-	i2c_detach_client(client);
-	kfree(i2c_get_clientdata(client));
-	return 0;
-}
-
-static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
-{
-	int ret = -EIO;
-	unsigned char buf[15];
-
-	_DBG(1, "client=%p, dt=%p", client, dt);
-
-	if (!dt || !client)
-		return -EINVAL;
-
-	memset(buf, 0, sizeof(buf));
-
-	ret = rtc8564_read(client, 0, buf, 15);
-	if (ret)
-		return ret;
-
-	/* century stored in minute alarm reg */
-	dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]);
-	dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
-	dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f);
-	dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7);
-	dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
-
-	dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f);
-	dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
-	dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f);
-	dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f);
-
-	_DBGRTCTM(2, *dt);
-
-	return 0;
-}
-
-static int
-rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
-{
-	int ret, len = 5;
-	unsigned char buf[15];
-
-	_DBG(1, "client=%p, dt=%p", client, dt);
-
-	if (!dt || !client)
-		return -EINVAL;
-
-	_DBGRTCTM(2, *dt);
-
-	buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
-	buf[RTC8564_REG_CTRL2] = CTRL2(client);
-	buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs);
-	buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins);
-	buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours);
-
-	if (datetoo) {
-		len += 5;
-		buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday);
-		buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday);
-		buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f;
-		/* century stored in minute alarm reg */
-		buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100);
-		buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100);
-	}
-
-	ret = rtc8564_write(client, 0, buf, len);
-	if (ret) {
-		_DBG(1, "error writing data! %d", ret);
-	}
-
-	buf[RTC8564_REG_CTRL1] = CTRL1(client);
-	ret = rtc8564_write(client, 0, buf, 1);
-	if (ret) {
-		_DBG(1, "error writing data! %d", ret);
-	}
-
-	return ret;
-}
-
-static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
-{
-	struct rtc8564_data *data = i2c_get_clientdata(client);
-
-	if (!ctrl || !client)
-		return -1;
-
-	*ctrl = data->ctrl;
-	return 0;
-}
-
-static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
-{
-	struct rtc8564_data *data = i2c_get_clientdata(client);
-	unsigned char buf[2];
-
-	if (!ctrl || !client)
-		return -1;
-
-	buf[0] = *ctrl & 0xff;
-	buf[1] = (*ctrl & 0xff00) >> 8;
-	data->ctrl = *ctrl;
-
-	return rtc8564_write(client, 0, buf, 2);
-}
-
-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
-{
-
-	if (!mem || !client)
-		return -EINVAL;
-
-	return rtc8564_read(client, mem->loc, mem->data, mem->nr);
-}
-
-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
-{
-
-	if (!mem || !client)
-		return -EINVAL;
-
-	return rtc8564_write(client, mem->loc, mem->data, mem->nr);
-}
-
-static int
-rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-
-	_DBG(1, "cmd=%d", cmd);
-
-	switch (cmd) {
-	case RTC_GETDATETIME:
-		return rtc8564_get_datetime(client, arg);
-
-	case RTC_SETTIME:
-		return rtc8564_set_datetime(client, arg, 0);
-
-	case RTC_SETDATETIME:
-		return rtc8564_set_datetime(client, arg, 1);
-
-	case RTC_GETCTRL:
-		return rtc8564_get_ctrl(client, arg);
-
-	case RTC_SETCTRL:
-		return rtc8564_set_ctrl(client, arg);
-
-	case MEM_READ:
-		return rtc8564_read_mem(client, arg);
-
-	case MEM_WRITE:
-		return rtc8564_write_mem(client, arg);
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static struct i2c_driver rtc8564_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "RTC8564",
-	.id		= I2C_DRIVERID_RTC8564,
-	.flags		= I2C_DF_NOTIFY,
-	.attach_adapter = rtc8564_probe,
-	.detach_client	= rtc8564_detach,
-	.command	= rtc8564_command
-};
-
-static __init int rtc8564_init(void)
-{
-	return i2c_add_driver(&rtc8564_driver);
-}
-
-static __exit void rtc8564_exit(void)
-{
-	i2c_del_driver(&rtc8564_driver);
-}
-
-MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>");
-MODULE_DESCRIPTION("EPSON RTC8564 Driver");
-MODULE_LICENSE("GPL");
-
-module_init(rtc8564_init);
-module_exit(rtc8564_exit);
+/*
+ *  linux/drivers/i2c/chips/rtc8564.c
+ *
+ *  RTC driver for the actelm7 board based on code from Stefan Eletzhofer
+ *  which is in turn based on
+ *
+ *  linux/drivers/acron/char/pcf8583.c
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver registers itself with i2c subsystem and misc driver subsystem 
+ */
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/rtc.h>		/* get the user-level API */
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+
+#include "rtc8564.h"
+
+#ifdef DEBUG
+# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
+#else
+# define _DBG(x, fmt, args...) do { } while(0);
+#endif
+
+#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl);
+
+struct rtc8564_data {
+	struct i2c_client client;
+	u16 ctrl;
+};
+
+static inline u8 _rtc8564_ctrl1(struct i2c_client *client)
+{
+	struct rtc8564_data *data = i2c_get_clientdata(client);
+	return data->ctrl & 0xff;
+}
+static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
+{
+	struct rtc8564_data *data = i2c_get_clientdata(client);
+	return (data->ctrl & 0xff00) >> 8;
+}
+
+#define CTRL1(c) _rtc8564_ctrl1(c)
+#define CTRL2(c) _rtc8564_ctrl2(c)
+
+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
+#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
+
+static int debug;;
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+static struct i2c_driver rtc8564_driver;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+	.normal_i2c		= normal_addr,
+	.normal_i2c_range	= ignore,
+	.probe			= ignore,
+	.probe_range		= ignore,
+	.ignore			= ignore,
+	.ignore_range		= ignore,
+	.force			= ignore,
+};
+
+static struct i2c_client *rtc_client = NULL;
+static char rtc_status = 0;
+
+static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
+static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem);
+
+static int rtc8564_read(struct i2c_client *client, unsigned char adr,
+			unsigned char *buf, unsigned char len)
+{
+	int ret = -EIO;
+	unsigned char addr[1] = { adr };
+	struct i2c_msg msgs[2] = {
+		{client->addr, 0, 1, addr},
+		{client->addr, I2C_M_RD, len, buf}
+	};
+
+	_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
+
+	if (!buf || !client) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = i2c_transfer(client->adapter, msgs, 2);
+	if (ret == 2) {
+		ret = 0;
+	}
+
+done:
+	return ret;
+}
+
+static int rtc8564_write(struct i2c_client *client, unsigned char adr,
+			 unsigned char *data, unsigned char len)
+{
+	int ret = 0;
+	unsigned char _data[16];
+	struct i2c_msg wr;
+	int i;
+
+	if (!client || !data || len > 15) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len);
+
+	_data[0] = adr;
+	for (i = 0; i < len; i++) {
+		_data[i + 1] = data[i];
+		_DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]);
+	}
+
+	wr.addr = client->addr;
+	wr.flags = 0;
+	wr.len = len + 1;
+	wr.buf = _data;
+
+	ret = i2c_transfer(client->adapter, &wr, 1);
+	if (ret == 1) {
+		ret = 0;
+	}
+
+done:
+	return ret;
+}
+
+static int rts8564_set_time(struct rtc_time *time)
+{
+	struct i2c_client *client = rtc_client;
+
+	int ret, len = 10;
+	unsigned char buf[15];
+
+
+	if (!time || !client)
+		return -EINVAL;
+
+	buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
+	buf[RTC8564_REG_CTRL2] = CTRL2(client);
+	buf[RTC8564_REG_SEC] = BIN_TO_BCD(time->tm_sec);
+	buf[RTC8564_REG_MIN] = BIN_TO_BCD(time->tm_min);
+	buf[RTC8564_REG_HR] = BIN_TO_BCD(time->tm_hour);
+	buf[RTC8564_REG_DAY] = BIN_TO_BCD(time->tm_mday);
+	buf[RTC8564_REG_WDAY] = BIN_TO_BCD(time->tm_wday);
+	buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(time->tm_mon) & 0x1f;
+	/* century stored in minute alarm reg */
+	buf[RTC8564_REG_YEAR] = BIN_TO_BCD(time->tm_year % 100);
+	buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(time->tm_year / 100);
+	
+
+	ret = rtc8564_write(client, 0, buf, len);
+	if (ret) {
+		_DBG(1, "error writing data! %d", ret);
+	}
+
+	buf[RTC8564_REG_CTRL1] = CTRL1(client);
+	ret = rtc8564_write(client, 0, buf, 1);
+	if (ret) {
+		_DBG(1, "error writing data! %d", ret);
+	}
+
+	return ret;
+}
+
+static int rts8564_read_time(struct rtc_time *time)
+{
+
+	struct i2c_client *client = rtc_client;
+
+	int ret = -EIO;
+	unsigned char buf[15];
+
+	memset(buf, 0, sizeof(buf));
+
+	ret = rtc8564_read(client, 0, buf, 15);
+	if (ret)
+		return ret;
+
+	/* century stored in minute alarm reg */
+	time->tm_year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]);
+	time->tm_year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
+
+	time->tm_mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f);
+	time->tm_wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7);
+	time->tm_mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
+
+	time->tm_sec = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f);
+	time->tm_min = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f);
+	time->tm_hour = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f);
+
+	return 0;
+}
+
+static int
+rtc8564_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	  unsigned long arg)
+{
+
+	switch(cmd) {
+		case RTC_RD_TIME:	/* read the time/date from RTC	*/
+		{
+			struct rtc_time rtc_tm;
+
+			memset(&rtc_tm, 0, sizeof (struct rtc_time));
+			rts8564_read_time(&rtc_tm);
+			if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
+				return -EFAULT;
+			return 0;
+		}
+
+		case RTC_SET_TIME:	/* set the RTC */
+		{
+			struct rtc_time rtc_tm;
+
+			if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
+				return -EFAULT;
+
+			rts8564_set_time(&rtc_tm);
+			
+			return 0;
+		}
+		default:
+			return -EINVAL;
+	}
+}
+
+/*
+ *	We enforce only one user at a time here with the open/close.
+ *	Also clear the previous interrupt data on an open, and clean
+ *	up things on a close.
+ */
+
+static int rtc8564_open(struct inode *inode, struct file *file)
+{
+	if(rtc_status)
+		return -EBUSY;
+
+	rtc_status = 1;
+	return 0;
+}
+
+static int rtc8564_release(struct inode *inode, struct file *file)
+{
+	lock_kernel();
+	rtc_status = 0;
+	unlock_kernel();
+	return 0;
+}
+
+static struct file_operations rts8564_fops = {
+        .owner          = THIS_MODULE,
+        .ioctl          = rtc8564_ioctl,
+	.open		= rtc8564_open,
+	.release	= rtc8564_release,
+};
+
+static struct miscdevice rtc_dev=
+{
+	RTC_MINOR,
+	"rtc",
+	&rts8564_fops
+};
+
+static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+	int ret;
+	struct i2c_client *new_client;
+	struct rtc8564_data *d;
+	unsigned char data[10];
+	unsigned char ad[1] = { 0 };
+	struct i2c_msg ctrl_wr[1] = {
+		{addr, 0, 2, data}
+	};
+	struct i2c_msg ctrl_rd[2] = {
+		{addr, 0, 1, ad},
+		{addr, I2C_M_RD, 2, data}
+	};
+
+	d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
+	if (!d) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	memset(d, 0, sizeof(struct rtc8564_data));
+	new_client = &d->client;
+
+	strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
+	i2c_set_clientdata(new_client, d);
+	new_client->id = rtc8564_driver.id;
+	new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
+	new_client->addr = addr;
+	new_client->adapter = adap;
+	new_client->driver = &rtc8564_driver;
+
+	_DBG(1, "client=%p", new_client);
+	_DBG(1, "client.id=%d", new_client->id);
+
+	/* init ctrl1 reg */
+	data[0] = 0;
+	data[1] = 0;
+	ret = i2c_transfer(new_client->adapter, ctrl_wr, 1);
+	if (ret != 1) {
+		printk(KERN_INFO "rtc8564: cant init ctrl1\n");
+		ret = -ENODEV;
+		goto done;
+	}
+
+	/* read back ctrl1 and ctrl2 */
+	ret = i2c_transfer(new_client->adapter, ctrl_rd, 2);
+	if (ret != 2) {
+		printk(KERN_INFO "rtc8564: cant read ctrl\n");
+		ret = -ENODEV;
+		goto done;
+	}
+
+	d->ctrl = data[0] | (data[1] << 8);
+
+	_DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x",
+	     data[0], data[1]);
+
+	ret = i2c_attach_client(new_client);
+
+	rtc_client = new_client;
+
+	ret = misc_register(&rtc_dev);
+    
+	if(ret) {
+		printk("Failed to register rtc char device\n");
+	}
+
+done:
+	if (ret) {
+		kfree(d);
+	}
+
+	return ret;
+}
+
+static int rtc8564_probe(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, rtc8564_attach);
+}
+
+static int rtc8564_detach(struct i2c_client *client)
+{
+	  i2c_detach_client(client);
+	  kfree(i2c_get_clientdata(client));
+	  return 0;
+}
+
+static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
+{
+	int ret = -EIO;
+	unsigned char buf[15];
+
+	_DBG(1, "client=%p, dt=%p", client, dt);
+
+	if (!dt || !client)
+		return -EINVAL;
+
+	memset(buf, 0, sizeof(buf));
+
+	ret = rtc8564_read(client, 0, buf, 15);
+	if (ret)
+		return ret;
+
+	/* century stored in minute alarm reg */
+	dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]);
+	dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
+	dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f);
+	dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7);
+	dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
+
+	dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f);
+	dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
+	dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f);
+	dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f);
+
+	_DBGRTCTM(2, *dt);
+
+	return 0;
+}
+
+static int
+rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
+{
+	int ret, len = 5;
+	unsigned char buf[15];
+
+	_DBG(1, "client=%p, dt=%p", client, dt);
+
+	if (!dt || !client)
+		return -EINVAL;
+
+	_DBGRTCTM(2, *dt);
+
+	buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
+	buf[RTC8564_REG_CTRL2] = CTRL2(client);
+	buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs);
+	buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins);
+	buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours);
+
+	if (datetoo) {
+		len += 5;
+		buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday);
+		buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday);
+		buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f;
+		/* century stored in minute alarm reg */
+		buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100);
+		buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100);
+	}
+
+	ret = rtc8564_write(client, 0, buf, len);
+	if (ret) {
+		_DBG(1, "error writing data! %d", ret);
+	}
+
+	buf[RTC8564_REG_CTRL1] = CTRL1(client);
+	ret = rtc8564_write(client, 0, buf, 1);
+	if (ret) {
+		_DBG(1, "error writing data! %d", ret);
+	}
+
+	return ret;
+}
+
+static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
+{
+	struct rtc8564_data *data = i2c_get_clientdata(client);
+
+	if (!ctrl || !client)
+		return -1;
+
+	*ctrl = data->ctrl;
+	return 0;
+}
+
+static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
+{
+	struct rtc8564_data *data = i2c_get_clientdata(client);
+	unsigned char buf[2];
+
+	if (!ctrl || !client)
+		return -1;
+
+	buf[0] = *ctrl & 0xff;
+	buf[1] = (*ctrl & 0xff00) >> 8;
+	data->ctrl = *ctrl;
+
+	return rtc8564_write(client, 0, buf, 2);
+}
+
+static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
+{
+
+	if (!mem || !client)
+		return -EINVAL;
+
+	return rtc8564_read(client, mem->loc, mem->data, mem->nr);
+}
+
+static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
+{
+
+	if (!mem || !client)
+		return -EINVAL;
+
+	return rtc8564_write(client, mem->loc, mem->data, mem->nr);
+}
+
+static int
+rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+
+	_DBG(1, "cmd=%d", cmd);
+
+	switch (cmd) {
+	case RTC_GETDATETIME:
+		return rtc8564_get_datetime(client, arg);
+
+	case RTC_SETTIME:
+		return rtc8564_set_datetime(client, arg, 0);
+
+	case RTC_SETDATETIME:
+		return rtc8564_set_datetime(client, arg, 1);
+
+	case RTC_GETCTRL:
+		return rtc8564_get_ctrl(client, arg);
+
+	case RTC_SETCTRL:
+		return rtc8564_set_ctrl(client, arg);
+
+	case MEM_READ:
+		return rtc8564_read_mem(client, arg);
+
+	case MEM_WRITE:
+		return rtc8564_write_mem(client, arg);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct i2c_driver rtc8564_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "RTC8564",
+	.id		= I2C_DRIVERID_RTC8564,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter = rtc8564_probe,
+	.detach_client	= rtc8564_detach,
+	.command	= rtc8564_command
+};
+
+static __init int rtc8564_init(void)
+{
+	return i2c_add_driver(&rtc8564_driver);
+}
+
+static __exit void rtc8564_exit(void)
+{
+	i2c_del_driver(&rtc8564_driver);
+}
+
+module_init(rtc8564_init);
+module_exit(rtc8564_exit);
+
+MODULE_AUTHOR("Steven taffs steventaffs@yahoo.com");
+MODULE_DESCRIPTION("EPSON RTC8564 Driver");
+MODULE_LICENSE("GPL");
diff -Naur linux-2.6.11.8/drivers/i2c/chips/rtc8564.h linux-2.6.x/drivers/i2c/chips/rtc8564.h
--- linux-2.6.11.8/drivers/i2c/chips/rtc8564.h	2005-04-30 02:24:26.000000000 +0100
+++ linux-2.6.x/drivers/i2c/chips/rtc8564.h	2009-09-06 22:42:40.000000000 +0100
@@ -1,14 +1,17 @@
-/*
- *  linux/drivers/i2c/chips/rtc8564.h
- *
- *  Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- *	based on linux/drivers/acron/char/pcf8583.h
- *  Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+/*
+ *  linux/drivers/i2c/chips/rtc8564.c
+ *
+ *  RTC driver for the actelm7 board based on code from Stefan Eletzhofer
+ *  which is in turn based on
+ *
+ *  linux/drivers/acron/char/pcf8583.c
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver registers itself with i2c subsystem and misc driver subsystem 
  */
 struct rtc_tm {
 	unsigned char	secs;
@@ -76,3 +79,4 @@
 #define RTC8564_TD_1_60HZ		(0x3)
 
 #define I2C_DRIVERID_RTC8564 0xf000
+
diff -Naur linux-2.6.11.8/drivers/input/touchscreen/ads7846_ts_input.c linux-2.6.x/drivers/input/touchscreen/ads7846_ts_input.c
--- linux-2.6.11.8/drivers/input/touchscreen/ads7846_ts_input.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/drivers/input/touchscreen/ads7846_ts_input.c	2009-09-06 22:47:01.000000000 +0100
@@ -0,0 +1,623 @@
+/*
+ * ads7846_ts_input.c
+ *
+ * Touch screen driver for the actelm7 board, this driver is based on code for
+ * the TI Innovator board.
+ *
+ * The touchscreen hardware on the actelm7 board consists of an m7core built 
+ * with a SPI unit which is used to 'talk' SPI to an ADS7846 touch screen controller.
+ *
+ *  Revision history
+ *  0.01  Initial version
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/ioport.h>       /* request_region */
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>        /* get_user,copy_to_user */
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+#define TS_NAME "ads7846_ts_input"
+#define TS_MINOR 14
+#define PFX TS_NAME
+
+#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
+
+
+// ADS7846 Control Byte bit defines
+#define ADS7846_S         (1<<7)
+#define ADS7846_ADDR_BIT  4
+#define ADS7846_ADDR_MASK (0x7<<ADS7846_ADDR_BIT)
+#define ADS7846_MEASURE_X  (0x5<<ADS7846_ADDR_BIT)
+#define ADS7846_MEASURE_Y  (0x1<<ADS7846_ADDR_BIT)
+#define ADS7846_MEASURE_Z1 (0x3<<ADS7846_ADDR_BIT)
+#define ADS7846_MEASURE_Z2 (0x4<<ADS7846_ADDR_BIT)
+#define ADS7846_8BITS     (1<<3)
+#define ADS7846_12BITS    0
+#define ADS7846_SER       (1<<2)
+#define ADS7846_DFR       0
+#define ADS7846_PWR_BIT   0
+#define ADS7846_PD      0
+#define ADS7846_ADC_ON  (0x1<<ADS7846_PWR_BIT)
+#define ADS7846_REF_ON  (0x2<<ADS7846_PWR_BIT)
+#define ADS7846_REF_ADC_ON (0x3<<ADS7846_PWR_BIT)
+
+#define MEASURE_12BIT_X (ADS7846_S | ADS7846_MEASURE_X | ADS7846_12BITS | ADS7846_DFR | ADS7846_REF_ADC_ON)
+#define MEASURE_12BIT_X_SLEEP (ADS7846_S | ADS7846_MEASURE_X | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
+#define MEASURE_12BIT_Y (ADS7846_S | ADS7846_MEASURE_Y | ADS7846_12BITS | ADS7846_DFR | ADS7846_REF_ADC_ON)
+#define MEASURE_12BIT_Z1 (ADS7846_S | ADS7846_MEASURE_Z1 | ADS7846_12BITS | ADS7846_DFR | ADS7846_ADC_ON)
+#define MEASURE_12BIT_Z2 (ADS7846_S | ADS7846_MEASURE_Z2 | ADS7846_12BITS | ADS7846_DFR | ADS7846_ADC_ON)
+
+/*
+ * Which pressure equation to use from ADS7846 datasheet.
+ * The first equation requires knowing only the X plate
+ * resistance, but needs 4 measurements (X, Y, Z1, Z2).
+ * The second equation requires knowing both X and Y plate
+ * resistance, but only needs 3 measurements (X, Y, Z1).
+ */
+enum {
+	PRESSURE_EQN_1 = 0,
+	PRESSURE_EQN_2
+};
+
+
+/*
+ * The touch screen's X and Y plate resistances, used by
+ * pressure equations.
+ */
+#define DEFAULT_X_PLATE_OHMS 560
+#define DEFAULT_Y_PLATE_OHMS 548
+
+/*
+ * The definition of the following structure is copied from ucb1x00-ts.c
+ * so the touchscreen will "just work" with tslib.
+ */
+struct ts_event {
+        u16 pressure;
+        u16 x;
+        u16 y;
+        u16 pad;
+        struct timeval stamp;
+};
+
+
+#define EVENT_BUFSIZE 32 // must be power of two
+
+struct innovator_ts_t {
+	// The X and Y plate resistance, needed to calculate pressure
+	int x_plate_ohms, y_plate_ohms;
+	int pressure_eqn;      // eqn to use for pressure calc
+	int pendown_irq;       // IRQ of pendown interrupt
+	int pen_is_down;       // 1 = pen is down, 0 = pen is up
+	int irq_enabled;
+	struct ts_event event_buf[EVENT_BUFSIZE];// The event queue
+	int nextIn, nextOut;
+	int event_count;
+	struct fasync_struct *fasync;     // asynch notification
+	struct timer_list acq_timer;      // Timer for triggering acquisitions
+	wait_queue_head_t wait;           // read wait queue
+	spinlock_t lock;
+	int debounce_max;				//maximum number of retries
+	int debounce_tol;				//tolerance between reads
+	int debounce_rep;				//repeated good results needed
+	int read_cnt;					
+	int read_rep;					
+	u16 last_read;					
+	int ignore;						//set if we have a bad reading
+	int read_ok;					//set this on good reading
+};
+
+static struct innovator_ts_t innovator_ts;
+
+static u8 spiWrite(u8 data)
+{
+	u8 received = 0x00;
+	u8 status = 0x00;
+	
+	//transmit data
+
+	SPI_TX = data;
+
+	//wait until transmit buffer is empty
+	while((status & 0x04) == 0)
+	{
+		status = SPI_STATUS;
+	}
+	
+	// wait for SPI recieve flag in Status register
+	while((status & 0x02) == 0)
+	{
+		status = SPI_STATUS;
+	}
+	
+	// store received data
+	received = SPI_RX;
+	
+	return received;	
+}
+
+static u16 ads7846_do(u8 cmd)
+{  	
+	
+	//clear variables
+	u16 val = 0x0000;
+	u8 dummy = 0x00;
+	u8 temp1 = 0x00;
+	u8 temp2 = 0x00;
+	u32 status = 0;
+
+	 //transmit ads7846 command byte
+	dummy = spiWrite(cmd);
+
+	//wait for busy line to go high
+	while ((status & 0x00000080) == 0)
+	{
+		status = DataIn;	
+	}
+	
+	//get x y or z value from ads7846 chip 
+	dummy = 0x00;
+	temp1 = spiWrite(dummy);
+	dummy = 0x00;	
+	temp2 = spiWrite(dummy); 
+
+	//put recieved value in the right order
+	val = ((temp1 & 0x7f) << 5);	
+	val |= (temp2 >> 3);
+
+	return val;
+}
+
+// hold the spinlock before calling.
+static void event_add(struct innovator_ts_t* ts,
+		      struct ts_event* event)
+{
+	// add this event to the event queue
+	ts->event_buf[ts->nextIn] = *event;
+	ts->nextIn = (ts->nextIn + 1) & (EVENT_BUFSIZE - 1);
+	if (ts->event_count < EVENT_BUFSIZE) {
+		ts->event_count++;
+	} else {
+		// throw out the oldest event
+		ts->nextOut = (ts->nextOut + 1) & (EVENT_BUFSIZE - 1);
+	}
+	
+	// async notify
+	if (ts->fasync)
+		kill_fasync(&ts->fasync, SIGIO, POLL_IN);
+	// wake up any read call
+	if (waitqueue_active(&ts->wait))
+		wake_up_interruptible(&ts->wait);
+}
+
+static int event_pull(struct innovator_ts_t* ts,
+		      struct ts_event* event)
+{
+	unsigned long flags;
+	int ret;
+	
+	spin_lock_irqsave(&ts->lock, flags);
+	ret = ts->event_count;
+	if (ts->event_count) {
+		*event = ts->event_buf[ts->nextOut];
+		ts->nextOut = (ts->nextOut + 1) & (EVENT_BUFSIZE - 1);
+		ts->event_count--;
+	}
+	spin_unlock_irqrestore(&ts->lock, flags);
+
+	return ret;
+}
+
+
+static irqreturn_t pendown_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct innovator_ts_t* ts = dev_id;
+
+	spin_lock(&ts->lock);
+
+if (ts->irq_enabled) {
+ts->irq_enabled = 0;
+	disable_irq(irq);
+}
+	ts->pen_is_down = 1;
+	// restart acquire
+	ts->acq_timer.expires = jiffies + HZ / 100;
+	add_timer(&ts->acq_timer);
+
+	spin_unlock(&ts->lock);
+
+	return IRQ_HANDLED;
+}
+
+static void ads7846_debounce(struct innovator_ts_t* ts,u16 val)
+{
+
+        if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) 
+		{
+                 /* Repeat it, if this was the first read or the read
+                  * wasn't consistent enough. */
+                 if (ts->read_cnt < ts->debounce_max) 
+				 {
+                         ts->last_read = val;
+                         ts->read_cnt++;
+                 } 
+				 else 
+				 {
+                         /* Maximum number of debouncing reached and still
+                          * not enough number of consistent readings. Abort
+                          * the whole sample, repeat it in the next sampling
+                          * period.
+                          */
+                         ts->ignore = 1;
+						 ts->read_ok = 0;
+                         ts->read_cnt = 0;
+                 }
+                 /* Start over collecting consistent readings. */
+                 ts->read_rep = 0;
+         } 
+	     else 
+		 {
+                 if (++ts->read_rep > ts->debounce_rep) 
+				 {
+                         /* Got a good reading for this coordinate,
+                          * go for the next one. */
+                         ts->ignore = 0;
+                         ts->read_cnt = 0;
+                         ts->read_rep = 0;
+						 ts->read_ok = 1;
+				 } 
+				 else
+				 {
+                         /* Read more values that are consistent. */
+                         ts->read_cnt++;
+				 }
+         }
+}
+
+
+/*
+ * Acquire Raw pen coodinate data and compute touch screen
+ * pressure resistance. Hold spinlock when calling.
+ */
+static void AcquireEvent(struct innovator_ts_t* ts,
+			 struct ts_event* event)
+{
+	u16 x_raw, y_raw, z1_raw, z2_raw=0;
+	unsigned int Rt = 0;
+
+	//set CS line low
+	DataOut &= 0xffffffef;	
+
+	//keep reading y until we have made a choice
+	while(ts->ignore != 1 && ts->read_ok != 1)
+	{
+		y_raw = ads7846_do(MEASURE_12BIT_Y);
+		ads7846_debounce(ts,y_raw);
+	}
+
+	if(ts->ignore == 1)
+		return;
+
+	//clear flag
+	ts->read_ok = 0;
+
+	//keep reading x until we have made a choice
+	while(ts->ignore != 1 && ts->read_ok != 1)
+	{
+		x_raw = ads7846_do(MEASURE_12BIT_X);
+		ads7846_debounce(ts,x_raw);
+	}
+
+	if(ts->ignore == 1)
+		return;
+
+	//clear flag
+	ts->read_ok = 0;
+
+	//keep reading z1 until we have made a choice
+	while(ts->ignore != 1 && ts->read_ok != 1)
+	{
+		z1_raw = ads7846_do(MEASURE_12BIT_Z1);
+		ads7846_debounce(ts,z1_raw);
+	}
+
+	if(ts->ignore == 1)
+		return;
+
+	//clear flag
+	ts->read_ok = 0;
+
+	if (ts->pressure_eqn == PRESSURE_EQN_1)
+	{
+		//keep reading z2 until we have made a choice
+		while(ts->ignore != 1 && ts->read_ok != 1)
+		{
+			z2_raw = ads7846_do(MEASURE_12BIT_Z2); 
+			ads7846_debounce(ts,z2_raw);
+		}
+	}
+
+	if(ts->ignore == 1)
+		return;
+
+	//clear flag
+	ts->read_ok = 0;
+
+	// Calculate touch pressure resistance
+	if (z1_raw) {
+		if (ts->pressure_eqn == PRESSURE_EQN_1) {
+			Rt = (ts->x_plate_ohms * (u32)x_raw *
+			      ((u32)z2_raw - (u32)z1_raw)) / (u32)z1_raw;
+		} else {
+			Rt = (ts->x_plate_ohms * (u32)x_raw *
+			      (4096 - (u32)z1_raw)) / (u32)z1_raw;
+			Rt -= (ts->y_plate_ohms * (u32)y_raw);
+		}
+
+		Rt = (Rt + 2048) >> 12; // round up to nearest ohm
+	}
+
+	event->x = x_raw;
+	event->y = y_raw;
+	event->pressure = (u16)Rt;
+	// timestamp this new event.
+	do_gettimeofday(&event->stamp);
+	//put ads7846 to sleep
+	x_raw = ads7846_do(MEASURE_12BIT_X_SLEEP);
+	//set CS line high
+	DataOut |= 0x00000010;
+
+}
+
+/*
+ * Raw X,Y,pressure acquisition timer function. It gets scheduled
+ * only while pen is down. Its duration between calls is the polling
+ * rate.
+ */
+static void
+innovator_acq_timer(unsigned long data)
+{
+	struct innovator_ts_t* ts = (struct innovator_ts_t*)data;
+	unsigned long flags;
+	struct ts_event event;
+	int pen_was_down = ts->pen_is_down;
+	u32 DataInput = DataIn;
+	u16 dummy;	
+
+	spin_lock_irqsave(&ts->lock, flags);
+
+	if (DataInput & 0x00000040) 
+	{
+		ts->pen_is_down = 1;
+		AcquireEvent(ts, &event);
+		if(ts->ignore == 1)
+		{
+			ts->ignore = 0;		
+			//put ads7846 to sleep
+			dummy = ads7846_do(MEASURE_12BIT_X_SLEEP);
+			//set CS line high
+			DataOut |= 0x00000010;
+		}
+		else
+		{
+			event_add(ts, &event);
+		}
+
+		// schedule next acquire
+		ts->acq_timer.expires = jiffies + HZ / 100;
+		add_timer(&ts->acq_timer);
+	} 
+	else 
+	{
+		if (!ts->irq_enabled) 
+		{
+			ts->irq_enabled = 1;
+			enable_irq(ts->pendown_irq);
+		}
+		ts->pen_is_down = 0;
+		if (pen_was_down) {
+			event.x = event.y = event.pressure = 0;
+			do_gettimeofday(&event.stamp);
+			event_add(ts, &event);
+		}
+	}
+	
+	spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+
+/*  File operations */
+
+static int
+innovator_fasync(int fd, struct file *filp, int mode)
+{
+	struct innovator_ts_t* ts = (struct innovator_ts_t*)filp->private_data;
+	return fasync_helper(fd, filp, mode, &ts->fasync);
+}
+
+
+static unsigned int
+innovator_poll(struct file * filp, poll_table * wait)
+{
+	struct innovator_ts_t* ts = (struct innovator_ts_t*)filp->private_data;
+	poll_wait(filp, &ts->wait, wait);
+	if (ts->event_count)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static ssize_t
+innovator_read(struct file * filp, char * buffer, size_t count, loff_t * ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct innovator_ts_t* ts = (struct innovator_ts_t*)filp->private_data;
+	char *ptr = buffer;
+	struct ts_event event;
+	int err = 0;
+
+	add_wait_queue(&ts->wait, &wait);
+	while (count >= sizeof(struct ts_event)) {
+		err = -ERESTARTSYS;
+		if (signal_pending(current))
+			break;
+
+		if (event_pull(ts, &event)) {
+			err = copy_to_user(ptr, &event,
+					   sizeof(struct ts_event));
+			if (err)
+				break;
+			ptr += sizeof(struct ts_event);
+			count -= sizeof(struct ts_event);
+		} else {
+			set_current_state(TASK_INTERRUPTIBLE);
+			err = -EAGAIN;
+			if (filp->f_flags & O_NONBLOCK)
+				break; 
+			schedule();
+		}
+	}
+	
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&ts->wait, &wait);
+	
+	return ptr == buffer ? err : ptr - buffer;
+}
+
+
+static int
+innovator_open(struct inode * inode, struct file * filp)
+{
+	struct innovator_ts_t* ts;
+	unsigned long flags;
+	int retval;
+	
+	filp->private_data = ts = &innovator_ts;
+
+	spin_lock_irqsave(&ts->lock, flags);
+
+	ts->pen_is_down = 0; // start with pen up
+	
+	// flush event queue
+	ts->nextIn = ts->nextOut = ts->event_count = 0;
+	
+	// Init acquisition timer function
+	init_timer(&ts->acq_timer);
+	ts->acq_timer.function = innovator_acq_timer;
+	ts->acq_timer.data = (unsigned long)ts;
+
+ts->irq_enabled = 1;
+
+	spin_unlock_irqrestore(&ts->lock, flags);
+
+	/* Since ts interrupt can happen immediately after request_irq,
+	 * we wait until we've completed init of all relevent driver
+	 * state variables. Now we grab the PenDown IRQ
+	 */
+	retval = request_irq(ts->pendown_irq, &pendown_interrupt,
+			     0, TS_NAME, ts);
+	if (retval) {
+		err("unable to get PenDown IRQ %d", ts->pendown_irq);
+		return retval;
+	}
+
+	return 0;
+}
+
+static int
+innovator_release(struct inode * inode, struct file * filp)
+{
+	struct innovator_ts_t* ts = (struct innovator_ts_t*)filp->private_data;
+
+	free_irq(ts->pendown_irq, ts);
+	innovator_fasync(-1, filp, 0);
+	del_timer_sync(&ts->acq_timer);
+
+	//MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+
+static struct file_operations ts_fops = {
+	owner:          THIS_MODULE,
+	read:           innovator_read,
+	poll:           innovator_poll,
+	fasync:         innovator_fasync,
+	open:			innovator_open,
+	release:		innovator_release,
+};
+
+/*  End File operations */
+
+
+static struct miscdevice innovator_ts_dev = {
+	minor:  TS_MINOR,
+	name:   TS_NAME,
+	fops:   &ts_fops,
+};
+
+int __init
+innovatorts_init_module(void)
+{
+	struct innovator_ts_t* ts = &innovator_ts;
+	int ret;
+
+	/* register our character device */
+	if ((ret = misc_register(&innovator_ts_dev)) < 0) {
+		err("can't register misc device");
+		return ret;
+	}
+	info("registered");
+
+	memset(ts, 0, sizeof(struct innovator_ts_t));
+	init_waitqueue_head(&ts->wait);
+	spin_lock_init(&ts->lock);
+
+	ts->pendown_irq = ACTELM7_INTERRUPT_PENDOWN;
+	ts->pressure_eqn = PRESSURE_EQN_1;
+	// init X and Y plate resistances
+	ts->x_plate_ohms = DEFAULT_X_PLATE_OHMS;
+	ts->y_plate_ohms = DEFAULT_Y_PLATE_OHMS;
+
+	//setup debounce
+	ts->debounce_max = 20;				//maximum number of retries
+	ts->debounce_tol = 6;				//tolerance between reads
+	ts->debounce_rep = 1;				//repeated good results needed
+
+	//set select line high
+	DataOut |= 0x00000010;
+
+	//setup SPI controller interrupt disabled, master mode, 
+	//MSB first, fclk / 16
+	SPI_CTRL1 = 0x43;
+
+	//enable SPI
+	SPI_CTRL2 = 0x80;
+
+	return 0;
+}
+
+void
+innovatorts_cleanup_module(void)
+{
+	misc_deregister(&innovator_ts_dev);
+}
+
+/* Module information */
+MODULE_AUTHOR("Steven taffs steventaffs@yahoo.com");
+MODULE_DESCRIPTION("ADS7846 Touch Screen Driver");
+MODULE_LICENSE("GPL");
+
+module_init(innovatorts_init_module);
+module_exit(innovatorts_cleanup_module);
+
diff -Naur linux-2.6.11.8/drivers/input/touchscreen/Kconfig linux-2.6.x/drivers/input/touchscreen/Kconfig
--- linux-2.6.11.8/drivers/input/touchscreen/Kconfig	2005-04-30 02:27:34.000000000 +0100
+++ linux-2.6.x/drivers/input/touchscreen/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -35,3 +35,14 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gunze.
 
+config TOUCHSCREEN_ADS7846
+	tristate "ACTELM7 ads7864 touchscreen input driver"
+	depends on INPUT && INPUT_TOUCHSCREEN
+	help
+	  say Y here if you have the ACTELM7 touchscreen connected to
+	  your system.
+
+	  if unsure, say N.
+ 
+	
+
diff -Naur linux-2.6.11.8/drivers/input/touchscreen/Makefile linux-2.6.x/drivers/input/touchscreen/Makefile
--- linux-2.6.11.8/drivers/input/touchscreen/Makefile	2005-04-30 02:31:29.000000000 +0100
+++ linux-2.6.x/drivers/input/touchscreen/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -6,3 +6,4 @@
 
 obj-$(CONFIG_TOUCHSCREEN_BITSY)	+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)	+= gunze.o
+obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846_ts_input.o
diff -Naur linux-2.6.11.8/drivers/mtd/maps/actelm7.c linux-2.6.x/drivers/mtd/maps/actelm7.c
--- linux-2.6.11.8/drivers/mtd/maps/actelm7.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/drivers/mtd/maps/actelm7.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,87 @@
+/*
+ * Flash map for actelm7 board
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+#include <linux/mtd/partitions.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+
+static struct mtd_info *flash_mtd;
+static struct mtd_partition *parsed_parts;
+
+struct map_info actelm7_flash_map = {
+	.name		= "ACTELM7 FLASH",
+	.phys		= 0x00000000,
+	.size		= 0x00800000,
+	.bankwidth	= 3,
+};
+
+static struct mtd_partition actelm7_partitions[] = {
+	{
+		.name	= "u-boot",
+		.offset	= 0x00000000,
+		.size	= 0x00080000,
+	},
+	{
+		.name	= "Kernel",
+		.offset	= 0x00080000,
+		.size	= 0x00180000,
+	},
+	{
+		.name	= "Flash FS",
+		.offset	= 0x00200000,
+		.size	= 0x005d0000,
+	}
+};
+
+static int __init init_actelm7_maps(void)
+{
+	int nr_parts;
+
+	actelm7_flash_map.phys = 0;
+	actelm7_flash_map.virt = (unsigned long) ioremap_nocache(actelm7_flash_map.phys,actelm7_flash_map.size);
+
+	simple_map_init(&actelm7_flash_map);
+
+	printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n");
+	flash_mtd = do_map_probe("map_rom", &actelm7_flash_map);
+	if (!flash_mtd) {
+		printk(KERN_NOTICE "Flash chips not detected at either possible location.\n");
+		return -ENXIO;
+	}
+	printk(KERN_NOTICE "INTEL: Flash at 0x%08lx\n", actelm7_flash_map.virt);
+	flash_mtd->owner = THIS_MODULE;
+
+	parsed_parts = actelm7_partitions;
+	nr_parts = ARRAY_SIZE(actelm7_partitions);
+
+	add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
+
+	return 0;
+
+}
+
+static void __exit cleanup_actelm7_maps(void)
+{
+	if (parsed_parts)
+		del_mtd_partitions(flash_mtd);
+	else
+		del_mtd_device(flash_mtd);
+	map_destroy(flash_mtd);
+}
+
+module_init(init_actelm7_maps);
+module_exit(cleanup_actelm7_maps);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steven taffs steventaffs@yahoo.com");
+MODULE_DESCRIPTION("MTD map driver for actelm7 board.");
diff -Naur linux-2.6.11.8/drivers/mtd/maps/Kconfig linux-2.6.x/drivers/mtd/maps/Kconfig
--- linux-2.6.11.8/drivers/mtd/maps/Kconfig	2005-04-30 02:32:19.000000000 +0100
+++ linux-2.6.x/drivers/mtd/maps/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -667,5 +667,12 @@
 	help
 	  This enables access to the flash chip on the Sharp SL Series of PDAs.
 
+config MTD_ACTELM7
+	tristate "Map driver for actel a3p-dev-kit-scs board"
+	depends on MTD
+	help
+	  Map driver for a3p-dev-kit-scs board
+	
+
 endmenu
 
diff -Naur linux-2.6.11.8/drivers/mtd/maps/Makefile linux-2.6.x/drivers/mtd/maps/Makefile
--- linux-2.6.11.8/drivers/mtd/maps/Makefile	2005-04-30 02:22:38.000000000 +0100
+++ linux-2.6.x/drivers/mtd/maps/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -72,3 +72,5 @@
 obj-$(CONFIG_MTD_WRSBC8260)	+= wr_sbc82xx_flash.o
 obj-$(CONFIG_MTD_DMV182)	+= dmv182.o
 obj-$(CONFIG_MTD_SHARP_SL)	+= sharpsl-flash.o
+obj-$(CONFIG_MTD_ACTELM7)	+= actelm7.o
+
diff -Naur linux-2.6.11.8/drivers/mtd/maps/physmap.c linux-2.6.x/drivers/mtd/maps/physmap.c
--- linux-2.6.11.8/drivers/mtd/maps/physmap.c	2005-04-30 02:29:03.000000000 +0100
+++ linux-2.6.x/drivers/mtd/maps/physmap.c	2009-09-06 22:42:40.000000000 +0100
@@ -47,11 +47,12 @@
 
 static int __init init_physmap(void)
 {
-	static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
+	//static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
+	static const char *rom_probe_types[] = { "map_rom", NULL}; 
 	const char **type;
 
        	printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys);
-	physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size);
+	physmap_map.virt = ioremap_nocache(physmap_map.phys, physmap_map.size);
 
 	if (!physmap_map.virt) {
 		printk("Failed to ioremap\n");
diff -Naur linux-2.6.11.8/drivers/mtd/maps/uclinux.c linux-2.6.x/drivers/mtd/maps/uclinux.c
--- linux-2.6.11.8/drivers/mtd/maps/uclinux.c	2009-09-06 22:49:57.000000000 +0100
+++ linux-2.6.x/drivers/mtd/maps/uclinux.c	2009-09-06 22:42:40.000000000 +0100
@@ -34,7 +34,7 @@
 /****************************************************************************/
 
 struct mtd_partition uclinux_romfs[] = {
-	{ .name = "ROMfs" }
+	{ .name = "ROMfs"}
 };
 
 #define	NUM_PARTITIONS	(sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0]))
@@ -61,7 +61,7 @@
 
 	mapp = &uclinux_ram_map;
 	mapp->phys = addr;
-	mapp->size = PAGE_ALIGN(*((unsigned long *)(addr + 8)));
+	mapp->size = 0x100000; //PAGE_ALIGN(*((unsigned long *)(addr + 8)));
 	mapp->bankwidth = 4;
 
 	printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
diff -Naur linux-2.6.11.8/drivers/net/8390.c linux-2.6.x/drivers/net/8390.c
--- linux-2.6.11.8/drivers/net/8390.c	2009-09-06 22:49:57.000000000 +0100
+++ linux-2.6.x/drivers/net/8390.c	2009-09-06 22:42:40.000000000 +0100
@@ -189,6 +189,9 @@
       
       	spin_lock_irqsave(&ei_local->page_lock, flags);
 	NS8390_init(dev, 1);
+#ifdef CONFIG_ARCH_ACTELM7
+	enable_irq(dev->irq);
+#endif
 	/* Set the flag before we drop the lock, That way the IRQ arrives
 	   after its set and we get no silly warnings */
 	netif_start_queue(dev);
diff -Naur linux-2.6.11.8/drivers/net/8390.h linux-2.6.x/drivers/net/8390.h
--- linux-2.6.11.8/drivers/net/8390.h	2009-09-06 22:49:57.000000000 +0100
+++ linux-2.6.x/drivers/net/8390.h	2009-09-06 22:42:40.000000000 +0100
@@ -142,6 +142,8 @@
 
 #elif defined(CONFIG_NET_CBUS) || defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE)
 #define EI_SHIFT(x)	(ei_local->reg_offset[x])
+#elif defined(CONFIG_ARCH_ACTELM7) /* according to board connection */
+#define EI_SHIFT(x) 	(x<<1)
 #else
 #define EI_SHIFT(x)	(x)
 #endif
diff -Naur linux-2.6.11.8/drivers/net/Kconfig linux-2.6.x/drivers/net/Kconfig
--- linux-2.6.11.8/drivers/net/Kconfig	2009-09-06 22:49:57.000000000 +0100
+++ linux-2.6.x/drivers/net/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -1095,6 +1095,17 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called ne.
 
+config RTL8019AS
+	tristate "rtl8019as support(NE2000 compatible)"
+	depends on ARCH_ACTELM7
+	select CRC32
+	help
+	  If you have a network (Ethernet) card of this type, say Y and read
+	  the Ethernet-HOWTO, available from 
+	  <http://www.tldp.org/docs.html#howto>.  
+	  Many Ethernet cards without a specific driver are compatible with
+	  NE2000, including the rtl8019as.
+
 config ZNET
 	tristate "Zenith Z-Note support (EXPERIMENTAL)"
 	depends on NET_ISA && EXPERIMENTAL
diff -Naur linux-2.6.11.8/drivers/net/Makefile linux-2.6.x/drivers/net/Makefile
--- linux-2.6.11.8/drivers/net/Makefile	2005-04-30 02:25:45.000000000 +0100
+++ linux-2.6.x/drivers/net/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -83,6 +83,7 @@
 obj-$(CONFIG_WD80x3) += wd.o 8390.o
 obj-$(CONFIG_EL2) += 3c503.o 8390.o
 obj-$(CONFIG_NE2000) += ne.o 8390.o
+obj-$(CONFIG_RTL8019AS) += rtl8019as.o 8390.o
 obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
 obj-$(CONFIG_HPLAN) += hp.o 8390.o
 obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
diff -Naur linux-2.6.11.8/drivers/net/ne.c linux-2.6.x/drivers/net/ne.c
--- linux-2.6.11.8/drivers/net/ne.c	2009-09-06 22:49:57.000000000 +0100
+++ linux-2.6.x/drivers/net/ne.c	2009-09-06 22:42:40.000000000 +0100
@@ -56,6 +56,10 @@
 #include <asm/io.h>
 
 #include "8390.h"
+#ifdef CONFIG_ARCH_ACTELM7
+#include "rtl8019as.h"
+unsigned char   ne_defethaddr[] = { 0x00, 0xd0, 0xcf, 0x00, 0x00, 0x01 };
+#endif
 
 #ifdef CONFIG_COLDFIRE
 #define COLDFIRE_NE2000_FUNCS
@@ -135,10 +139,17 @@
 /* ---- No user-serviceable parts below ---- */
 
 #define NE_BASE	 (dev->base_addr)
+#ifdef CONFIG_ARCH_ACTELM7
+#define NE_CMD	 	EI_SHIFT(0x00)
+#define NE_DATAPORT	EI_SHIFT(0x10)	/* NatSemi-defined port window offset. */
+#define NE_RESET	EI_SHIFT(0x1f)	/* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	EI_SHIFT(0x20)
+#else
 #define NE_CMD	 	0x00
 #define NE_DATAPORT	0x10	/* NatSemi-defined port window offset. */
 #define NE_RESET	0x1f	/* Issue a read to reset, a write to clear. */
 #define NE_IO_EXTENT	0x20
+#endif
 
 #define NE1SM_START_PG	0x20	/* First page of TX buffer */
 #define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
@@ -268,6 +279,10 @@
 	sprintf(dev->name, "eth%d", unit);
 	netdev_boot_setup_check(dev);
 
+#ifdef CONFIG_ARCH_ACTELM7 /* determined by ACTEL M7 board design */ 
+	  dev->base_addr = 0x82000600;
+	  dev->irq = 16; //ext2
+#endif
 	err = do_ne_probe(dev);
 	if (err)
 		goto out;
@@ -377,6 +392,14 @@
 	   cause the driver to skip these parts of the probe. */
 
 	bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+#ifdef CONFIG_ARCH_ACTELM7
+	/* initialize rtl8019as related registers */
+	outb_p(E8390_PAGE3, ioaddr + E8390_CMD); // set to page 3
+	outb_p(0xcf, ioaddr + CR9346);  //enable write config reg
+	outb_p(0x60, ioaddr + CONFIG3); //clear pwrdn, sleep mode 
+	outb_p(0x0f, ioaddr + CR9346);  //disable write config reg
+	outb_p(E8390_PAGE0, ioaddr + E8390_CMD); // restore to page 0
+#endif
 
 	/* Reset card. Who knows what dain-bramaged state it was left in. */
 
@@ -625,6 +648,10 @@
 
 	dev->base_addr = ioaddr;
 
+#ifdef CONFIG_ARCH_ACTELM7
+	for(i = 0; i < 6; i++)
+		SA_prom[i] = ne_defethaddr[i];
+#endif
 #ifdef CONFIG_PLAT_MAPPI
 	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
 		ioaddr + E8390_CMD); /* 0x61 */
diff -Naur linux-2.6.11.8/drivers/net/rtl8019as.c linux-2.6.x/drivers/net/rtl8019as.c
--- linux-2.6.11.8/drivers/net/rtl8019as.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/drivers/net/rtl8019as.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,861 @@
+/* rtl8019as.c: A rtl8019as ethernet driver for linux. Based on ne.c(for ne1000/2000 compatible ethernet driver) */
+
+/* Copyright (C) Philips Semiconductors */
+
+/*
+    Written 1992-94 by Donald Becker.
+
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.
+
+    This software may be used and distributed according to the terms
+    of the GNU General Public License, incorporated herein by reference.
+
+    The author may be reached as becker@scyld.com, or C/O
+    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+    This driver should work with many programmed-I/O 8390-based ethernet
+    boards.  Currently it supports the NE1000, NE2000, many clones,
+    and some Cabletron products.
+
+    Changelog:
+
+    Paul Gortmaker	: use ENISR_RDC to monitor Tx PIO uploads, made
+			  sanity checks and bad clone support optional.
+    Paul Gortmaker	: new reset code, reset card after probe at boot.
+    Paul Gortmaker	: multiple card support for module users.
+    Paul Gortmaker	: Support for PCI ne2k clones, similar to lance.c
+    Paul Gortmaker	: Allow users with bad cards to avoid full probe.
+    Paul Gortmaker	: PCI probe changes, more PCI cards supported.
+    rjohnson@analogic.com : Changed init order so an interrupt will only
+    occur after memory is allocated for dev->priv. Deallocated memory
+    last in cleanup_modue()
+    Richard Guenther    : Added support for ISAPnP cards
+    Paul Gortmaker	: Discontinued PCI support - use ne2k-pci.c instead.
+
+*/
+
+/* Routines for the NatSemi-based designs (NE[12]000). */
+
+static const char version1[] =
+"rtl8019as.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n";
+static const char version2[] =
+"Last modified Dec 1, 2005 by Lucy Wang\n";
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "8390.h"
+#include "rtl8019as.h"
+
+/* Some defines that people can play with if so inclined. */
+
+/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
+#define SUPPORT_NE_BAD_CLONES
+
+/* Do we perform extra sanity checks on stuff ? */
+/* #define NE_SANITY_CHECK */
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
+/* #define PACKETBUF_MEMSIZE	0x40 */
+
+/* A zero-terminated list of I/O addresses to be probed at boot. */
+#ifndef MODULE
+static unsigned int netcard_portlist[] __initdata = {
+	0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
+};
+#endif
+
+static struct isapnp_device_id isapnp_clone_list[] __initdata = {
+	{	ISAPNP_CARD_ID('A','X','E',0x2011),
+		ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
+		(long) "NetGear EA201" },
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
+		(long) "NN NE2000" },
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
+		(long) "Generic PNP" },
+	{ }	/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
+
+#ifdef SUPPORT_NE_BAD_CLONES
+/* A list of bad clones that we none-the-less recognize. */
+static struct { const char *name8, *name16; unsigned char SAprefix[4];}
+bad_clone_list[] __initdata = {
+    {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
+    {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
+    {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh?  */
+    {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
+    {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
+    {"NN1000", "NN2000",  {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
+    {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}},  /* Outlaw 4-Dimension cards. */
+    {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
+    {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
+    {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
+    {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
+    {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
+    {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
+    {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
+    {0,}
+};
+#endif
+
+/* ---- No user-serviceable parts below ---- */
+
+#define NE_BASE	 (dev->base_addr)
+#ifdef CONFIG_ARCH_ACTELM7 /* determined by on-board connection between ACTELM7 and rtl8019as */
+#define NE_CMD	 	EI_SHIFT(0x00)
+#define NE_DATAPORT	EI_SHIFT(0x10)	/* NatSemi-defined port window offset. */
+#define NE_RESET	EI_SHIFT(0x1f)	/* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	EI_SHIFT(0x20)
+#else
+#define NE_CMD	 	(0x00)
+#define NE_DATAPORT	(0x10)	/* NatSemi-defined port window offset. */
+#define NE_RESET	(0x1f)	/* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	(0x20)
+#endif
+
+#define NE1SM_START_PG	0x20	/* First page of TX buffer */
+#define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
+#define NESM_START_PG	0x40	/* First page of TX buffer */
+#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+static int ne_probe1(struct net_device *dev, int ioaddr);
+static int ne_probe_isapnp(struct net_device *dev);
+
+static int ne_open(struct net_device *dev);
+static int ne_close(struct net_device *dev);
+
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			  int ring_page);
+static void ne_block_input(struct net_device *dev, int count,
+			  struct sk_buff *skb, int ring_offset);
+static void ne_block_output(struct net_device *dev, const int count,
+		const unsigned char *buf, const int start_page);
+
+
+/*  Probe for various non-shared-memory ethercards.
+
+   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
+   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
+   the SAPROM, while other supposed NE2000 clones must be detected by their
+   SA prefix.
+
+   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
+   mode results in doubled values, which can be detected and compensated for.
+
+   The probe is also responsible for initializing the card and filling
+   in the 'dev' and 'ei_status' structures.
+
+   We use the minimum memory size for some ethercard product lines, iff we can't
+   distinguish models.  You can increase the packet buffer size by setting
+   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
+	E1010   starts at 0x100 and ends at 0x2000.
+	E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
+	E2010	 starts at 0x100 and ends at 0x4000.
+	E2010-x starts at 0x100 and ends at 0xffff.  */
+
+static int __init do_ne_probe(struct net_device *dev)
+{
+	unsigned int base_addr = dev->base_addr;
+#ifndef MODULE
+	int orig_irq = dev->irq;
+#endif
+
+	SET_MODULE_OWNER(dev);
+
+	/* First check any supplied i/o locations. User knows best. <cough> */
+	if (base_addr > 0x1ff)	/* Check a single specified location. */
+		return ne_probe1(dev, base_addr);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+	/* Then look for any installed ISAPnP clones */
+	if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
+		return 0;
+
+#ifndef MODULE
+	/* Last resort. The semi-risky ISA auto-probe. */
+	for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
+		int ioaddr = netcard_portlist[base_addr];
+		dev->irq = orig_irq;
+		if (ne_probe1(dev, ioaddr) == 0)
+			return 0;
+	}
+#endif
+
+	return -ENODEV;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+	struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+	if (idev)
+		pnp_device_detach(idev);
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr, NE_IO_EXTENT);
+}
+//#ifndef MODULE
+struct net_device * __init rtl8019as_probe(int unit)
+{
+	struct net_device *dev = alloc_ei_netdev();
+	int err;
+
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+#ifdef CONFIG_ARCH_ACTELM7 /* determined by ACTELM7 board design */ 
+	  dev->base_addr = 0x82000600;
+	  dev->irq = 16; //ext2
+#endif
+	err = do_ne_probe(dev);
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	cleanup_card(dev);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
+}
+//#endif //MODULE
+static int __init ne_probe_isapnp(struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
+		struct pnp_dev *idev = NULL;
+
+		while ((idev = pnp_find_dev(NULL,
+					    isapnp_clone_list[i].vendor,
+					    isapnp_clone_list[i].function,
+					    idev))) {
+			/* Avoid already found cards from previous calls */
+			if (pnp_device_attach(idev) < 0)
+				continue;
+			if (pnp_activate_dev(idev) < 0) {
+			      	pnp_device_detach(idev);
+			      	continue;
+			}
+			/* if no io and irq, search for next */
+			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
+				pnp_device_detach(idev);
+				continue;
+			}
+			/* found it */
+			dev->base_addr = pnp_port_start(idev, 0);
+			dev->irq = pnp_irq(idev, 0);
+			printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
+				(char *) isapnp_clone_list[i].driver_data,
+				dev->base_addr, dev->irq);
+			if (ne_probe1(dev, dev->base_addr) != 0) {	/* Shouldn't happen. */
+				printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
+				pnp_device_detach(idev);
+				return -ENXIO;
+			}
+			ei_status.priv = (unsigned long)idev;
+			break;
+		}
+		if (!idev)
+			continue;
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int __init ne_probe1(struct net_device *dev, int ioaddr)
+{
+	int i;
+	unsigned char SA_prom[32];
+	int wordlength = 2;
+	const char *name = NULL;
+	int start_page, stop_page;
+	int neX000, ctron, copam, bad_card;
+	int reg0, ret;
+	static unsigned version_printed;
+
+	if (!request_region(ioaddr, NE_IO_EXTENT, dev->name))
+		return -EBUSY;
+
+	reg0 = inb_p(ioaddr);
+	if (reg0 == 0xFF) {
+		ret = -ENODEV;
+		goto err_out;
+	}
+
+	/* Do a preliminary verification that we have a 8390. */
+	{
+		int regd;
+		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+		regd = inb_p(ioaddr + EN0_COUNTER0);
+		outb_p(0xff, ioaddr + EN0_TXCR);
+		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
+			outb_p(reg0, ioaddr);
+			outb_p(regd, ioaddr + EN0_TXCR);	/* Restore the old values. */
+			ret = -ENODEV;
+			goto err_out;
+		}
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
+
+	printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);
+
+	/* A user with a poor card that fails to ack the reset, or that
+	   does not have a valid 0x57,0x57 signature can still use this
+	   without having to recompile. Specifying an i/o address along
+	   with an otherwise unused dev->mem_end value of "0xBAD" will
+	   cause the driver to skip these parts of the probe. */
+
+	bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+
+	/* initialize rtl8019as related registers */
+	outb_p(E8390_PAGE3, ioaddr + E8390_CMD); // set to page 3
+	outb_p(0xcf, ioaddr + CR9346);  //enable write config reg
+	outb_p(0x60, ioaddr + CONFIG3); //clear pwrdn, sleep mode 
+	outb_p(0x0f, ioaddr + CR9346);  //disable write config reg
+	outb_p(E8390_PAGE0, ioaddr + E8390_CMD); // restore to page 0
+
+	/* Reset card. Who knows what dain-bramaged state it was left in. */
+
+	{
+		unsigned long reset_start_time = jiffies;
+
+		/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+		outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+		while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
+		if (jiffies - reset_start_time > 2*HZ/100) {
+			if (bad_card) {
+				printk(" (warning: no reset ack)");
+				break;
+			} else {
+				printk(" not found (no reset ack).\n");
+				ret = -ENODEV;
+				goto err_out;
+			}
+		}
+
+		outb_p(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
+	}
+
+	/* Read the 16 bytes of station address PROM.
+	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
+	   We can't reliably read the SAPROM address without this.
+	   (I learned the hard way!). */
+	{
+		struct {unsigned char value, offset; } program_seq[] =
+		{
+			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+			{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
+			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_IMR},	/* Mask completion irq. */
+			{0xFF,	EN0_ISR},
+			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
+			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
+			{32,	EN0_RCNTLO},
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
+			{0x00,	EN0_RSARHI},
+			{E8390_RREAD+E8390_START, E8390_CMD},
+		};
+
+		for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
+			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+	}
+
+	for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
+		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+		SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
+		if (SA_prom[i] != SA_prom[i+1])
+			wordlength = 1;
+	}
+
+	if (wordlength == 2)
+	{
+		for (i = 0; i < 16; i++)
+			SA_prom[i] = SA_prom[i+i];
+		/* We must set the 8390 for word mode. */
+		outb_p(0x49, ioaddr + EN0_DCFG);
+		start_page = NESM_START_PG;
+		stop_page = NESM_STOP_PG;
+	} else {
+		start_page = NE1SM_START_PG;
+		stop_page = NE1SM_STOP_PG;
+	}
+
+
+	neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+	ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
+	copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
+
+	/* Set up the rest of the parameters. */
+	if (neX000 || bad_card || copam) {
+		name = (wordlength == 2) ? "NE2000" : "NE1000";
+	}
+	else if (ctron)
+	{
+		name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
+		start_page = 0x01;
+		stop_page = (wordlength == 2) ? 0x40 : 0x20;
+	}
+	else
+	{
+#ifdef SUPPORT_NE_BAD_CLONES
+		/* Ack!  Well, there might be a *bad* NE*000 clone there.
+		   Check for total bogus addresses. */
+		for (i = 0; bad_clone_list[i].name8; i++)
+		{
+			if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
+				SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
+				SA_prom[2] == bad_clone_list[i].SAprefix[2])
+			{
+				if (wordlength == 2)
+				{
+					name = bad_clone_list[i].name16;
+				} else {
+					name = bad_clone_list[i].name8;
+				}
+				break;
+			}
+		}
+		if (bad_clone_list[i].name8 == NULL)
+		{
+			printk(" not found (invalid signature %2.2x %2.2x).\n",
+				SA_prom[14], SA_prom[15]);
+			ret = -ENXIO;
+			goto err_out;
+		}
+#else
+		printk(" not found.\n");
+		ret = -ENXIO;
+		goto err_out;
+#endif
+	}
+
+	if (dev->irq < 2)
+	{
+		unsigned long cookie = probe_irq_on();
+		outb_p(0x50, ioaddr + EN0_IMR);	/* Enable one interrupt. */
+		outb_p(0x00, ioaddr + EN0_RCNTLO);
+		outb_p(0x00, ioaddr + EN0_RCNTHI);
+		outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
+		mdelay(10);		/* wait 10ms for interrupt to propagate */
+		outb_p(0x00, ioaddr + EN0_IMR); 		/* Mask it again. */
+		dev->irq = probe_irq_off(cookie);
+		if (ei_debug > 2)
+			printk(" autoirq is %d\n", dev->irq);
+	} else if (dev->irq == 2)
+		/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
+		   or don't know which one to set. */
+		dev->irq = 9;
+
+	if (! dev->irq) {
+		printk(" failed to detect IRQ line.\n");
+		ret = -EAGAIN;
+		goto err_out;
+	}
+
+	/* Snarf the interrupt now.  There's no point in waiting since we cannot
+	   share and the board will usually be enabled. */
+	ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
+	if (ret) {
+		printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
+		goto err_out;
+	}
+
+	dev->base_addr = ioaddr;
+
+#ifdef CONFIG_ARCH_ACTELM7 /* set a MAC address randomly, only for testing */
+	SA_prom[0] = 0x00;
+	SA_prom[1] = 0x12;
+	SA_prom[2] = 0x34;
+	SA_prom[3] = 0x56;
+	SA_prom[4] = 0x78;
+	SA_prom[5] = 0x9a;
+#endif
+	for(i = 0; i < ETHER_ADDR_LEN; i++) {
+		printk(" %2.2x", SA_prom[i]);
+		dev->dev_addr[i] = SA_prom[i];
+	}
+
+	printk("\n%s: %s found at %#x, using IRQ %d.\n",
+		dev->name, name, ioaddr, dev->irq);
+
+	ei_status.name = name;
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = (wordlength == 2);
+
+	ei_status.rx_start_page = start_page + TX_PAGES;
+#ifdef PACKETBUF_MEMSIZE
+	 /* Allow the packet buffer size to be overridden by know-it-alls. */
+	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+	ei_status.reset_8390 = &ne_reset_8390;
+	ei_status.block_input = &ne_block_input;
+	ei_status.block_output = &ne_block_output;
+	ei_status.get_8390_hdr = &ne_get_8390_hdr;
+	ei_status.priv = 0;
+	dev->open = &ne_open;
+	dev->stop = &ne_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ei_poll;
+#endif
+	NS8390_init(dev, 0);
+	return 0;
+
+err_out:
+	release_region(ioaddr, NE_IO_EXTENT);
+	return ret;
+}
+
+static int ne_open(struct net_device *dev)
+{
+	ei_open(dev);
+	return 0;
+}
+
+static int ne_close(struct net_device *dev)
+{
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+	ei_close(dev);
+	return 0;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+
+static void ne_reset_8390(struct net_device *dev)
+{
+	unsigned long reset_start_time = jiffies;
+
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+		if (jiffies - reset_start_time > 2*HZ/100) {
+			printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+			break;
+		}
+	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	int nic_base = dev->base_addr;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+	outb_p(0, nic_base + EN0_RCNTHI);
+	outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
+	outb_p(ring_page, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.word16)
+		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	else
+		insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+
+	le16_to_cpus(&hdr->count);
+}
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for hints.
+   The NEx000 doesn't share the on-board packet memory -- you have to put
+   the packet out through the "remote DMA" dataport using outb. */
+
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+#ifdef NE_SANITY_CHECK
+	int xfer_count = count;
+#endif
+	int nic_base = dev->base_addr;
+	char *buf = skb->data;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8, nic_base + EN0_RCNTHI);
+	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16)
+	{
+		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+		if (count & 0x01)
+		{
+			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+#ifdef NE_SANITY_CHECK
+			xfer_count++;
+#endif
+		}
+	} else {
+		insb(NE_BASE + NE_DATAPORT, buf, count);
+	}
+
+#ifdef NE_SANITY_CHECK
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here.  If you see
+	   this message you either 1) have a slightly incompatible clone
+	   or 2) have noise/speed problems with your bus. */
+
+	if (ei_debug > 1)
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+			   -- it's broken for Rx on some cards! */
+			int high = inb_p(nic_base + EN0_RSARHI);
+			int low = inb_p(nic_base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if (((ring_offset + xfer_count) & 0xff) == low)
+				break;
+		} while (--tries > 0);
+	 	if (tries <= 0)
+			printk(KERN_WARNING "%s: RX transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, ring_offset + xfer_count, addr);
+	}
+#endif
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+}
+
+static void ne_block_output(struct net_device *dev, int count,
+		const unsigned char *buf, const int start_page)
+{
+	int nic_base = NE_BASE;
+	unsigned long dma_start;
+#ifdef NE_SANITY_CHECK
+	int retries = 0;
+#endif
+
+	/* Round the count up for word writes.  Do we need to do this?
+	   What effect will an odd byte count have on the 8390?
+	   I should check someday. */
+
+	if (ei_status.word16 && (count & 0x01))
+		count++;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing)
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+			"[DMAstat:%d][irqlock:%d]\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+#ifdef NE_SANITY_CHECK
+retry:
+#endif
+
+#ifdef NE8390_RW_BUGFIX
+	/* Handle the read-before-write bug the same way as the
+	   Crynwr packet driver -- the NatSemi method doesn't work.
+	   Actually this doesn't always work either, but if you have
+	   problems with your NEx000 this is better than nothing! */
+
+	outb_p(0x42, nic_base + EN0_RCNTLO);
+	outb_p(0x00,   nic_base + EN0_RCNTHI);
+	outb_p(0x42, nic_base + EN0_RSARLO);
+	outb_p(0x00, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	/* Make certain that the dummy read has occurred. */
+	udelay(6);
+#endif
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+	/* Now the normal output. */
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8,   nic_base + EN0_RCNTHI);
+	outb_p(0x00, nic_base + EN0_RSARLO);
+	outb_p(start_page, nic_base + EN0_RSARHI);
+
+	outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16) {
+		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+	} else {
+		outsb(NE_BASE + NE_DATAPORT, buf, count);
+	}
+
+	dma_start = jiffies;
+
+#ifdef NE_SANITY_CHECK
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here. */
+
+	if (ei_debug > 1)
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			int high = inb_p(nic_base + EN0_RSARHI);
+			int low = inb_p(nic_base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if ((start_page << 8) + count == addr)
+				break;
+		} while (--tries > 0);
+
+		if (tries <= 0)
+		{
+			printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, (start_page << 8) + count, addr);
+			if (retries++ == 0)
+				goto retry;
+		}
+	}
+#endif
+
+	while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
+			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+			ne_reset_8390(dev);
+			NS8390_init(dev,1);
+			break;
+		}
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+	return;
+}
+
+
+#ifdef MODULE
+#define MAX_NE_CARDS	4	/* Max number of NE cards per module */
+static struct net_device *dev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */
+
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
+MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
+MODULE_PARM_DESC(io, "I/O base address(es),required");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
+MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
+that the ne2k probe is the last 8390 based probe to take place (as it
+is at boot) and so the probe will get confused by any other 8390 cards.
+ISA device autoprobes on a running machine are not recommended anyway. */
+
+int init_module(void)
+{
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		struct net_device *dev = alloc_ei_netdev();
+		if (!dev)
+			break;
+		dev->irq = irq[this_dev];
+		dev->mem_end = bad[this_dev];
+		dev->base_addr = io[this_dev];
+		if (do_ne_probe(dev) == 0) {
+			if (register_netdev(dev) == 0) {
+				dev_ne[found++] = dev;
+				continue;
+			}
+			cleanup_card(dev);
+		}
+		free_netdev(dev);
+		if (found)
+			break;
+		if (io[this_dev] != 0)
+			printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
+		else
+			printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+		return -ENXIO;
+	}
+	if (found)
+		return 0;
+	return -ENODEV;
+}
+
+void cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+		struct net_device *dev = dev_ne[this_dev];
+		if (dev) {
+			unregister_netdev(dev);
+			cleanup_card(dev);
+			free_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
diff -Naur linux-2.6.11.8/drivers/net/rtl8019as.h linux-2.6.x/drivers/net/rtl8019as.h
--- linux-2.6.11.8/drivers/net/rtl8019as.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/drivers/net/rtl8019as.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,22 @@
+/* rtl8019as register definitions.
+ *
+ * Copyright (C) Philips Semiconductors
+ *
+*/
+
+#ifndef _rtl8019as_h
+#define _rtl8019as_h
+
+#include "8390.h"
+
+/* PAGE3 is for rtl8019as registers */
+#define E8390_PAGE3	0xC0
+
+/*  Page 3 register offsets */
+#define CR9346		EI_SHIFT(0x01)
+#define CONFIG0		EI_SHIFT(0x03)
+#define CONFIG1		EI_SHIFT(0x04)
+#define CONFIG2		EI_SHIFT(0x05)
+#define CONFIG3		EI_SHIFT(0x06)
+
+#endif /* _rtl8019as_h */
diff -Naur linux-2.6.11.8/drivers/net/Space.c linux-2.6.x/drivers/net/Space.c
--- linux-2.6.11.8/drivers/net/Space.c	2005-04-30 02:23:56.000000000 +0100
+++ linux-2.6.x/drivers/net/Space.c	2009-09-06 22:42:40.000000000 +0100
@@ -47,6 +47,7 @@
 extern struct net_device *wd_probe(int unit);
 extern struct net_device *el2_probe(int unit);
 extern struct net_device *ne_probe(int unit);
+extern struct net_device *rtl8019as_probe(int unit);
 extern struct net_device *hp_probe(int unit);
 extern struct net_device *hp_plus_probe(int unit);
 extern struct net_device *express_probe(int unit);
@@ -195,6 +196,9 @@
     defined(CONFIG_NE_H8300)  /* ISA (use ne2k-pci for PCI cards) */
 	{ne_probe, 0},
 #endif
+#if defined(CONFIG_RTL8019AS) 
+	{rtl8019as_probe, 0},
+#endif
 #ifdef CONFIG_LANCE		/* ISA/VLB (use pcnet32 for PCI cards) */
 	{lance_probe, 0},
 #endif
diff -Naur linux-2.6.11.8/drivers/serial/8250.c linux-2.6.x/drivers/serial/8250.c
--- linux-2.6.11.8/drivers/serial/8250.c	2005-04-30 02:23:21.000000000 +0100
+++ linux-2.6.x/drivers/serial/8250.c	2009-09-06 22:42:40.000000000 +0100
@@ -104,7 +104,12 @@
  */
 #define CONFIG_HUB6 1
 
+#ifdef CONFIG_ARCH_ACTELM7
+#include <asm/arch/serial.h>
+#else
 #include <asm/serial.h>
+#endif
+
 
 /*
  * SERIAL_PORT_DFNS tells us about built-in ports that have no
@@ -792,6 +797,7 @@
 #endif
 		scratch3 = serial_inp(up, UART_IER);
 		serial_outp(up, UART_IER, scratch);
+
 		if (scratch2 != 0 || scratch3 != 0x0F) {
 			/*
 			 * We failed; there's nothing here
diff -Naur linux-2.6.11.8/drivers/video/fbmem.c linux-2.6.x/drivers/video/fbmem.c
--- linux-2.6.11.8/drivers/video/fbmem.c	2005-04-30 02:22:33.000000000 +0100
+++ linux-2.6.x/drivers/video/fbmem.c	2009-09-06 22:42:40.000000000 +0100
@@ -978,7 +978,7 @@
 #else
 #warning What do we have to do here??
 #endif
-	if (io_remap_page_range(vma, vma->vm_start, off,
+	if (remap_pfn_range(vma, vma->vm_start, off,
 			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
 #endif /* !__sparc_v9__ */
diff -Naur linux-2.6.11.8/drivers/video/Kconfig linux-2.6.x/drivers/video/Kconfig
--- linux-2.6.11.8/drivers/video/Kconfig	2005-04-30 02:23:15.000000000 +0100
+++ linux-2.6.x/drivers/video/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -1053,6 +1053,13 @@
 
 	  Say Y here to enable kernel support for the on-board framebuffer.
 
+config FB_VHDLFB
+       bool "ActelM7 frame buffer driver support"
+       depends on FB
+       help
+	 Select this option if you have ACTEL board and would like to use
+	 the linux frame buffer	
+
 config FB_G364
 	bool
 	depends on MIPS_MAGNUM_4000 || OLIVETTI_M700
diff -Naur linux-2.6.11.8/drivers/video/Makefile linux-2.6.x/drivers/video/Makefile
--- linux-2.6.11.8/drivers/video/Makefile	2005-04-30 02:23:57.000000000 +0100
+++ linux-2.6.x/drivers/video/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -98,6 +98,7 @@
 obj-$(CONFIG_FB_PMAGB_B)	  += pmagb-b-fb.o  cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_MAXINE)		  += maxinefb.o  cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_TX3912)		  += tx3912fb.o  cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_VHDLFB)		  += vhdlfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
diff -Naur linux-2.6.11.8/drivers/video/vhdlfb.c linux-2.6.x/drivers/video/vhdlfb.c
--- linux-2.6.11.8/drivers/video/vhdlfb.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/drivers/video/vhdlfb.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,446 @@
+/*
+ *  linux/drivers/video/vhdlfb.c -- Low level implementation of a
+ *                                  vhdl LCD frame buffer device
+ *
+ *  this version is based on :
+ *
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *  Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#define VHDLFB_MAX_Y 240
+#define VHDLFB_MAX_X 320
+#define VHDLFB_MIN_Y 240
+#define VHDLFB_MIN_X 320
+#define VHDLFB_VIDEOMEMSTART 0x40000000
+#define VHDLFB_VIDEOMEMSIZE 0x2580
+
+static u_long videomemory = VHDLFB_VIDEOMEMSTART;
+static u_long videomemorysize = VHDLFB_VIDEOMEMSIZE;
+
+static struct fb_info fb_info;
+
+static struct fb_var_screeninfo vhdlfb_default __initdata = {
+		.xres = VHDLFB_MIN_X,
+        .yres = VHDLFB_MIN_Y,
+		.xres_virtual = VHDLFB_MAX_X,
+		.yres_virtual = VHDLFB_MAX_Y,
+		.bits_per_pixel = 1,
+		.red =		{ 0, 1, 0 },
+      	.green =	{ 0, 1, 0 },
+      	.blue =		{ 0, 1, 0 },
+      	.activate =	FB_ACTIVATE_TEST,
+      	.height =	-1,
+      	.width =	-1,
+      	.left_margin =	0,
+      	.right_margin =	0,
+      	.upper_margin =	0,
+      	.lower_margin =	0,
+      	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo vhdlfb_fix __initdata = {
+	.id =		"vhdlfb",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_MONO01,
+	.xpanstep =	0,
+	.ypanstep =	0,
+	.ywrapstep =    0,
+	.accel =	FB_ACCEL_NONE,
+}; 
+
+    /*
+     *  Interface used by the world
+     */
+int vhdlfb_init(void);
+
+static int vhdlfb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info);
+static int vhdlfb_set_par(struct fb_info *info);
+static int vhdlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info);
+static int vhdlfb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info);
+static int vhdlfb_mmap(struct fb_info *info, struct file *file,
+		    struct vm_area_struct *vma);
+
+static struct fb_ops vhdlfb_ops = {
+	.fb_check_var	= vhdlfb_check_var,
+	.fb_set_par	= vhdlfb_set_par,
+	.fb_setcolreg	= vhdlfb_setcolreg,
+	//.fb_pan_display	= vhdlfb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_mmap	= vhdlfb_mmap,
+};
+
+    /*
+     *  Internal routines
+     */
+
+static u_long get_line_length(int xres_virtual, int bpp)
+{
+	u_long length;
+
+	length = xres_virtual * bpp;
+	length = (length + 31) & ~31;
+	length >>= 3;
+	return (length);
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var. 
+     */
+
+static int vhdlfb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+	u_long line_length;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/*
+	 *  Some very basic checks
+	 */
+	if (!var->xres)
+		var->xres = VHDLFB_MIN_X;
+	if (!var->yres)
+		var->yres = VHDLFB_MIN_Y;
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+	if (var->bits_per_pixel <= 1)
+		var->bits_per_pixel = 1;
+	else if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xoffset + var->xres)
+		var->xres_virtual = var->xoffset + var->xres;
+	if (var->yres_virtual < var->yoffset + var->yres)
+		var->yres_virtual = var->yoffset + var->yres;
+
+	/*
+	 *  Memory limit
+	 */
+	line_length =
+	    get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > videomemorysize)
+		return -ENOMEM;
+
+	/*
+	 * Now that we checked it we alter var. The reason being is that the video
+	 * mode passed in might not work but slight changes to it might make it 
+	 * work. This way we let the user know what is acceptable.
+	 */
+	switch (var->bits_per_pixel) {
+	case 1:
+		var->red.offset = 0;
+		var->red.length = 1;
+		var->green.offset = 0;
+		var->green.length = 1;
+		var->blue.offset = 0;
+		var->blue.length = 1;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGBA 5551 */
+		if (var->transp.length) {
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 10;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else {	/* RGB 565 */
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 11;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24:		/* RGB 888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	return 0;
+}
+
+/* This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the 
+ * change in par. For this driver it doesn't do much. 
+ */
+static int vhdlfb_set_par(struct fb_info *info)
+{
+	info->fix.line_length = get_line_length(info->var.xres_virtual,
+						info->var.bits_per_pixel);
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int vhdlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info)
+{
+	if (regno >= 256)	/* no. of hw registers */
+		return 1;
+	/*
+	 * Program hardware... do anything you want with transp
+	 */
+
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Directcolor:
+	 *   var->{color}.offset contains start of bitfield
+	 *   var->{color}.length contains length of bitfield
+	 *   {hardwarespecific} contains width of RAMDAC
+	 *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+	 *   RAMDAC[X] is programmed to (red, green, blue)
+	 * 
+	 * Pseudocolor:
+	 *    uses offset = 0 && length = RAMDAC register width.
+	 *    var->{color}.offset is 0
+	 *    var->{color}.length contains widht of DAC
+	 *    cmap is not used
+	 *    RAMDAC[X] is programmed to (red, green, blue)
+	 * Truecolor:
+	 *    does not use DAC. Usually 3 are present.
+	 *    var->{color}.offset contains start of bitfield
+	 *    var->{color}.length contains length of bitfield
+	 *    cmap is programmed to (red << red.offset) | (green << green.offset) |
+	 *                      (blue << blue.offset) | (transp << transp.offset)
+	 *    RAMDAC does not exist
+	 */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		transp = CNVT_TOHW(transp, info->var.transp.length);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return 1;
+
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		case 24:
+		case 32:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+    /*
+     *  Pan or Wrap the Display
+     *
+     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+     */
+
+static int vhdlfb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset < 0
+		    || var->yoffset >= info->var.yres_virtual
+		    || var->xoffset)
+			return -EINVAL;
+	} else {
+		if (var->xoffset + var->xres > info->var.xres_virtual ||
+		    var->yoffset + var->yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+    /*
+     *  Most drivers don't need their own mmap function 
+     */
+
+static int vhdlfb_mmap(struct fb_info *info, struct file *file,
+		    struct vm_area_struct *vma)
+{
+#ifndef MMU
+	/* this is uClinux (no MMU) specific code */
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_start = videomemory;
+
+	return 0;
+#else
+	return -EINVAL;
+#endif
+}
+    /*
+     *  Initialisation
+     */
+
+int __init vhdlfb_init(void)
+{
+	/*
+	 *  initialize the default mode from the LCD controller registers
+	 */
+	fb_info.screen_base = (void *)videomemory;
+	fb_info.fbops = &vhdlfb_ops;
+	fb_info.var = vhdlfb_default;
+	fb_info.fix = vhdlfb_fix;
+	fb_info.fix.smem_start = videomemory;
+	fb_info.fix.smem_len = videomemorysize;
+	fb_info.fix.line_length =
+		get_line_length(vhdlfb_default.xres_virtual, vhdlfb_default.bits_per_pixel);
+	fb_info.fix.visual = FB_VISUAL_MONO01;
+	if (fb_info.var.bits_per_pixel == 1) {
+		fb_info.var.red.length = fb_info.var.green.length = fb_info.var.blue.length = 1;
+		fb_info.var.red.offset = fb_info.var.green.offset = fb_info.var.blue.offset = 0;
+	}
+
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	if (register_framebuffer(&fb_info) < 0) {
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO
+		"fb%d: %s frame buffer device\n", fb_info.node,	fb_info.fix.id);
+	printk(KERN_INFO
+		"fb%d: %dx%dx%d at 0x%08lx\n", fb_info.node,
+		vhdlfb_default.xres_virtual, vhdlfb_default.yres_virtual,
+		1 << vhdlfb_default.bits_per_pixel, videomemory);
+
+	return 0;
+}
+
+module_init(vhdlfb_init);
+
+#ifdef MODULE
+
+static void __exit vhdlfb_cleanup(void)
+{
+	unregister_framebuffer(&fb_info);
+}
+
+module_exit(vhdlfb_cleanup);
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
diff -Naur linux-2.6.11.8/fs/jffs2/pushpull.c linux-2.6.x/fs/jffs2/pushpull.c
--- linux-2.6.11.8/fs/jffs2/pushpull.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/fs/jffs2/pushpull.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,71 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2001 Red Hat, Inc.
+ *
+ * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
+ *
+ * The original JFFS, from which the design for JFFS2 was derived,
+ * was designed and implemented by Axis Communications AB.
+ *
+ * The contents of this file are subject to the Red Hat eCos Public
+ * License Version 1.1 (the "Licence"); you may not use this file
+ * except in compliance with the Licence.  You may obtain a copy of
+ * the Licence at http://www.redhat.com/
+ *
+ * Software distributed under the Licence is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing rights and
+ * limitations under the Licence.
+ *
+ * The Original Code is JFFS2 - Journalling Flash File System, version 2
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above.  If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the RHEPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL.  If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the RHEPL or the GPL.
+ *
+ * $Id: pushpull.c,v 1.7 2001/09/23 10:04:15 rmk Exp $
+ *
+ */
+
+#include <linux/string.h>
+#include "pushpull.h"
+#include <linux/errno.h>
+
+void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve)
+{
+	pp->buf = buf;
+	pp->buflen = buflen;
+	pp->ofs = ofs;
+	pp->reserve = reserve;
+}
+     
+
+int pushbit(struct pushpull *pp, int bit, int use_reserved)
+{
+	if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) {
+		return -ENOSPC;
+	}
+
+	if (bit) {
+		pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7)));
+	}
+	else {
+		pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7)));
+	}
+	pp->ofs++;
+
+	return 0;
+}
+
+int pushedbits(struct pushpull *pp)
+{
+	return pp->ofs;
+}
diff -Naur linux-2.6.11.8/fs/jffs2/zlib.c linux-2.6.x/fs/jffs2/zlib.c
--- linux-2.6.11.8/fs/jffs2/zlib.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/fs/jffs2/zlib.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,2194 @@
+/*
+ * This file is derived from various .h and .c files from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.  See zlib.h for conditions of
+ * distribution and use.
+ *
+ * Changes that have been made include:
+ * - changed functions not used outside this file to "local"
+ * - added minCompression parameter to deflateInit2
+ * - added Z_PACKET_FLUSH (see zlib.h for details)
+ * - added inflateIncomp
+ *
+  Copyright (C) 1995 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
+
+ *
+ * 
+ */
+
+/*+++++*/
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
+
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+#define FAR
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern char *z_errmsg[]; /* indexed by 1-zlib_error */
+
+#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
+/* To be used only when the state is known to be valid */
+
+#ifndef NULL
+#define NULL	((void *) 0)
+#endif
+
+        /* common constants */
+
+#define DEFLATED   8
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+         /* functions */
+
+extern void *memcpy(void *, const void *, unsigned long);
+#define zmemcpy memcpy
+
+/* Diagnostic functions */
+#ifdef DEBUG_ZLIB
+#  include <stdio.h>
+#  ifndef verbose
+#    define verbose 0
+#  endif
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
+
+/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
+/* void   zcfree  OF((voidpf opaque, voidpf ptr)); */
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr, size)	\
+	   (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
+#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
+
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/*+++++*/
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+local inflate_blocks_statef * inflate_blocks_new OF((
+    z_stream *z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+local int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));                      /* initial return code */
+
+local void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    uLongf *));                  /* check value on output */
+
+local int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    uLongf *));                  /* check value on output */
+
+local int inflate_addhistory OF((
+    inflate_blocks_statef *,
+    z_stream *));
+
+local int inflate_packet_flush OF((
+    inflate_blocks_statef *));
+
+/*+++++*/
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+  union {
+    struct {
+      Byte Exop;        /* number of extra bits or operation */
+      Byte Bits;        /* number of bits in this code or subcode */
+    } what;
+    uInt Nalloc;	/* number of these allocated here */
+    Bytef *pad;         /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit machines) */
+  union {
+    uInt Base;          /* literal, length base, or distance base */
+    inflate_huft *Next; /* pointer to next level of table */
+  } more;
+};
+
+#ifdef DEBUG_ZLIB
+  local uInt inflate_hufts;
+#endif
+
+local int inflate_trees_bits OF((
+    uIntf *,                    /* 19 code lengths */
+    uIntf *,                    /* bits tree desired/actual depth */
+    inflate_huft * FAR *,       /* bits tree result */
+    z_stream *));               /* for zalloc, zfree functions */
+
+local int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uIntf *,                    /* that many (total) code lengths */
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    z_stream *));               /* for zalloc, zfree functions */
+
+local int inflate_trees_fixed OF((
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *));     /* distance tree result */
+
+local int inflate_trees_free OF((
+    inflate_huft *,             /* tables to free */
+    z_stream *));               /* for zfree function */
+
+
+/*+++++*/
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+local inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_stream *));
+
+local int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));
+
+local void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_stream *));
+
+
+/*+++++*/
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  enum {
+      METHOD,   /* waiting for method byte */
+      FLAG,     /* waiting for flag byte */
+      BLOCKS,   /* decompressing blocks */
+      CHECK4,   /* four check bytes to go */
+      CHECK3,   /* three check bytes to go */
+      CHECK2,   /* two check bytes to go */
+      CHECK1,   /* one check byte to go */
+      DONE,     /* finished check, done */
+      BAD}      /* got an error--stay here */
+    mode;               /* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;        /* if FLAGS, method byte */
+    struct {
+      uLong was;                /* computed check value */
+      uLong need;               /* stream check value */
+    } check;            /* if CHECK, check values to compare */
+    uInt marker;        /* if BAD, inflateSync's marker bytes count */
+  } sub;        /* submode */
+
+  /* mode independent information */
+  int  nowrap;          /* flag for no wrapper */
+  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
+  inflate_blocks_statef 
+    *blocks;            /* current inflate_blocks state */
+
+};
+
+
+int inflateReset(
+	z_stream *z
+)
+{
+  uLong c;
+
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+  inflate_blocks_reset(z->state->blocks, z, &c);
+  Trace((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+
+int inflateEnd(
+	z_stream *z
+)
+{
+  uLong c;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z, &c);
+  ZFREE(z, z->state, sizeof(struct internal_state));
+  z->state = Z_NULL;
+  Trace((stderr, "inflate: end\n"));
+  return Z_OK;
+}
+
+
+int inflateInit2(
+	z_stream *z,
+	int w
+)
+{
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+/*  if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
+/*  if (z->zfree == Z_NULL) z->zfree = zcfree; */
+  if ((z->state = (struct internal_state FAR *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->blocks = Z_NULL;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Trace((stderr, "inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+
+
+int inflateInit(
+	z_stream *z
+)
+{
+  return inflateInit2(z, DEF_WBITS);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int inflate(
+	z_stream *z,
+	int f	
+)
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      NEEDBYTE
+      if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
+      {
+        z->state->mode = BAD;
+        z->msg = "unknown compression method";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+      {
+        z->state->mode = BAD;
+        z->msg = "invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      NEEDBYTE
+      if ((b = NEXTBYTE) & 0x20)
+      {
+        z->state->mode = BAD;
+        z->msg = "invalid reserved bit";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = BAD;
+        z->msg = "incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Trace((stderr, "inflate: zlib header ok\n"));
+      z->state->mode = BLOCKS;
+    case BLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
+	  r = inflate_packet_flush(z->state->blocks);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = BAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r != Z_STREAM_END)
+        return r;
+      r = Z_OK;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = DONE;
+        break;
+      }
+      z->state->mode = CHECK4;
+    case CHECK4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = CHECK3;
+    case CHECK3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = CHECK2;
+    case CHECK2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = CHECK1;
+    case CHECK1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = BAD;
+        z->msg = "incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Trace((stderr, "inflate: zlib check ok\n"));
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case BAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+
+ empty:
+  if (f != Z_PACKET_FLUSH)
+    return r;
+  z->state->mode = BAD;
+  z->state->sub.marker = 0;       /* can try inflateSync */
+  return Z_DATA_ERROR;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+
+int inflateIncomp(
+	z_stream *z
+)
+{
+    if (z->state->mode != BLOCKS)
+	return Z_DATA_ERROR;
+    return inflate_addhistory(z->state->blocks, z);
+}
+
+
+int inflateSync(
+	z_stream *z
+)
+{
+  uInt n;       /* number of bytes to look at */
+  Bytef *p;     /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != BAD)
+  {
+    z->state->mode = BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    if (*p == (Byte)(m < 2 ? 0 : 0xff))
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+#undef NEEDBYTE
+#undef NEXTBYTE
+
+/*+++++*/
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  enum {
+      TYPE,     /* get type bits (3, including end bit) */
+      LENS,     /* get lengths for stored */
+      STORED,   /* processing stored block */
+      TABLE,    /* get table lengths */
+      BTREE,    /* get bit lengths tree for a dynamic block */
+      DTREE,    /* get length, distance trees for a dynamic block */
+      CODES,    /* processing fixed or dynamic block */
+      DRY,      /* output remaining window bytes */
+      DONEB,     /* finished last block, done */
+      BADB}      /* got a data error--stuck here */
+    mode;               /* current inflate_block mode */
+
+  /* mode dependent information */
+  union {
+    uInt left;          /* if STORED, bytes left to copy */
+    struct {
+      uInt table;               /* table lengths (14 bits) */
+      uInt index;               /* index into blens (or border) */
+      uIntf *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+      int nblens;		/* # elements allocated at blens */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_huft *tl, *td;    /* trees to free */
+      inflate_codes_statef 
+         *codes;
+    } decode;           /* if CODES, current state */
+  } sub;                /* submode */
+  uInt last;            /* true if this block is the last block */
+
+  /* mode independent information */
+  uInt bitk;            /* bits in bit buffer */
+  uLong bitb;           /* bit buffer */
+  Bytef *window;        /* sliding window */
+  Bytef *end;           /* one byte after sliding window */
+  Bytef *read;          /* window read pointer */
+  Bytef *write;         /* window write pointer */
+  check_func checkfn;   /* check function */
+  uLong check;          /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/*   update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/*   get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/*   output bytes */
+#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/*   load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* And'ing with mask[n] masks the lower n bits */
+local uInt inflate_mask[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));
+
+/*+++++*/
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+local int inflate_fast OF((
+    uInt,
+    uInt,
+    inflate_huft *,
+    inflate_huft *,
+    inflate_blocks_statef *,
+    z_stream *));
+
+
+/*+++++*/
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local uInt border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+local void inflate_blocks_reset(
+	inflate_blocks_statef *s,
+	z_stream *z,
+	uLongf *c
+)
+{
+  if (s->checkfn != Z_NULL)
+    *c = s->check;
+  if (s->mode == BTREE || s->mode == DTREE)
+    ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+  if (s->mode == CODES)
+  {
+    inflate_codes_free(s->sub.decode.codes, z);
+    inflate_trees_free(s->sub.decode.td, z);
+    inflate_trees_free(s->sub.decode.tl, z);
+  }
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    s->check = (*s->checkfn)(0L, Z_NULL, 0);
+  Trace((stderr, "inflate:   blocks reset\n"));
+}
+
+
+local inflate_blocks_statef *inflate_blocks_new(
+	z_stream *z,
+	check_func c,
+	uInt w
+)
+{
+  inflate_blocks_statef *s;
+
+  if ((s = (inflate_blocks_statef *)ZALLOC
+       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+    return s;
+  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+  {
+    ZFREE(z, s, sizeof(struct inflate_blocks_state));
+    return Z_NULL;
+  }
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Trace((stderr, "inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, &s->check);
+  return s;
+}
+
+
+local int inflate_blocks(
+	inflate_blocks_statef *s,
+	z_stream *z,
+	int r
+)
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input based on current state */
+  while (1) switch (s->mode)
+  {
+    case TYPE:
+      NEEDBITS(3)
+      t = (uInt)b & 7;
+      s->last = t & 1;
+      switch (t >> 1)
+      {
+        case 0:                         /* stored */
+          Trace((stderr, "inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Trace((stderr, "inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, &tl, &td);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+            s->sub.decode.tl = Z_NULL;  /* don't try to free these */
+            s->sub.decode.td = Z_NULL;
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Trace((stderr, "inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BADB;
+          z->msg = "invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if (((~b) >> 16) != (b & 0xffff))
+      {
+        s->mode = BADB;
+        z->msg = "invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : TYPE;
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      zmemcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev((stderr, "inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      s->mode = s->last ? DRY : TYPE;
+      break;
+    case TABLE:
+      NEEDBITS(14)
+      s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+      {
+        s->mode = BADB;
+        z->msg = "too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+      if (t < 19)
+        t = 19;
+      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+      {
+        r = Z_MEM_ERROR;
+        LEAVE
+      }
+      s->sub.trees.nblens = t;
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       table sizes ok\n"));
+      s->mode = BTREE;
+    case BTREE:
+      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+      {
+        NEEDBITS(3)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+        DUMPBITS(3)
+      }
+      while (s->sub.trees.index < 19)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+      s->sub.trees.bb = 7;
+      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, z);
+      if (t != Z_OK)
+      {
+        r = t;
+        if (r == Z_DATA_ERROR)
+          s->mode = BADB;
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       bits tree ok\n"));
+      s->mode = DTREE;
+    case DTREE:
+      while (t = s->sub.trees.table,
+             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+      {
+        inflate_huft *h;
+        uInt i, j, c;
+
+        t = s->sub.trees.bb;
+        NEEDBITS(t)
+        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+        t = h->word.what.Bits;
+        c = h->more.Base;
+        if (c < 16)
+        {
+          DUMPBITS(t)
+          s->sub.trees.blens[s->sub.trees.index++] = c;
+        }
+        else /* c == 16..18 */
+        {
+          i = c == 18 ? 7 : c - 14;
+          j = c == 18 ? 11 : 3;
+          NEEDBITS(t + i)
+          DUMPBITS(t)
+          j += (uInt)b & inflate_mask[i];
+          DUMPBITS(i)
+          i = s->sub.trees.index;
+          t = s->sub.trees.table;
+          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+              (c == 16 && i < 1))
+          {
+            s->mode = BADB;
+            z->msg = "invalid bit length repeat";
+            r = Z_DATA_ERROR;
+            LEAVE
+          }
+          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+          do {
+            s->sub.trees.blens[i++] = c;
+          } while (--j);
+          s->sub.trees.index = i;
+        }
+      }
+      inflate_trees_free(s->sub.trees.tb, z);
+      s->sub.trees.tb = Z_NULL;
+      {
+        uInt bl, bd;
+        inflate_huft *tl, *td;
+        inflate_codes_statef *c;
+
+        bl = 9;         /* must be <= 9 for lookahead assumptions */
+        bd = 6;         /* must be <= 9 for lookahead assumptions */
+        t = s->sub.trees.table;
+        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+            s->mode = BADB;
+          r = t;
+          LEAVE
+        }
+        Tracev((stderr, "inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          inflate_trees_free(td, z);
+          inflate_trees_free(tl, z);
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+        s->sub.decode.codes = c;
+        s->sub.decode.tl = tl;
+        s->sub.decode.td = td;
+      }
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      inflate_trees_free(s->sub.decode.td, z);
+      inflate_trees_free(s->sub.decode.tl, z);
+      LOAD
+      Tracev((stderr, "inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      if (k > 7)              /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;                    /* can always return one */
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONEB;
+    case DONEB:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADB:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+local int inflate_blocks_free(
+	inflate_blocks_statef *s,
+	z_stream *z,
+	uLongf *c
+)
+{
+  inflate_blocks_reset(s, z, c);
+  ZFREE(z, s->window, s->end - s->window);
+  ZFREE(z, s, sizeof(struct inflate_blocks_state));
+  Trace((stderr, "inflate:   blocks freed\n"));
+  return Z_OK;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+local int inflate_addhistory(
+	inflate_blocks_statef *s,
+	z_stream *z
+)
+{
+    uLong b;              /* bit buffer */  /* NOT USED HERE */
+    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
+    uInt t;               /* temporary storage */
+    Bytef *p;             /* input data pointer */
+    uInt n;               /* bytes available there */
+    Bytef *q;             /* output window write pointer */
+    uInt m;               /* bytes to end of window or read pointer */
+
+    if (s->read != s->write)
+	return Z_STREAM_ERROR;
+    if (s->mode != TYPE)
+	return Z_DATA_ERROR;
+
+    /* we're ready to rock */
+    LOAD
+    /* while there is input ready, copy to output buffer, moving
+     * pointers as needed.
+     */
+    while (n) {
+	t = n;  /* how many to do */
+	/* is there room until end of buffer? */
+	if (t > m) t = m;
+	/* update check information */
+	if (s->checkfn != Z_NULL)
+	    s->check = (*s->checkfn)(s->check, q, t);
+	zmemcpy(q, p, t);
+	q += t;
+	p += t;
+	n -= t;
+	z->total_out += t;
+	s->read = q;    /* drag read pointer forward */
+/*      WRAP  */ 	/* expand WRAP macro by hand to handle s->read */
+	if (q == s->end) {
+	    s->read = q = s->window;
+	    m = WAVAIL;
+	}
+    }
+    UPDATE
+    return Z_OK;
+}
+
+
+/*
+ * At the end of a Deflate-compressed PPP packet, we expect to have seen
+ * a `stored' block type value but not the (zero) length bytes.
+ */
+local int inflate_packet_flush(
+	inflate_blocks_statef *s
+)
+{
+    if (s->mode != LENS)
+	return Z_DATA_ERROR;
+    s->mode = TYPE;
+    return Z_OK;
+}
+
+
+/*+++++*/
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+    uIntf *,            /* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    uIntf *,            /* list of base values for non-simple codes */
+    uIntf *,            /* list of extra bits for non-simple codes */
+    inflate_huft * FAR*,/* result: starting table */
+    uIntf *,            /* maximum lookup bits (returns actual) */
+    z_stream *));       /* for zalloc function */
+
+local voidpf falloc OF((
+    voidpf,             /* opaque pointer (not used) */
+    uInt,               /* number of items */
+    uInt));             /* size of item */
+
+local void ffree OF((
+    voidpf q,           /* opaque pointer (not used) */
+    voidpf p,           /* what to free (not used) */
+    uInt n));		/* number of bytes (not used) */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* actually lengths - 2; also see note #13 above about 258 */
+local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
+local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+local uInt cpdext[] = { /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+#define N_MAX 288       /* maximum number of codes in any set */
+
+#ifdef DEBUG_ZLIB
+  uInt inflate_hufts;
+#endif
+
+local int huft_build(
+	uIntf *b,               /* code lengths in bits (all assumed <= BMAX) */
+	uInt n,                 /* number of codes (assumed <= N_MAX) */
+	uInt s,                 /* number of simple-valued codes (0..s-1) */
+	uIntf *d,               /* list of base values for non-simple codes */
+	uIntf *e,               /* list of extra bits for non-simple codes */
+	inflate_huft * FAR *t,  /* result: starting table */
+	uIntf *m,               /* maximum lookup bits, returns actual */
+	z_stream *zs            /* for zalloc function */
+)
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+   if the given code set is incomplete (the tables are still built in this
+   case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
+   over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+  uInt a;                       /* counter for codes of length k */
+  uInt c[BMAX+1];               /* bit length count table */
+  uInt f;                       /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register uInt i;              /* counter, current code */
+  register uInt j;              /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  register uIntf *p;            /* pointer into c[], b[], or v[] */
+  inflate_huft *q;              /* points to current table */
+  struct inflate_huft_s r;      /* table entry for structure assignment */
+  inflate_huft *u[BMAX];        /* table stack */
+  uInt v[N_MAX];                /* values in order of bit length */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uIntf *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+  C4                            /* clear c[]--assume BMAX+1 is 16 */
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((uInt)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((uInt)l > i)
+    l = i;
+  *m = l;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return Z_DATA_ERROR;
+  if ((y -= c[i]) < 0)
+    return Z_DATA_ERROR;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_NULL;   /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = (z = g - w) > (uInt)l ? l : z;      /* table size upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          if (j < z)
+            while (++j < z)     /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;          /* enough codes to use up j bits */
+              f -= *xp;         /* else deduct codes from patterns */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate and link in new table */
+        if ((q = (inflate_huft *)ZALLOC
+             (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+        {
+          if (h)
+            inflate_trees_free(u[0], zs);
+          return Z_MEM_ERROR;   /* not enough memory */
+        }
+	q->word.Nalloc = z + 1;
+#ifdef DEBUG_ZLIB
+        inflate_hufts += z + 1;
+#endif
+        *t = q + 1;             /* link to list for huft_free() */
+        *(t = &(q->next)) = Z_NULL;
+        u[h] = ++q;             /* table starts after link */
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.bits = (Byte)l;     /* bits to dump before this table */
+          r.exop = (Byte)j;     /* bits in this table */
+          r.next = q;           /* pointer to this table */
+          j = i >> (w - l);     /* (get around Turbo C bug) */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+      }
+
+      /* set up table entry in r */
+      r.bits = (Byte)(k - w);
+      if (p >= v + n)
+        r.exop = 128 + 64;      /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
+        r.base = *p++;          /* simple code is just the value */
+      }
+      else
+      {
+        r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
+        r.base = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      while ((i & ((1 << w) - 1)) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+local int inflate_trees_bits(
+	uIntf *c,               /* 19 code lengths */
+	uIntf *bb,              /* bits tree desired/actual depth */
+	inflate_huft * FAR *tb, /* bits tree result */
+	z_stream *z             /* for zfree function */
+)
+{
+  int r;
+
+  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+  if (r == Z_DATA_ERROR)
+    z->msg = "oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR)
+  {
+    inflate_trees_free(*tb, z);
+    z->msg = "incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  return r;
+}
+
+
+local int inflate_trees_dynamic(
+	uInt nl,                /* number of literal/length codes */
+	uInt nd,                /* number of distance codes */
+	uIntf *c,               /* that many (total) code lengths */
+	uIntf *bl,              /* literal desired/actual bit depth */
+	uIntf *bd,              /* distance desired/actual bit depth */
+	inflate_huft * FAR *tl, /* literal/length tree result */
+	inflate_huft * FAR *td, /* distance tree result */
+	z_stream *z             /* for zfree function */
+)
+{
+  int r;
+
+  /* build literal/length tree */
+  if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = "oversubscribed literal/length tree";
+    else if (r == Z_BUF_ERROR)
+    {
+      inflate_trees_free(*tl, z);
+      z->msg = "incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    return r;
+  }
+
+  /* build distance tree */
+  if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = "oversubscribed literal/length tree";
+    else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      inflate_trees_free(*td, z);
+      z->msg = "incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    inflate_trees_free(*tl, z);
+    return r;
+#endif
+  }
+
+  /* done */
+  return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+local int fixed_lock = 0;
+local int fixed_built = 0;
+#define FIXEDH 530      /* number of hufts used by fixed tables */
+local uInt fixed_left = FIXEDH;
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+
+
+local voidpf falloc(
+	voidpf q,       /* opaque pointer (not used) */
+	uInt n,         /* number of items */
+	uInt s          /* size of item */
+)
+{
+  Assert(s == sizeof(inflate_huft) && n <= fixed_left,
+         "inflate_trees falloc overflow");
+  if (q) s++; /* to make some compilers happy */
+  fixed_left -= n;
+  return (voidpf)(fixed_mem + fixed_left);
+}
+
+
+local void ffree(
+	voidpf q,
+	voidpf p,
+	uInt n
+)
+{
+  Assert(0, "inflate_trees ffree called!");
+  if (q) q = p; /* to make some compilers happy */
+}
+
+
+local int inflate_trees_fixed(
+	uIntf *bl,               /* literal desired/actual bit depth */
+	uIntf *bd,               /* distance desired/actual bit depth */
+	inflate_huft * FAR *tl,  /* literal/length tree result */
+	inflate_huft * FAR *td   /* distance tree result */
+)
+{
+  /* build fixed tables if not built already--lock out other instances */
+  while (++fixed_lock > 1)
+    fixed_lock--;
+  if (!fixed_built)
+  {
+    int k;              /* temporary variable */
+    unsigned c[288];    /* length list for huft_build */
+    z_stream z;         /* for falloc function */
+
+    /* set up fake z_stream for memory routines */
+    z.zalloc = falloc;
+    z.zfree = ffree;
+    z.opaque = Z_NULL;
+
+    /* literal table */
+    for (k = 0; k < 144; k++)
+      c[k] = 8;
+    for (; k < 256; k++)
+      c[k] = 9;
+    for (; k < 280; k++)
+      c[k] = 7;
+    for (; k < 288; k++)
+      c[k] = 8;
+    fixed_bl = 7;
+    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+
+    /* distance table */
+    for (k = 0; k < 30; k++)
+      c[k] = 5;
+    fixed_bd = 5;
+    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
+
+    /* done */
+    fixed_built = 1;
+  }
+  fixed_lock--;
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
+
+
+local int inflate_trees_free(
+	inflate_huft *t,        /* table to free */
+	z_stream *z             /* for zfree function */
+)
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+  register inflate_huft *p, *q;
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != Z_NULL)
+  {
+    q = (--p)->next;
+    ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
+    p = q;
+  } 
+  return Z_OK;
+}
+
+/*+++++*/
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+      START,    /* x: set up for LEN */
+      LEN,      /* i: get length/literal/eob next */
+      LENEXT,   /* i: getting length extra (have base) */
+      DIST,     /* i: get distance next */
+      DISTEXT,  /* i: getting distance extra */
+      COPY,     /* o: copying bytes in window, waiting for space */
+      LIT,      /* o: got literal, waiting for output space */
+      WASH,     /* o: got eob, possibly still output waiting */
+      END,      /* x: got eob and all data flushed */
+      BADCODE}  /* x: got error */
+    mode;               /* current inflate_codes mode */
+
+  /* mode dependent information */
+  uInt len;
+  union {
+    struct {
+      inflate_huft *tree;       /* pointer into tree */
+      uInt need;                /* bits needed */
+    } code;             /* if LEN or DIST, where in tree */
+    uInt lit;           /* if LIT, literal */
+    struct {
+      uInt get;                 /* bits to get for extra */
+      uInt dist;                /* distance back to copy from */
+    } copy;             /* if EXT or COPY, where and how much */
+  } sub;                /* submode */
+
+  /* mode independent information */
+  Byte lbits;           /* ltree bits decoded per branch */
+  Byte dbits;           /* dtree bits decoder per branch */
+  inflate_huft *ltree;          /* literal/length/eob tree */
+  inflate_huft *dtree;          /* distance tree */
+
+};
+
+
+local inflate_codes_statef *inflate_codes_new(
+	uInt bl,
+	uInt bd,
+	inflate_huft *tl,
+	inflate_huft *td,
+	z_stream *z
+)
+{
+  inflate_codes_statef *c;
+
+  if ((c = (inflate_codes_statef *)
+       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev((stderr, "inflate:       codes new\n"));
+  }
+  return c;
+}
+
+
+local int inflate_codes(
+	inflate_blocks_statef *s,
+	z_stream *z,
+	int r
+)
+{
+  uInt j;               /* temporary storage */
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Bytef *f;             /* pointer to copy strings from */
+  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input and output based on current state */
+  while (1) switch (c->mode)
+  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+    case START:         /* x: set up for LEN */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+        LOAD
+        if (r != Z_OK)
+        {
+          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+          break;
+        }
+      }
+#endif /* !SLOW */
+      c->sub.code.need = c->lbits;
+      c->sub.code.tree = c->ltree;
+      c->mode = LEN;
+    case LEN:           /* i: get length/literal/eob next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", t->base));
+        c->mode = LIT;
+        break;
+      }
+      if (e & 16)               /* length */
+      {
+        c->sub.copy.get = e & 15;
+        c->len = t->base;
+        c->mode = LENEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t->next;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv((stderr, "inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = "invalid literal/length code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case LENEXT:        /* i: getting length extra (have base) */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->len += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv((stderr, "inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e & 16)               /* distance */
+      {
+        c->sub.copy.get = e & 15;
+        c->sub.copy.dist = t->base;
+        c->mode = DISTEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t->next;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = "invalid distance code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case DISTEXT:       /* i: getting distance extra */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->sub.copy.dist += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+      f = (uInt)(q - s->window) < c->sub.copy.dist ?
+          s->end - (c->sub.copy.dist - (q - s->window)) :
+          q - c->sub.copy.dist;
+#else
+      f = q - c->sub.copy.dist;
+      if ((uInt)(q - s->window) < c->sub.copy.dist)
+        f = s->end - (c->sub.copy.dist - (q - s->window));
+#endif
+      while (c->len)
+      {
+        NEEDOUT
+        OUTBYTE(*f++)
+        if (f == s->end)
+          f = s->window;
+        c->len--;
+      }
+      c->mode = START;
+      break;
+    case LIT:           /* o: got literal, waiting for output space */
+      NEEDOUT
+      OUTBYTE(c->sub.lit)
+      c->mode = START;
+      break;
+    case WASH:          /* o: got eob, possibly more output */
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      c->mode = END;
+    case END:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADCODE:       /* x: got error */
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+local void inflate_codes_free(
+	inflate_codes_statef *c,
+	z_stream *z
+)
+{
+  ZFREE(z, c, sizeof(struct inflate_codes_state));
+  Tracev((stderr, "inflate:       codes free\n"));
+}
+
+/*+++++*/
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush(
+	inflate_blocks_statef *s,
+	z_stream *z,
+	int r
+)
+{
+  uInt n;
+  Bytef *p, *q;
+
+  /* local copies of source and destination pointers */
+  p = z->next_out;
+  q = s->read;
+
+  /* compute number of bytes to copy as far as end of window */
+  n = (uInt)((q <= s->write ? s->write : s->end) - q);
+  if (n > z->avail_out) n = z->avail_out;
+  if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+  /* update counters */
+  z->avail_out -= n;
+  z->total_out += n;
+
+  /* update check information */
+  if (s->checkfn != Z_NULL)
+    s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as far as end of window */
+  zmemcpy(p, q, n);
+  p += n;
+  q += n;
+
+  /* see if more to copy at beginning of window */
+  if (q == s->end)
+  {
+    /* wrap pointers */
+    q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
+
+    /* compute bytes to copy */
+    n = (uInt)(s->write - q);
+    if (n > z->avail_out) n = z->avail_out;
+    if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+    /* update counters */
+    z->avail_out -= n;
+    z->total_out += n;
+
+    /* update check information */
+    if (s->checkfn != Z_NULL)
+      s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    zmemcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
+
+
+/*+++++*/
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
+
+/* Called with number of bytes left to write in window at least 258
+   (the maximum string length) and number of input bytes available
+   at least ten.  The ten bytes are six bytes for the longest length/
+   distance pair plus four bytes for overloading the bit buffer. */
+
+local int inflate_fast(
+	uInt bl,
+	uInt bd,
+	inflate_huft *tl,
+	inflate_huft *td,
+	inflate_blocks_statef *s,
+	z_stream *z
+)
+{
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  uInt ml;              /* mask for literal/length tree */
+  uInt md;              /* mask for distance tree */
+  uInt c;               /* bytes to copy */
+  uInt d;               /* distance back to copy from */
+  Bytef *r;             /* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks */
+  ml = inflate_mask[bl];
+  md = inflate_mask[bd];
+
+  /* do until not enough input or output space for fast loop */
+  do {                          /* assume called with m >= 258 && n >= 10 */
+    /* get literal/length code */
+    GRABBITS(20)                /* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+    {
+      DUMPBITS(t->bits)
+      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
+      *q++ = (Byte)t->base;
+      m--;
+      continue;
+    }
+    do {
+      DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv((stderr, "inflate:         * length %u\n", c));
+
+        /* decode distance base of block to copy */
+        GRABBITS(15);           /* max bits for distance code */
+        e = (t = td + ((uInt)b & md))->exop;
+        do {
+          DUMPBITS(t->bits)
+          if (e & 16)
+          {
+            /* get extra bits to add to distance base */
+            e &= 15;
+            GRABBITS(e)         /* get extra bits (up to 13) */
+            d = t->base + ((uInt)b & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv((stderr, "inflate:         * distance %u\n", d));
+
+            /* do the copy */
+            m -= c;
+            if ((uInt)(q - s->window) >= d)     /* offset before dest */
+            {                                   /*  just copy */
+              r = q - d;
+              *q++ = *r++;  c--;        /* minimum count is three, */
+              *q++ = *r++;  c--;        /*  so unroll loop a little */
+            }
+            else                        /* else offset after destination */
+            {
+              e = d - (q - s->window);  /* bytes from offset to end */
+              r = s->end - e;           /* pointer to offset */
+              if (c > e)                /* if source crosses, */
+              {
+                c -= e;                 /* copy to end of window */
+                do {
+                  *q++ = *r++;
+                } while (--e);
+                r = s->window;          /* copy rest from start of window */
+              }
+            }
+            do {                        /* copy all or what's left */
+              *q++ = *r++;
+            } while (--c);
+            break;
+          }
+          else if ((e & 64) == 0)
+            e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+          else
+          {
+            z->msg = "invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
+      }
+      if ((e & 64) == 0)
+      {
+        if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
+      }
+      else if (e & 32)
+      {
+        Tracevv((stderr, "inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = "invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
+
+
+/*+++++*/
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
+
+char *zlib_version = ZLIB_VERSION;
+
+char *z_errmsg[] = {
+"stream end",          /* Z_STREAM_END    1 */
+"",                    /* Z_OK            0 */
+"file error",          /* Z_ERRNO        (-1) */
+"stream error",        /* Z_STREAM_ERROR (-2) */
+"data error",          /* Z_DATA_ERROR   (-3) */
+"insufficient memory", /* Z_MEM_ERROR    (-4) */
+"buffer error",        /* Z_BUF_ERROR    (-5) */
+""};
+
+
+/*+++++*/
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf)  {s1 += *buf++; s2 += s1;}
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+#define DO16(buf) DO8(buf); DO8(buf);
+
+/* ========================================================================= */
+uLong adler32(
+	uLong adler,
+	Bytef *buf,
+	uInt len
+)
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+            k -= 16;
+        }
+        if (k != 0) do {
+            DO1(buf);
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
diff -Naur linux-2.6.11.8/fs/jffs2/zlib.h linux-2.6.x/fs/jffs2/zlib.h
--- linux-2.6.11.8/fs/jffs2/zlib.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/fs/jffs2/zlib.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,432 @@
+/*		*/
+
+/*
+ * This file is derived from zlib.h and zconf.h from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.
+ */
+
+/*
+ *  ==FILEVERSION 960122==
+ *
+ * This marker is used by the Linux installation script to determine
+ * whether an up-to-date version of this file is already installed.
+ */
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 0.95, Aug 16th, 1995.
+
+  Copyright (C) 1995 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
+ */
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+/* #include "zconf.h" */	/* included directly here */
+
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
+
+/*
+     The library does not install any signal handler. It is recommended to
+  add at least a handler for SIGSEGV when decompressing; the library checks
+  the consistency of the input data whenever possible but may go nuts
+  for some forms of corrupted input.
+ */
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
+ * at addresses which are not a multiple of their size.
+ * Under DOS, -DFAR=far or -DFAR=__far may be needed.
+ */
+
+#ifndef STDC
+#  if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
+#    define STDC
+#  endif
+#endif
+
+#ifdef	__MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
+#  include <unix.h>
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            1 << (windowBits+2)   +  1 << (memLevel+9)
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+typedef unsigned char  Byte;  /* 8 bits */
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+typedef Byte FAR Bytef;
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void FAR *voidpf;
+   typedef void     *voidp;
+#else
+   typedef Byte FAR *voidpf;
+   typedef Byte     *voidp;
+#endif
+
+/* end of original zconf.h */
+
+#define ZLIB_VERSION "0.95P"
+
+/* 
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms may be added later and will have the same
+  stream interface.
+
+     For compression the application must provide the output buffer and
+  may optionally provide the input buffer for optimization. For decompression,
+  the application must provide the input buffer and may optionally provide
+  the output buffer for optimization.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address, uInt nbytes));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidp      opaque;  /* private data object passed to zalloc and zfree */
+
+    Byte     data_type; /* best guess about the data type: ascii or binary */
+
+} z_stream;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_FULL_FLUSH    2
+#define Z_SYNC_FLUSH    3 /* experimental: partial_flush + byte align */
+#define Z_FINISH        4
+#define Z_PACKET_FLUSH	5
+/* See deflate() below for the usage of these constants */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+/* error codes for the compression/decompression functions */
+
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Used to set the data_type field */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+extern char *zlib_version;
+/* The application can compare zlib_version and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+ */
+
+                        /* basic functions */
+
+extern int inflateInit OF((z_stream *strm));
+/* 
+     Initializes the internal stream state for decompression. The fields
+   zalloc and zfree must be initialized before by the caller.  If zalloc and
+   zfree are set to Z_NULL, inflateInit updates them to use default allocation
+   functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory.  msg is set to null if there is no error message.
+   inflateInit does not perform any decompression: this will be done by
+   inflate().
+*/
+
+
+extern int inflate OF((z_stream *strm, int flush));
+/*
+  Performs one or both of the following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() always provides as much output as possible
+    (until there is no more input data or no more space in the output buffer).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate().
+
+    If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
+  inflate flushes as much output as possible to the output buffer. The
+  flushing behavior of inflate is not specified for values of the flush
+  parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
+  current implementation actually flushes as much output as possible
+  anyway.  For Z_PACKET_FLUSH, inflate checks that once all the input data
+  has been consumed, it is expecting to see the length field of a stored
+  block; if not, it returns Z_DATA_ERROR.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster routine
+  may be used for the single inflate() call.
+
+    inflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if the end of the
+  compressed data has been reached and all uncompressed output has been
+  produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
+  the stream structure was inconsistent (for example if next_in or next_out
+  was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
+  progress is possible or if there was not enough room in the output buffer
+  when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
+  call inflateSync to look for a good compression block.  */
+
+
+extern int inflateEnd OF((z_stream *strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* advanced functions */
+
+extern int inflateInit2 OF((z_stream *strm,
+                            int  windowBits));
+/*   
+     This is another version of inflateInit with more compression options. The
+   fields next_out, zalloc and zfree must be initialized before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library (the value 16 will be allowed soon). The
+   default value is 15 if inflateInit is used instead. If a compressed stream
+   with a larger window size is given as input, inflate() will return with
+   the error code Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     If next_out is not null, the library will use this buffer for the history
+   buffer; the buffer must either be large enough to hold the entire output
+   data, or have at least 1<<windowBits bytes.  If next_out is null, the
+   library will allocate its own buffer (and leave next_out null). next_in
+   need not be provided here but must be provided by the application for the
+   next call of inflate().
+
+     If the history buffer is provided by the application, next_out must
+   never be changed by the application since the decompressor maintains
+   history information inside this buffer from call to call; the application
+   can only reset next_out to the beginning of the history buffer when
+   avail_out is zero and all output has been consumed.
+
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+   not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+   windowBits < 8). msg is set to null if there is no error message.
+   inflateInit2 does not perform any decompression: this will be done by
+   inflate().
+*/
+
+extern int inflateSync OF((z_stream *strm));
+/* 
+    Skips invalid compressed data until the special marker (see deflate()
+  above) can be found, or until all available input is skipped. No output
+  is provided.
+
+    inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no marker has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+extern int inflateReset OF((z_stream *strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+extern int inflateIncomp OF((z_stream *strm));
+/*
+     This function adds the data at next_in (avail_in bytes) to the output
+   history without performing any output.  There must be no pending output,
+   and the decompressor must be expecting to see the start of a block.
+   Calling this function is equivalent to decompressing a stored block
+   containing the data at next_in (except that the data is not output).
+*/
+
+                        /* checksum functions */
+
+/*
+     This function is not related to compression but is exported
+   anyway because it might be useful in applications using the
+   compression library.
+*/
+
+extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+#ifndef _Z_UTIL_H
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+#endif /* _ZLIB_H */
diff -Naur linux-2.6.11.8/fs/proc/proc_misc.c linux-2.6.x/fs/proc/proc_misc.c
--- linux-2.6.11.8/fs/proc/proc_misc.c	2005-04-30 02:24:07.000000000 +0100
+++ linux-2.6.x/fs/proc/proc_misc.c	2009-09-06 22:42:40.000000000 +0100
@@ -304,6 +304,8 @@
 };
 #endif
 
+
+#ifdef CONFIG_SLAB
 extern struct seq_operations slabinfo_op;
 extern ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *);
 static int slabinfo_open(struct inode *inode, struct file *file)
@@ -317,6 +319,7 @@
 	.llseek		= seq_lseek,
 	.release	= seq_release,
 };
+#endif
 
 static int show_stat(struct seq_file *p, void *v)
 {
@@ -581,7 +584,9 @@
 	create_seq_entry("partitions", 0, &proc_partitions_operations);
 	create_seq_entry("stat", 0, &proc_stat_operations);
 	create_seq_entry("interrupts", 0, &proc_interrupts_operations);
+#ifdef CONFIG_SLAB	
 	create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
+#endif	
 	create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
 	create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
 	create_seq_entry("diskstats", 0, &proc_diskstats_operations);
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/actelm7.h linux-2.6.x/include/asm-arm/arch-actelm7/actelm7.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/actelm7.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/actelm7.h	2009-09-06 22:44:04.000000000 +0100
@@ -0,0 +1,73 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/actelm7.h
+ */
+
+#ifndef __ASM_ARCH_actelm7_H
+#define __ASM_ARCH_actelm7_H
+
+/* Vectored Interrupt Controller (VIC) */
+#define IRQStatus	(*((volatile unsigned char *) 0x2400002c))
+#define FIQStatus       (*((volatile unsigned char *) 0x24000014))
+#define IRQRawStatus    (*((volatile unsigned char *) 0x24000028))
+#define IRQEnable	(*((volatile unsigned char *) 0x24000020))
+#define IRQEnableClear  (*((volatile unsigned char *) 0x24000024))
+#define IRQSoftInt      (*((volatile unsigned char *) 0x24000018))
+#define IRQSoftIntClear (*((volatile unsigned char *) 0x2400001C))
+
+//* General Purpose Input/Output (GPIO) */
+
+#define DataOut         (*((volatile unsigned long *) 0x20000000))
+#define DataIn          (*((volatile unsigned long *) 0x20000000))
+
+/* Universal Asynchronous Receiver Transmitter 0 (UART0) */
+#define U0RBR           (*((volatile unsigned char *) 0x22000000))
+#define U0THR           (*((volatile unsigned char *) 0x22000000))
+#define U0IER           (*((volatile unsigned char *) 0x22000004))
+#define U0IIR           (*((volatile unsigned char *) 0x22000008))
+#define U0FCR           (*((volatile unsigned char *) 0x22000008))
+#define U0LCR           (*((volatile unsigned char *) 0x2200000C))
+#define U0MCR		(*((volatile unsigned char *) 0x22000010))
+#define U0LSR           (*((volatile unsigned char *) 0x22000014))
+#define U0SCR           (*((volatile unsigned char *) 0x2200001C))
+#define U0DLL           (*((volatile unsigned char *) 0x22000000))
+#define U0DLM           (*((volatile unsigned char *) 0x22000004))
+
+/* SPI (Serial Peripheral Interface) */
+
+#define SPI_TX          (*((volatile unsigned char *) 0x25000000))
+#define SPI_RX		(*((volatile unsigned char *) 0x25000000))
+#define SPI_CTRL1       (*((volatile unsigned char *) 0x25000004))
+#define SPI_CTRL2       (*((volatile unsigned char *) 0x25000008))
+#define SPI_STATUS      (*((volatile unsigned char *) 0x25000008))
+#define SPI_SLAVE	(*((volatile unsigned char *) 0x2500000c))
+
+/* Timer 0 */
+#define T0_INT_CLR      (*((volatile unsigned long *) 0x21000010))
+#define T0_TCR          (*((volatile unsigned long *) 0x21000008))
+#define T0_TLR          (*((volatile unsigned long *) 0x21000000))
+#define T0_PR           (*((volatile unsigned long *) 0x2100000C))
+#define T0_VALUE        (*((volatile unsigned long *) 0x21000004))
+#define T0_MIS          (*((volatile unsigned long *) 0x21000018))
+
+/* Watchdog */
+#define WDT_LOAD        (*((volatile unsigned long *) 0x23000000))
+#define WDT_VALUE       (*((volatile unsigned long *) 0x23000004))
+#define WDT_CNTR        (*((volatile unsigned long *) 0x23000008))
+#define WDT_REFRESH     (*((volatile unsigned long *) 0x2300000C))
+
+/* I2C */
+
+#define I2C_CNTR	(*((volatile unsigned char *) 0x26000000))
+#define I2C_STATUS	(*((volatile unsigned char *) 0x26000004))
+#define I2C_DATA	(*((volatile unsigned char *) 0x26000008))
+#define I2C_ADDR0	(*((volatile unsigned char *) 0x2600000C))
+#define I2C_SMB		(*((volatile unsigned char *) 0x26000010))
+#define I2C_ADDR1	(*((volatile unsigned char *) 0x2600001C))
+
+#define	actelm7_Fcclk	CONFIG_ARM_CLK  /* system clk frequecy,<=30Mhz, defined in system configuration */
+#define actelm7_Fpclk	(actelm7_Fcclk) /* used for pclk */
+
+#endif
+/*********************************************************************************************************
+**                            End Of File
+********************************************************************************************************/
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/dma.h linux-2.6.x/include/asm-arm/arch-actelm7/dma.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/dma.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/dma.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-armnommu/arch-actelm7/dma.h
+ */
+
+#include <linux/config.h>
+#include <asm/hardware.h>
+#include <linux/wait.h>
+
+#ifndef __ASM_actelm7_ARCH_DMA_H
+#define __ASM_actelm7_ARCH_DMA_H
+
+/*
+ * This is the maximum DMA address(physical address) that can be DMAd to.
+ * 
+ */
+#define MAX_DMA_ADDRESS		0xffffffff  /* used in alloc_bootmem,see linux/bootmem.h*/
+
+/*
+ * Actelm7 has no DMA channels.
+ */
+#define MAX_DMA_CHANNELS	0		/* actelm7 has no dma */    
+
+#endif /* _ASM_actelm7_ARCH_DMA_H */
+
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/entry-macro.S linux-2.6.x/include/asm-arm/arch-actelm7/entry-macro.S
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/entry-macro.S	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/entry-macro.S	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,32 @@
+/*
+ *  include/arm/arch-actelm7/entry-macro.S
+ *
+ *  defines machine dependent entry macros.
+ *  included in the arch/armnommu/kernel/entry.S
+ *  
+ */
+.EQU	IrqStatus,	0x2400002C
+
+#if defined(CONFIG_ARCH_ACTELM7)
+        .macro  disable_fiq
+        .endm
+
+		.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+		
+		ldr	\irqstat, =(IrqStatus)	@ load address of interrupt pending
+		ldr	\irqstat, [\irqstat]	@ get the register content
+
+		mov     \irqnr, #0
+1001:
+		tst     \irqstat, #1
+		bne     1002f
+		add     \irqnr, \irqnr, #1
+		mov     \irqstat, \irqstat, lsr #1
+		cmp     \irqnr, #NR_IRQS
+		bcc     1001b
+1002:		/* EQ will be set if we reach 32 */
+		.endm
+
+		.macro irq_prio_table
+		.endm
+#endif
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/hardware.h linux-2.6.x/include/asm-arm/arch-actelm7/hardware.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/hardware.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/hardware.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,28 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/hardware.h
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/arch/sizes.h>
+#include <asm/arch/actelm7.h>
+
+#ifndef __ASSEMBLY__
+
+#define HARD_RESET_NOW()
+
+/* the machine dependent  bootmem reserve and free routines */
+#define MACH_RESERVE_BOOTMEM()
+
+#define MACH_FREE_BOOTMEM()
+
+/* yes, freeing initmem is okay */
+#define DO_FREE_INITMEM() 	(1)
+
+#endif
+
+#define actelm7_MEM_SIZE     (CONFIG_DRAM_SIZE) 
+#define MEM_SIZE             actelm7_MEM_SIZE
+#define PA_SDRAM_BASE        CONFIG_DRAM_BASE
+
+#endif  /*   END OF __ASM_ARCH_HARDWARE_H */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/io.h linux-2.6.x/include/asm-arm/arch-actelm7/io.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/io.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/io.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,63 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+/* Used in kernel/resource.c */
+
+/*
+ * We have the this routine to use usb host device driver
+ */
+
+
+#define PCI_IO_VADDR      (0x0)
+#define PCI_MEMORY_VADDR  (0x0)
+
+#define __io(a)			(PCI_IO_VADDR + (a))
+#define __mem_pci(a)		((unsigned long)(a))
+#define __mem_isa(a)		(PCI_MEMORY_VADDR + (unsigned long)(a))
+
+
+/*
+ * These macros were copied from arch/armnommu/io.h and are used instead
+ * of the definitions found there, because we want to do 16/32 bit i/o
+ * without byte swapping.
+ * --the
+ */
+
+#undef __io
+
+#ifndef __iob
+  #define __iob(a) __io(a)
+#endif
+
+#define outb(v,p)       __raw_writeb(v, p)
+#define outw(v,p)       __raw_writew(v, p)
+#define outl(v,p)       __raw_writel(v, p)
+
+#define inb(p)          ({ unsigned int __v = __raw_readb(p); __v; })
+#define inw(p)          ({ unsigned int __v = __raw_readw(p); __v; })
+#define inl(p)          ({ unsigned int __v = __raw_readl(p); __v; })
+
+#define outsb(p,d,l)    __raw_writesb(p, d, l)
+#define outsw(p,d,l)    __raw_writesw(p, d, l)
+#define outsl(p,d,l)    __raw_writesl(p, d, l)
+
+#define insb(p,d,l)     __raw_readsb(p, d, l)
+#define insw(p,d,l)     __raw_readsw(p, d, l)
+#define insl(p,d,l)     __raw_readsl(p, d, l)
+
+/*
+ * Validate the pci memory address for ioremap.
+ */
+#define iomem_valid_addr(iomem,size)	(1)
+
+
+/*
+ * Convert PCI memory space to a CPU physical address
+ */
+#define iomem_to_phys(iomem)	(iomem)
+
+#endif
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/irq.h linux-2.6.x/include/asm-arm/arch-actelm7/irq.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/irq.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/irq.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,20 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/irq.h
+ */
+#ifndef __actelm7_irq_h
+#define __actelm7_irq_h
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+#include <asm/arch/irqs.h>
+
+extern unsigned  int fixup_irq(int i);
+
+extern void do_IRQ(int irq, struct pt_regs *regs);
+
+extern void actelm7_init_irq(void);
+
+#define 	irq_init_irq 	actelm7_init_irq
+
+#endif 
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/irqs.h linux-2.6.x/include/asm-arm/arch-actelm7/irqs.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/irqs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/irqs.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,19 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/irqs.h
+ *
+ *  IRQ number definition
+ *  All IRQ numbers of the actelm7 CPUs.
+ *
+ */
+
+#ifndef __actelm7_irqs_h
+#define __actelm7_irqs_h                        1
+
+#define NR_IRQS		4
+	
+#define ACTELM7_INTERRUPT_TIMER0  0	/* Timer 0 */
+#define ACTELM7_INTERRUPT_UART0	  1	/* UART 0 */
+#define ACTELM7_INTERRUPT_SPI0 	  2	/* SPI0 */
+#define ACTELM7_INTERRUPT_PENDOWN 3     /* ADS7864 */
+
+#endif /* End of __irqs_h */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/keyboard.h linux-2.6.x/include/asm-arm/arch-actelm7/keyboard.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/keyboard.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/keyboard.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,16 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/keyboard.h
+ */
+#ifndef __ASM_ARMNOMMU_ARCH_actelm7_KEYBOARD_H
+#define __ASM_ARMNOMMU_ARCH_actelm7_KEYBOARD_H
+
+#define kbd_setkeycode(sc,kc) (-EINVAL)
+#define kbd_getkeycode(sc) (-EINVAL)
+#define kbd_translate(sc,kcp,rm) ({ *(kcp) = (sc); 1; })
+#define kbd_unexpected_up(kc) (0200)
+#define kbd_leds(leds)
+#define kbd_init_hw()
+#define kbd_enable_irq()
+#define kbd_disable_irq()
+
+#endif /* __ASM_ARMNOMMU_ARCH_actelm7_KEYBOARD_H */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/memory.h linux-2.6.x/include/asm-arm/arch-actelm7/memory.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/memory.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/memory.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-actelm7/memory.h
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <linux/config.h>
+
+#define TASK_SIZE	(0x80100000)	
+#define TASK_SIZE_26	TASK_SIZE
+#define TASK_UNMAPPED_BASE	(0x0)	
+
+#define PHYS_OFFSET	(CONFIG_DRAM_BASE)
+#define PAGE_OFFSET 	(PHYS_OFFSET)
+#define END_MEM     	(CONFIG_DRAM_BASE + CONFIG_DRAM_SIZE)
+
+#define __virt_to_phys(vpage) ((unsigned long) (vpage))
+#define __phys_to_virt(ppage) ((void *) (ppage))
+#define __virt_to_bus(vpage) ((unsigned long) (vpage))
+#define __bus_to_virt(ppage) ((void *) (ppage))
+
+#endif /*  __ASM_ARCH_MEMORY_H */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/mtd-xip.h linux-2.6.x/include/asm-arm/arch-actelm7/mtd-xip.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/mtd-xip.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/mtd-xip.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,32 @@
+/*
+ * MTD primitives for XIP support. Architecture specific functions
+ *
+ * Do not include this file directly. It's included from linux/mtd/xip.h
+ * 
+ * Author:	Nicolas Pitre
+ * Created:	Nov 2, 2004
+ * Copyright:	(C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $
+ */
+
+#ifndef __ARM_MTD_XIP_H__
+#define __ARM_MTD_XIP_H__
+
+#include <asm/hardware.h>
+#include <asm/arch/mtd-xip.h>
+
+#define xip_irqpending()	(IRQStatus)
+
+/* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */
+#define xip_currtime()		(T0_VALUE)
+#define xip_elapsed_since(x)	(signed)((T0_VALUE - (x)) * 1000)
+
+/* fill instruction prefetch */
+#define xip_iprefetch() 	do { asm volatile (".rep 8; nop; .endr"); } while (0)
+
+#endif /* __ARM_MTD_XIP_H__ */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/param.h linux-2.6.x/include/asm-arm/arch-actelm7/param.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/param.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/param.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,9 @@
+#ifndef __ARCH_ASM_PARAM_H__
+#define __ARCH_ASM_PARAM_H__
+#endif
+
+#ifndef HZ
+#define HZ	100
+#endif 
+
+/* __ARCH_ASM_PARAM_H__ */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/serial.h linux-2.6.x/include/asm-arm/arch-actelm7/serial.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/serial.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/serial.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,34 @@
+/*
+ * include/asm-arm/arch-actelm7/serial.h
+ */
+
+#ifndef __ASM_ARCH_SERIAL_H__
+#define __ASM_ARCH_SERIAL_H__
+
+#include <asm/hardware.h>
+
+#define BASE_BAUD  (actelm7_Fpclk / 16)
+#define UART0_BASE  0x22000000
+
+/* Standard COM flags */
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+#define RS_TABLE_SIZE 1
+
+/*
+ * Rather empty table...
+ * Hardwired serial ports should be defined here.
+ * PCMCIA will fill it dynamically.
+ */
+#define STD_SERIAL_PORT_DEFNS	\
+       /* UART	CLK     	PORT		IRQ	FLAGS		*/ \
+	{ 0,	BASE_BAUD,	UART0_BASE, 	1,	STD_COM_FLAGS,	\
+	.iomem_reg_shift = 2,		\
+	.iomem_base = UART0_BASE,	\
+	.io_type = UPIO_MEM},	\
+
+
+#define SERIAL_PORT_DFNS	\
+	STD_SERIAL_PORT_DEFNS
+
+#endif /* __ASM_ARCH_SERIAL_H__ */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/sizes.h linux-2.6.x/include/asm-arm/arch-actelm7/sizes.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/sizes.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/sizes.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,52 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* DO NOT EDIT!! - this file automatically generated
+ *                 from .s file by awk -f s2h.awk
+ */
+/*  Size defintions
+ *  Copyright (C) ARM Limited 1998. All rights reserved.
+ */
+
+#ifndef __sizes_h
+#define __sizes_h                       1
+
+/* handy sizes */
+#define SZ_1K                           0x00000400
+#define SZ_4K                           0x00001000
+#define SZ_8K                           0x00002000
+#define SZ_16K                          0x00004000
+#define SZ_64K                          0x00010000
+#define SZ_128K                         0x00020000
+#define SZ_256K                         0x00040000
+#define SZ_512K                         0x00080000
+
+#define SZ_1M                           0x00100000
+#define SZ_2M                           0x00200000
+#define SZ_4M                           0x00400000
+#define SZ_8M                           0x00800000
+#define SZ_16M                          0x01000000
+#define SZ_32M                          0x02000000
+#define SZ_64M                          0x04000000
+#define SZ_128M                         0x08000000
+#define SZ_256M                         0x10000000
+#define SZ_512M                         0x20000000
+
+#define SZ_1G                           0x40000000
+#define SZ_2G                           0x80000000
+
+#endif
+
+/*         END */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/system.h linux-2.6.x/include/asm-arm/arch-actelm7/system.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/system.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/system.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,25 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/system.h
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+
+static void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+ 	/* machine should reboot */
+ 	mdelay(5000);
+ 	panic("Watchdog timer reset failed!\n");
+ 	printk(" Jump to address 0 \n");
+ 	cpu_reset(0);/*will jump to cpu_arm7_reset in proc-arm67.S,since actelm7 have no cache,we must modify the code*/
+}
+
+#endif
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/time.h linux-2.6.x/include/asm-arm/arch-actelm7/time.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/time.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/time.h	2009-09-12 17:44:20.000000000 +0100
@@ -0,0 +1,22 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/time.h
+ *
+ *  Copyright (C) 2004 Philips Semiconductors
+ */
+
+#ifndef __ASM_ARCH_TIME_H__
+#define __ASM_ARCH_TIME_H__
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/timex.h>
+
+#define CLOCKS_PER_USEC	(actelm7_Fpclk / 1000000)
+
+/* set timer to generate interrupt every 10ms */
+#define INIT_VALUE 0x186A0				
+#define PRESCALE_COUNTER_INIT_VALUE 0
+
+
+#endif /*__ASM_ARCH_TIME_H__*/
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/timex.h linux-2.6.x/include/asm-arm/arch-actelm7/timex.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/timex.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/timex.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,24 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/timex.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H__
+#define __ASM_ARCH_TIMEX_H__
+
+#define CLOCK_TICK_RATE (CONFIG_ARM_CLK)
+
+#endif /* __ASM_ARCH_TIMEX_H__ */
diff -Naur linux-2.6.11.8/include/asm-arm/arch-actelm7/vmalloc.h linux-2.6.x/include/asm-arm/arch-actelm7/vmalloc.h
--- linux-2.6.11.8/include/asm-arm/arch-actelm7/vmalloc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/include/asm-arm/arch-actelm7/vmalloc.h	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,35 @@
+/*
+ *  linux/include/asm-arm/arch-actelm7/vmalloc.h
+ *
+ *  Copyright (C) 2000 Russell King. 
+ *  modified by steven taffs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define MAX_actelm7_SDRAM_SIZE (0x10000000)
+
+#define VMALLOC_OFFSET	  (8*1024*1024)
+#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (PAGE_OFFSET + MAX_actelm7_SDRAM_SIZE)   
diff -Naur linux-2.6.11.8/include/asm-arm/cacheflush.h linux-2.6.x/include/asm-arm/cacheflush.h
--- linux-2.6.11.8/include/asm-arm/cacheflush.h	2009-09-06 22:49:58.000000000 +0100
+++ linux-2.6.x/include/asm-arm/cacheflush.h	2009-09-06 22:42:40.000000000 +0100
@@ -50,6 +50,14 @@
 # endif
 #endif
 
+#if defined(CONFIG_CPU_ACTELM7)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE actelm7
+# endif
+#endif
+
 #if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
     defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020)
 # define MULTI_CACHE 1
diff -Naur linux-2.6.11.8/include/asm-arm/glue.h linux-2.6.x/include/asm-arm/glue.h
--- linux-2.6.11.8/include/asm-arm/glue.h	2009-09-06 22:49:58.000000000 +0100
+++ linux-2.6.x/include/asm-arm/glue.h	2009-09-06 22:42:40.000000000 +0100
@@ -51,7 +51,7 @@
 # endif
 #endif
 
-#if defined(CONFIG_CPU_ARM7TDMI) || defined(CONFIG_CPU_S3C4510B)
+#if defined(CONFIG_CPU_ARM7TDMI) || defined(CONFIG_CPU_S3C4510B) || defined(CONFIG_CPU_ACTELM7)
 # ifdef CPU_ABORT_HANDLER
 #  define MULTI_ABORT 1
 # else
diff -Naur linux-2.6.11.8/include/asm-arm/proc-fns.h linux-2.6.x/include/asm-arm/proc-fns.h
--- linux-2.6.11.8/include/asm-arm/proc-fns.h	2009-09-06 22:49:58.000000000 +0100
+++ linux-2.6.x/include/asm-arm/proc-fns.h	2009-09-06 22:42:40.000000000 +0100
@@ -67,6 +67,14 @@
 #   define CPU_NAME cpu_arm7
 #  endif
 # endif
+# ifdef CONFIG_CPU_ACTELM7
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_arm7
+#  endif
+# endif
 # ifdef CONFIG_CPU_ARM720T
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
diff -Naur linux-2.6.11.8/include/asm-arm/unistd.h linux-2.6.x/include/asm-arm/unistd.h
--- linux-2.6.11.8/include/asm-arm/unistd.h	2005-04-30 02:31:50.000000000 +0100
+++ linux-2.6.x/include/asm-arm/unistd.h	2009-09-06 22:42:40.000000000 +0100
@@ -152,9 +152,11 @@
 #define __NR_adjtimex			(__NR_SYSCALL_BASE+124)
 #define __NR_mprotect			(__NR_SYSCALL_BASE+125)
 #define __NR_sigprocmask		(__NR_SYSCALL_BASE+126)
+#define __NR_create_module		(__NR_SYSCALL_BASE+127) /*added for ACTELM7*/
 					/* 127 was sys_create_module */
 #define __NR_init_module		(__NR_SYSCALL_BASE+128)
 #define __NR_delete_module		(__NR_SYSCALL_BASE+129)
+#define __NR_get_kernel_syms		(__NR_SYSCALL_BASE+130) /*added for ACTELM7*/
 					/* 130 was sys_get_kernel_syms */
 #define __NR_quotactl			(__NR_SYSCALL_BASE+131)
 #define __NR_getpgid			(__NR_SYSCALL_BASE+132)
diff -Naur linux-2.6.11.8/include/asm-m68knommu/asm-offsets.h linux-2.6.x/include/asm-m68knommu/asm-offsets.h
--- linux-2.6.11.8/include/asm-m68knommu/asm-offsets.h	2005-04-30 02:30:31.000000000 +0100
+++ linux-2.6.x/include/asm-m68knommu/asm-offsets.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,49 +0,0 @@
-#ifndef __ASM_OFFSETS_H__
-#define __ASM_OFFSETS_H__
-/*
- * DO NOT MODIFY.
- *
- * This file was generated by arch/m68knommu/Makefile
- *
- */
-
-#define TASK_STATE 0 /* offsetof(struct task_struct, state) */
-#define TASK_FLAGS 12 /* offsetof(struct task_struct, flags) */
-#define TASK_PTRACE 16 /* offsetof(struct task_struct, ptrace) */
-#define TASK_BLOCKED 922 /* offsetof(struct task_struct, blocked) */
-#define TASK_THREAD 772 /* offsetof(struct task_struct, thread) */
-#define TASK_THREAD_INFO 4 /* offsetof(struct task_struct, thread_info) */
-#define TASK_MM 92 /* offsetof(struct task_struct, mm) */
-#define TASK_ACTIVE_MM 96 /* offsetof(struct task_struct, active_mm) */
-#define CPUSTAT_SOFTIRQ_PENDING 0 /* offsetof(irq_cpustat_t, __softirq_pending) */
-#define THREAD_KSP 0 /* offsetof(struct thread_struct, ksp) */
-#define THREAD_USP 4 /* offsetof(struct thread_struct, usp) */
-#define THREAD_SR 8 /* offsetof(struct thread_struct, sr) */
-#define THREAD_FS 10 /* offsetof(struct thread_struct, fs) */
-#define THREAD_CRP 12 /* offsetof(struct thread_struct, crp) */
-#define THREAD_ESP0 20 /* offsetof(struct thread_struct, esp0) */
-#define THREAD_FPREG 24 /* offsetof(struct thread_struct, fp) */
-#define THREAD_FPCNTL 120 /* offsetof(struct thread_struct, fpcntl) */
-#define THREAD_FPSTATE 132 /* offsetof(struct thread_struct, fpstate) */
-#define PT_D0 32 /* offsetof(struct pt_regs, d0) */
-#define PT_ORIG_D0 36 /* offsetof(struct pt_regs, orig_d0) */
-#define PT_D1 0 /* offsetof(struct pt_regs, d1) */
-#define PT_D2 4 /* offsetof(struct pt_regs, d2) */
-#define PT_D3 8 /* offsetof(struct pt_regs, d3) */
-#define PT_D4 12 /* offsetof(struct pt_regs, d4) */
-#define PT_D5 16 /* offsetof(struct pt_regs, d5) */
-#define PT_A0 20 /* offsetof(struct pt_regs, a0) */
-#define PT_A1 24 /* offsetof(struct pt_regs, a1) */
-#define PT_A2 28 /* offsetof(struct pt_regs, a2) */
-#define PT_PC 48 /* offsetof(struct pt_regs, pc) */
-#define PT_SR 46 /* offsetof(struct pt_regs, sr) */
-#define PT_VECTOR 52 /* offsetof(struct pt_regs, pc) + 4 */
-#define STAT_IRQ 5140 /* offsetof(struct kernel_stat, irqs) */
-#define SIGSEGV 11 /* SIGSEGV */
-#define SEGV_MAPERR 196609 /* SEGV_MAPERR */
-#define SIGTRAP 5 /* SIGTRAP */
-#define TRAP_TRACE 196610 /* TRAP_TRACE */
-#define PT_PTRACED 1 /* PT_PTRACED */
-#define PT_DTRACE 2 /* PT_DTRACE */
-
-#endif
diff -Naur linux-2.6.11.8/include/linux/mtd/xip.h linux-2.6.x/include/linux/mtd/xip.h
--- linux-2.6.11.8/include/linux/mtd/xip.h	2005-04-30 02:29:45.000000000 +0100
+++ linux-2.6.x/include/linux/mtd/xip.h	2009-09-06 22:42:40.000000000 +0100
@@ -19,6 +19,7 @@
 #define __LINUX_MTD_XIP_H__
 
 #include <linux/config.h>
+#include <asm/hardware.h>
 
 #ifdef CONFIG_MTD_XIP
 
@@ -27,7 +28,7 @@
  * obviously not be running from flash.  The __xipram is therefore marking
  * those functions so they get relocated to ram.
  */
-#define __xipram __attribute__ ((__section__ (".data")))
+#define __xipram __attribute__ ((long_call,__section__ (".data")))
 
 /*
  * We really don't want gcc to guess anything.
@@ -75,13 +76,22 @@
 
 #else
 
-#warning "missing IRQ and timer primitives for XIP MTD support"
-#warning "some of the XIP MTD support code will be disabled"
-#warning "your system will therefore be unresponsive when writing or erasing flash"
-
-#define xip_irqpending()	(0)
-#define xip_currtime()		(0)
-#define xip_elapsed_since(x)	(0)
+//#warning "missing IRQ and timer primitives for XIP MTD support"
+//#warning "some of the XIP MTD support code will be disabled"
+//#warning "your system will therefore be unresponsive when writing or erasing flash"
+
+//#define xip_irqpending()	(0)
+//#define xip_currtime()		(0)
+//#define xip_elapsed_since(x)	(0)
+
+#define xip_irqpending()	(IRQStatus)
+
+/* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */
+#define xip_currtime()		(T0_VALUE)
+#define xip_elapsed_since(x)	(signed)((T0_VALUE - (x)) * 1000)
+
+/* fill instruction prefetch */
+#define xip_iprefetch() 	do { asm volatile (".rep 8; nop; .endr"); } while (0)
 
 #endif
 
diff -Naur linux-2.6.11.8/include/linux/slab.h linux-2.6.x/include/linux/slab.h
--- linux-2.6.11.8/include/linux/slab.h	2005-04-30 02:32:41.000000000 +0100
+++ linux-2.6.x/include/linux/slab.h	2009-09-06 22:42:40.000000000 +0100
@@ -44,7 +44,7 @@
 #define SLAB_MUST_HWCACHE_ALIGN	0x00008000UL	/* force alignment */
 #define SLAB_STORE_USER		0x00010000UL	/* store the last owner for bug hunting */
 #define SLAB_RECLAIM_ACCOUNT	0x00020000UL	/* track pages allocated to indicate
-						   what is reclaimable later*/
+						   what is reclaimable later */
 #define SLAB_PANIC		0x00040000UL	/* panic if kmem_cache_create() fails */
 #define SLAB_DESTROY_BY_RCU	0x00080000UL	/* defer freeing pages to RCU */
 
@@ -53,6 +53,9 @@
 #define SLAB_CTOR_ATOMIC	0x002UL		/* tell constructor it can't sleep */
 #define	SLAB_CTOR_VERIFY	0x004UL		/* tell constructor it's a verify call */
 
+
+#ifndef CONFIG_SLOB
+
 /* prototypes */
 extern void __init kmem_cache_init(void);
 
@@ -112,6 +115,36 @@
 extern int FASTCALL(kmem_cache_reap(int));
 extern int FASTCALL(kmem_ptr_validate(kmem_cache_t *cachep, void *ptr));
 
+#else /* CONFIG_SLOB */
+
+/* SLOB allocator routines */
+
+void kmem_cache_init(void);
+kmem_cache_t *kmem_find_general_cachep(size_t, gfp_t gfpflags);
+kmem_cache_t *kmem_cache_create(const char *c, size_t, size_t, unsigned long,void (*)(void *, kmem_cache_t *, unsigned long),void (*)(void *, kmem_cache_t *, unsigned long));
+int kmem_cache_destroy(kmem_cache_t *c);
+void *kmem_cache_alloc(kmem_cache_t *c, gfp_t flags);
+void kmem_cache_free(kmem_cache_t *c, void *b);
+const char *kmem_cache_name(kmem_cache_t *);
+void *kmalloc(size_t size, gfp_t flags);
+void *kzalloc(size_t size, gfp_t flags);
+void kfree(const void *m);
+unsigned int ksize(const void *m);
+unsigned int kmem_cache_size(kmem_cache_t *c);
+
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+	return kzalloc(n * size, flags);
+}
+
+#define kmem_cache_shrink(d) (0)
+#define kmem_cache_reap(a)
+#define kmem_ptr_validate(a, b) (0)
+#define kmem_cache_alloc_node(c, f, n) kmem_cache_alloc(c, f)
+#define kmalloc_node(s, f, n) kmalloc(s, f)
+
+#endif /* CONFIG_SLOB */
+
 /* System wide caches */
 extern kmem_cache_t	*vm_area_cachep;
 extern kmem_cache_t	*mm_cachep;
diff -Naur linux-2.6.11.8/include/linux/types.h linux-2.6.x/include/linux/types.h
--- linux-2.6.11.8/include/linux/types.h	2005-04-30 02:31:20.000000000 +0100
+++ linux-2.6.x/include/linux/types.h	2009-09-06 22:42:40.000000000 +0100
@@ -162,6 +162,8 @@
 typedef __u64 __bitwise __be64;
 #endif
 
+typedef unsigned __bitwise gfp_t;
+
 struct ustat {
 	__kernel_daddr_t	f_tfree;
 	__kernel_ino_t		f_tinode;
diff -Naur linux-2.6.11.8/init/do_mounts.c linux-2.6.x/init/do_mounts.c
--- linux-2.6.11.8/init/do_mounts.c	2005-04-30 02:26:32.000000000 +0100
+++ linux-2.6.x/init/do_mounts.c	2009-09-06 22:42:40.000000000 +0100
@@ -289,9 +289,19 @@
 	char b[BDEVNAME_SIZE];
 
 	get_fs_names(fs_names);
+
+	/*printk("*****\nVFS: test  name = <%s> \n",name);
+	for (p = fs_names; *p; p +=strlen(p)+1)
+	{
+		printk("VFS: fs_name = <%s> \n",p);
+	}
+	printk("VFS: root name <%s> \n ******\n",kdevname(ROOT_DEV)); */
 retry:
 	for (p = fs_names; *p; p += strlen(p)+1) {
 		int err = do_mount_root(name, p, flags, root_mount_data);
+		
+		/*printk("VFS: tried fs_name = <%s> err %d\n",p,err); */
+		
 		switch (err) {
 			case 0:
 				goto out;
diff -Naur linux-2.6.11.8/init/Kconfig linux-2.6.x/init/Kconfig
--- linux-2.6.11.8/init/Kconfig	2009-09-06 22:49:58.000000000 +0100
+++ linux-2.6.x/init/Kconfig	2009-09-06 22:42:40.000000000 +0100
@@ -352,6 +352,15 @@
 	  no dummy operations need be executed.
 	  Zero means use compiler's default.
 
+config SLAB
+	default y
+	bool "Use full SLAB allocator" if EMBEDDED
+	help
+	  Disabling this replaces the advanced SLAB allocator and
+	  kmalloc support with the drastically simple SLOB allocator
+	  SLOB is more space efficient but does not scale well and is
+	  more susceptible to fragmentation.
+
 endmenu		# General setup
 
 config TINY_SHMEM
@@ -359,6 +368,10 @@
 	depends MMU
 	bool
 
+config SLOB
+	default !SLAB
+	bool
+
 menu "Loadable module support"
 
 config MODULES
diff -Naur linux-2.6.11.8/init/main.c linux-2.6.x/init/main.c
--- linux-2.6.11.8/init/main.c	2005-04-30 02:24:18.000000000 +0100
+++ linux-2.6.x/init/main.c	2009-09-06 22:42:40.000000000 +0100
@@ -421,10 +421,15 @@
  * Interrupts are still disabled. Do necessary setups, then
  * enable them
  */
+	
 	lock_kernel();
+
 	page_address_init();
+
 	printk(linux_banner);
+
 	setup_arch(&command_line);
+
 	setup_per_cpu_areas();
 
 	/*
@@ -443,14 +448,21 @@
 	 * Disable preemption - early bootup scheduling is extremely
 	 * fragile until we cpu_idle() for the first time.
 	 */
+
 	preempt_disable();
+
 	build_all_zonelists();
+
 	page_alloc_init();
+
 	printk("Kernel command line: %s\n", saved_command_line);
+
 	parse_early_param();
+
 	parse_args("Booting kernel", command_line, __start___param,
 		   __stop___param - __start___param,
 		   &unknown_bootoption);
+
 	sort_main_extable();
 	trap_init();
 	rcu_init();
@@ -488,6 +500,7 @@
 	pidmap_init();
 	pgtable_cache_init();
 	prio_tree_init();
+	
 	anon_vma_init();
 #ifdef CONFIG_X86
 	if (efi_enabled)
diff -Naur linux-2.6.11.8/kernel/printk.c linux-2.6.x/kernel/printk.c
--- linux-2.6.11.8/kernel/printk.c	2005-04-30 02:32:46.000000000 +0100
+++ linux-2.6.x/kernel/printk.c	2009-09-06 22:42:40.000000000 +0100
@@ -518,9 +518,17 @@
 	int r;
 
 	va_start(args, fmt);
+	
+	//U0RBR = 0x3b;			//11
+
 	r = vprintk(fmt, args);
+	
+	//U0RBR = 0x43;			//18
+
 	va_end(args);
 
+	//U0RBR = 0x44;			//19
+
 	return r;
 }
 
@@ -532,15 +540,21 @@
 	static char printk_buf[1024];
 	static int log_level_unknown = 1;
 
+	//U0RBR = 0x3c;			//12
+
 	if (unlikely(oops_in_progress))
 		zap_locks();
 
 	/* This stops the holder of console_sem just where we want him */
 	spin_lock_irqsave(&logbuf_lock, flags);
 
+	//U0RBR = 0x3d;			//13
+
 	/* Emit the output into the temporary buffer */
 	printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
 
+	//U0RBR = 0x3e;			//14
+
 	/*
 	 * Copy the output into log_buf.  If the caller didn't provide
 	 * appropriate log level tags, we insert them here
@@ -559,6 +573,8 @@
 			log_level_unknown = 1;
 	}
 
+	//U0RBR = 0x3f;			//15
+
 	if (!cpu_online(smp_processor_id()) &&
 	    system_state != SYSTEM_RUNNING) {
 		/*
@@ -570,6 +586,9 @@
 		spin_unlock_irqrestore(&logbuf_lock, flags);
 		goto out;
 	}
+
+	//U0RBR = 0x40;			//16
+
 	if (!down_trylock(&console_sem)) {
 		console_locked = 1;
 		/*
@@ -580,6 +599,9 @@
 		console_may_schedule = 0;
 		release_console_sem();
 	} else {
+
+	//U0RBR = 0x41;			//17
+
 		/*
 		 * Someone else owns the drivers.  We drop the spinlock, which
 		 * allows the semaphore holder to proceed and to call the
@@ -588,6 +610,7 @@
 		spin_unlock_irqrestore(&logbuf_lock, flags);
 	}
 out:
+	//U0RBR = 0x42;			//18
 	return printed_len;
 }
 EXPORT_SYMBOL(printk);
diff -Naur linux-2.6.11.8/mm/Makefile linux-2.6.x/mm/Makefile
--- linux-2.6.11.8/mm/Makefile	2005-04-30 02:29:07.000000000 +0100
+++ linux-2.6.x/mm/Makefile	2009-09-06 22:42:40.000000000 +0100
@@ -9,7 +9,7 @@
 
 obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
 			   page_alloc.o page-writeback.o pdflush.o \
-			   readahead.o slab.o swap.o truncate.o vmscan.o \
+			   readahead.o swap.o truncate.o vmscan.o \
 			   prio_tree.o $(mmu-y)
 
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
@@ -17,4 +17,5 @@
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
 obj-$(CONFIG_SHMEM) += shmem.o
 obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
-
+obj-$(CONFIG_SLOB)	+= slob.o
+obj-$(CONFIG_SLAB)	+= slab.o
diff -Naur linux-2.6.11.8/mm/slob.c linux-2.6.x/mm/slob.c
--- linux-2.6.11.8/mm/slob.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.x/mm/slob.c	2009-09-06 22:42:40.000000000 +0100
@@ -0,0 +1,395 @@
+/*
+ * SLOB Allocator: Simple List Of Blocks
+ *
+ * Matt Mackall <mpm@selenic.com> 12/30/03
+ *
+ * How SLOB works:
+ *
+ * The core of SLOB is a traditional K&R style heap allocator, with
+ * support for returning aligned objects. The granularity of this
+ * allocator is 8 bytes on x86, though it's perhaps possible to reduce
+ * this to 4 if it's deemed worth the effort. The slob heap is a
+ * singly-linked list of pages from __get_free_page, grown on demand
+ * and allocation from the heap is currently first-fit.
+ *
+ * Above this is an implementation of kmalloc/kfree. Blocks returned
+ * from kmalloc are 8-byte aligned and prepended with a 8-byte header.
+ * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
+ * __get_free_pages directly so that it can return page-aligned blocks
+ * and keeps a linked list of such pages and their orders. These
+ * objects are detected in kfree() by their page alignment.
+ *
+ * SLAB is emulated on top of SLOB by simply calling constructors and
+ * destructors for every SLAB allocation. Objects are returned with
+ * the 8-byte alignment unless the SLAB_MUST_HWCACHE_ALIGN flag is
+ * set, in which case the low-level allocator will fragment blocks to
+ * create the proper alignment. Again, objects of page-size or greater
+ * are allocated by calling __get_free_pages. As SLAB objects know
+ * their size, no separate size bookkeeping is necessary and there is
+ * essentially no allocation space overhead.
+ */
+
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/cache.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+
+struct slob_block {
+	int units;
+	struct slob_block *next;
+};
+typedef struct slob_block slob_t;
+
+#define SLOB_UNIT sizeof(slob_t)
+#define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT)
+#define SLOB_ALIGN L1_CACHE_BYTES
+
+struct bigblock {
+	int order;
+	void *pages;
+	struct bigblock *next;
+};
+typedef struct bigblock bigblock_t;
+
+static slob_t arena = { .next = &arena, .units = 1 };
+static slob_t *slobfree = &arena;
+static bigblock_t *bigblocks;
+static DEFINE_SPINLOCK(slob_lock);
+static DEFINE_SPINLOCK(block_lock);
+
+static void slob_free(void *b, int size);
+
+static void *slob_alloc(size_t size, gfp_t gfp, int align)
+{
+	slob_t *prev, *cur, *aligned = 0;
+	int delta = 0, units = SLOB_UNITS(size);
+	unsigned long flags;
+
+	spin_lock_irqsave(&slob_lock, flags);
+	prev = slobfree;
+	for (cur = prev->next; ; prev = cur, cur = cur->next) {
+		if (align) {
+			aligned = (slob_t *)ALIGN((unsigned long)cur, align);
+			delta = aligned - cur;
+		}
+		if (cur->units >= units + delta) { /* room enough? */
+			if (delta) { /* need to fragment head to align? */
+				aligned->units = cur->units - delta;
+				aligned->next = cur->next;
+				cur->next = aligned;
+				cur->units = delta;
+				prev = cur;
+				cur = aligned;
+			}
+
+			if (cur->units == units) /* exact fit? */
+				prev->next = cur->next; /* unlink */
+			else { /* fragment */
+				prev->next = cur + units;
+				prev->next->units = cur->units - units;
+				prev->next->next = cur->next;
+				cur->units = units;
+			}
+
+			slobfree = prev;
+			spin_unlock_irqrestore(&slob_lock, flags);
+			return cur;
+		}
+		if (cur == slobfree) {
+			spin_unlock_irqrestore(&slob_lock, flags);
+
+			if (size == PAGE_SIZE) /* trying to shrink arena? */
+				return 0;
+
+			cur = (slob_t *)__get_free_page(gfp);
+			if (!cur)
+				return 0;
+
+			slob_free(cur, PAGE_SIZE);
+			spin_lock_irqsave(&slob_lock, flags);
+			cur = slobfree;
+		}
+	}
+}
+
+static void slob_free(void *block, int size)
+{
+	slob_t *cur, *b = (slob_t *)block;
+	unsigned long flags;
+
+	if (!block)
+		return;
+
+	if (size)
+		b->units = SLOB_UNITS(size);
+
+	/* Find reinsertion point */
+	spin_lock_irqsave(&slob_lock, flags);
+	for (cur = slobfree; !(b > cur && b < cur->next); cur = cur->next)
+		if (cur >= cur->next && (b > cur || b < cur->next))
+			break;
+
+	if (b + b->units == cur->next) {
+		b->units += cur->next->units;
+		b->next = cur->next->next;
+	} else
+		b->next = cur->next;
+
+	if (cur + cur->units == b) {
+		cur->units += b->units;
+		cur->next = b->next;
+	} else
+		cur->next = b;
+
+	slobfree = cur;
+
+	spin_unlock_irqrestore(&slob_lock, flags);
+}
+
+static int FASTCALL(find_order(int size));
+static int fastcall find_order(int size)
+{
+	int order = 0;
+	for ( ; size > 4096 ; size >>=1)
+		order++;
+	return order;
+}
+
+void *kmalloc(size_t size, gfp_t gfp)
+{
+	slob_t *m;
+	bigblock_t *bb;
+	unsigned long flags;
+
+	if (size < PAGE_SIZE - SLOB_UNIT) {
+		m = slob_alloc(size + SLOB_UNIT, gfp, 0);
+		return m ? (void *)(m + 1) : 0;
+	}
+
+	bb = slob_alloc(sizeof(bigblock_t), gfp, 0);
+	if (!bb)
+		return 0;
+
+	bb->order = find_order(size);
+	bb->pages = (void *)__get_free_pages(gfp, bb->order);
+
+	if (bb->pages) {
+		spin_lock_irqsave(&block_lock, flags);
+		bb->next = bigblocks;
+		bigblocks = bb;
+		spin_unlock_irqrestore(&block_lock, flags);
+		return bb->pages;
+	}
+
+	slob_free(bb, sizeof(bigblock_t));
+	return 0;
+}
+
+EXPORT_SYMBOL(kmalloc);
+
+void *kzalloc(size_t size, gfp_t flags)
+{
+	void *ret = kmalloc(size, flags);
+	if (ret)
+		memset(ret, 0, size);
+	return ret;
+}
+
+EXPORT_SYMBOL(kzalloc);
+
+void kfree(const void *block)
+{
+	bigblock_t *bb, **last = &bigblocks;
+	unsigned long flags;
+
+	if (!block)
+		return;
+
+	if (!((unsigned int)block & (PAGE_SIZE-1))) {
+		/* might be on the big block list */
+		spin_lock_irqsave(&block_lock, flags);
+		for (bb = bigblocks; bb; last = &bb->next, bb = bb->next) {
+			if (bb->pages == block) {
+				*last = bb->next;
+				spin_unlock_irqrestore(&block_lock, flags);
+				free_pages((unsigned long)block, bb->order);
+				slob_free(bb, sizeof(bigblock_t));
+				return;
+			}
+		}
+		spin_unlock_irqrestore(&block_lock, flags);
+	}
+
+	slob_free((slob_t *)block - 1, 0);
+	return;
+}
+
+EXPORT_SYMBOL(kfree);
+
+unsigned int ksize(const void *block)
+{
+	bigblock_t *bb;
+	unsigned long flags;
+
+	if (!block)
+		return 0;
+
+	if (!((unsigned int)block & (PAGE_SIZE-1))) {
+		spin_lock_irqsave(&block_lock, flags);
+		for (bb = bigblocks; bb; bb = bb->next)
+			if (bb->pages == block) {
+				spin_unlock_irqrestore(&slob_lock, flags);
+				return PAGE_SIZE << bb->order;
+			}
+		spin_unlock_irqrestore(&block_lock, flags);
+	}
+
+	return ((slob_t *)block - 1)->units * SLOB_UNIT;
+}
+
+struct kmem_cache_s {
+	unsigned int size, align;
+	const char *name;
+	void (*ctor)(void *, kmem_cache_t *, unsigned long);
+	void (*dtor)(void *, kmem_cache_t *, unsigned long);
+};
+
+kmem_cache_t *kmem_cache_create(const char *name, size_t size, size_t align,
+	unsigned long flags,
+	void (*ctor)(void*, kmem_cache_t *, unsigned long),
+	void (*dtor)(void*, kmem_cache_t *, unsigned long))
+{
+	kmem_cache_t *c;
+
+	c = slob_alloc(sizeof(kmem_cache_t), flags, 0);
+
+	if (c) {
+		c->name = name;
+		c->size = size;
+		c->ctor = ctor;
+		c->dtor = dtor;
+		/* ignore alignment unless it's forced */
+		c->align = (flags & SLAB_MUST_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
+		if (c->align < align)
+			c->align = align;
+	}
+
+	return c;
+}
+EXPORT_SYMBOL(kmem_cache_create);
+
+int kmem_cache_destroy(kmem_cache_t *c)
+{
+	slob_free(c, sizeof(kmem_cache_t));
+	return 0;
+}
+EXPORT_SYMBOL(kmem_cache_destroy);
+
+void *kmem_cache_alloc(kmem_cache_t *c, gfp_t flags)
+{
+	void *b;
+
+	if (c->size < PAGE_SIZE)
+		b = slob_alloc(c->size, flags, c->align);
+	else
+		b = (void *)__get_free_pages(flags, find_order(c->size));
+
+	if (c->ctor)
+		c->ctor(b, c, SLAB_CTOR_CONSTRUCTOR);
+
+	return b;
+}
+EXPORT_SYMBOL(kmem_cache_alloc);
+
+void kmem_cache_free(kmem_cache_t *c, void *b)
+{
+	if (c->dtor)
+		c->dtor(b, c, 0);
+
+	if (c->size < PAGE_SIZE)
+		slob_free(b, c->size);
+	else
+		free_pages((unsigned long)b, find_order(c->size));
+}
+EXPORT_SYMBOL(kmem_cache_free);
+
+unsigned int kmem_cache_size(kmem_cache_t *c)
+{
+	return c->size;
+}
+EXPORT_SYMBOL(kmem_cache_size);
+
+const char *kmem_cache_name(kmem_cache_t *c)
+{
+	return c->name;
+}
+EXPORT_SYMBOL(kmem_cache_name);
+
+static struct timer_list slob_timer = TIMER_INITIALIZER(
+	(void (*)(unsigned long))kmem_cache_init, 0, 0);
+
+void kmem_cache_init(void)
+{
+	void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
+
+	if (p)
+		free_page((unsigned int)p);
+
+	mod_timer(&slob_timer, jiffies + HZ);
+}
+
+atomic_t slab_reclaim_pages = ATOMIC_INIT(0);
+EXPORT_SYMBOL(slab_reclaim_pages);
+
+#ifdef CONFIG_SMP
+
+void *__alloc_percpu(size_t size, size_t align)
+{
+	int i;
+	struct percpu_data *pdata = kmalloc(sizeof (*pdata), GFP_KERNEL);
+
+	if (!pdata)
+		return NULL;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (!cpu_possible(i))
+			continue;
+		pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
+		if (!pdata->ptrs[i])
+			goto unwind_oom;
+		memset(pdata->ptrs[i], 0, size);
+	}
+
+	/* Catch derefs w/o wrappers */
+	return (void *) (~(unsigned long) pdata);
+
+unwind_oom:
+	while (--i >= 0) {
+		if (!cpu_possible(i))
+			continue;
+		kfree(pdata->ptrs[i]);
+	}
+	kfree(pdata);
+	return NULL;
+}
+EXPORT_SYMBOL(__alloc_percpu);
+
+void
+free_percpu(const void *objp)
+{
+	int i;
+	struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (!cpu_possible(i))
+			continue;
+		kfree(p->ptrs[i]);
+	}
+	kfree(p);
+}
+EXPORT_SYMBOL(free_percpu);
+
+#endif
\ No newline at end of file
