Initial revision
diff --git a/common/cmd_cache.c b/common/cmd_cache.c
new file mode 100644
index 0000000..f2015b3
--- /dev/null
+++ b/common/cmd_cache.c
@@ -0,0 +1,98 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Cache support: switch on or off, get status
+ */
+#include <common.h>
+#include <command.h>
+#include <cmd_cache.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_CACHE)
+
+static int on_off (const char *);
+
+int do_icache ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	switch (argc) {
+	case 2:			/* on / off	*/
+		switch (on_off(argv[1])) {
+#if 0	/* prevented by varargs handling; FALLTROUGH is harmless, too */
+		default: printf ("Usage:\n%s\n", cmdtp->usage);
+			return;
+#endif
+		case 0:	icache_disable();
+			break;
+		case 1:	icache_enable ();
+			break;
+		}
+		/* FALL TROUGH */
+	case 1:			/* get status */
+		printf ("Instruction Cache is %s\n",
+			icache_status() ? "ON" : "OFF");
+		return 0;
+	default:
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+	return 0;
+}
+
+int do_dcache ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	switch (argc) {
+	case 2:			/* on / off	*/
+		switch (on_off(argv[1])) {
+#if 0	/* prevented by varargs handling; FALLTROUGH is harmless, too */
+		default: printf ("Usage:\n%s\n", cmdtp->usage);
+			return;
+#endif
+		case 0:	dcache_disable();
+			break;
+		case 1:	dcache_enable ();
+			break;
+		}
+		/* FALL TROUGH */
+	case 1:			/* get status */
+		printf ("Data (writethrough) Cache is %s\n",
+			dcache_status() ? "ON" : "OFF");
+		return 0;
+	default:
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+	return 0;
+
+}
+
+static int on_off (const char *s)
+{
+	if (strcmp(s, "on") == 0) {
+		return (1);
+	} else if (strcmp(s, "off") == 0) {
+		return (0);
+	}
+	return (-1);
+}
+
+#endif	/* CFG_CMD_CACHE */
diff --git a/common/cmd_console.c b/common/cmd_console.c
new file mode 100644
index 0000000..a5f792b
--- /dev/null
+++ b/common/cmd_console.c
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <devices.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_CONSOLE)
+
+extern void _do_coninfo (void);
+int do_coninfo (cmd_tbl_t * cmd, int flag, int argc, char *argv[])
+{
+	int i, l;
+
+	/* Scan for valid output and input devices */
+
+	printf ("List of available devices:\n");
+
+	for (i = 1; i <= ListNumItems (devlist); i++) {
+		device_t *dev = ListGetPtrToItem (devlist, i);
+
+		printf ("%-8s %08x %c%c%c ",
+			dev->name,
+			dev->flags,
+			(dev->flags & DEV_FLAGS_SYSTEM) ? 'S' : '.',
+			(dev->flags & DEV_FLAGS_INPUT) ? 'I' : '.',
+			(dev->flags & DEV_FLAGS_OUTPUT) ? 'O' : '.');
+
+		for (l = 0; l < MAX_FILES; l++) {
+			if (stdio_devices[l] == dev) {
+				printf ("%s ", stdio_names[l]);
+			}
+		}
+		putc ('\n');
+	}
+	return 0;
+}
+#endif /* CFG_CMD_CONSOLE */
diff --git a/common/cmd_date.c b/common/cmd_date.c
new file mode 100644
index 0000000..1472e3f
--- /dev/null
+++ b/common/cmd_date.c
@@ -0,0 +1,189 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * RTC, Date & Time support: get and set date & time
+ */
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_DATE)
+
+const char *weekdays[] = {
+	"Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
+};
+
+int mk_date (char *, struct rtc_time *);
+
+int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	struct rtc_time tm;
+	int rcode = 0;
+
+	switch (argc) {
+	case 2:			/* set date & time */
+		if (strcmp(argv[1],"reset") == 0) {
+			printf ("Reset RTC...\n");
+			rtc_reset ();
+		} else {
+			/* initialize tm with current time */
+			rtc_get (&tm);
+			/* insert new date & time */
+			if (mk_date (argv[1], &tm) != 0) {
+				printf ("## Bad date format\n");
+				return 1;
+			}
+			/* and write to RTC */
+			rtc_set (&tm);
+		}
+		/* FALL TROUGH */
+	case 1:			/* get date & time */
+		rtc_get (&tm);
+
+		printf ("Date: %4d-%02d-%02d (%sday)    Time: %2d:%02d:%02d\n",
+			tm.tm_year, tm.tm_mon, tm.tm_mday,
+			(tm.tm_wday<0 || tm.tm_wday>6) ?
+				"unknown " : weekdays[tm.tm_wday],
+			tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+		return 0;
+	default:
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		rcode = 1;
+	}
+	return rcode;
+}
+
+/*
+ * simple conversion of two-digit string with error checking
+ */
+static int cnvrt2 (char *str, int *valp)
+{
+	int val;
+
+	if ((*str < '0') || (*str > '9'))
+		return (-1);
+
+	val = *str - '0';
+
+	++str;
+
+	if ((*str < '0') || (*str > '9'))
+		return (-1);
+
+	*valp = 10 * val + (*str - '0');
+
+	return (0);
+}
+
+/*
+ * Convert date string: MMDDhhmm[[CC]YY][.ss]
+ *
+ * Some basic checking for valid values is done, but this will not catch
+ * all possible error conditions.
+ */
+int mk_date (char *datestr, struct rtc_time *tmp)
+{
+	int len, val;
+	char *ptr;
+
+	ptr = strchr (datestr,'.');
+	len = strlen (datestr);
+
+	/* Set seconds */
+	if (ptr) {
+		int sec;
+
+		*ptr++ = '\0';
+		if ((len - (ptr - datestr)) != 2)
+			return (-1);
+
+		len = strlen (datestr);
+
+		if (cnvrt2 (ptr, &sec))
+			return (-1);
+
+		tmp->tm_sec = sec;
+	} else {
+		tmp->tm_sec = 0;
+	}
+
+	if (len == 12) {		/* MMDDhhmmCCYY	*/
+		int year, century;
+
+		if (cnvrt2 (datestr+ 8, &century) ||
+		    cnvrt2 (datestr+10, &year) ) {
+			return (-1);
+		}
+		tmp->tm_year = 100 * century + year;
+	} else if (len == 10) {		/* MMDDhhmmYY	*/
+		int year, century;
+
+		century = tmp->tm_year / 100;
+		if (cnvrt2 (datestr+ 8, &year))
+			return (-1);
+		tmp->tm_year = 100 * century + year;
+	}
+
+	switch (len) {
+	case 8:			/* MMDDhhmm	*/
+		/* fall thru */
+	case 10:		/* MMDDhhmmYY	*/
+		/* fall thru */
+	case 12:		/* MMDDhhmmCCYY	*/
+		if (cnvrt2 (datestr+0, &val) ||
+		    val > 12) {
+			break;
+		}
+		tmp->tm_mon  = val;
+		if (cnvrt2 (datestr+2, &val) ||
+		    val > ((tmp->tm_mon==2) ? 29 : 31)) {
+			break;
+		}
+		tmp->tm_mday = val;
+
+		if (cnvrt2 (datestr+4, &val) ||
+		    val > 23) {
+			break;
+		}
+		tmp->tm_hour = val;
+
+		if (cnvrt2 (datestr+6, &val) ||
+		    val > 59) {
+			break;
+		}
+		tmp->tm_min  = val;
+
+		/* calculate day of week */
+		GregorianDay (tmp);
+
+		return (0);
+	default:
+		break;
+	}
+
+	return (-1);
+}
+
+#endif	/* CFG_CMD_DATE */
diff --git a/common/cmd_dcr.c b/common/cmd_dcr.c
new file mode 100644
index 0000000..072685e
--- /dev/null
+++ b/common/cmd_dcr.c
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen,  Wave 7 Optics, etheisen@mindspring.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * IBM 4XX DCR Functions
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <cmd_dcr.h>
+
+#if defined(CONFIG_4xx) && defined(CFG_CMD_SETGETDCR)
+
+/* ======================================================================
+ * Interpreter command to retrieve an IBM PPC 4xx Device Control Register
+ * ======================================================================
+ */
+int do_getdcr ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
+{
+    unsigned short dcrn;                     /* Device Control Register Num */
+    unsigned long value;                     /* DCR's value */
+
+    /* Validate arguments */
+    if (argc < 2) {
+        printf("Usage:\n%s\n", cmdtp->usage);
+        return 1;
+    }
+
+    /* Get a DCR */
+    dcrn = (unsigned short)simple_strtoul(argv[ 1 ], NULL, 16);
+    value = get_dcr(dcrn);
+
+    printf("%04x: %08lx\n", dcrn, value);
+
+    return 0;
+} /* do_getdcr */
+
+
+/* ======================================================================
+ * Interpreter command to set an IBM PPC 4xx Device Control Register
+ * ======================================================================
+*/
+int do_setdcr ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+    unsigned short dcrn;                     /* Device Control Register Num */
+    unsigned long value;                     /* DCR's value */
+    int nbytes;
+    extern char console_buffer[];
+
+    /* Validate arguments */
+    if (argc < 2) {
+        printf("Usage:\n%s\n", cmdtp->usage);
+        return 1;
+    }
+
+    /* Set a DCR */
+    dcrn = (unsigned short)simple_strtoul(argv[1], NULL, 16);
+    do {
+        value = get_dcr(dcrn);
+        printf("%04x: %08lx", dcrn, value);
+        nbytes = readline(" ? ");
+        if (nbytes == 0) {
+            /*
+             * <CR> pressed as only input, don't modify current
+             * location and exit command.
+             */
+            nbytes = 1;
+            return 0;
+        } else {
+            unsigned long i;
+            char *endp;
+            i = simple_strtoul(console_buffer, &endp, 16);
+            nbytes = endp - console_buffer;
+            if (nbytes)
+                set_dcr(dcrn, i);
+        }
+    } while (nbytes);
+
+    return 0;
+} /* do_setdcr */
+
+#endif /* CONFIG_4xx & CFG_CMD_SETGETDCR */
diff --git a/common/cmd_dtt.c b/common/cmd_dtt.c
new file mode 100644
index 0000000..943b0c7
--- /dev/null
+++ b/common/cmd_dtt.c
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <cmd_dtt.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_DTT)
+
+#include <dtt.h>
+
+int do_dtt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	int i;
+	unsigned char sensors[] = CONFIG_DTT_SENSORS;
+
+	/*
+	 * Loop through sensors, read
+	 * temperature, and output it.
+	 */
+	for (i = 0; i < sizeof (sensors); i++) {
+		printf ("DTT%d: %i C\n", i + 1, dtt_get_temp (sensors[i]));
+	}
+
+	return 0;
+}	/* do_dtt() */
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_DTT */
diff --git a/common/cmd_eeprom.c b/common/cmd_eeprom.c
new file mode 100644
index 0000000..29e9faf
--- /dev/null
+++ b/common/cmd_eeprom.c
@@ -0,0 +1,353 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ *
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <i2c.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
+
+extern void eeprom_init  (void);
+extern int  eeprom_read  (unsigned dev_addr, unsigned offset,
+			  uchar *buffer, unsigned cnt);
+extern int  eeprom_write (unsigned dev_addr, unsigned offset,
+			  uchar *buffer, unsigned cnt);
+#endif
+
+
+#if defined(CFG_EEPROM_X40430)
+	/* Maximum number of times to poll for acknowledge after write */
+#define MAX_ACKNOWLEDGE_POLLS	10
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#if (CONFIG_COMMANDS & CFG_CMD_EEPROM)
+int do_eeprom ( cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	const char *const fmt =
+		"\nEEPROM @0x%lX %s: addr %08lx  off %04lx  count %ld ... ";
+
+#if defined(CFG_I2C_MULTI_EEPROMS)
+	if (argc == 6) {
+		ulong dev_addr = simple_strtoul (argv[2], NULL, 16);
+		ulong addr = simple_strtoul (argv[3], NULL, 16);
+		ulong off  = simple_strtoul (argv[4], NULL, 16);
+		ulong cnt  = simple_strtoul (argv[5], NULL, 16);
+#else
+	if (argc == 5) {
+		ulong dev_addr = CFG_DEF_EEPROM_ADDR;
+		ulong addr = simple_strtoul (argv[2], NULL, 16);
+		ulong off  = simple_strtoul (argv[3], NULL, 16);
+		ulong cnt  = simple_strtoul (argv[4], NULL, 16);
+#endif /* CFG_I2C_MULTI_EEPROMS */
+
+# ifndef CONFIG_SPI
+		eeprom_init ();
+# endif /* !CONFIG_SPI */
+
+		if (strcmp (argv[1], "read") == 0) {
+			int rcode;
+
+			printf (fmt, dev_addr, argv[1], addr, off, cnt);
+
+			rcode = eeprom_read (dev_addr, off, (uchar *) addr, cnt);
+
+			printf ("done\n");
+			return rcode;
+		} else if (strcmp (argv[1], "write") == 0) {
+			int rcode;
+
+			printf (fmt, dev_addr, argv[1], addr, off, cnt);
+
+			rcode = eeprom_write (dev_addr, off, (uchar *) addr, cnt);
+
+			printf ("done\n");
+			return rcode;
+		}
+	}
+
+	printf ("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+}
+#endif	/* CFG_CMD_EEPROM */
+
+/*-----------------------------------------------------------------------
+ *
+ * for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
+ *   0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
+ *
+ * for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
+ *   0x00000nxx for EEPROM address selectors and page number at n.
+ */
+
+#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
+
+#ifndef CONFIG_SPI
+#if !defined(CFG_I2C_EEPROM_ADDR_LEN) || CFG_I2C_EEPROM_ADDR_LEN < 1 || CFG_I2C_EEPROM_ADDR_LEN > 2
+#error CFG_I2C_EEPROM_ADDR_LEN must be 1 or 2
+#endif
+#endif
+
+int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
+{
+	unsigned end = offset + cnt;
+	unsigned blk_off;
+	int rcode = 0;
+
+	/* Read data until done or would cross a page boundary.
+	 * We must write the address again when changing pages
+	 * because the next page may be in a different device.
+	 */
+	while (offset < end) {
+		unsigned alen, len, maxlen;
+#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
+		uchar addr[2];
+
+		blk_off = offset & 0xFF;	/* block offset */
+
+		addr[0] = offset >> 8;		/* block number */
+		addr[1] = blk_off;		/* block offset */
+		alen	= 2;
+#else
+		uchar addr[3];
+
+		blk_off = offset & 0xFF;	/* block offset */
+
+		addr[0] = offset >> 16;		/* block number */
+		addr[1] = offset >>  8;		/* upper address octet */
+		addr[2] = blk_off;		/* lower address octet */
+		alen	= 3;
+#endif	/* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
+
+		addr[0] |= dev_addr;		/* insert device address */
+
+		maxlen = 0x100 - blk_off;
+		if (maxlen > I2C_RXTX_LEN)
+			maxlen = I2C_RXTX_LEN;
+		len    = end - offset;
+		if (len > maxlen)
+			len = maxlen;
+#ifdef CONFIG_SPI
+		spi_read (addr, alen, buffer, len);
+#else
+		if (i2c_read (addr[0], offset, alen-1, buffer, len) != 0)
+			rcode = 1;
+#endif
+		buffer += len;
+		offset += len;
+	}
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ *
+ * for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
+ *   0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
+ *
+ * for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
+ *   0x00000nxx for EEPROM address selectors and page number at n.
+ */
+
+int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
+{
+	unsigned end = offset + cnt;
+	unsigned blk_off;
+	int rcode = 0;
+
+#if defined(CFG_EEPROM_X40430)
+	uchar	contr_r_addr[2];
+	uchar	addr_void[2];
+	uchar	contr_reg[2];
+	uchar	ctrl_reg_v;
+	int	i;
+#endif
+
+	/* Write data until done or would cross a write page boundary.
+	 * We must write the address again when changing pages
+	 * because the address counter only increments within a page.
+	 */
+
+	while (offset < end) {
+		unsigned alen, len, maxlen;
+#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
+		uchar addr[2];
+
+		blk_off = offset & 0xFF;	/* block offset */
+
+		addr[0] = offset >> 8;		/* block number */
+		addr[1] = blk_off;		/* block offset */
+		alen	= 2;
+#else
+		uchar addr[3];
+
+		blk_off = offset & 0xFF;	/* block offset */
+
+		addr[0] = offset >> 16;		/* block number */
+		addr[1] = offset >>  8;		/* upper address octet */
+		addr[2] = blk_off;		/* lower address octet */
+		alen	= 3;
+#endif	/* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
+
+		addr[0] |= dev_addr;		/* insert device address */
+
+#if defined(CFG_EEPROM_PAGE_WRITE_BITS)
+
+#define	EEPROM_PAGE_SIZE	(1 << CFG_EEPROM_PAGE_WRITE_BITS)
+#define	EEPROM_PAGE_OFFSET(x)	((x) & (EEPROM_PAGE_SIZE - 1))
+
+		maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off);
+#else
+		maxlen = 0x100 - blk_off;
+#endif
+		if (maxlen > I2C_RXTX_LEN)
+			maxlen = I2C_RXTX_LEN;
+
+		len = end - offset;
+		if (len > maxlen)
+			len = maxlen;
+#ifdef CONFIG_SPI
+		spi_write (addr, alen, buffer, len);
+#else
+#if defined(CFG_EEPROM_X40430)
+		/* Get the value of the control register.
+		 * Set current address (internal pointer in the x40430)
+		 * to 0x1ff.
+		 */
+		contr_r_addr[0] = 9;
+		contr_r_addr[1] = 0xff;
+		addr_void[0]    = 0;
+		addr_void[1]    = addr[1];
+#ifdef CFG_I2C_EEPROM_ADDR
+		contr_r_addr[0] |= CFG_I2C_EEPROM_ADDR;
+		addr_void[0]    |= CFG_I2C_EEPROM_ADDR;
+#endif
+		contr_reg[0] = 0xff;
+		if (i2c_read (contr_r_addr[0], contr_r_addr[1], 1, contr_reg, 1) != 0) {
+			rcode = 1;
+		}
+		ctrl_reg_v = contr_reg[0];
+
+		/* Are any of the eeprom blocks write protected?
+		 */
+		if (ctrl_reg_v & 0x18) {
+			ctrl_reg_v &= ~0x18;   /* reset block protect bits  */
+			ctrl_reg_v |=  0x02;   /* set write enable latch    */
+			ctrl_reg_v &= ~0x04;   /* clear RWEL                */
+
+			/* Set write enable latch.
+			 */
+			contr_reg[0] = 0x02;
+			if (i2c_write (contr_r_addr[0], 0xff, 1, contr_reg, 1) != 0) {
+				rcode = 1;
+			}
+
+			/* Set register write enable latch.
+			 */
+			contr_reg[0] = 0x06;
+			if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
+				rcode = 1;
+			}
+
+			/* Modify ctrl register.
+			 */
+			contr_reg[0] = ctrl_reg_v;
+			if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
+				rcode = 1;
+			}
+
+			/* The write (above) is an operation on NV memory.
+			 * These can take some time (~5ms), and the device
+			 * will not respond to further I2C messages till
+			 * it's completed the write.
+			 * So poll device for an I2C acknowledge.
+			 * When we get one we know we can continue with other
+			 * operations.
+			 */
+			contr_reg[0] = 0;
+			for (i = 0; i < MAX_ACKNOWLEDGE_POLLS; i++) {
+				if (i2c_read (addr_void[0], addr_void[1], 1, contr_reg, 1) == 1)
+					break;	/* got ack */
+#if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
+				udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
+#endif
+			}
+			if (i == MAX_ACKNOWLEDGE_POLLS) {
+				printf("EEPROM poll acknowledge failed\n");
+				rcode = 1;
+			}
+		}
+
+		/* Is the write enable latch on?.
+		 */
+		else if (!(ctrl_reg_v & 0x02)) {
+			/* Set write enable latch.
+			 */
+			contr_reg[0] = 0x02;
+			if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
+			       rcode = 1;
+			}
+		}
+		/* Write is enabled ... now write eeprom value.
+		 */
+#endif
+		if (i2c_write (addr[0], offset, alen-1, buffer, len) != 0)
+			rcode = 1;
+
+#endif
+		buffer += len;
+		offset += len;
+
+#if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
+		udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
+#endif
+	}
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ * Set default values
+ */
+#ifndef	CFG_I2C_SPEED
+#define	CFG_I2C_SPEED	50000
+#endif
+
+#ifndef	CFG_I2C_SLAVE
+#define	CFG_I2C_SLAVE	0xFE
+#endif
+
+void eeprom_init  (void)
+{
+#if defined(CONFIG_SPI)
+	spi_init_f ();
+#endif
+#if defined(CONFIG_HARD_I2C) || \
+    defined(CONFIG_SOFT_I2C)
+	i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+#endif
+}
+/*-----------------------------------------------------------------------
+ */
+#endif	/* CFG_CMD_EEPROM */
diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c
new file mode 100644
index 0000000..712c14b
--- /dev/null
+++ b/common/cmd_fdc.c
@@ -0,0 +1,735 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG, d.peter@mpl.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ *
+ */
+/*
+ * Floppy Disk support
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <image.h>
+
+
+#undef	FDC_DEBUG
+
+#ifdef	FDC_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#ifndef	TRUE
+#define TRUE            1
+#endif
+#ifndef FALSE
+#define FALSE           0
+#endif
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_DATE)
+#include <rtc.h>
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDC)
+
+
+typedef struct {
+	int						flags;		/* connected drives ect */
+	unsigned long blnr;			/* Logical block nr */
+	uchar					drive; 		/* drive no */
+	uchar					cmdlen; 	/* cmd length */
+	uchar					cmd[16]; 	/* cmd desc */
+	uchar					dma;			/* if > 0 dma enabled */
+	uchar					result[11];/* status information */
+	uchar					resultlen; /* lenght of result */
+} FDC_COMMAND_STRUCT;
+/* flags: only the lower 8bit used:
+ * bit 0 if set drive 0 is present
+ * bit 1 if set drive 1 is present
+ * bit 2 if set drive 2 is present
+ * bit 3 if set drive 3 is present
+ * bit 4 if set disk in drive 0 is inserted
+ * bit 5 if set disk in drive 1 is inserted
+ * bit 6 if set disk in drive 2 is inserted
+ * bit 7 if set disk in drive 4 is inserted
+ */
+
+
+/* cmd indexes */
+#define COMMAND 		0
+#define DRIVE 			1
+#define CONFIG0			1
+#define SPEC_HUTSRT	1
+#define TRACK 			2
+#define CONFIG1			2
+#define SPEC_HLT		2
+#define HEAD				3
+#define CONFIG2			3
+#define SECTOR 			4
+#define SECTOR_SIZE	5
+#define LAST_TRACK	6
+#define GAP					7
+#define DTL					8
+/* result indexes */
+#define STATUS_0						0
+#define STATUS_PCN					1
+#define STATUS_1						1
+#define STATUS_2						2
+#define STATUS_TRACK				3
+#define STATUS_HEAD					4
+#define STATUS_SECT					5
+#define STATUS_SECT_SIZE		6
+
+
+/* Register addresses */
+#define FDC_BASE	0x3F0
+#define FDC_SRA		FDC_BASE + 0	/* Status Register A */
+#define FDC_SRB		FDC_BASE + 1	/* Status Register B */
+#define FDC_DOR		FDC_BASE + 2	/* Digital Output Register */
+#define FDC_TDR		FDC_BASE + 3	/* Tape Drive Register */
+#define FDC_DSR		FDC_BASE + 4	/* Data rate Register */
+#define FDC_MSR		FDC_BASE + 4	/* Main Status Register */
+#define FDC_FIFO	FDC_BASE + 5	/* FIFO */
+#define FDC_DIR		FDC_BASE + 6	/* Digital Input Register */
+#define FDC_CCR		FDC_BASE + 7	/* Configuration Control */
+/* Commands */
+#define FDC_CMD_SENSE_INT 		0x08
+#define FDC_CMD_CONFIGURE 		0x13
+#define FDC_CMD_SPECIFY	 			0x03
+#define FDC_CMD_RECALIBRATE 	0x07
+#define FDC_CMD_READ				 	0x06
+#define FDC_CMD_READ_TRACK	 	0x02
+#define FDC_CMD_READ_ID			 	0x0A
+#define FDC_CMD_DUMP_REG		 	0x0E
+#define FDC_CMD_SEEK				 	0x0F
+
+#define FDC_CMD_SENSE_INT_LEN 		0x01
+#define FDC_CMD_CONFIGURE_LEN 		0x04
+#define FDC_CMD_SPECIFY_LEN	 			0x03
+#define FDC_CMD_RECALIBRATE_LEN 	0x02
+#define FDC_CMD_READ_LEN				 	0x09
+#define FDC_CMD_READ_TRACK_LEN	 	0x09
+#define FDC_CMD_READ_ID_LEN			 	0x02
+#define FDC_CMD_DUMP_REG_LEN		 	0x01
+#define FDC_CMD_SEEK_LEN				 	0x03
+
+#define FDC_FIFO_THR			0x0C
+#define FDC_FIFO_DIS			0x00
+#define FDC_IMPLIED_SEEK	0x01
+#define FDC_POLL_DIS			0x00
+#define FDC_PRE_TRK				0x00
+#define FDC_CONFIGURE			FDC_FIFO_THR | (FDC_POLL_DIS<<4) | (FDC_FIFO_DIS<<5) | (FDC_IMPLIED_SEEK << 6)
+#define FDC_MFM_MODE			0x01 /* MFM enable */
+#define FDC_SKIP_MODE			0x00 /* skip enable */
+
+#define FDC_TIME_OUT 100000 /* time out */
+#define	FDC_RW_RETRIES		3 /* read write retries */
+#define FDC_CAL_RETRIES		3 /* calibration and seek retries */
+
+
+/* Disk structure */
+typedef struct  {
+	unsigned int size;			/* nr of sectors total */
+	unsigned int sect;			/* sectors per track */
+	unsigned int head;			/* nr of heads */
+	unsigned int track;			/* nr of tracks */
+	unsigned int stretch;		/* !=0 means double track steps */
+	unsigned char	gap;			/* gap1 size */
+	unsigned char	rate;			/* data rate. |= 0x40 for perpendicular */
+	unsigned char	spec1;		/* stepping rate, head unload time */
+	unsigned char	fmt_gap;	/* gap2 size */
+	unsigned char hlt;			/* head load time */
+	unsigned char sect_code; /* Sector Size code */
+	const char	* name; 		/* used only for predefined formats */
+} FD_GEO_STRUCT;
+
+
+/* supported Floppy types (currently only one) */
+const static FD_GEO_STRUCT floppy_type[2] = {
+	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,16,2,"H1440" },	/*  7 1.44MB 3.5"   */
+	{    0, 0,0, 0,0,0x00,0x00,0x00,0x00, 0,0,NULL    },	/*  end of table    */
+};
+
+static FDC_COMMAND_STRUCT cmd; /* global command struct */
+
+/* Supporting Functions */
+/* reads a Register of the FDC */
+unsigned char read_fdc_reg(unsigned int addr)
+{
+	volatile unsigned char *val = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS | addr);
+	return val[0];
+}
+
+/* writes a Register of the FDC */
+void write_fdc_reg(unsigned int addr, unsigned char val)
+{
+		volatile unsigned char *tmp = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS | addr);
+		tmp[0]=val;
+}
+
+/* waits for an interrupt (polling) */
+int wait_for_fdc_int(void)
+{
+	unsigned long timeout;
+	timeout = FDC_TIME_OUT;
+	while((read_fdc_reg(FDC_SRA)&0x80)==0) {
+		timeout--;
+		udelay(10);
+		if(timeout==0) /* timeout occured */
+			return FALSE;
+	}
+	return TRUE;
+}
+
+
+/* reads a byte from the FIFO of the FDC and checks direction and RQM bit
+   of the MSR. returns -1 if timeout, or byte if ok */
+int read_fdc_byte(void)
+{
+	unsigned long timeout;
+	timeout = FDC_TIME_OUT;
+	while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {
+		/* direction out and ready */
+		udelay(10);
+		timeout--;
+		if(timeout==0) /* timeout occured */
+			return -1;
+	}
+	return read_fdc_reg(FDC_FIFO);
+}
+
+/* if the direction of the FIFO is wrong, this routine is used to
+   empty the FIFO. Should _not_ be used */
+int fdc_need_more_output(void)
+{
+	unsigned char c;
+	while((read_fdc_reg(FDC_MSR)&0xC0)==0xC0)	{
+			c=(unsigned char)read_fdc_byte();
+			printf("Error: more output: %x\n",c);
+	}
+	return TRUE;
+}
+
+
+/* writes a byte to the FIFO of the FDC and checks direction and RQM bit
+   of the MSR */
+int write_fdc_byte(unsigned char val)
+{
+	unsigned long timeout;
+	timeout = FDC_TIME_OUT;
+	while((read_fdc_reg(FDC_MSR)&0xC0)!=0x80) {
+		/* direction in and ready for byte */
+		timeout--;
+		udelay(10);
+		fdc_need_more_output();
+		if(timeout==0) /* timeout occured */
+			return FALSE;
+	}
+	write_fdc_reg(FDC_FIFO,val);
+	return TRUE;
+}
+
+/* sets up all FDC commands and issues it to the FDC. If
+   the command causes direct results (no Execution Phase)
+   the result is be read as well. */
+
+int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
+{
+	int i;
+	unsigned long head,track,sect,timeout;
+	track = pCMD->blnr / (pFG->sect * pFG->head); /* track nr */
+	sect =  pCMD->blnr % (pFG->sect * pFG->head); /* remaining blocks */
+	head = sect / pFG->sect; /* head nr */
+	sect =  sect % pFG->sect; /* remaining blocks */
+	sect++; /* sectors are 1 based */
+	PRINTF("Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",track,head,sect,pCMD->drive,pCMD->blnr);
+	if(head|=0) { /* max heads = 2 */
+		pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */
+		pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
+	}
+	else {
+		pCMD->cmd[DRIVE]=pCMD->drive; /* head 0 */
+		pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
+	}
+	pCMD->cmd[TRACK]=(unsigned char) track; /* track */
+	switch (pCMD->cmd[COMMAND]) {
+		case FDC_CMD_READ:
+			pCMD->cmd[SECTOR]=(unsigned char) sect; /* sector */
+			pCMD->cmd[SECTOR_SIZE]=pFG->sect_code; /* sector size code */
+			pCMD->cmd[LAST_TRACK]=pFG->sect; /* End of track */
+			pCMD->cmd[GAP]=pFG->gap; /* gap */
+			pCMD->cmd[DTL]=0xFF; /* DTL */
+			pCMD->cmdlen=FDC_CMD_READ_LEN;
+			pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */
+			pCMD->cmd[COMMAND]|=(FDC_SKIP_MODE<<5); /* set Skip bit */
+			pCMD->resultlen=0;  /* result only after execution */
+			break;
+		case FDC_CMD_SEEK:
+			pCMD->cmdlen=FDC_CMD_SEEK_LEN;
+			pCMD->resultlen=0;  /* no result */
+			break;
+		case FDC_CMD_CONFIGURE:
+			pCMD->cmd[CONFIG0]=0;
+			pCMD->cmd[CONFIG1]=FDC_CONFIGURE; /* FIFO Threshold, Poll, Enable FIFO */
+			pCMD->cmd[CONFIG2]=FDC_PRE_TRK; 	/* Precompensation Track */
+			pCMD->cmdlen=FDC_CMD_CONFIGURE_LEN;
+			pCMD->resultlen=0;  /* no result */
+			break;
+		case FDC_CMD_SPECIFY:
+			pCMD->cmd[SPEC_HUTSRT]=pFG->spec1;
+			pCMD->cmd[SPEC_HLT]=(pFG->hlt)<<1; /* head load time */
+			if(pCMD->dma==0)
+				pCMD->cmd[SPEC_HLT]|=0x1; /* no dma */
+			pCMD->cmdlen=FDC_CMD_SPECIFY_LEN;
+			pCMD->resultlen=0;  /* no result */
+			break;
+		case FDC_CMD_DUMP_REG:
+			pCMD->cmdlen=FDC_CMD_DUMP_REG_LEN;
+			pCMD->resultlen=10;  /* 10 byte result */
+			break;
+		case FDC_CMD_READ_ID:
+			pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */
+			pCMD->cmdlen=FDC_CMD_READ_ID_LEN;
+			pCMD->resultlen=7;  /* 7 byte result */
+			break;
+		case FDC_CMD_RECALIBRATE:
+			pCMD->cmd[DRIVE]&=0x03; /* don't set the head bit */
+			pCMD->cmdlen=FDC_CMD_RECALIBRATE_LEN;
+			pCMD->resultlen=0;  /* no result */
+			break;
+			break;
+		case FDC_CMD_SENSE_INT:
+			pCMD->cmdlen=FDC_CMD_SENSE_INT_LEN;
+			pCMD->resultlen=2;
+			break;
+	}
+	for(i=0;i<pCMD->cmdlen;i++) {
+		/* PRINTF("write cmd%d = 0x%02X\n",i,pCMD->cmd[i]); */
+		if(write_fdc_byte(pCMD->cmd[i])==FALSE) {
+			PRINTF("Error: timeout while issue cmd%d\n",i);
+			return FALSE;
+		}
+	}
+	timeout=FDC_TIME_OUT;
+	for(i=0;i<pCMD->resultlen;i++) {
+		while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {
+			timeout--;
+			if(timeout==0) {
+				PRINTF(" timeout while reading result%d MSR=0x%02X\n",i,read_fdc_reg(FDC_MSR));
+				return FALSE;
+			}
+		}
+		pCMD->result[i]=(unsigned char)read_fdc_byte();
+	}
+	return TRUE;
+}
+
+/* selects the drive assigned in the cmd structur and
+   switches on the Motor */
+void select_fdc_drive(FDC_COMMAND_STRUCT *pCMD)
+{
+	unsigned char val;
+
+	val=(1<<(4+pCMD->drive))|pCMD->drive|0xC; /* set reset, dma gate and motor bits */
+	if((read_fdc_reg(FDC_DOR)&val)!=val) {
+		write_fdc_reg(FDC_DOR,val);
+		for(val=0;val<255;val++)
+			udelay(500); /* wait some time to start motor */
+	}
+}
+
+/* switches off the Motor of the specified drive */
+void stop_fdc_drive(FDC_COMMAND_STRUCT *pCMD)
+{
+	unsigned char val;
+
+	val=(1<<(4+pCMD->drive))|pCMD->drive; /* sets motor bits */
+	write_fdc_reg(FDC_DOR,(read_fdc_reg(FDC_DOR)&~val));
+}
+
+/* issues a recalibrate command, waits for interrupt and
+ * issues a sense_interrupt */
+int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
+{
+	pCMD->cmd[COMMAND]=FDC_CMD_RECALIBRATE;
+	if(fdc_issue_cmd(pCMD,pFG)==FALSE)
+		return FALSE;
+	while(wait_for_fdc_int()!=TRUE);
+	pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
+	return(fdc_issue_cmd(pCMD,pFG));
+}
+
+/* issues a recalibrate command, waits for interrupt and
+ * issues a sense_interrupt */
+int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
+{
+	pCMD->cmd[COMMAND]=FDC_CMD_SEEK;
+	if(fdc_issue_cmd(pCMD,pFG)==FALSE)
+		return FALSE;
+	while(wait_for_fdc_int()!=TRUE);
+	pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
+	return(fdc_issue_cmd(pCMD,pFG));
+}
+
+
+/* terminates current command, by not servicing the FIFO
+ * waits for interrupt and fills in the result bytes */
+int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)
+{
+	int i;
+	for(i=0;i<100;i++)
+		udelay(500); /* wait 500usec for fifo overrun */
+	while((read_fdc_reg(FDC_SRA)&0x80)==0x00); /* wait as long as no int has occured */
+	for(i=0;i<7;i++) {
+		pCMD->result[i]=(unsigned char)read_fdc_byte();
+	}
+	return TRUE;
+}
+
+/* reads data from FDC, seek commands are issued automatic */
+int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
+{
+  /* first seek to start address */
+	unsigned long len,lastblk,readblk,i,timeout,ii,offset;
+	unsigned char pcn,c,retriesrw,retriescal;
+	unsigned char *bufferw; /* working buffer */
+	int sect_size;
+	int flags;
+
+	flags=disable_interrupts(); /* switch off all Interrupts */
+	select_fdc_drive(pCMD); /* switch on drive */
+	sect_size=0x080<<pFG->sect_code;
+	retriesrw=0;
+	retriescal=0;
+	offset=0;
+	if(fdc_seek(pCMD,pFG)==FALSE) {
+		stop_fdc_drive(pCMD);
+		enable_interrupts();
+		return FALSE;
+	}
+	if((pCMD->result[STATUS_0]&0x20)!=0x20) {
+		printf("Seek error Status: %02X\n",pCMD->result[STATUS_0]);
+		stop_fdc_drive(pCMD);
+		enable_interrupts();
+		return FALSE;
+	}
+	pcn=pCMD->result[STATUS_PCN]; /* current track */
+	/* now determine the next seek point */
+	lastblk=pCMD->blnr + blocks;
+	/*	readblk=(pFG->head*pFG->sect)-(pCMD->blnr%(pFG->head*pFG->sect)); */
+	readblk=pFG->sect-(pCMD->blnr%pFG->sect);
+	PRINTF("1st nr of block possible read %ld start %ld\n",readblk,pCMD->blnr);
+	if(readblk>blocks) /* is end within 1st track */
+		readblk=blocks; /* yes, correct it */
+	PRINTF("we read %ld blocks start %ld\n",readblk,pCMD->blnr);
+	bufferw=&buffer[0]; /* setup working buffer */
+	do {
+retryrw:
+		len=sect_size * readblk;
+		pCMD->cmd[COMMAND]=FDC_CMD_READ;
+		if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
+			stop_fdc_drive(pCMD);
+			enable_interrupts();
+			return FALSE;
+		}
+		for (i=0;i<len;i++) {
+			timeout=FDC_TIME_OUT;
+			do {
+				c=read_fdc_reg(FDC_MSR);
+				if((c&0xC0)==0xC0) {
+					bufferw[i]=read_fdc_reg(FDC_FIFO);
+					break;
+				}
+				if((c&0xC0)==0x80) { /* output */
+					PRINTF("Transfer error transfered: at %ld, MSR=%02X\n",i,c);
+					if(i>6) {
+						for(ii=0;ii<7;ii++) {
+							pCMD->result[ii]=bufferw[(i-7+ii)];
+						} /* for */
+					}
+					if(retriesrw++>FDC_RW_RETRIES) {
+						if (retriescal++>FDC_CAL_RETRIES) {
+							stop_fdc_drive(pCMD);
+							enable_interrupts();
+							return FALSE;
+						}
+						else {
+							PRINTF(" trying to recalibrate Try %d\n",retriescal);
+							if(fdc_recalibrate(pCMD,pFG)==FALSE) {
+								stop_fdc_drive(pCMD);
+								enable_interrupts();
+								return FALSE;
+							}
+							retriesrw=0;
+							goto retrycal;
+						} /* else >FDC_CAL_RETRIES */
+					}
+					else {
+						PRINTF("Read retry %d\n",retriesrw);
+						goto retryrw;
+					} /* else >FDC_RW_RETRIES */
+				}/* if output */
+				timeout--;
+			}while(TRUE);
+		} /* for len */
+		/* the last sector of a track or all data has been read,
+		 * we need to get the results */
+		fdc_terminate(pCMD);
+		offset+=(sect_size*readblk); /* set up buffer pointer */
+		bufferw=&buffer[offset];
+		pCMD->blnr+=readblk; /* update current block nr */
+		blocks-=readblk; /* update blocks */
+		if(blocks==0)
+			break; /* we are finish */
+		/* setup new read blocks */
+		/*	readblk=pFG->head*pFG->sect; */
+		readblk=pFG->sect;
+		if(readblk>blocks)
+			readblk=blocks;
+retrycal:
+		/* a seek is necessary */
+		if(fdc_seek(pCMD,pFG)==FALSE) {
+			stop_fdc_drive(pCMD);
+			enable_interrupts();
+			return FALSE;
+		}
+		if((pCMD->result[STATUS_0]&0x20)!=0x20) {
+			PRINTF("Seek error Status: %02X\n",pCMD->result[STATUS_0]);
+			stop_fdc_drive(pCMD);
+			return FALSE;
+		}
+		pcn=pCMD->result[STATUS_PCN]; /* current track */
+	}while(TRUE); /* start over */
+	stop_fdc_drive(pCMD); /* switch off drive */
+	enable_interrupts();
+	return TRUE;
+}
+
+/* Scan all drives and check if drive is present and disk is inserted */
+int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
+{
+	int i,drives,state;
+  /* OK procedure of data book is satisfied.
+	 * trying to get some information over the drives */
+	state=0; /* no drives, no disks */
+	for(drives=0;drives<4;drives++) {
+		pCMD->drive=drives;
+		select_fdc_drive(pCMD);
+		pCMD->blnr=0; /* set to the 1st block */
+		if(fdc_recalibrate(pCMD,pFG)==FALSE)
+			break;
+		if((pCMD->result[STATUS_0]&0x10)==0x10)
+			break;
+		/* ok drive connected check for disk */
+		state|=(1<<drives);
+		pCMD->blnr=pFG->size; /* set to the last block */
+		if(fdc_seek(pCMD,pFG)==FALSE)
+			break;
+		pCMD->blnr=0; /* set to the 1st block */
+		if(fdc_recalibrate(pCMD,pFG)==FALSE)
+			break;
+		pCMD->cmd[COMMAND]=FDC_CMD_READ_ID;
+		if(fdc_issue_cmd(pCMD,pFG)==FALSE)
+			break;
+		state|=(0x10<<drives);
+	}
+	stop_fdc_drive(pCMD);
+	for(i=0;i<4;i++) {
+		PRINTF("Floppy Drive %d %sconnected %sDisk inserted %s\n",i,
+			((state&(1<<i))==(1<<i)) ? "":"not ",
+			((state&(0x10<<i))==(0x10<<i)) ? "":"no ",
+			((state&(0x10<<i))==(0x10<<i)) ? pFG->name : "");
+	}
+	pCMD->flags=state;
+	return TRUE;
+}
+
+
+/**************************************************************************
+* int fdc_setup
+* setup the fdc according the datasheet
+* assuming in PS2 Mode
+*/
+int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)
+{
+
+	int i;
+	/* first, we reset the FDC via the DOR */
+	write_fdc_reg(FDC_DOR,0x00);
+	for(i=0; i<255; i++) /* then we wait some time */
+		udelay(500);
+	/* then, we clear the reset in the DOR */
+	pCMD->drive=0;
+	select_fdc_drive(pCMD);
+	/* initialize the CCR */
+	write_fdc_reg(FDC_CCR,pFG->rate);
+	/* then initialize the DSR */
+	write_fdc_reg(FDC_DSR,pFG->rate);
+	if(wait_for_fdc_int()==FALSE) {
+			PRINTF("Time Out after writing CCR\n");
+			return FALSE;
+	}
+	/* now issue sense Interrupt and status command
+	 * assuming only one drive present (drive 0) */
+	pCMD->dma=0; /* we don't use any dma at all */
+	for(i=0;i<4;i++) {
+		/* issue sense interrupt for all 4 possible drives */
+		pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
+		if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
+			PRINTF("Sense Interrupt for drive %d failed\n",i);
+		}
+	}
+	/* assuming drive 0 for rest of configuration
+	 * issue the configure command */
+	pCMD->drive=0;
+	select_fdc_drive(pCMD);
+	pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE;
+	if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
+		PRINTF(" configure timeout\n");
+		stop_fdc_drive(pCMD);
+		return FALSE;
+	}
+	/* issue specify command */
+	pCMD->cmd[COMMAND]=FDC_CMD_SPECIFY;
+	if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
+		PRINTF(" specify timeout\n");
+		stop_fdc_drive(pCMD);
+		return FALSE;
+
+	}
+	/* then, we clear the reset in the DOR */
+	/* fdc_check_drive(pCMD,pFG);	*/
+	/*	write_fdc_reg(FDC_DOR,0x04); */
+	return TRUE;
+}
+
+/****************************************************************************
+ * main routine do_fdcboot
+ */
+int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
+	FDC_COMMAND_STRUCT *pCMD = &cmd;
+ 	unsigned long addr,imsize;
+	image_header_t *hdr;  /* used for fdc boot */
+	unsigned char boot_drive;
+	int i,nrofblk;
+	char *ep;
+	int rcode = 0;
+
+	switch (argc) {
+	case 1:
+		addr = CFG_LOAD_ADDR;
+		boot_drive=0; /* default boot from drive 0 */
+		break;
+	case 2:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_drive=0; /* default boot from drive 0 */
+		break;
+	case 3:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_drive=simple_strtoul(argv[2], NULL, 10);
+		break;
+	default:
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+	/* setup FDC and scan for drives  */
+	if(fdc_setup(pCMD,pFG)==FALSE) {
+		printf("\n** Error in setup FDC **\n");
+		return 1;
+	}
+	if(fdc_check_drive(pCMD,pFG)==FALSE) {
+		printf("\n** Error in check_drives **\n");
+		return 1;
+	}
+	if((pCMD->flags&(1<<boot_drive))==0) {
+		/* drive not available */
+		printf("\n** Drive %d not availabe **\n",boot_drive);
+		return 1;
+	}
+	if((pCMD->flags&(0x10<<boot_drive))==0) {
+		/* no disk inserted */
+		printf("\n** No disk inserted in drive %d **\n",boot_drive);
+		return 1;
+	}
+	/* ok, we have a valid source */
+	pCMD->drive=boot_drive;
+	/* read first block */
+	pCMD->blnr=0;
+	if(fdc_read_data((unsigned char *)addr,1,pCMD,pFG)==FALSE) {
+		printf("\nRead error:");
+		for(i=0;i<7;i++)
+			printf("result%d: 0x%02X\n",i,pCMD->result[i]);
+		return 1;
+	}
+	hdr = (image_header_t *)addr;
+	if (hdr->ih_magic  != IH_MAGIC) {
+		printf ("Bad Magic Number\n");
+		return 1;
+	}
+	print_image_hdr(hdr);
+
+	imsize= hdr->ih_size+sizeof(image_header_t);
+	nrofblk=imsize/512;
+	if((imsize%512)>0)
+		nrofblk++;
+	printf("Loading %ld Bytes (%d blocks) at 0x%08lx..\n",imsize,nrofblk,addr);
+	pCMD->blnr=0;
+	if(fdc_read_data((unsigned char *)addr,nrofblk,pCMD,pFG)==FALSE) {
+		/* read image block */
+		printf("\nRead error:");
+		for(i=0;i<7;i++)
+			printf("result%d: 0x%02X\n",i,pCMD->result[i]);
+		return 1;
+	}
+	printf("OK %ld Bytes loaded.\n",imsize);
+
+	flush_cache (addr, imsize);
+	/* Loading ok, update default load address */
+
+	load_addr = addr;
+	if(hdr->ih_type  == IH_TYPE_KERNEL) {
+		/* Check if we should attempt an auto-start */
+		if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
+			char *local_args[2];
+			extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+
+			local_args[0] = argv[0];
+			local_args[1] = NULL;
+
+			printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
+
+			do_bootm (cmdtp, 0, 1, local_args);
+			rcode ++;
+		}
+	}
+	return rcode;
+}
+
+
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_FDC */
+
+
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
new file mode 100644
index 0000000..eb44f2e
--- /dev/null
+++ b/common/cmd_mem.c
@@ -0,0 +1,850 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Memory Functions
+ *
+ * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cmd_mem.h>
+
+#if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C))
+int cmd_get_data_size(char* arg, int default_size)
+{
+	/* Check for a size specification .b, .w or .l.
+	 */
+	int len = strlen(arg);
+	if (len > 2 && arg[len-2] == '.') {
+		switch(arg[len-1]) {
+		case 'b':
+			return 1;
+		case 'w':
+			return 2;
+		case 'l':
+			return 4;
+		}
+	}
+	return default_size;
+}
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_MEMORY)
+
+#ifdef	CMD_MEM_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+static int mod_mem(cmd_tbl_t *, int, int, int, char *[]);
+
+/* Display values from last command.
+ * Memory modify remembered values are different from display memory.
+ */
+uint	dp_last_addr, dp_last_size;
+uint	dp_last_length = 0x40;
+uint	mm_last_addr, mm_last_size;
+
+static	ulong	base_address = 0;
+
+/* Memory Display
+ *
+ * Syntax:
+ *	md{.b, .w, .l} {addr} {len}
+ */
+#define DISP_LINE_LEN	16
+int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong	addr, size, length;
+	ulong	i, nbytes, linebytes;
+	u_char	*cp;
+	int rc = 0;
+
+	/* We use the last specified parameters, unless new ones are
+	 * entered.
+	 */
+	addr = dp_last_addr;
+	size = dp_last_size;
+	length = dp_last_length;
+
+	if (argc < 2) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	if ((flag & CMD_FLAG_REPEAT) == 0) {
+		/* New command specified.  Check for a size specification.
+		 * Defaults to long if no or incorrect specification.
+		 */
+		size = cmd_get_data_size(argv[0], 4);
+
+		/* Address is specified since argc > 1
+		*/
+		addr = simple_strtoul(argv[1], NULL, 16);
+		addr += base_address;
+
+		/* If another parameter, it is the length to display.
+		 * Length is the number of objects, not number of bytes.
+		 */
+		if (argc > 2)
+			length = simple_strtoul(argv[2], NULL, 16);
+	}
+
+	/* Print the lines.
+	 *
+	 * We buffer all read data, so we can make sure data is read only
+	 * once, and all accesses are with the specified bus width.
+	 */
+	nbytes = length * size;
+	do {
+		char	linebuf[DISP_LINE_LEN];
+		uint	*uip = (uint   *)linebuf;
+		ushort	*usp = (ushort *)linebuf;
+		u_char	*ucp = (u_char *)linebuf;
+
+		printf("%08lx:", addr);
+		linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
+		for (i=0; i<linebytes; i+= size) {
+			if (size == 4) {
+				printf(" %08x", (*uip++ = *((uint *)addr)));
+			} else if (size == 2) {
+				printf(" %04x", (*usp++ = *((ushort *)addr)));
+			} else {
+				printf(" %02x", (*ucp++ = *((u_char *)addr)));
+			}
+			addr += size;
+		}
+		printf("    ");
+		cp = linebuf;
+		for (i=0; i<linebytes; i++) {
+			if ((*cp < 0x20) || (*cp > 0x7e))
+				printf(".");
+			else
+				printf("%c", *cp);
+			cp++;
+		}
+		printf("\n");
+		nbytes -= linebytes;
+		if (ctrlc()) {
+			rc = 1;
+			break;
+		}
+	} while (nbytes > 0);
+
+	dp_last_addr = addr;
+	dp_last_length = length;
+	dp_last_size = size;
+	return (rc);
+}
+
+int do_mem_mm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	return mod_mem (cmdtp, 1, flag, argc, argv);
+}
+int do_mem_nm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	return mod_mem (cmdtp, 0, flag, argc, argv);
+}
+
+int do_mem_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong	addr, size, writeval, count;
+
+	if ((argc < 3) || (argc > 4)) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	/* Check for size specification.
+	*/
+	size = cmd_get_data_size(argv[0], 4);
+
+	/* Address is specified since argc > 1
+	*/
+	addr = simple_strtoul(argv[1], NULL, 16);
+	addr += base_address;
+
+	/* Get the value to write.
+	*/
+	writeval = simple_strtoul(argv[2], NULL, 16);
+
+	/* Count ? */
+	if (argc == 4) {
+		count = simple_strtoul(argv[3], NULL, 16);
+	} else {
+		count = 1;
+	}
+
+	while (count-- > 0) {
+		if (size == 4)
+			*((ulong  *)addr) = (ulong )writeval;
+		else if (size == 2)
+			*((ushort *)addr) = (ushort)writeval;
+		else
+			*((u_char *)addr) = (u_char)writeval;
+		addr += size;
+	}
+	return 0;
+}
+
+int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong	size, addr1, addr2, count, ngood;
+	int     rcode = 0;
+
+	if (argc != 4) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	/* Check for size specification.
+	*/
+	size = cmd_get_data_size(argv[0], 4);
+
+	addr1 = simple_strtoul(argv[1], NULL, 16);
+	addr1 += base_address;
+
+	addr2 = simple_strtoul(argv[2], NULL, 16);
+	addr2 += base_address;
+
+	count = simple_strtoul(argv[3], NULL, 16);
+
+	ngood = 0;
+
+	while (count-- > 0) {
+		if (size == 4) {
+			ulong word1 = *(ulong *)addr1;
+			ulong word2 = *(ulong *)addr2;
+			if (word1 != word2) {
+				printf("word at 0x%08lx (0x%08lx) "
+					"!= word at 0x%08lx (0x%08lx)\n",
+					addr1, word1, addr2, word2);
+				rcode = 1;
+				break;
+			}
+		}
+		else if (size == 2) {
+			ushort hword1 = *(ushort *)addr1;
+			ushort hword2 = *(ushort *)addr2;
+			if (hword1 != hword2) {
+				printf("halfword at 0x%08lx (0x%04x) "
+					"!= halfword at 0x%08lx (0x%04x)\n",
+					addr1, hword1, addr2, hword2);
+				rcode = 1;
+				break;
+			}
+		}
+		else {
+			u_char byte1 = *(u_char *)addr1;
+			u_char byte2 = *(u_char *)addr2;
+			if (byte1 != byte2) {
+				printf("byte at 0x%08lx (0x%02x) "
+					"!= byte at 0x%08lx (0x%02x)\n",
+					addr1, byte1, addr2, byte2);
+				rcode = 1;
+				break;
+			}
+		}
+		ngood++;
+		addr1 += size;
+		addr2 += size;
+	}
+
+	printf("Total of %ld %s%s were the same\n",
+		ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
+		ngood == 1 ? "" : "s");
+	return rcode;
+}
+
+int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong	addr, size, dest, count;
+
+	if (argc != 4) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	/* Check for size specification.
+	*/
+	size = cmd_get_data_size(argv[0], 4);
+
+	addr = simple_strtoul(argv[1], NULL, 16);
+	addr += base_address;
+
+	dest = simple_strtoul(argv[2], NULL, 16);
+	dest += base_address;
+
+	count = simple_strtoul(argv[3], NULL, 16);
+
+	if (count == 0) {
+		puts ("Zero length ???\n");
+		return 1;
+	}
+
+#ifndef CFG_NO_FLASH
+	/* check if we are copying to Flash */
+	if (addr2info(dest) != NULL) {
+		int rc;
+
+		printf ("Copy to Flash... ");
+
+		rc = flash_write ((uchar *)addr, dest, count*size);
+		if (rc != 0) {
+			flash_perror (rc);
+			return (1);
+		}
+		puts ("done\n");
+		return 0;
+	}
+#endif
+
+	while (count-- > 0) {
+		if (size == 4)
+			*((ulong  *)dest) = *((ulong  *)addr);
+		else if (size == 2)
+			*((ushort *)dest) = *((ushort *)addr);
+		else
+			*((u_char *)dest) = *((u_char *)addr);
+		addr += size;
+		dest += size;
+	}
+	return 0;
+}
+
+int do_mem_base (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	if (argc > 1) {
+		/* Set new base address.
+		*/
+		base_address = simple_strtoul(argv[1], NULL, 16);
+	}
+	/* Print the current base address.
+	*/
+	printf("Base Address: 0x%08lx\n", base_address);
+	return 0;
+}
+
+int do_mem_loop (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong	addr, size, length, i, junk;
+	volatile uint	*longp;
+	volatile ushort *shortp;
+	volatile u_char	*cp;
+
+	if (argc < 3) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	/* Check for a size spefication.
+	 * Defaults to long if no or incorrect specification.
+	 */
+	size = cmd_get_data_size(argv[0], 4);
+
+	/* Address is always specified.
+	*/
+	addr = simple_strtoul(argv[1], NULL, 16);
+
+	/* Length is the number of objects, not number of bytes.
+	*/
+	length = simple_strtoul(argv[2], NULL, 16);
+
+	/* We want to optimize the loops to run as fast as possible.
+	 * If we have only one object, just run infinite loops.
+	 */
+	if (length == 1) {
+		if (size == 4) {
+			longp = (uint *)addr;
+			for (;;)
+				i = *longp;
+		}
+		if (size == 2) {
+			shortp = (ushort *)addr;
+			for (;;)
+				i = *shortp;
+		}
+		cp = (u_char *)addr;
+		for (;;)
+			i = *cp;
+	}
+
+	if (size == 4) {
+		for (;;) {
+			longp = (uint *)addr;
+			i = length;
+			while (i-- > 0)
+				junk = *longp++;
+		}
+	}
+	if (size == 2) {
+		for (;;) {
+			shortp = (ushort *)addr;
+			i = length;
+			while (i-- > 0)
+				junk = *shortp++;
+		}
+	}
+	for (;;) {
+		cp = (u_char *)addr;
+		i = length;
+		while (i-- > 0)
+			junk = *cp++;
+	}
+}
+
+/*
+ * Perform a memory test. A more complete alternative test can be
+ * configured using CFG_ALT_MEMTEST. The complete test loops until
+ * interrupted by ctrl-c or by a failure of one of the sub-tests.
+ */
+int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	vu_long	*addr, *start, *end;
+	ulong	val;
+	ulong	readback;
+
+#if defined(CFG_ALT_MEMTEST)
+	vu_long	addr_mask;
+	vu_long	offset;
+	vu_long	test_offset;
+	vu_long	pattern;
+	vu_long	temp;
+	vu_long	anti_pattern;
+	vu_long	num_words;
+	vu_long *dummy = NULL;
+	int	j;
+	int iterations = 1;
+
+	static const ulong bitpattern[] = {
+		0x00000001,	/* single bit */
+		0x00000003,	/* two adjacent bits */
+		0x00000007,	/* three adjacent bits */
+		0x0000000F,	/* four adjacent bits */
+		0x00000005,	/* two non-adjacent bits */
+		0x00000015,	/* three non-adjacent bits */
+		0x00000055,	/* four non-adjacent bits */
+		0xaaaaaaaa,	/* alternating 1/0 */
+	};
+#else
+	ulong	incr;
+	ulong	pattern;
+	int     rcode = 0;
+#endif
+
+	if (argc > 1) {
+		start = (ulong *)simple_strtoul(argv[1], NULL, 16);
+	} else {
+		start = (ulong *)CFG_MEMTEST_START;
+	}
+
+	if (argc > 2) {
+		end = (ulong *)simple_strtoul(argv[2], NULL, 16);
+	} else {
+		end = (ulong *)(CFG_MEMTEST_END);
+	}
+
+	if (argc > 3) {
+		pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
+	} else {
+		pattern = 0;
+	}
+
+#if defined(CFG_ALT_MEMTEST)
+	printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end);
+	PRINTF("%s:%d: start 0x%p end 0x%p\n",
+		__FUNCTION__, __LINE__, start, end);
+
+	for (;;) {
+		if (ctrlc()) {
+			putc ('\n');
+			return 1;
+		}
+
+		printf("Iteration: %6d\r", iterations);
+		PRINTF("Iteration: %6d\n", iterations);
+		iterations++;
+
+		/*
+		 * Data line test: write a pattern to the first
+		 * location, write the 1's complement to a 'parking'
+		 * address (changes the state of the data bus so a
+		 * floating bus doen't give a false OK), and then
+		 * read the value back. Note that we read it back
+		 * into a variable because the next time we read it,
+		 * it might be right (been there, tough to explain to
+		 * the quality guys why it prints a failure when the
+		 * "is" and "should be" are obviously the same in the
+		 * error message).
+		 *
+		 * Rather than exhaustively testing, we test some
+		 * patterns by shifting '1' bits through a field of
+		 * '0's and '0' bits through a field of '1's (i.e.
+		 * pattern and ~pattern).
+		 */
+		addr = start;
+		for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) {
+		    val = bitpattern[j];
+		    for(; val != 0; val <<= 1) {
+			*addr  = val;
+			*dummy  = ~val; /* clear the test data off of the bus */
+			readback = *addr;
+			if(readback != val) {
+			     printf ("FAILURE (data line): "
+				"expected %08lx, actual %08lx\n",
+					  val, readback);
+			}
+			*addr  = ~val;
+			*dummy  = val;
+			readback = *addr;
+			if(readback != ~val) {
+			    printf ("FAILURE (data line): "
+				"Is %08lx, should be %08lx\n",
+					val, readback);
+			}
+		    }
+		}
+
+		/*
+		 * Based on code whose Original Author and Copyright
+		 * information follows: Copyright (c) 1998 by Michael
+		 * Barr. This software is placed into the public
+		 * domain and may be used for any purpose. However,
+		 * this notice must not be changed or removed and no
+		 * warranty is either expressed or implied by its
+		 * publication or distribution.
+		 */
+
+		/*
+		 * Address line test
+		 *
+		 * Description: Test the address bus wiring in a
+		 *              memory region by performing a walking
+		 *              1's test on the relevant bits of the
+		 *              address and checking for aliasing.
+		 *              This test will find single-bit
+		 *              address failures such as stuck -high,
+		 *              stuck-low, and shorted pins. The base
+		 *              address and size of the region are
+		 *              selected by the caller.
+		 *
+		 * Notes:	For best results, the selected base
+		 *              address should have enough LSB 0's to
+		 *              guarantee single address bit changes.
+		 *              For example, to test a 64-Kbyte
+		 *              region, select a base address on a
+		 *              64-Kbyte boundary. Also, select the
+		 *              region size as a power-of-two if at
+		 *              all possible.
+		 *
+		 * Returns:     0 if the test succeeds, 1 if the test fails.
+		 *
+		 * ## NOTE ##	Be sure to specify start and end
+		 *              addresses such that addr_mask has
+		 *              lots of bits set. For example an
+		 *              address range of 01000000 02000000 is
+		 *              bad while a range of 01000000
+		 *              01ffffff is perfect.
+		 */
+		addr_mask = ((ulong)end - (ulong)start)/sizeof(vu_long);
+		pattern = (vu_long) 0xaaaaaaaa;
+		anti_pattern = (vu_long) 0x55555555;
+
+		PRINTF("%s:%d: addr mask = 0x%.8lx\n",
+			__FUNCTION__, __LINE__,
+			addr_mask);
+		/*
+		 * Write the default pattern at each of the
+		 * power-of-two offsets.
+		 */
+		for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
+			start[offset] = pattern;
+		}
+
+		/*
+		 * Check for address bits stuck high.
+		 */
+		test_offset = 0;
+		start[test_offset] = anti_pattern;
+
+		for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
+		    temp = start[offset];
+		    if (temp != pattern) {
+			printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
+				" expected 0x%.8lx, actual 0x%.8lx\n",
+				(ulong)&start[offset], pattern, temp);
+			return 1;
+		    }
+		}
+		start[test_offset] = pattern;
+
+		/*
+		 * Check for addr bits stuck low or shorted.
+		 */
+		for (test_offset = 1; (test_offset & addr_mask) != 0; test_offset <<= 1) {
+		    start[test_offset] = anti_pattern;
+
+		    for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
+			temp = start[offset];
+			if ((temp != pattern) && (offset != test_offset)) {
+			    printf ("\nFAILURE: Address bit stuck low or shorted @"
+				" 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
+				(ulong)&start[offset], pattern, temp);
+			    return 1;
+			}
+		    }
+		    start[test_offset] = pattern;
+		}
+
+		/*
+		 * Description: Test the integrity of a physical
+		 *		memory device by performing an
+		 *		increment/decrement test over the
+		 *		entire region. In the process every
+		 *		storage bit in the device is tested
+		 *		as a zero and a one. The base address
+		 *		and the size of the region are
+		 *		selected by the caller.
+		 *
+		 * Returns:     0 if the test succeeds, 1 if the test fails.
+		 */
+		num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
+
+		/*
+		 * Fill memory with a known pattern.
+		 */
+		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+			start[offset] = pattern;
+		}
+
+		/*
+		 * Check each location and invert it for the second pass.
+		 */
+		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+		    temp = start[offset];
+		    if (temp != pattern) {
+			printf ("\nFAILURE (read/write) @ 0x%.8lx:"
+				" expected 0x%.8lx, actual 0x%.8lx)\n",
+				(ulong)&start[offset], pattern, temp);
+			return 1;
+		    }
+
+		    anti_pattern = ~pattern;
+		    start[offset] = anti_pattern;
+		}
+
+		/*
+		 * Check each location for the inverted pattern and zero it.
+		 */
+		for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+		    anti_pattern = ~pattern;
+		    temp = start[offset];
+		    if (temp != anti_pattern) {
+			printf ("\nFAILURE (read/write): @ 0x%.8lx:"
+				" expected 0x%.8lx, actual 0x%.8lx)\n",
+				(ulong)&start[offset], anti_pattern, temp);
+			return 1;
+		    }
+		    start[offset] = 0;
+		}
+	}
+
+#else /* The original, quickie test */
+	incr = 1;
+	for (;;) {
+		if (ctrlc()) {
+			putc ('\n');
+			return 1;
+		}
+
+		printf ("\rPattern %08lX  Writing..."
+			"%12s"
+			"\b\b\b\b\b\b\b\b\b\b",
+			pattern, "");
+
+		for (addr=start,val=pattern; addr<end; addr++) {
+			*addr = val;
+			val  += incr;
+		}
+
+		printf("Reading...");
+
+		for (addr=start,val=pattern; addr<end; addr++) {
+			readback = *addr;
+			if (readback != val) {
+				printf ("\nMem error @ 0x%08X: "
+					"found %08lX, expected %08lX\n",
+					(uint)addr, readback, val);
+				rcode = 1;
+			}
+			val += incr;
+		}
+
+		/*
+		 * Flip the pattern each time to make lots of zeros and
+		 * then, the next time, lots of ones.  We decrement
+		 * the "negative" patterns and increment the "positive"
+		 * patterns to preserve this feature.
+		 */
+		if(pattern & 0x80000000) {
+			pattern = -pattern;	/* complement & increment */
+		}
+		else {
+			pattern = ~pattern;
+		}
+		incr = -incr;
+	}
+	return rcode;
+#endif
+}
+
+
+/* Modify memory.
+ *
+ * Syntax:
+ *	mm{.b, .w, .l} {addr}
+ *	nm{.b, .w, .l} {addr}
+ */
+static int
+mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
+{
+	ulong	addr, size, i;
+	int	nbytes;
+	extern char console_buffer[];
+
+	if (argc != 2) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+#ifdef CONFIG_BOOT_RETRY_TIME
+	reset_cmd_timeout();	/* got a good command to get here */
+#endif
+	/* We use the last specified parameters, unless new ones are
+	 * entered.
+	 */
+	addr = mm_last_addr;
+	size = mm_last_size;
+
+	if ((flag & CMD_FLAG_REPEAT) == 0) {
+		/* New command specified.  Check for a size specification.
+		 * Defaults to long if no or incorrect specification.
+		 */
+		size = cmd_get_data_size(argv[0], 4);
+
+		/* Address is specified since argc > 1
+		*/
+		addr = simple_strtoul(argv[1], NULL, 16);
+		addr += base_address;
+	}
+
+	/* Print the address, followed by value.  Then accept input for
+	 * the next value.  A non-converted value exits.
+	 */
+	do {
+		printf("%08lx:", addr);
+		if (size == 4)
+			printf(" %08x", *((uint   *)addr));
+		else if (size == 2)
+			printf(" %04x", *((ushort *)addr));
+		else
+			printf(" %02x", *((u_char *)addr));
+
+		nbytes = readline (" ? ");
+		if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
+			/* <CR> pressed as only input, don't modify current
+			 * location and move to next. "-" pressed will go back.
+			 */
+			if (incrflag)
+				addr += nbytes ? -size : size;
+			nbytes = 1;
+#ifdef CONFIG_BOOT_RETRY_TIME
+			reset_cmd_timeout(); /* good enough to not time out */
+#endif
+		}
+#ifdef CONFIG_BOOT_RETRY_TIME
+		else if (nbytes == -2) {
+			break;	/* timed out, exit the command	*/
+		}
+#endif
+		else {
+			char *endp;
+			i = simple_strtoul(console_buffer, &endp, 16);
+			nbytes = endp - console_buffer;
+			if (nbytes) {
+#ifdef CONFIG_BOOT_RETRY_TIME
+				/* good enough to not time out
+				 */
+				reset_cmd_timeout();
+#endif
+				if (size == 4)
+					*((uint   *)addr) = i;
+				else if (size == 2)
+					*((ushort *)addr) = i;
+				else
+					*((u_char *)addr) = i;
+				if (incrflag)
+					addr += size;
+			}
+		}
+	} while (nbytes);
+
+	mm_last_addr = addr;
+	mm_last_size = size;
+	return 0;
+}
+
+int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong	addr, length;
+	ulong	crc;
+	ulong   *ptr;
+
+	if (argc < 3) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	addr = simple_strtoul(argv[1], NULL, 16);
+	addr += base_address;
+
+	length = simple_strtoul(argv[2], NULL, 16);
+
+	crc = crc32 (0, (const uchar *)addr, length);
+
+	printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
+		addr, addr + length -1, crc);
+
+	if (argc > 3)
+	  {
+	    ptr = (ulong *)simple_strtoul(argv[3], NULL, 16);
+	    *ptr = crc;
+	  }
+
+	return 0;
+}
+
+#endif	/* CFG_CMD_MEMORY */
diff --git a/common/cmd_misc.c b/common/cmd_misc.c
new file mode 100644
index 0000000..e3e0e44
--- /dev/null
+++ b/common/cmd_misc.c
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Misc functions
+ */
+#include <common.h>
+#include <command.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_MISC)
+
+int do_sleep (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	ulong delay;
+
+	if (argc != 2) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	delay = simple_strtoul(argv[1], NULL, 10);
+
+	while (delay) {
+		int i;
+		for (i=0; i<1000; ++i) {
+			if (ctrlc ()) {
+				return (-1);
+			}
+			udelay (1000);
+		}
+		--delay;
+	}
+	return 0;
+}
+
+#endif	/* CFG_CMD_MISC */
diff --git a/common/cmd_net.c b/common/cmd_net.c
new file mode 100644
index 0000000..c9ce85f
--- /dev/null
+++ b/common/cmd_net.c
@@ -0,0 +1,164 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <cmd_net.h>
+#include <net.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+
+# if (CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT)
+# include <cmd_autoscript.h>
+# endif
+
+extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+
+static int netboot_common (int, cmd_tbl_t *, int , char *[]);
+
+int do_bootp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	return netboot_common (BOOTP, cmdtp, argc, argv);
+}
+
+int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	return netboot_common (TFTP, cmdtp, argc, argv);
+}
+
+int do_rarpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	return netboot_common (RARP, cmdtp, argc, argv);
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
+int do_dhcp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	return netboot_common(DHCP, cmdtp, argc, argv);
+}
+#endif	/* CFG_CMD_DHCP */
+
+static void netboot_update_env(void)
+{
+    char tmp[16] ;
+
+    if (NetOurGatewayIP) {
+	ip_to_string (NetOurGatewayIP, tmp);
+	setenv("gatewayip", tmp);
+    }
+
+    if (NetOurSubnetMask) {
+	ip_to_string (NetOurSubnetMask, tmp);
+	setenv("netmask", tmp);
+    }
+
+    if (NetOurHostName[0])
+	setenv("hostname", NetOurHostName);
+
+    if (NetOurRootPath[0])
+	setenv("rootpath", NetOurRootPath);
+
+    if (NetOurIP) {
+	ip_to_string (NetOurIP, tmp);
+	setenv("ipaddr", tmp);
+    }
+
+    if (NetServerIP) {
+	ip_to_string (NetServerIP, tmp);
+	setenv("serverip", tmp);
+    }
+
+    if (NetOurDNSIP) {
+	ip_to_string (NetOurDNSIP, tmp);
+	setenv("dnsip", tmp);
+    }
+}
+static int
+netboot_common (int proto, cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+	char *s;
+	int   rcode = 0;
+	int   size;
+
+	/* pre-set load_addr */
+	if ((s = getenv("loadaddr")) != NULL) {
+		load_addr = simple_strtoul(s, NULL, 16);
+	}
+
+	switch (argc) {
+	case 1:
+		break;
+
+	case 2:	/* only one arg - accept two forms:
+		 * just load address, or just boot file name.
+		 * The latter form must be written "filename" here.
+		 */
+		if (argv[1][0] == '"') {	/* just boot filename */
+			copy_filename (BootFile, argv[1], sizeof(BootFile));
+		} else {			/* load address	*/
+			load_addr = simple_strtoul(argv[1], NULL, 16);
+		}
+		break;
+
+	case 3:	load_addr = simple_strtoul(argv[1], NULL, 16);
+		copy_filename (BootFile, argv[2], sizeof(BootFile));
+
+		break;
+
+	default: printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	if ((size = NetLoop(proto)) == 0)
+		return 1;
+
+	/* NetLoop ok, update environment */
+	netboot_update_env();
+
+	/* flush cache */
+	flush_cache(load_addr, size);
+
+	/* Loading ok, check if we should attempt an auto-start */
+	if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) {
+		char *local_args[2];
+		local_args[0] = argv[0];
+		local_args[1] = NULL;
+
+		printf ("Automatic boot of image at addr 0x%08lX ...\n",
+			load_addr);
+		rcode = do_bootm (cmdtp, 0, 1, local_args);
+	}
+
+#ifdef CONFIG_AUTOSCRIPT
+	if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
+		printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
+		rcode = autoscript (load_addr);
+	}
+#endif
+	return rcode;
+}
+
+#endif	/* CFG_CMD_NET */