* Avoid flicker on the TRAB's VFD by synchronizing the enable with
  the HSYNC/VSYNC. Requires new CPLD code (Version 101 for Rev. 100
  boards, version 153 for Rev. 200 boards).

* Patch by Vladimir Gurevich, 12 Mar 2003:
  Fix relocation problem of statically initialized string pointers
  in common/cmd_pci.c

* Patch by Kai-Uwe Blöm, 12 Mar 2003:
  Cleanup & bug fixes for JFFS2 code:
  - the memory mangement was broken. It caused havoc on malloc by
    writing beyond the block boundaries.
  - the length calculation for files was wrong, sometimes resulting
    in short file reads.
  - data copying now optionally takes fragment version numbers into
    account, to avoid copying from older data.
  See doc/README.JFFS2 for details.
diff --git a/CHANGELOG b/CHANGELOG
index 1b36b41..18613a8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,24 @@
 Changes since U-Boot 0.2.2:
 ======================================================================
 
+* Avoid flicker on the TRAB's VFD by synchronizing the enable with
+  the HSYNC/VSYNC. Requires new CPLD code (Version 101 for Rev. 100
+  boards, version 153 for Rev. 200 boards).
+
+* Patch by Vladimir Gurevich, 12 Mar 2003:
+  Fix relocation problem of statically initialized string pointers
+  in common/cmd_pci.c
+
+* Patch by Kai-Uwe Blöm, 12 Mar 2003:
+  Cleanup & bug fixes for JFFS2 code:
+  - the memory mangement was broken. It caused havoc on malloc by
+    writing beyond the block boundaries.
+  - the length calculation for files was wrong, sometimes resulting
+    in short file reads.
+  - data copying now optionally takes fragment version numbers into
+    account, to avoid copying from older data.
+  See doc/README.JFFS2 for details.
+
 * Patch by Josef Wagner, 12 Mar 2003:
   - 16/32 MB and 50/80 MHz support with auto-detection for IP860
   - ETH05 and BEDBUG support for CU824
diff --git a/board/csb226/csb226.c b/board/csb226/csb226.c
index 11cab00..a79d168 100644
--- a/board/csb226/csb226.c
+++ b/board/csb226/csb226.c
@@ -38,10 +38,10 @@
 
 int misc_init_r(void)
 {
+#if 0	
 	uchar *str;
 	
 	/* determine if the software update key is pressed during startup */
-#if 0	
 	/* not ported yet... */
 	if (GPLR0 & 0x00000800) {
 		printf("using bootcmd_normal (sw-update button not pressed)\n");
diff --git a/board/emk/top860/config.mk b/board/emk/top860/config.mk
index 95917a1..7b940cb 100644
--- a/board/emk/top860/config.mk
+++ b/board/emk/top860/config.mk
@@ -21,4 +21,8 @@
 # MA 02111-1307 USA
 #
 
+#
+# TOP860 board
+#
+
 TEXT_BASE = 0x80000000
diff --git a/board/innokom/innokom.c b/board/innokom/innokom.c
index 17f6353..0176d9c 100644
--- a/board/innokom/innokom.c
+++ b/board/innokom/innokom.c
@@ -39,7 +39,7 @@
  * The Innokom board has GPIO70 connected to SCLK which can be toggled
  * until all chips think that their current cycles are finished.
  */
-int i2c_init_board(void)
+void i2c_init_board(void)
 {
 	int i;
 
@@ -53,8 +53,6 @@
 	}
         /* set gpio pin to input */
         GPDR(70) &= ~GPIO_bit(70);
-
-	return 0;
 }
 
 
diff --git a/board/lubbock/flash.c b/board/lubbock/flash.c
index a938750..dcf829b 100644
--- a/board/lubbock/flash.c
+++ b/board/lubbock/flash.c
@@ -28,7 +28,7 @@
 #include <linux/byteorder/swab.h>
 
 
-flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];	/* info for FLASH chips    */
 
 /* Board support for 1 or 2 flash devices */
 #define FLASH_PORT_WIDTH32
@@ -53,50 +53,47 @@
  * Functions
  */
 static ulong flash_get_size (FPW *addr, flash_info_t *info);
-static int   write_data (flash_info_t *info, ulong dest, FPW data);
-static void  flash_get_offsets (ulong base, flash_info_t *info);
-void inline  spin_wheel(void);
+static int write_data (flash_info_t *info, ulong dest, FPW data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+void inline spin_wheel (void);
 
 /*-----------------------------------------------------------------------
  */
 
 unsigned long flash_init (void)
 {
-   int i;
-    ulong size = 0;
+	int i;
+	ulong size = 0;
 
-    for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
-    {
-        switch (i)
-        {
-           case 0:
-            flash_get_size((FPW *)PHYS_FLASH_1, &flash_info[i]);
-	         flash_get_offsets(PHYS_FLASH_1, &flash_info[i]);
-                break;
-           case 1:
-            flash_get_size((FPW *)PHYS_FLASH_2, &flash_info[i]);
-	         flash_get_offsets(PHYS_FLASH_2, &flash_info[i]);
-                break;
-           default:
-	        panic("configured to many flash banks!\n");
-                break;
-        }
-	size += flash_info[i].size;
-    }
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+		switch (i) {
+		case 0:
+			flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]);
+			flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
+			break;
+		case 1:
+			flash_get_size ((FPW *) PHYS_FLASH_2, &flash_info[i]);
+			flash_get_offsets (PHYS_FLASH_2, &flash_info[i]);
+			break;
+		default:
+			panic ("configured to many flash banks!\n");
+			break;
+		}
+		size += flash_info[i].size;
+	}
 
-    /* Protect monitor and environment sectors
-     */
-    flash_protect(FLAG_PROTECT_SET,
-		  CFG_FLASH_BASE,
-		  CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
-		  &flash_info[0]);
+	/* Protect monitor and environment sectors
+	 */
+	flash_protect ( FLAG_PROTECT_SET,
+			CFG_FLASH_BASE,
+			CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
+			&flash_info[0] );
 
-    flash_protect(FLAG_PROTECT_SET,
-		  CFG_ENV_ADDR,
-		  CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
-		  &flash_info[0]);
+	flash_protect ( FLAG_PROTECT_SET,
+			CFG_ENV_ADDR,
+			CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0] );
 
-    return size;
+	return size;
 }
 
 /*-----------------------------------------------------------------------
@@ -119,39 +116,45 @@
 
 /*-----------------------------------------------------------------------
  */
-void flash_print_info  (flash_info_t *info)
+void flash_print_info (flash_info_t *info)
 {
 	int i;
 
 	if (info->flash_id == FLASH_UNKNOWN) {
 		printf ("missing or unknown FLASH type\n");
 		return;
-        }
+	}
 
 	switch (info->flash_id & FLASH_VENDMASK) {
-		case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
-		default:		printf ("Unknown Vendor ");	break;
+	case FLASH_MAN_INTEL:
+		printf ("INTEL ");
+		break;
+	default:
+		printf ("Unknown Vendor ");
+		break;
 	}
 
 	switch (info->flash_id & FLASH_TYPEMASK) {
-   case FLASH_28F128J3A:
-				printf ("28F128J3A\n"); break;
-	default:		printf ("Unknown Chip Type\n"); break;
-        }
+	case FLASH_28F128J3A:
+		printf ("28F128J3A\n");
+		break;
+	default:
+		printf ("Unknown Chip Type\n");
+		break;
+	}
 
 	printf ("  Size: %ld MB in %d Sectors\n",
-	        info->size >> 20, info->sector_count);
+			info->size >> 20, info->sector_count);
 
 	printf ("  Sector Start Addresses:");
-	for (i=0; i<info->sector_count; ++i) {
-	        if ((i % 5) == 0)
-	        printf ("\n   ");
+	for (i = 0; i < info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n   ");
 		printf (" %08lX%s",
 			info->start[i],
-			info->protect[i] ? " (RO)" : "     "
-		);
-        }
-        printf ("\n");
+			info->protect[i] ? " (RO)" : "     ");
+	}
+	printf ("\n");
 	return;
 }
 
@@ -163,37 +166,37 @@
 	volatile FPW value;
 
 	/* Write auto select command: read Manufacturer ID */
-	addr[0x5555] = (FPW)0x00AA00AA;
-	addr[0x2AAA] = (FPW)0x00550055;
-	addr[0x5555] = (FPW)0x00900090;
+	addr[0x5555] = (FPW) 0x00AA00AA;
+	addr[0x2AAA] = (FPW) 0x00550055;
+	addr[0x5555] = (FPW) 0x00900090;
 
-   mb();
+	mb ();
 	value = addr[0];
 
-   switch (value) {
+	switch (value) {
 
-   case (FPW)INTEL_MANUFACT:
-      info->flash_id = FLASH_MAN_INTEL;
-      break;
+	case (FPW) INTEL_MANUFACT:
+		info->flash_id = FLASH_MAN_INTEL;
+		break;
 
 	default:
 		info->flash_id = FLASH_UNKNOWN;
 		info->sector_count = 0;
 		info->size = 0;
-		addr[0] = (FPW)0x00FF00FF;      /* restore read mode */
-		return (0);			/* no or unknown flash	*/
+		addr[0] = (FPW) 0x00FF00FF;	/* restore read mode */
+		return (0);			/* no or unknown flash  */
 	}
 
-   mb();
-	value = addr[1];			/* device ID		*/
+	mb ();
+	value = addr[1];			/* device ID        */
 
-   switch (value) {
+	switch (value) {
 
-   case (FPW)INTEL_ID_28F128J3A:
-      info->flash_id += FLASH_28F128J3A;
-      info->sector_count = 128;
-      info->size = 0x02000000;
-      break;            /* => 16 MB     */
+	case (FPW) INTEL_ID_28F128J3A:
+		info->flash_id += FLASH_28F128J3A;
+		info->sector_count = 128;
+		info->size = 0x02000000;
+		break;				/* => 16 MB     */
 
 	default:
 		info->flash_id = FLASH_UNKNOWN;
@@ -204,9 +207,9 @@
 		printf ("** ERROR: sector count %d > max (%d) **\n",
 			info->sector_count, CFG_MAX_FLASH_SECT);
 		info->sector_count = CFG_MAX_FLASH_SECT;
-    }
+	}
 
-	addr[0] = (FPW)0x00FF00FF;      /* restore read mode */
+	addr[0] = (FPW) 0x00FF00FF;		/* restore read mode */
 
 	return (info->size);
 }
@@ -215,34 +218,34 @@
 /*-----------------------------------------------------------------------
  */
 
-int	flash_erase (flash_info_t *info, int s_first, int s_last)
+int flash_erase (flash_info_t *info, int s_first, int s_last)
 {
-    int flag, prot, sect;
-	ulong type, start, now, last;
+	int flag, prot, sect;
+	ulong type, start, last;
 	int rcode = 0;
 
-    if ((s_first < 0) || (s_first > s_last)) {
+	if ((s_first < 0) || (s_first > s_last)) {
 		if (info->flash_id == FLASH_UNKNOWN) {
 			printf ("- missing\n");
 		} else {
 			printf ("- no sectors to erase\n");
 		}
 		return 1;
-    }
+	}
 
 	type = (info->flash_id & FLASH_VENDMASK);
 	if ((type != FLASH_MAN_INTEL)) {
 		printf ("Can't erase unknown flash type %08lx - aborted\n",
 			info->flash_id);
 		return 1;
-    }
+	}
 
-    prot = 0;
-    for (sect=s_first; sect<=s_last; ++sect) {
-	if (info->protect[sect]) {
-	    prot++;
+	prot = 0;
+	for (sect = s_first; sect <= s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
 	}
-    }
 
 	if (prot) {
 		printf ("- Warning: %d protected sectors will not be erased!\n",
@@ -252,42 +255,42 @@
 	}
 
 	start = get_timer (0);
-	last  = start;
+	last = start;
 
-   /* Disable interrupts which might cause a timeout here */
-    flag = disable_interrupts();
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts ();
 
-    /* Start erase on unprotected sectors */
-	for (sect = s_first; sect<=s_last; sect++) {
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect <= s_last; sect++) {
 		if (info->protect[sect] == 0) {	/* not protected */
-			FPWV *addr = (FPWV *)(info->start[sect]);
+			FPWV *addr = (FPWV *) (info->start[sect]);
 			FPW status;
 
-	printf("Erasing sector %2d ... ", sect);
+			printf ("Erasing sector %2d ... ", sect);
 
-	/* arm simple, non interrupt dependent timer */
-	reset_timer_masked();
+			/* arm simple, non interrupt dependent timer */
+			reset_timer_masked ();
 
-			*addr = (FPW)0x00500050;	/* clear status register */
-			*addr = (FPW)0x00200020;	/* erase setup */
-			*addr = (FPW)0x00D000D0;	/* erase confirm */
+			*addr = (FPW) 0x00500050;	/* clear status register */
+			*addr = (FPW) 0x00200020;	/* erase setup */
+			*addr = (FPW) 0x00D000D0;	/* erase confirm */
 
-			while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) {
-		if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
+			while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
+				if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
 					printf ("Timeout\n");
-					*addr = (FPW)0x00B000B0; /* suspend erase	  */
-					*addr = (FPW)0x00FF00FF; /* reset to read mode */
+					*addr = (FPW) 0x00B000B0;	/* suspend erase     */
+					*addr = (FPW) 0x00FF00FF;	/* reset to read mode */
 					rcode = 1;
 					break;
-	}
-    }
+				}
+			}
 
-			*addr = 0x00500050; /* clear status register cmd.   */
-			*addr = 0x00FF00FF; /* resest to read mode          */
+			*addr = 0x00500050;	/* clear status register cmd.   */
+			*addr = 0x00FF00FF;	/* resest to read mode          */
 
 			printf (" done\n");
-        }
-        }
+		}
+	}
 	return rcode;
 }
 
@@ -301,7 +304,7 @@
 
 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 {
-    ulong cp, wp;
+	ulong cp, wp;
 	FPW data;
 	int count, i, l, rc, port_width;
 
@@ -317,67 +320,66 @@
 	port_width = 4;
 #endif
 
-    /*
-     * handle unaligned start bytes
-     */
-    if ((l = addr - wp) != 0) {
-	data = 0;
-	for (i=0, cp=wp; i<l; ++i, ++cp) {
-			data = (data << 8) | (*(uchar *)cp);
-	}
-		for (; i<port_width && cnt>0; ++i) {
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i = 0, cp = wp; i < l; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *) cp);
+		}
+		for (; i < port_width && cnt > 0; ++i) {
 			data = (data << 8) | *src++;
-	    --cnt;
-	    ++cp;
-	}
-		for (; cnt==0 && i<port_width; ++i, ++cp) {
-			data = (data << 8) | (*(uchar *)cp);
-	}
+			--cnt;
+			++cp;
+		}
+		for (; cnt == 0 && i < port_width; ++i, ++cp) {
+			data = (data << 8) | (*(uchar *) cp);
+		}
 
-		if ((rc = write_data(info, wp, SWAP(data))) != 0) {
-	    return (rc);
-	}
+		if ((rc = write_data (info, wp, SWAP (data))) != 0) {
+			return (rc);
+		}
 		wp += port_width;
-    }
+	}
 
-    /*
-     * handle word aligned part
-     */
+	/*
+	 * handle word aligned part
+	 */
 	count = 0;
 	while (cnt >= port_width) {
 		data = 0;
-		for (i=0; i<port_width; ++i) {
+		for (i = 0; i < port_width; ++i) {
 			data = (data << 8) | *src++;
 		}
-		if ((rc = write_data(info, wp, SWAP(data))) != 0) {
-	    return (rc);
-	}
-		wp  += port_width;
+		if ((rc = write_data (info, wp, SWAP (data))) != 0) {
+			return (rc);
+		}
+		wp += port_width;
 		cnt -= port_width;
-		if (count++ > 0x800)
-		{
-         spin_wheel();
+		if (count++ > 0x800) {
+			spin_wheel ();
 			count = 0;
 		}
-    }
+	}
 
-    if (cnt == 0) {
+	if (cnt == 0) {
 		return (0);
-    }
+	}
 
-    /*
-     * handle unaligned tail bytes
-     */
-    data = 0;
-	for (i=0, cp=wp; i<port_width && cnt>0; ++i, ++cp) {
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
 		data = (data << 8) | *src++;
-	--cnt;
-    }
-	for (; i<port_width; ++i, ++cp) {
-		data = (data << 8) | (*(uchar *)cp);
+		--cnt;
+	}
+	for (; i < port_width; ++i, ++cp) {
+		data = (data << 8) | (*(uchar *) cp);
 	}
 
-	return (write_data(info, wp, SWAP(data)));
+	return (write_data (info, wp, SWAP (data)));
 }
 
 /*-----------------------------------------------------------------------
@@ -388,45 +390,42 @@
  */
 static int write_data (flash_info_t *info, ulong dest, FPW data)
 {
-	FPWV *addr = (FPWV *)dest;
+	FPWV *addr = (FPWV *) dest;
 	ulong status;
-	ulong start;
 	int flag;
 
 	/* Check if Flash is (sufficiently) erased */
 	if ((*addr & data) != data) {
-		printf("not erased at %08lx (%x)\n",(ulong)addr,*addr);
+		printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
 		return (2);
 	}
 	/* Disable interrupts which might cause a timeout here */
-	flag = disable_interrupts();
+	flag = disable_interrupts ();
 
-	*addr = (FPW)0x00400040;		/* write setup */
+	*addr = (FPW) 0x00400040;	/* write setup */
 	*addr = data;
 
 	/* arm simple, non interrupt dependent timer */
-	reset_timer_masked();
+	reset_timer_masked ();
 
 	/* wait while polling the status register */
-	while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) {
-		if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) {
-			*addr = (FPW)0x00FF00FF;	/* restore read mode */
+	while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
+		if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) {
+			*addr = (FPW) 0x00FF00FF;	/* restore read mode */
 			return (1);
 		}
-    }
+	}
 
-	*addr = (FPW)0x00FF00FF;	/* restore read mode */
+	*addr = (FPW) 0x00FF00FF;	/* restore read mode */
 
 	return (0);
 }
 
-void inline
-spin_wheel(void)
+void inline spin_wheel (void)
 {
-   static int r=0,p=0;
-   static char w[] = "\\/-";
+	static int p = 0;
+	static char w[] = "\\/-";
 
-   printf("\010%c", w[p]);
-   (++p == 3) ? (p = 0) : 0;
+	printf ("\010%c", w[p]);
+	(++p == 3) ? (p = 0) : 0;
 }
-
diff --git a/board/mpl/common/common_util.c b/board/mpl/common/common_util.c
index 0a67090..19ead33 100644
--- a/board/mpl/common/common_util.c
+++ b/board/mpl/common/common_util.c
@@ -49,7 +49,9 @@
 	unsigned long start;
 	flash_info_t *info;
 	int i,rc;
+#if defined(CONFIG_PIP405) || defined(CONFIG_MIP405)
 	unsigned long *magic = (unsigned long *)src;
+#endif
 
 	info = &flash_info[0];
 
diff --git a/board/mpl/vcma9/cmd_vcma9.c b/board/mpl/vcma9/cmd_vcma9.c
index cdafc50..80bb61b2b 100644
--- a/board/mpl/vcma9/cmd_vcma9.c
+++ b/board/mpl/vcma9/cmd_vcma9.c
@@ -102,7 +102,7 @@
 				printf("\nplease defined 'ethaddr'\n");
 			}
 		} else if (strcmp(argv[2], "dump") == 0) {
-			uchar addr, endaddr, csum; ushort data;
+			uchar addr = 0, endaddr, csum; ushort data;
 
 			printf("Dump of CS8900 config device: ");
 			cs8900_e2prom_read(addr, &data);
diff --git a/board/mpl/vcma9/vcma9.c b/board/mpl/vcma9/vcma9.c
index 8e3552e..e452a7b 100644
--- a/board/mpl/vcma9/vcma9.c
+++ b/board/mpl/vcma9/vcma9.c
@@ -183,7 +183,6 @@
 int checkboard(void)
 {
 	unsigned char s[50];
-	unsigned char bc, var, rc;
 	int i;
 	backup_t *b = (backup_t *) s;
 
diff --git a/board/trab/vfd.c b/board/trab/vfd.c
index 894e315..9b61f6e 100644
--- a/board/trab/vfd.c
+++ b/board/trab/vfd.c
@@ -59,10 +59,24 @@
 #define	FRAME_BUF_SIZE	((256*4*56)/8)
 #define frame_buf_offs 4
 
+/* defines for starting Timer3 as CPLD-Clk */
+#define START3			(1 << 16)
+#define UPDATE3			(1 << 17)
+#define INVERT3			(1 << 18)
+#define RELOAD3			(1 << 19)
+
+/* CPLD-Register for controlling vfd-blank-signal */
+#define VFD_DISABLE	(*(volatile uchar *)0x04038000=0x0000)
+#define VFD_ENABLE	(*(volatile uchar *)0x04038000=0x0001)
+
 /* Supported VFD Types */
 #define	VFD_TYPE_T119C		1	/* Noritake T119C VFD */
 #define	VFD_TYPE_MN11236	2
 
+/*#define NEW_CPLD_CLK*/
+
+int vfd_board_id;
+
 /* taken from armboot/common/vfd.c */
 unsigned long adr_vfd_table[112][18][2][4][2];
 unsigned char bit_vfd_table[112][18][2][4][2];
@@ -80,9 +94,7 @@
 	/*
 	 * clear frame buffer (logical clear => set to "black")
 	 */
-	memset ((void *)(gd->fb_base),
-		gd->vfd_inv_data ? 0xFF : 0,
-		FRAME_BUF_SIZE);
+	memset ((void *)(gd->fb_base), 0, FRAME_BUF_SIZE);
 
 	switch (gd->vfd_type) {
 	case VFD_TYPE_T119C:
@@ -98,10 +110,7 @@
 			bit_nr = bit % 8;
 			bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
 			temp=(*(volatile unsigned char*)(adr));
-			if (gd->vfd_inv_data)
-				temp &= ~(1<<bit_nr);
-			else
-				temp |=  (1<<bit_nr);
+			temp |=  (1<<bit_nr);
 			(*(volatile unsigned char*)(adr))=temp;
 
 			if(grid_cycle<55)
@@ -115,10 +124,7 @@
 			bit_nr = bit%8;
 			bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
 			temp=(*(volatile unsigned char*)(adr));
-			if (gd->vfd_inv_data)
-				temp &= ~(1<<bit_nr);
-			else
-				temp |=  (1<<bit_nr);
+			temp |=  (1<<bit_nr);
 			(*(volatile unsigned char*)(adr))=temp;
 		}
 	    }
@@ -136,10 +142,7 @@
 			bit_nr = bit % 8;
 			bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;
 			temp=(*(volatile unsigned char*)(adr));
-			if (gd->vfd_inv_data)
-				temp &= ~(1<<bit_nr);
-			else
-				temp |=  (1<<bit_nr);
+			temp |=  (1<<bit_nr);
 			(*(volatile unsigned char*)(adr))=temp;
 
 			if(grid_cycle<37)
@@ -152,10 +155,7 @@
 			bit_nr = bit%8;
 			bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;
 			temp=(*(volatile unsigned char*)(adr));
-			if (gd->vfd_inv_data)
-				temp &= ~(1<<bit_nr);
-			else
-				temp |=  (1<<bit_nr);
+			temp |=  (1<<bit_nr);
 			(*(volatile unsigned char*)(adr))=temp;
 		}
 	    }
@@ -250,7 +250,7 @@
 			for(entry=0;entry<2;entry++) {
 			    unsigned long adr  = gd->fb_base;
 			    unsigned int bit_nr = 0;
-			    
+
 			    if (vfd_table[x][y][color][display][entry]) {
 
 				pixel  = vfd_table[x][y][color][display][entry] + frame_buf_offs;
@@ -295,18 +295,11 @@
 	bit_nr = bit_vfd_table[x][y][color][display][0];
 	temp=(*(volatile unsigned char*)(adr));
 
-	if (gd->vfd_inv_data) {
-		if (value)
-			temp &= ~(1<<bit_nr);
-		else
-			temp |=  (1<<bit_nr);
-	} else {
-		if (value)
-			temp |=  (1<<bit_nr);
-		else
-			temp &= ~(1<<bit_nr);
-	}
-	
+	if (value)
+		temp |=  (1<<bit_nr);
+	else
+		temp &= ~(1<<bit_nr);
+
 	(*(volatile unsigned char*)(adr))=temp;
 }
 
@@ -363,22 +356,59 @@
  * This function initializes VFD clock that is needed for the CPLD that
  * manages the keyboard.
  */
-int vfd_init_clocks(void)
+int vfd_init_clocks (void)
 {
-	/* Port-Pins als LCD-Ausgang */
-	rPCCON =   (rPCCON & 0xFFFFFF00)| 0x000000AA;
-	/* Port-Pins als LCD-Ausgang */
-	rPDCON =   (rPDCON & 0xFFFFFF03)| 0x000000A8;
-#ifdef CFG_WITH_VFRAME
-	/* mit VFRAME zum Messen */
-	rPDCON =   (rPDCON & 0xFFFFFF00)| 0x000000AA;
-#endif
 
-	rLCDCON2 = 0x000DC000;
-	rLCDCON3 = 0x0051000A;
-	rLCDCON4 = 0x00000001;
-	rLCDCON5 = 0x00000440;
+	/* try to determine display type from the value
+	 * defined by pull-ups
+	 */
+	rPCUP = (rPCUP & 0xFFF0);	/* activate  GPC0...GPC3 pullups */
+	rPCCON = (rPCCON & 0xFFFFFF00);	/* configure GPC0...GPC3 as inputs */
+	udelay (10);				/* allow signals to settle */
+	vfd_board_id = (~rPCDAT) & 0x000F;	/* read GPC0...GPC3 port pins */
+
+	VFD_DISABLE;				/* activate blank for the vfd */
+
+#define	NEW_CPLD_CLK
+
+#ifdef NEW_CPLD_CLK
+	if (vfd_board_id) {
+		/* If new board revision, then use PWM 3 as cpld-clock */
+		/* Enable 500 Hz timer for fill level sensor to operate properly */
+		/* Configure TOUT3 as functional pin, disable pull-up */
+		rPDCON &= ~0x30000;
+		rPDCON |= 0x20000;
+		rPDUP |= (1 << 8);
+
+		/* Configure the prescaler */
+		rTCFG0 &= ~0xff00;
+		rTCFG0 |= 0x0f00;
+
+		/* Select MUX input (divider) for timer3 (1/16) */
+		rTCFG1 &= ~0xf000;
+		rTCFG1 |= 0x3000;
+
+		/* Enable autoreload and set the counter and compare
+		 * registers to values for the 500 Hz clock
+		 * (for a given  prescaler (15) and divider (16)):
+		 * counter = (66000000 / 500) >> 9;
+		 */
+		rTCNTB3 = 0x101;
+		rTCMPB3 = 0x101 / 2;
+
+		/* Start timer */
+		rTCON = (rTCON | UPDATE3 | RELOAD3) & ~INVERT3;
+		rTCON = (rTCON | START3) & ~UPDATE3;
+	}
+#endif
+	/* If old board revision, then use vm-signal as cpld-clock */
+	rLCDCON2 = 0x00FFC000;
+	rLCDCON3 = 0x0007FF00;
+	rLCDCON4 = 0x00000000;
+	rLCDCON5 = 0x00000400;
 	rLCDCON1 = 0x00000B75;
+	/* VM (GPD1) is used as clock for the CPLD */
+	rPDCON = (rPDCON & 0xFFFFFFF3) | 0x00000008;
 
 	return 0;
 }
@@ -397,7 +427,7 @@
 	char *tmp;
 	ulong palette;
 	static int vfd_init_done = 0;
-	int vfd_id;
+	int vfd_inv_data = 0;
 
 	DECLARE_GLOBAL_DATA_PTR;
 
@@ -405,17 +435,9 @@
 		return (0);
 	vfd_init_done = 1;
 
-	/* try to determine display type from the value
-	 * defined by pull-ups
-	 */
-	rPCUP  = (rPCUP & 0xFFF0);	/* activate  GPC0...GPC3 pullups */
-	rPCCON = (rPCCON & 0xFFFFFF00);	/* configure GPC0...GPC3 as inputs */
-	udelay(10);			/* allow signals to settle */
+	debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_board_id);
 
-	vfd_id = (~rPCDAT) & 0x000F;	/* read GPC0...GPC3 port pins */
-	debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_id);
-
-	switch (vfd_id) {
+	switch (vfd_board_id) {
 	case 0:			/* board revision < Rev.200 */
 		if ((tmp = getenv ("vfd_type")) == NULL) {
 			break;
@@ -428,19 +450,18 @@
 			/* cannot use printf for a warning here */
 			gd->vfd_type = 0;	/* unknown */
 		}
-		gd->vfd_inv_data = 0;
 
 		break;
 	default:		/* default to MN11236, data inverted */
 		gd->vfd_type = VFD_TYPE_MN11236;
-		gd->vfd_inv_data = 1;
+		vfd_inv_data = 1;
 		setenv ("vfd_type", "MN11236");
 	}
 	debug ("VFD type: %s%s\n",
 		(gd->vfd_type == VFD_TYPE_T119C)   ? "T119C" :
 		(gd->vfd_type == VFD_TYPE_MN11236) ? "MN11236" :
 		"unknown",
-		gd->vfd_inv_data ? ", inverted data" : "");
+		vfd_inv_data ? ", inverted data" : "");
 
 	gd->fb_base = gd->fb_base;
 	create_vfd_table();
@@ -458,11 +479,33 @@
 	 * (wrap around)
 	 * see manual S3C2400
 	 */
+	/* Stopp LCD-Controller */
+	rLCDCON1 = 0x00000000;
 	/* frame buffer startadr */
 	rLCDSADDR1 = gd->fb_base >> 1;
  	/* frame buffer endadr */
 	rLCDSADDR2 = (gd->fb_base + FRAME_BUF_SIZE) >> 1;
 	rLCDSADDR3 = ((256/4));
+	rLCDCON2 = 0x000DC000;
+	rLCDCON3 = 0x0051000A;
+	rLCDCON4 = 0x00000001;
+	if (gd->vfd_type && vfd_inv_data)
+		rLCDCON5 = 0x000004C0;
+	else
+		rLCDCON5 = 0x00000440;
+
+	/* Port pins as LCD output */
+	rPCCON =   (rPCCON & 0xFFFFFF00)| 0x000000AA;
+	rPDCON =   (rPDCON & 0xFFFFFF03)| 0x000000A8;
+
+	/* Synchronize VFD enable with LCD controller to avoid flicker	*/
+	rLCDCON1 = 0x00000B75;			/* Start LCD-Controller	*/
+	while((rLCDCON5 & 0x180000)!=0x100000);	/* Wait for end of VSYNC */
+	while((rLCDCON5 & 0x060000)!=0x040000);	/* Wait for next HSYNC	*/
+	while((rLCDCON5 & 0x060000)==0x040000);
+	while((rLCDCON5 & 0x060000)!=0x000000);
+	if(gd->vfd_type)
+		VFD_ENABLE;
 
 	debug ("LCDSADDR1: %lX\n", rLCDSADDR1);
 	debug ("LCDSADDR2: %lX\n", rLCDSADDR2);
@@ -471,6 +514,17 @@
 	return 0;
 }
 
+/*
+ * Disable VFD: should be run before resetting the system:
+ * disable VM, enable pull-up
+ */
+void disable_vfd (void)
+{
+	VFD_DISABLE;
+	rPDCON &= ~0xC;
+	rPDUP  &= ~0x2;
+}
+
 /************************************************************************/
 /* ** ROM capable initialization part - needed to reserve FB memory	*/
 /************************************************************************/
diff --git a/common/cmd_pci.c b/common/cmd_pci.c
index 5a3b557..a26dedd 100644
--- a/common/cmd_pci.c
+++ b/common/cmd_pci.c
@@ -115,28 +115,65 @@
 
 char* pci_classes_str(u8 class)
 {
-	static char *pci_classes[] = {
-		"Build before PCI Rev2.0",
-		"Mass storage controller",
-		"Network controller     ",
-		"Display controller     ",
-		"Multimedia device      ",
-		"Memory controller      ",
-		"Bridge device          ",
-		"Simple comm. controller",
-		"Base system peripheral ",
-		"Input device           ",
-		"Docking station        ",
-		"Processor              ",
-		"Serial bus controller  ",
-		"Reserved entry         ",
-		"Does not fit any class "
-	};
-
-	if (class < (sizeof pci_classes / sizeof *pci_classes))
-		return pci_classes[(int) class];
-
+	switch (class) {
+        case PCI_CLASS_NOT_DEFINED:
+                return "Build before PCI Rev2.0";
+                break;
+        case PCI_BASE_CLASS_STORAGE:
+                return "Mass storage controller";
+                break;
+        case PCI_BASE_CLASS_NETWORK:
+                return "Network controller     ";
+                break;
+        case PCI_BASE_CLASS_DISPLAY:
+                return "Display controller     ";
+                break;
+        case PCI_BASE_CLASS_MULTIMEDIA:
+                return "Multimedia device      ";
+                break;
+        case PCI_BASE_CLASS_MEMORY:
+                return "Memory controller      ";
+                break;
+        case PCI_BASE_CLASS_BRIDGE:
+                return "Bridge device          ";
+                break;
+        case PCI_BASE_CLASS_COMMUNICATION:
+                return "Simple comm. controller";
+                break;
+        case PCI_BASE_CLASS_SYSTEM:
+                return "Base system peripheral ";
+                break;
+        case PCI_BASE_CLASS_INPUT:
+                return "Input device           ";
+                break;
+        case PCI_BASE_CLASS_DOCKING:
+                return "Docking station        ";
+                break;
+        case PCI_BASE_CLASS_PROCESSOR:
+                return "Processor              ";
+                break;
+        case PCI_BASE_CLASS_SERIAL:
+                return "Serial bus controller  ";
+                break;
+        case PCI_BASE_CLASS_INTELLIGENT:
+                return "Intelligent controller ";
+                break;
+        case PCI_BASE_CLASS_SATELLITE:
+                return "Satellite controller   ";
+                break;
+        case PCI_BASE_CLASS_CRYPT:
+                return "Cryptographic device   ";
+                break;
+        case PCI_BASE_CLASS_SIGNAL_PROCESSING:
+                return "DSP                    ";
+                break;
+        case PCI_CLASS_OTHERS:
+                return "Does not fit any class ";
+                break;
+        default:
 	return  "???                    ";
+                break;
+	};
 }
 
 /*
diff --git a/cpu/arm920t/interrupts.c b/cpu/arm920t/interrupts.c
index 963ccbd..195fb01 100644
--- a/cpu/arm920t/interrupts.c
+++ b/cpu/arm920t/interrupts.c
@@ -199,9 +199,9 @@
 	/* load value for 10 ms timeout */
 	lastdec = rTCNTB4 = timer_load_val;
 	/* auto load, manual update of Timer 4 */
-	rTCON = 0x600000;
+	rTCON = (rTCON & ~0x0700000) | 0x600000;
 	/* auto load, start Timer 4 */
-	rTCON = 0x500000;
+	rTCON = (rTCON & ~0x0700000) | 0x500000;
 	timestamp = 0;
 
 	return (0);
@@ -296,8 +296,10 @@
 
 #if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
 	tbclk = timer_load_val * 100;
-#elif defined(CONFIG_SMDK2410)
+#elif defined(CONFIG_SMDK2410) || defined(CONFIG_VCMA9)
 	tbclk = CFG_HZ;
+#else
+#	error "tbclk not configured"
 #endif
 
 	return tbclk;
diff --git a/cpu/arm920t/start.S b/cpu/arm920t/start.S
index a858dfa..4a4825a 100644
--- a/cpu/arm920t/start.S
+++ b/cpu/arm920t/start.S
@@ -446,6 +446,9 @@
 reset_cpu:
 #ifdef CONFIG_S3C2400
 	bl	disable_interrupts
+# ifdef CONFIG_TRAB
+	bl	disable_vfd
+# endif
 	ldr	r1, _rWTCON
 	ldr	r2, _rWTCNT
 	/* Disable watchdog */
diff --git a/doc/README.JFFS2 b/doc/README.JFFS2
index 0d39c46..3243895 100644
--- a/doc/README.JFFS2
+++ b/doc/README.JFFS2
@@ -9,6 +9,14 @@
 fsinfo  - print information about file systems
 ls      - list files in a directory
 
+If you boot from a partition which is mounted writable, and you
+update your boot environment by replacing single files on that
+partition, you should also define CFG_JFFS2_SORT_FRAGMENTS. Scanning
+the JFFS2 filesystem takes *much* longer with this feature, though.
+Sorting is done while inserting into the fragment list, which is
+more or less a bubble sort. That algorithm is known to be O(n^2),
+thus you should really consider if you can avoid it!
+
 
 There is two ways for JFFS2 to find the disk. The default way uses
 the flash_info structure to find the start of a JFFS2 disk (called
diff --git a/drivers/cs8900.c b/drivers/cs8900.c
index b9fac8c..d35332c 100644
--- a/drivers/cs8900.c
+++ b/drivers/cs8900.c
@@ -296,7 +296,7 @@
 /* write a 16-bit word into the EEPROM                     */
 /***********************************************************/
 
-void cs8900_e2prom_write(unsigned char addr, unsigned short value)
+int cs8900_e2prom_write(unsigned char addr, unsigned short value)
 {
 	cs8900_e2prom_ready();
 	put_reg(PP_EECMD, EEPROM_WRITE_EN);
@@ -307,7 +307,7 @@
 	put_reg(PP_EECMD, EEPROM_WRITE_DIS);
 	cs8900_e2prom_ready();
 
-	return;
+	return 0;
 }
 
 #endif	/* COMMANDS & CFG_NET */
diff --git a/drivers/cs8900.h b/drivers/cs8900.h
index dbfda3c..d772cad 100644
--- a/drivers/cs8900.h
+++ b/drivers/cs8900.h
@@ -253,6 +253,6 @@
 #define EEPROM_ERASE_CMD	0x0300
 
 extern int cs8900_e2prom_read(uchar, ushort *);
-extern void cs8900_e2prom_write(uchar, ushort);
+extern int cs8900_e2prom_write(uchar, ushort);
 
 #endif /* CONFIG_DRIVER_CS8900 */
diff --git a/drivers/s3c24x0_i2c.c b/drivers/s3c24x0_i2c.c
index bf435c9..b501761 100644
--- a/drivers/s3c24x0_i2c.c
+++ b/drivers/s3c24x0_i2c.c
@@ -64,10 +64,12 @@
 	return (rGPEDAT & 0x8000) >> 15;
 }
 
+#if 0
 static void SetIICSDA(int x)
 {
 	rGPEDAT = (rGPEDAT & ~0x8000) | (x&1) << 15;
 }
+#endif
 
 static void SetIICSCL(int x)
 {
diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index bacec8e..a5d9583 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
 /*
 -------------------------------------------------------------------------
  * Filename:      jffs2.c
@@ -75,6 +76,42 @@
  *
  */
 
+/*
+ * Bugfixing by Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>, (C) Mar/2003
+ *
+ * - overhaul of the memory management. Removed much of the "paper-bagging"
+ *   in that part of the code, fixed several bugs, now frees memory when
+ *   partition is changed.
+ *   It's still ugly :-(
+ * - fixed a bug in jffs2_1pass_read_inode where the file length calculation
+ *   was incorrect. Removed a bit of the paper-bagging as well.
+ * - removed double crc calculation for fragment headers in jffs2_private.h
+ *   for speedup.
+ * - scan_empty rewritten in a more "standard" manner (non-paperbag, that is).
+ * - spinning wheel now spins depending on how much memory has been scanned
+ * - lots of small changes all over the place to "improve" readability.
+ * - implemented fragment sorting to ensure that the newest data is copied
+ *   if there are multiple copies of fragments for a certain file offset.
+ *
+ * The fragment sorting feature must be enabled by CFG_JFFS2_SORT_FRAGMENTS.
+ * Sorting is done while adding fragments to the lists, which is more or less a
+ * bubble sort. This takes a lot of time, and is most probably not an issue if
+ * the boot filesystem is always mounted readonly.
+ *
+ * You should define it if the boot filesystem is mounted writable, and updates
+ * to the boot files are done by copying files to that filesystem.
+ *
+ *
+ * There's a big issue left: endianess is completely ignored in this code. Duh!
+ *
+ *
+ * You still should have paper bags at hand :-(. The code lacks more or less
+ * any comment, and is still arcane and difficult to read in places. As this
+ * is incompatible with any new code from the jffs2 maintainers anyway, it
+ * should probably be dumped and replaced by something like jffs2reader!
+ */
+
+
 #include <common.h>
 #include <config.h>
 #include <malloc.h>
@@ -88,124 +125,197 @@
 
 #include "jffs2_private.h"
 
-/* Compression names */
-static char *compr_names[] = {
-        "NONE",
-        "ZERO",
-        "RTIME",
-        "RUBINMIPS",
-        "COPY",
-        "DYNRUBIN",
-        "ZLIB" };
+
+#define	NODE_CHUNK  	1024	/* size of memory allocation chunk in b_nodes */
+#define	SPIN_BLKSIZE	18  	/* spin after having scanned 1<<BLKSIZE bytes */
 
-static char spinner[] = { '|', '\\', '-', '/' };
+/* Debugging switches */
+#undef	DEBUG_DIRENTS		/* print directory entry list after scan */
+#undef	DEBUG_FRAGMENTS		/* print fragment list after scan */
+#undef	DEBUG   			/* enable debugging messages */
 
-#define DEBUG
+
 #ifdef  DEBUG
 # define DEBUGF(fmt,args...)	printf(fmt ,##args)
 #else
 # define DEBUGF(fmt,args...)
 #endif
 
+
-#define MALLOC_CHUNK (10*1024)
+/* Compression names */
+static char *compr_names[] = {
+	"NONE",
+	"ZERO",
+	"RTIME",
+	"RUBINMIPS",
+	"COPY",
+	"DYNRUBIN",
+	"ZLIB"
+};
+
+/* Spinning wheel */
+static char spinner[] = { '|', '/', '-', '\\' };
 
+/* Memory management */
+struct mem_block {
+	u32	index;
+	struct mem_block *next;
+	struct b_node nodes[NODE_CHUNK];
+};
+
+
+static void
+free_nodes(struct b_list *list)
+{
+	while (list->listMemBase != NULL) {
+		struct mem_block *next = list->listMemBase->next;
+		free( list->listMemBase );
+		list->listMemBase = next;
+	}
+}
 
 static struct b_node *
-add_node(struct b_node *tail, u32 * count, u32 * memBase)
+add_node(struct b_list *list)
 {
-	u32 index;
-	u32 memLimit;
+	u32 index = 0;
+	struct mem_block *memBase;
 	struct b_node *b;
 
-	index = (*count) * sizeof(struct b_node) % MALLOC_CHUNK;
-	memLimit = MALLOC_CHUNK;
-
+	memBase = list->listMemBase;
+	if (memBase != NULL)
+		index = memBase->index;
 #if 0
 	putLabeledWord("add_node: index = ", index);
-	putLabeledWord("add_node: memLimit = ", memLimit);
-	putLabeledWord("add_node: memBase = ", *memBase);
+	putLabeledWord("add_node: memBase = ", list->listMemBase);
 #endif
 
-	/* we need not keep a list of bases since we'll never free the */
-	/* memory, just jump the the kernel */
-	if ((index == 0) || (index > memLimit)) {	/* we need mode space before we continue */
-		if ((*memBase = (u32) mmalloc(MALLOC_CHUNK)) == (u32) NULL) {
+	if (memBase == NULL || index >= NODE_CHUNK) {
+		/* we need more space before we continue */
+		memBase = mmalloc(sizeof(struct mem_block));
+		if (memBase == NULL) {
 			putstr("add_node: malloc failed\n");
 			return NULL;
 		}
+		memBase->next = list->listMemBase;
+		index = 0;
 #if 0
 		putLabeledWord("add_node: alloced a new membase at ", *memBase);
 #endif
 
 	}
 	/* now we have room to add it. */
-	b = (struct b_node *) (*memBase + index);
-
-	/* null on first call */
-	if (tail)
-		tail->next = b;
+	b = &memBase->nodes[index];
+	index ++;
 
-#if 0
-	putLabeledWord("add_node: tail = ", (u32) tail);
-	if (tail)
-		putLabeledWord("add_node: tail->next = ", (u32) tail->next);
+	memBase->index = index;
+	list->listMemBase = memBase;
+	list->listCount++;
+	return b;
+}
 
+static struct b_node *
+insert_node(struct b_list *list, u32 offset)
+{
+	struct b_node *new;
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+	struct b_node *b, *prev;
 #endif
 
-#if 0
-	putLabeledWord("add_node: mb+i = ", (u32) (*memBase + index));
-	putLabeledWord("add_node: b = ", (u32) b);
+	if (!(new = add_node(list))) {
+		putstr("add_node failed!\r\n");
+		return NULL;
+	}
+	new->offset = offset;
+
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+	if (list->listTail != NULL && list->listCompare(new, list->listTail))
+		prev = list->listTail;
+	else if (list->listLast != NULL && list->listCompare(new, list->listLast))
+		prev = list->listLast;
+	else
+		prev = NULL;
+
+	for (b = (prev ? prev->next : list->listHead);
+	     b != NULL && list->listCompare(new, b);
+	     prev = b, b = b->next) {
+		list->listLoops++;
+	}
+	if (b != NULL)
+		list->listLast = prev;
+
+	if (b != NULL) {
+		new->next = b;
+		if (prev != NULL)
+			prev->next = new;
+		else
+			list->listHead = new;
+	} else
 #endif
-	(*count)++;
-	b->next = (struct b_node *) NULL;
-	return b;
+	{
+		new->next = (struct b_node *) NULL;
+		if (list->listTail != NULL) {
+			list->listTail->next = new;
+			list->listTail = new;
+		} else {
+			list->listTail = list->listHead = new;
+		}
+	}
 
+	return new;
 }
 
-/* we know we have empties at the start offset so we will hop */
-/* t points that would be non F if there were a node here to speed this up. */
-struct jffs2_empty_node {
-	u32 first;
-	u32 second;
-};
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+static int compare_inodes(struct b_node *new, struct b_node *old)
+{
+	struct jffs2_raw_inode *jNew = (struct jffs2_raw_inode *)new->offset;
+	struct jffs2_raw_inode *jOld = (struct jffs2_raw_inode *)old->offset;
+
+	return jNew->version < jOld->version;
+}
+
+static int compare_dirents(struct b_node *new, struct b_node *old)
+{
+	struct jffs2_raw_dirent *jNew = (struct jffs2_raw_dirent *)new->offset;
+	struct jffs2_raw_dirent *jOld = (struct jffs2_raw_dirent *)old->offset;
+
+	return jNew->version > jOld->version;
+}
+#endif
 
 static u32
 jffs2_scan_empty(u32 start_offset, struct part_info *part)
 {
-	u32 max = part->size - sizeof(struct jffs2_raw_inode);
-
-	/* this would be either dir node_crc or frag isize */
-	u32 offset = start_offset + 32;
-	struct jffs2_empty_node *node;
+	char *max = part->offset + part->size - sizeof(struct jffs2_raw_inode);
+	char *offset = part->offset + start_offset;
 
-	start_offset += 4;
-	while (offset < max) {
-		node = (struct jffs2_empty_node *) (part->offset + offset);
-		if ((node->first == 0xFFFFFFFF) && (node->second == 0xFFFFFFFF)) {
-			/* we presume that there were no nodes in between and advance in a hop */
-			/* putLabeledWord("\t\tjffs2_scan_empty: empty at offset=",offset); */
-			start_offset = offset + 4;
-			offset = start_offset + 32;	/* orig 32 + 4 bytes for the second==0xfffff */
-		} else {
-			return start_offset;
-		}
+	while (offset < max && *(u32 *)offset == 0xFFFFFFFF) {
+		offset += sizeof(u32);
+		/* return if spinning is due */
+		if (((u32)offset & ((1 << SPIN_BLKSIZE)-1)) == 0) break;
 	}
-	return start_offset;
+
+	return offset - part->offset;
 }
 
 static u32
 jffs_init_1pass_list(struct part_info *part)
 {
-	if ( 0 != ( part->jffs2_priv=malloc(sizeof(struct b_lists)))){
-		struct b_lists *pL =(struct b_lists *)part->jffs2_priv;
+	struct b_lists *pL;
+
+	if (part->jffs2_priv != NULL) {
+		pL = (struct b_lists *)part->jffs2_priv;
+		free_nodes(&pL->frag);
+		free_nodes(&pL->dir);
+		free(pL);
+	}
+	if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) {
+		pL = (struct b_lists *)part->jffs2_priv;
 
-		pL->dirListHead = pL->dirListTail = NULL;
-		pL->fragListHead = pL->fragListTail = NULL;
-		pL->dirListCount = 0;
-		pL->dirListMemBase = 0;
-		pL->fragListCount = 0;
-		pL->fragListMemBase = 0;
-		pL->partOffset = 0x0;
+		memset(pL, 0, sizeof(*pL));
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+		pL->dir.listCompare = compare_dirents;
+		pL->frag.listCompare = compare_inodes;
+#endif
 	}
 	return 0;
 }
@@ -216,21 +326,18 @@
 {
 	struct b_node *b;
 	struct jffs2_raw_inode *jNode;
-	u32 totalSize = 1;
-	u32 oldTotalSize = 0;
-	u32 size = 0;
-	char *lDest = (char *) dest;
+	u32 totalSize = 0;
+	u16 latestVersion = 0;
+	char *lDest;
 	char *src;
 	long ret;
 	int i;
 	u32 counter = 0;
-	char totalSizeSet = 0;
 
-#if 0
-	b = pL->fragListHead;
-	while (b) {
+	for (b = pL->frag.listHead; b != NULL; b = b->next) {
 		jNode = (struct jffs2_raw_inode *) (b->offset);
 		if ((inode == jNode->ino)) {
+#if 0
 			putLabeledWord("\r\n\r\nread_inode: totlen = ", jNode->totlen);
 			putLabeledWord("read_inode: inode = ", jNode->ino);
 			putLabeledWord("read_inode: version = ", jNode->version);
@@ -241,58 +348,26 @@
 			putLabeledWord("read_inode: compr = ", jNode->compr);
 			putLabeledWord("read_inode: usercompr = ", jNode->usercompr);
 			putLabeledWord("read_inode: flags = ", jNode->flags);
-		}
-
-		b = b->next;
-	}
-
 #endif
-
-#if 1
-	b = pL->fragListHead;
-	while (b && (size < totalSize)) {
-		jNode = (struct jffs2_raw_inode *) (b->offset);
-		if ((inode == jNode->ino)) {
-			if ((jNode->isize == oldTotalSize) && (jNode->isize > totalSize)) {
-				/* 2 consecutive isizes indicate file length */
+			/* get actual file length from the newest node */
+			if (jNode->version >= latestVersion) {
 				totalSize = jNode->isize;
-				totalSizeSet = 1;
-			} else if (!totalSizeSet) {
-				totalSize = size + jNode->dsize + 1;
+				latestVersion = jNode->version;
 			}
-			oldTotalSize = jNode->isize;
 
 			if(dest) {
 				src = ((char *) jNode) + sizeof(struct jffs2_raw_inode);
-				/* lDest = (char *) (dest + (jNode->offset & ~3)); */
+				/* ignore data behind latest known EOF */
+				if (jNode->offset > totalSize)
+					continue;
+
 				lDest = (char *) (dest + jNode->offset);
 #if 0
-				putLabeledWord("\r\n\r\nread_inode: src = ", src);
+				putLabeledWord("read_inode: src = ", src);
 				putLabeledWord("read_inode: dest = ", lDest);
-				putLabeledWord("read_inode: dsize = ", jNode->dsize);
-				putLabeledWord("read_inode: csize = ", jNode->csize);
-				putLabeledWord("read_inode: version = ", jNode->version);
-				putLabeledWord("read_inode: isize = ", jNode->isize);
-				putLabeledWord("read_inode: offset = ", jNode->offset);
-				putLabeledWord("read_inode: compr = ", jNode->compr);
-				putLabeledWord("read_inode: flags = ", jNode->flags);
 #endif
 				switch (jNode->compr) {
 				case JFFS2_COMPR_NONE:
-#if 0
-					{
-						int i;
-
-						if ((dest > 0xc0092ff0) && (dest < 0xc0093000))
-							for (i = 0; i < first->length; i++) {
-								putLabeledWord("\tCOMPR_NONE: src =", src + i);
-								putLabeledWord("\tCOMPR_NONE: length =", first->length);
-								putLabeledWord("\tCOMPR_NONE: dest =", dest + i);
-								putLabeledWord("\tCOMPR_NONE: data =", (unsigned char) *(src + i));
-							}
-					}
-#endif
-
 					ret = (unsigned long) ldr_memcpy(lDest, src, jNode->dsize);
 					break;
 				case JFFS2_COMPR_ZERO:
@@ -320,22 +395,18 @@
 				}
 			}
 
-			size += jNode->dsize;
 #if 0
-			putLabeledWord("read_inode: size = ", size);
 			putLabeledWord("read_inode: totalSize = ", totalSize);
 			putLabeledWord("read_inode: compr ret = ", ret);
 #endif
 		}
-		b = b->next;
 		counter++;
 	}
-#endif
 
 #if 0
-	putLabeledWord("read_inode: returning = ", size);
+	putLabeledWord("read_inode: returning = ", totalSize);
 #endif
-	return size;
+	return totalSize;
 }
 
 /* find the inode from the slashless name given a parent */
@@ -354,18 +425,19 @@
 
 	counter = 0;
 	/* we need to search all and return the inode with the highest version */
-	for(b = pL->dirListHead;b;b=b->next,counter++) {
+	for(b = pL->dir.listHead; b; b = b->next, counter++) {
 		jDir = (struct jffs2_raw_dirent *) (b->offset);
-		if ((pino == jDir->pino) && (len == jDir->nsize) && (jDir->ino) &&	/* 0 for unlink */
+		if ((pino == jDir->pino) && (len == jDir->nsize) &&
+		    (jDir->ino) &&	/* 0 for unlink */
 		    (!strncmp(jDir->name, name, len))) {	/* a match */
 			if (jDir->version < version) continue;
 
-		        if(jDir->version==0) {
+		        if(jDir->version == 0) {
 			    	/* Is this legal? */
 				putstr(" ** WARNING ** ");
 				putnstr(jDir->name, jDir->nsize);
 				putstr(" is version 0 (in find, ignoring)\r\n");
-			} else if(jDir->version==version) {
+			} else if(jDir->version == version) {
 			    	/* Im pretty sure this isn't ... */
 				putstr(" ** ERROR ** ");
 				putnstr(jDir->name, jDir->nsize);
@@ -389,53 +461,53 @@
 
 static char *mkmodestr(unsigned long mode, char *str)
 {
-    static const char *l="xwr";
-    int mask=1, i;
-    char c;
+	static const char *l = "xwr";
+	int mask = 1, i;
+	char c;
 
-    switch (mode & S_IFMT) {
-        case S_IFDIR:    str[0]='d'; break;
-        case S_IFBLK:    str[0]='b'; break;
-        case S_IFCHR:    str[0]='c'; break;
-        case S_IFIFO:    str[0]='f'; break;
-        case S_IFLNK:    str[0]='l'; break;
-        case S_IFSOCK:   str[0]='s'; break;
-        case S_IFREG:    str[0]='-'; break;
-        default:        str[0]='?';
-    }
+	switch (mode & S_IFMT) {
+		case S_IFDIR:    str[0] = 'd'; break;
+		case S_IFBLK:    str[0] = 'b'; break;
+		case S_IFCHR:    str[0] = 'c'; break;
+		case S_IFIFO:    str[0] = 'f'; break;
+		case S_IFLNK:    str[0] = 'l'; break;
+		case S_IFSOCK:   str[0] = 's'; break;
+		case S_IFREG:    str[0] = '-'; break;
+		default:         str[0] = '?';
+	}
 
-    for(i=0;i<9;i++) {
-        c=l[i%3];
-        str[9-i]=(mode & mask)?c:'-';
-        mask=mask<<1;
-    }
+	for(i = 0; i < 9; i++) {
+		c = l[i%3];
+		str[9-i] = (mode & mask)?c:'-';
+		mask = mask<<1;
+	}
 
-    if(mode & S_ISUID) str[3]=(mode & S_IXUSR)?'s':'S';
-    if(mode & S_ISGID) str[6]=(mode & S_IXGRP)?'s':'S';
-    if(mode & S_ISVTX) str[9]=(mode & S_IXOTH)?'t':'T';
-    str[10]='\0';
-    return str;
+	if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S';
+	if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S';
+	if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T';
+	str[10] = '\0';
+	return str;
 }
 
 static inline void dump_stat(struct stat *st, const char *name)
 {
-    char str[20];
-    char s[64], *p;
+	char str[20];
+	char s[64], *p;
 
-    if (st->st_mtime == (time_t)(-1))	/* some ctimes really hate -1 */
-        st->st_mtime = 1;
+	if (st->st_mtime == (time_t)(-1)) /* some ctimes really hate -1 */
+		st->st_mtime = 1;
 
-    ctime_r(&st->st_mtime, s/*, 64*/);   /* newlib ctime doesn't have buflen */
+	ctime_r(&st->st_mtime, s/*,64*/); /* newlib ctime doesn't have buflen */
 
-    if((p=strchr(s,'\n'))!=NULL) *p='\0';
-    if((p=strchr(s,'\r'))!=NULL) *p='\0';
+	if ((p = strchr(s,'\n')) != NULL) *p = '\0';
+	if ((p = strchr(s,'\r')) != NULL) *p = '\0';
 
 /*
-    printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str),
-        st->st_size, s, name);
+	printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str),
+		st->st_size, s, name);
 */
 
-    printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name);
+	printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name);
 }
 
 static inline u32 dump_inode(struct b_lists * pL, struct jffs2_raw_dirent *d, struct jffs2_raw_inode *i)
@@ -446,16 +518,16 @@
 	if(!d || !i) return -1;
 
 	strncpy(fname, d->name, d->nsize);
-	fname[d->nsize]='\0';
+	fname[d->nsize] = '\0';
 
 	memset(&st,0,sizeof(st));
 
-	st.st_mtime=i->mtime;
-	st.st_mode=i->mode;
-	st.st_ino=i->ino;
+	st.st_mtime = i->mtime;
+	st.st_mode = i->mode;
+	st.st_ino = i->ino;
 
 	/* neither dsize nor isize help us.. do it the long way */
-	st.st_size=jffs2_1pass_read_inode(pL, i->ino, NULL);
+	st.st_size = jffs2_1pass_read_inode(pL, i->ino, NULL);
 
 	dump_stat(&st, fname);
 
@@ -477,18 +549,18 @@
 	struct b_node *b;
 	struct jffs2_raw_dirent *jDir;
 
-	for(b = pL->dirListHead;b;b=b->next) {
+	for (b = pL->dir.listHead; b; b = b->next) {
 		jDir = (struct jffs2_raw_dirent *) (b->offset);
-		if ((pino == jDir->pino) && (jDir->ino)) {	/* 0 inode for unlink */
-			u32 i_version=0;
-			struct jffs2_raw_inode *jNode, *i=NULL;
-			struct b_node *b2 = pL->fragListHead;
+		if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */
+			u32 i_version = 0;
+			struct jffs2_raw_inode *jNode, *i = NULL;
+			struct b_node *b2 = pL->frag.listHead;
 
 			while (b2) {
 				jNode = (struct jffs2_raw_inode *) (b2->offset);
 				if (jNode->ino == jDir->ino
-				    && jNode->version>=i_version)
-					i=jNode;
+				    && jNode->version >= i_version)
+					i = jNode;
 				b2 = b2->next;
 			}
 
@@ -568,7 +640,7 @@
 	unsigned char *src;
 
 	/* we need to search all and return the inode with the highest version */
-	for(b = pL->dirListHead; b; b=b->next) {
+	for(b = pL->dir.listHead; b; b = b->next) {
 		jDir = (struct jffs2_raw_dirent *) (b->offset);
 		if (ino == jDir->ino) {
 		    	if(jDir->version < version) continue;
@@ -593,8 +665,9 @@
 	/* now we found the right entry again. (shoulda returned inode*) */
 	if (jDirFound->type != DT_LNK)
 		return jDirFound->ino;
-	/* so its a soft link so we follow it again. */
-	b2 = pL->fragListHead;
+
+	/* it's a soft link so we follow it again. */
+	b2 = pL->frag.listHead;
 	while (b2) {
 		jNode = (struct jffs2_raw_inode *) (b2->offset);
 		if (jNode->ino == jDirFound->ino) {
@@ -644,7 +717,8 @@
 			tmp[i] = c[i + 1];
 		tmp[i] = '\0';
 		/* only a failure if we arent looking at top level */
-		if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && (working_tmp[0])) {
+		if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) &&
+		    (working_tmp[0])) {
 			putstr("find_inode failed for name=");
 			putstr(working_tmp);
 			putstr("\r\n");
@@ -674,42 +748,102 @@
 {
 	struct b_node *b;
 	struct jffs2_unknown_node *node;
-	struct b_lists *pL=(struct b_lists *)part->jffs2_priv;
+	struct b_lists *pL = (struct b_lists *)part->jffs2_priv;
 
 	if (part->jffs2_priv == 0){
 		DEBUGF ("rescan: First time in use\n");
 		return 1;
 	}
 	/* if we have no list, we need to rescan */
-	if (pL->fragListCount == 0) {
+	if (pL->frag.listCount == 0) {
 		DEBUGF ("rescan: fraglist zero\n");
 		return 1;
 	}
 
-	/* or if we are scanninga new partition */
+	/* or if we are scanning a new partition */
 	if (pL->partOffset != part->offset) {
 		DEBUGF ("rescan: different partition\n");
 		return 1;
 	}
-	/* but suppose someone reflashed the root partition at the same offset... */
-	b = pL->dirListHead;
+	/* but suppose someone reflashed a partition at the same offset... */
+	b = pL->dir.listHead;
 	while (b) {
 		node = (struct jffs2_unknown_node *) (b->offset);
 		if (node->nodetype != JFFS2_NODETYPE_DIRENT) {
-			DEBUGF ("rescan: fs changed beneath me? (%lx)\n", (unsigned long) b->offset);
+			DEBUGF ("rescan: fs changed beneath me? (%lx)\n",
+					(unsigned long) b->offset);
 			return 1;
 		}
 		b = b->next;
 	}
 	return 0;
 }
+
+#ifdef DEBUG_FRAGMENTS
+static void
+dump_fragments(struct b_lists *pL)
+{
+	struct b_node *b;
+	struct jffs2_raw_inode *jNode;
+
+	putstr("\r\n\r\n******The fragment Entries******\r\n");
+	b = pL->frag.listHead;
+	while (b) {
+		jNode = (struct jffs2_raw_inode *) (b->offset);
+		putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset);
+		putLabeledWord("\tbuild_list: totlen = ", jNode->totlen);
+		putLabeledWord("\tbuild_list: inode = ", jNode->ino);
+		putLabeledWord("\tbuild_list: version = ", jNode->version);
+		putLabeledWord("\tbuild_list: isize = ", jNode->isize);
+		putLabeledWord("\tbuild_list: atime = ", jNode->atime);
+		putLabeledWord("\tbuild_list: offset = ", jNode->offset);
+		putLabeledWord("\tbuild_list: csize = ", jNode->csize);
+		putLabeledWord("\tbuild_list: dsize = ", jNode->dsize);
+		putLabeledWord("\tbuild_list: compr = ", jNode->compr);
+		putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr);
+		putLabeledWord("\tbuild_list: flags = ", jNode->flags);
+		putLabeledWord("\tbuild_list: offset = ", b->offset);	// FIXME: ? [RS]
+		b = b->next;
+	}
+}
+#endif
+
+#ifdef DEBUG_DIRENTS
+static void
+dump_dirents(struct b_lists *pL)
+{
+	struct b_node *b;
+	struct jffs2_raw_dirent *jDir;
+
+	putstr("\r\n\r\n******The directory Entries******\r\n");
+	b = pL->dir.listHead;
+	while (b) {
+		jDir = (struct jffs2_raw_dirent *) (b->offset);
+		putstr("\r\n");
+		putnstr(jDir->name, jDir->nsize);
+		putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic);
+		putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype);
+		putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc);
+		putLabeledWord("\tbuild_list: pino = ", jDir->pino);
+		putLabeledWord("\tbuild_list: version = ", jDir->version);
+		putLabeledWord("\tbuild_list: ino = ", jDir->ino);
+		putLabeledWord("\tbuild_list: mctime = ", jDir->mctime);
+		putLabeledWord("\tbuild_list: nsize = ", jDir->nsize);
+		putLabeledWord("\tbuild_list: type = ", jDir->type);
+		putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc);
+		putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc);
+		putLabeledWord("\tbuild_list: offset = ", b->offset); 	// FIXME: ? [RS]
+		b = b->next;
+	}
+}
+#endif
 
 static u32
 jffs2_1pass_build_lists(struct part_info * part)
 {
 	struct b_lists *pL;
 	struct jffs2_unknown_node *node;
-	u32 offset;
+	u32 offset, oldoffset = 0;
 	u32 max = part->size - sizeof(struct jffs2_raw_inode);
 	u32 counter = 0;
 	u32 counter4 = 0;
@@ -722,71 +856,52 @@
 	/* lcd_off(); */
 
 	/* if we are building a list we need to refresh the cache. */
-	/* note that since we don't free our memory, eventually this will be bad. */
-	/* but we're a bootldr so what the hell. */
 	jffs_init_1pass_list(part);
-	pL=(struct b_lists *)part->jffs2_priv;
+	pL = (struct b_lists *)part->jffs2_priv;
 	pL->partOffset = part->offset;
 	offset = 0;
 	printf("Scanning JFFS2 FS:   ");
 
 	/* start at the beginning of the partition */
 	while (offset < max) {
-	    	if (! (++counter%10000))
-			printf("\b\b%c ", spinner[(counter / 10000) % 4]);
+	    	if ((oldoffset >> SPIN_BLKSIZE) != (offset >> SPIN_BLKSIZE)) {
+			printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]);
+			oldoffset = offset;
+		}
 
 		node = (struct jffs2_unknown_node *) (part->offset + offset);
 		if (node->magic == JFFS2_MAGIC_BITMASK && hdr_crc(node)) {
 			/* if its a fragment add it */
-			if (node->nodetype == JFFS2_NODETYPE_INODE && inode_crc((struct jffs2_raw_inode *) node)) {
-				if (!(pL->fragListTail = add_node(pL->fragListTail, &(pL->fragListCount),
-								  &(pL->fragListMemBase)))) {
-					putstr("add_node failed!\r\n");
+			if (node->nodetype == JFFS2_NODETYPE_INODE &&
+				    inode_crc((struct jffs2_raw_inode *) node)) {
+				if (insert_node(&pL->frag, (u32) part->offset +
+								offset) == NULL)
 					return 0;
-				}
-				pL->fragListTail->offset = (u32) (part->offset + offset);
-				if (!pL->fragListHead)
-					pL->fragListHead = pL->fragListTail;
 			} else if (node->nodetype == JFFS2_NODETYPE_DIRENT &&
 				   dirent_crc((struct jffs2_raw_dirent *) node)  &&
 				   dirent_name_crc((struct jffs2_raw_dirent *) node)) {
 				if (! (counterN%100))
 					printf("\b\b.  ");
-#if 0
-				printf("Found DIRENT @ 0x%lx\n", offset);
-				putstr("\r\nbuild_lists:p&l ->");
-				putnstr(((struct jffs2_raw_dirent *) node)->name, ((struct jffs2_raw_dirent *) node)->nsize);
-				putstr("\r\n");
-				putLabeledWord("\tpino = ", ((struct jffs2_raw_dirent *) node)->pino);
-				putLabeledWord("\tnsize = ", ((struct jffs2_raw_dirent *) node)->nsize);
-#endif
-
-				if (!(pL->dirListTail = add_node(pL->dirListTail, &(pL->dirListCount), &(pL->dirListMemBase)))) {
-					putstr("add_node failed!\r\n");
+				if (insert_node(&pL->dir, (u32) part->offset +
+								offset) == NULL)
 					return 0;
-				}
-				pL->dirListTail->offset = (u32) (part->offset + offset);
-#if 0
-				putLabeledWord("\ttail = ", (u32) pL->dirListTail);
-				putstr("\ttailName ->");
-				putnstr(((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->name,
-					((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->nsize);
-				putstr("\r\n");
-#endif
-				if (!pL->dirListHead)
-					pL->dirListHead = pL->dirListTail;
 				counterN++;
 			} else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) {
 				if (node->totlen != sizeof(struct jffs2_unknown_node))
-					printf("OOPS Cleanmarker has bad size %d != %d\n", node->totlen, sizeof(struct jffs2_unknown_node));
+					printf("OOPS Cleanmarker has bad size "
+						"%d != %d\n", node->totlen,
+						sizeof(struct jffs2_unknown_node));
 			} else {
-				printf("Unknown node type: %x len %d offset 0x%x\n", node->nodetype, node->totlen, offset);
+				printf("Unknown node type: %x len %d "
+					"offset 0x%x\n", node->nodetype,
+					node->totlen, offset);
 			}
 			offset += ((node->totlen + 3) & ~3);
 			counterF++;
-		} else if (node->magic == JFFS2_EMPTY_BITMASK && node->nodetype == JFFS2_EMPTY_BITMASK) {
+		} else if (node->magic == JFFS2_EMPTY_BITMASK &&
+			   node->nodetype == JFFS2_EMPTY_BITMASK) {
 			offset = jffs2_scan_empty(offset, part);
-		} else {	/* if we know nothing of the filesystem, we just step and look. */
+		} else {	/* if we know nothing, we just step and look. */
 			offset += 4;
 			counter4++;
 		}
@@ -799,66 +914,21 @@
 	/* splash(); */
 
 #if 0
-	putLabeledWord("dir entries = ", pL->dirListCount);
-	putLabeledWord("frag entries = ", pL->fragListCount);
+	putLabeledWord("dir entries = ", pL->dir.listCount);
+	putLabeledWord("frag entries = ", pL->frag.listCount);
 	putLabeledWord("+4 increments = ", counter4);
 	putLabeledWord("+file_offset increments = ", counterF);
 
 #endif
 
-#undef SHOW_ALL
-#undef SHOW_ALL_FRAGMENTS
-
-#ifdef SHOW_ALL
-	{
-		struct b_node *b;
-		struct b_node *b2;
-		struct jffs2_raw_dirent *jDir;
-		struct jffs2_raw_inode *jNode;
-
-		putstr("\r\n\r\n******The directory Entries******\r\n");
-		b = pL->dirListHead;
-		while (b) {
-			jDir = (struct jffs2_raw_dirent *) (b->offset);
-			putstr("\r\n");
-			putnstr(jDir->name, jDir->nsize);
-			putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic);
-			putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype);
-			putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc);
-			putLabeledWord("\tbuild_list: pino = ", jDir->pino);
-			putLabeledWord("\tbuild_list: version = ", jDir->version);
-			putLabeledWord("\tbuild_list: ino = ", jDir->ino);
-			putLabeledWord("\tbuild_list: mctime = ", jDir->mctime);
-			putLabeledWord("\tbuild_list: nsize = ", jDir->nsize);
-			putLabeledWord("\tbuild_list: type = ", jDir->type);
-			putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc);
-			putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc);
-			b = b->next;
-		}
+#ifdef DEBUG_DIRENTS
+	dump_dirents(pL);
+#endif
 
-#ifdef SHOW_ALL_FRAGMENTS
-		putstr("\r\n\r\n******The fragment Entries******\r\n");
-		b = pL->fragListHead;
-		while (b) {
-			jNode = (struct jffs2_raw_inode *) (b->offset);
-			putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset);
-			putLabeledWord("\tbuild_list: totlen = ", jNode->totlen);
-			putLabeledWord("\tbuild_list: inode = ", jNode->ino);
-			putLabeledWord("\tbuild_list: version = ", jNode->version);
-			putLabeledWord("\tbuild_list: isize = ", jNode->isize);
-			putLabeledWord("\tbuild_list: atime = ", jNode->atime);
-			putLabeledWord("\tbuild_list: offset = ", jNode->offset);
-			putLabeledWord("\tbuild_list: csize = ", jNode->csize);
-			putLabeledWord("\tbuild_list: dsize = ", jNode->dsize);
-			putLabeledWord("\tbuild_list: compr = ", jNode->compr);
-			putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr);
-			putLabeledWord("\tbuild_list: flags = ", jNode->flags);
-			b = b->next;
-		}
-#endif /* SHOW_ALL_FRAGMENTS */
-	}
+#ifdef DEBUG_FRAGMENTS
+	dump_fragments(pL);
+#endif
 
-#endif	/* SHOW_ALL */
 	/* give visual feedback that we are done scanning the flash */
 	led_blink(0x0, 0x0, 0x1, 0x1);	/* off, forever, on 100ms, off 100ms */
 	return 1;
@@ -875,13 +945,13 @@
 	struct jffs2_raw_inode *jNode;
 	int i;
 
-	b = pL->fragListHead;
 	for (i = 0; i < JFFS2_NUM_COMPR; i++) {
 		piL->compr_info[i].num_frags = 0;
 		piL->compr_info[i].compr_sum = 0;
 		piL->compr_info[i].decompr_sum = 0;
 	}
 
+	b = pL->frag.listHead;
 	while (b) {
 		jNode = (struct jffs2_raw_inode *) (b->offset);
 		if (jNode->compr < JFFS2_NUM_COMPR) {
@@ -917,7 +987,7 @@
 	long ret = 0;
 	u32 inode;
 
-	if (! (pl  = jffs2_get_list(part, "ls")))
+	if (! (pl = jffs2_get_list(part, "ls")))
 		return 0;
 
 	if (! (inode = jffs2_1pass_search_list_inodes(pl, fname, 1))) {
@@ -983,7 +1053,7 @@
 		return 0;
 
 	jffs2_1pass_fill_info(pl, &info);
-	for (i=0; i < JFFS2_NUM_COMPR; i++) {
+	for (i = 0; i < JFFS2_NUM_COMPR; i++) {
 		printf("Compression: %s\n", compr_names[i]);
 		printf("\tfrag count: %d\n", info.compr_info[i].num_frags);
 		printf("\tcompressed sum: %d\n", info.compr_info[i].compr_sum);
diff --git a/fs/jffs2/jffs2_private.h b/fs/jffs2/jffs2_private.h
index ca0af1f..c6d5fe3 100644
--- a/fs/jffs2/jffs2_private.h
+++ b/fs/jffs2/jffs2_private.h
@@ -3,23 +3,31 @@
 
 #include <jffs2/jffs2.h>
 
+
 struct b_node {
 	u32 offset;
 	struct b_node *next;
 };
 
+struct b_list {
+	struct b_node *listTail;
+	struct b_node *listHead;
+#ifdef CFG_JFFS2_SORT_FRAGMENTS
+	struct b_node *listLast;
+	int (*listCompare)(struct b_node *new, struct b_node *node);
+	u32 listLoops;
+#endif
+	u32 listCount;
+	struct mem_block *listMemBase;
+};
+
 struct b_lists {
 	char *partOffset;
-	struct b_node *dirListTail;
-	struct b_node *dirListHead;
-	u32 dirListCount;
-	u32 dirListMemBase;
-	struct b_node *fragListTail;
-	struct b_node *fragListHead;
-	u32 fragListCount;
-	u32 fragListMemBase;
+	struct b_list dir;
+	struct b_list frag;
 
 };
+
 struct b_compr_info {
 	u32 num_frags;
 	u32 compr_sum;
@@ -33,11 +41,14 @@
 static inline int
 hdr_crc(struct jffs2_unknown_node *node)
 {
+#if 1
         u32 crc = crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
-        u32 crc_blah = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
-
-        crc_blah ^= ~0;
+#else
+	/* what's the semantics of this? why is this here? */
+        u32 crc = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4);
 
+        crc ^= ~0;
+#endif
         if (node->hdr_crc != crc) {
                 return 0;
         } else {
diff --git a/include/asm-arm/global_data.h b/include/asm-arm/global_data.h
index e0a95e0..892710d 100644
--- a/include/asm-arm/global_data.h
+++ b/include/asm-arm/global_data.h
@@ -44,7 +44,6 @@
 #ifdef CONFIG_VFD
 	unsigned long	fb_base;	/* base address of frame buffer */
 	unsigned char	vfd_type;	/* display type */
-	unsigned char	vfd_inv_data;	/* inverted data lines ? */
 #endif
 #if 0
 	unsigned long	cpu_clk;	/* CPU clock in Hz!		*/
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 0d55ca2..122419f 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -71,22 +71,37 @@
 #include <asm/arch/io.h>
 
 /*
- * IO definitions.  We define {out,in,outs,ins}[bwl] if __io is defined
- * by the machine.  Otherwise, these definitions are left for the machine
- * specific header files to pick up.
+ *  IO port access primitives
+ *  -------------------------
+ *
+ * The ARM doesn't have special IO access instructions; all IO is memory
+ * mapped.  Note that these are defined to perform little endian accesses
+ * only.  Their primary purpose is to access PCI and ISA peripherals.
+ *
+ * Note that for a big endian machine, this implies that the following
+ * big endian mode connectivity is in place, as described by numerious
+ * ARM documents:
+ *
+ *    PCI:  D0-D7   D8-D15 D16-D23 D24-D31
+ *    ARM: D24-D31 D16-D23  D8-D15  D0-D7
+ *
+ * The machine specific io.h include defines __io to translate an "IO"
+ * address to a memory address.
  *
  * Note that we prevent GCC re-ordering or caching values in expressions
  * by introducing sequence points into the in*() definitions.  Note that
  * __raw_* do not guarantee this behaviour.
+ *
+ * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
  */
 #ifdef __io
 #define outb(v,p)			__raw_writeb(v,__io(p))
-#define outw(v,p)			__raw_writew(v,__io(p))
-#define outl(v,p)			__raw_writel(v,__io(p))
+#define outw(v,p)			__raw_writew(cpu_to_le16(v),__io(p))
+#define outl(v,p)			__raw_writel(cpu_to_le32(v),__io(p))
 
-#define inb(p)		({ unsigned int __v = __raw_readb(__io(p)); __v; })
-#define inw(p)		({ unsigned int __v = __raw_readw(__io(p)); __v; })
-#define inl(p)		({ unsigned int __v = __raw_readl(__io(p)); __v; })
+#define inb(p)	({ unsigned int __v = __raw_readb(__io(p)); __v; })
+#define inw(p)	({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
+#define inl(p)	({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
 
 #define outsb(p,d,l)			__raw_writesb(__io(p),d,l)
 #define outsw(p,d,l)			__raw_writesw(__io(p),d,l)
@@ -171,20 +186,20 @@
  */
 #ifdef __mem_pci
 
-#define readb(addr) ({ unsigned int __v = __raw_readb(__mem_pci(addr)); __v; })
-#define readw(addr) ({ unsigned int __v = __raw_readw(__mem_pci(addr)); __v; })
-#define readl(addr) ({ unsigned int __v = __raw_readl(__mem_pci(addr)); __v; })
+#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
+#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
+#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
 
-#define writeb(val,addr)		__raw_writeb(val,__mem_pci(addr))
-#define writew(val,addr)		__raw_writew(val,__mem_pci(addr))
-#define writel(val,addr)		__raw_writel(val,__mem_pci(addr))
+#define writeb(v,c)		__raw_writeb(v,__mem_pci(c))
+#define writew(v,c)		__raw_writew(cpu_to_le16(v),__mem_pci(c))
+#define writel(v,c)		__raw_writel(cpu_to_le32(v),__mem_pci(c))
 
-#define memset_io(a,b,c)		_memset_io(__mem_pci(a),(b),(c))
-#define memcpy_fromio(a,b,c)		_memcpy_fromio((a),__mem_pci(b),(c))
-#define memcpy_toio(a,b,c)		_memcpy_toio(__mem_pci(a),(b),(c))
+#define memset_io(c,v,l)		_memset_io(__mem_pci(c),(v),(l))
+#define memcpy_fromio(a,c,l)		_memcpy_fromio((a),__mem_pci(c),(l))
+#define memcpy_toio(c,a,l)		_memcpy_toio(__mem_pci(c),(a),(l))
 
-#define eth_io_copy_and_sum(a,b,c,d) \
-				eth_copy_and_sum((a),__mem_pci(b),(c),(d))
+#define eth_io_copy_and_sum(s,c,l,b) \
+				eth_copy_and_sum((s),__mem_pci(c),(l),(b))
 
 static inline int
 check_signature(unsigned long io_addr, const unsigned char *signature,
@@ -219,14 +234,6 @@
 #endif	/* __mem_pci */
 
 /*
- * remap a physical address `phys' of size `size' with page protection `prot'
- * into virtual address `from'
- */
-#define io_remap_page_range(from,phys,size,prot) \
-		remap_page_range(from,phys,size,prot)
-
-
-/*
  * If this architecture has ISA IO, then define the isa_read/isa_write
  * macros.
  */
@@ -245,6 +252,10 @@
 #define isa_eth_io_copy_and_sum(a,b,c,d) \
 				eth_copy_and_sum((a),__mem_isa(b),(c),(d))
 
+#ifndef PCI_MEMORY_VADDR	/* XXX problem not understood -- wd */
+#define	PCI_MEMORY_VADDR	0
+#endif	/* XXX */
+
 static inline int
 isa_check_signature(unsigned long io_addr, const unsigned char *signature,
 		    int length)
diff --git a/include/configs/innokom.h b/include/configs/innokom.h
index a8ee99a..c2267bd 100644
--- a/include/configs/innokom.h
+++ b/include/configs/innokom.h
@@ -60,9 +60,9 @@
 #define CONFIG_ENV_OVERWRITE
 
 #define CONFIG_BAUDRATE		19200
+#define CONFIG_MISC_INIT_R	1	/* we have a misc_init_r() function */
 
-#define CONFIG_COMMANDS		((CONFIG_CMD_DFL | CFG_CMD_I2C | CFG_CMD_EEPROM) & ~CFG_CMD_NET)
-
+#define CONFIG_COMMANDS (CONFIG_CMD_DFL|CFG_CMD_I2C|CFG_CMD_EEPROM|CFG_CMD_NET|CFG_CMD_JFFS2|CFG_CMD_DHCP)
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any)   */
 #include <cmd_confdefs.h>
 
@@ -90,13 +90,13 @@
 /*
  * Size of malloc() pool; this lives below the uppermost 128 KiB which are
  * used for the RAM copy of the uboot code
+ *
  */
-/* #define CFG_MALLOC_LEN	(CFG_ENV_SIZE + 128*1024) */
-#define CFG_MALLOC_LEN		(128*1024)
+#define CFG_MALLOC_LEN		(256*1024)
 
 #define CFG_LONGHELP				/* undef to save memory         */
 #define CFG_PROMPT		"uboot> "	/* Monitor Command Prompt       */
-#define CFG_CBSIZE		128		/* Console I/O Buffer Size      */
+#define CFG_CBSIZE		256		/* Console I/O Buffer Size      */
 #define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
 #define CFG_MAXARGS		16		/* max number of command args   */
 #define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size    */
@@ -106,10 +106,7 @@
 
 #undef  CFG_CLKS_IN_HZ          /* everything, incl board info, in Hz */
 
-#define CFG_LOAD_ADDR           0xa7fe0000      /* default load address */
-						/* RS: where is this documented? */
-						/* RS: is this where U-Boot is  */
-						/* RS: relocated to in RAM?      */
+#define CFG_LOAD_ADDR           0xa3000000      /* load kernel to this address   */
 
 #define CFG_HZ                  3686400         /* incrementer freq: 3.6864 MHz */
 						/* RS: the oscillator is actually 3680130?? */
@@ -128,9 +125,9 @@
 /*
  * I2C bus
  */
-#define CONFIG_HARD_I2C 1
-#define CFG_I2C_SPEED 50000
-#define CFG_I2C_SLAVE 0xfe
+#define CONFIG_HARD_I2C 		1
+#define CFG_I2C_SPEED 			50000
+#define CFG_I2C_SLAVE 			0xfe
 
 #define CFG_ENV_IS_IN_EEPROM 		1
 
@@ -138,9 +135,20 @@
 #define CFG_ENV_SIZE			1024	/* 1 KiB                    */
 #define CFG_I2C_EEPROM_ADDR		0x50	/* A0 = 0 (hardwired)       */
 #define CFG_EEPROM_PAGE_WRITE_BITS	5	/* 5 bits = 32 octets       */
-#define CFG_EEPROM_PAGE_WRITE_DELAY_MS	10	/* between stop and start   */
+#define CFG_EEPROM_PAGE_WRITE_DELAY_MS	15	/* between stop and start   */
 #define CFG_I2C_EEPROM_ADDR_LEN		2	/* length of address        */
 #define CFG_EEPROM_SIZE			4096	/* size in bytes            */
+#define CFG_I2C_INIT_BOARD		1	/* board has it's own init  */
+
+/*
+ * SMSC91C111 Network Card
+ */
+#define CONFIG_DRIVER_SMC91111		1
+#define CONFIG_SMC91111_BASE		0x14000000 /* chip select 5         */
+#undef  CONFIG_SMC_USE_32_BIT		           /* 16 bit bus access     */
+#undef  CONFIG_SMC_91111_EXT_PHY		   /* we use internal phy   */
+#undef  CONFIG_SHOW_ACTIVITY
+#define CONFIG_NET_RETRY_COUNT		10	   /* # of retries          */
 
 /*
  * Stack sizes
@@ -168,11 +176,19 @@
 
 #define CFG_FLASH_BASE          PHYS_FLASH_1
 
+
 /*
- * GPIO settings;
+ * JFFS2 Partitions
  */
+#define CFG_JFFS_CUSTOM_PART	1		/* see board/innokom/flash.c */
+#define CONFIG_MTD_INNOKOM_16MB 1		/* development flash         */	
+#undef  CONFIG_MTD_INNOKOM_64MB			/* production flash          */
 
-/* GP15 == nCS1      is 1
+
+/*
+ * GPIO settings; see BDI2000 config file for details
+ *
+ * GP15 == nCS1      is 1
  * GP24 == SFRM      is 1
  * GP25 == TXD       is 1
  * GP33 == nCS5      is 1
@@ -273,6 +289,7 @@
 #define CFG_GAFR2_L_VAL     0xA0000000
 #define CFG_GAFR2_U_VAL     0x00000002
 
+
 /* FIXME: set GPIO_RER/FER */
 
 /* RDH = 1
@@ -285,9 +302,8 @@
 
 /*
  * Memory settings
- */
-
-/* This is the configuration for nCS0/1 -> flash banks
+ *
+ * This is the configuration for nCS0/1 -> flash banks
  * configuration for nCS1:
  * [31]    0    - Slower Device
  * [30:28] 010  - CS deselect to CS time: 2*(2*MemClk) = 40 ns
@@ -321,7 +337,7 @@
  * [03]    1    - 16 Bit bus width
  * [02:00] 100  - variable latency I/O
  */
-#define CFG_MSC1_VAL		0x132C593C /* TDM switch, DSP               */
+#define CFG_MSC1_VAL		0x123C593C /* TDM switch, DSP               */
 
 /* This is the configuration for nCS4/5 -> ExtBus, LAN Controller
  *
@@ -340,7 +356,7 @@
  * [03]    1    - 16 Bit bus width
  * [02:00] 100  - variable latency I/O
  */
-#define CFG_MSC2_VAL		0x132C6CDC /* extra bus, LAN controller     */
+#define CFG_MSC2_VAL		0x123C6CDC /* extra bus, LAN controller     */
 
 /* MDCNFG: SDRAM Configuration Register
  *
@@ -359,16 +375,15 @@
  * [12]      1	 - SA1111 compatiblity mode
  * [11]      1   - latch return data with return clock
  * [10]      0   - no alternate addressing for pair 0/1
- * [09:08]   01  - tRP=2*MemClk; CL=2; tRCD=2*MemClk; tRAS=5*MemClk; tRC=8*MemClk
+ * [09:08]   01  - tRP=2*MemClk CL=2 tRCD=2*MemClk tRAS=5*MemClk tRC=8*MemClk
  * [7]       1   - 4 internal banks in lower partition pair
  * [06:05]   10  - 13 row address bits for partition 0/1
  * [04:03]   01  - 9 column address bits for partition 0/1
  * [02]      0   - SDRAM partition 0/1 width is 32 bit
  * [01]      0   - disable SDRAM partition 1
  * [00]      1   - enable  SDRAM partition 0
- *
- * use the configuration above but disable partition 0
  */
+/* use the configuration above but disable partition 0 */
 #define CFG_MDCNFG_VAL		0x000019c8
 
 /* MDREFR: SDRAM Refresh Control Register
@@ -434,11 +449,4 @@
 #define CFG_FLASH_ERASE_TOUT    (2*CFG_HZ) /* Timeout for Flash Erase       */
 #define CFG_FLASH_WRITE_TOUT    (2*CFG_HZ) /* Timeout for Flash Write       */
 
-#if 0
-#define CFG_ENV_IS_IN_FLASH	1
-#define CFG_ENV_ADDR            (PHYS_FLASH_1 + 0x1C000)
-                                        /* Addr of Environment Sector       */
-#define CFG_ENV_SIZE            0x4000  /* Total Size of Environment Sector */
-#endif
-
 #endif  /* __CONFIG_H */
diff --git a/include/i2c.h b/include/i2c.h
index 43d76fd..6d39080 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -51,6 +51,9 @@
  * repeatedly to change the speed and slave addresses.
  */
 void i2c_init(int speed, int slaveaddr);
+#ifdef CFG_I2C_INIT_BOARD
+void i2c_init_board(void);
+#endif
 
 /*
  * Probe the given I2C chip address.  Returns 0 if a chip responded,