* Patch by Daniel Engström, 13 Nov 2002:
  Add support for i386 architecture and AMD SC520 board

* Patch by Pierre Aubert, 12 Nov 2002:
  Add support for DOS filesystem and booting from DOS floppy disk
diff --git a/common/Makefile b/common/Makefile
index 3f4ff01..67387ef 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -31,7 +31,7 @@
 	  cmd_autoscript.o cmd_bedbug.o cmd_boot.o \
 	  cmd_bootm.o cmd_cache.o cmd_console.o cmd_date.o \
 	  cmd_dcr.o cmd_diag.o cmd_doc.o cmd_dtt.o \
-	  cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_flash.o \
+	  cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_fdos.o cmd_flash.o \
 	  cmd_fpga.o cmd_i2c.o cmd_ide.o cmd_immap.o \
 	  cmd_jffs2.o cmd_log.o cmd_mem.o cmd_mii.o cmd_misc.o \
 	  cmd_net.o cmd_nvedit.o env_common.o \
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 70ca999..a0587d0 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -70,6 +70,10 @@
 #endif
 static void print_type (image_header_t *hdr);
 
+#ifdef __I386__
+image_header_t *fake_header(image_header_t *hdr, void *ptr, int size);
+#endif
+
 /*
  *  Continue booting an OS image; caller already has:
  *  - copied image header to global variable `header'
@@ -84,7 +88,7 @@
 			  ulong	*len_ptr,	/* multi-file image length table */
 			  int	verify);	/* getenv("verify")[0] != 'n' */
 
-#ifndef CONFIG_ARM
+#ifdef CONFIG_PPC
 static boot_os_Fcn do_bootm_linux;
 #else
 extern boot_os_Fcn do_bootm_linux;
@@ -128,9 +132,21 @@
 	memmove (&header, (char *)addr, sizeof(image_header_t));
 
 	if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+#ifdef __I386__	/* correct image format not implemented yet - fake it */
+		if (fake_header(hdr, (void*)addr, -1) != NULL) {
+			/* to compensate for the addition below */
+			addr -= sizeof(image_header_t);
+			/* turnof verify,
+			 * fake_header() does not fake the data crc
+			 */
+			verify = 0;
+		} else
+#endif	/* __I386__ */
+	    {
 		printf ("Bad Magic Number\n");
 		SHOW_BOOT_PROGRESS (-1);
 		return 1;
+	    }
 	}
 	SHOW_BOOT_PROGRESS (2);
 
@@ -148,7 +164,7 @@
 	SHOW_BOOT_PROGRESS (3);
 
 	/* for multi-file images we need the data part, too */
-	print_image_hdr ((image_header_t *)addr);
+	print_image_hdr (hdr);
 
 	data = addr + sizeof(image_header_t);
 	len  = ntohl(hdr->ih_size);
@@ -166,8 +182,17 @@
 
 	len_ptr = (ulong *)data;
 
-	if (hdr->ih_arch != IH_CPU_PPC && hdr->ih_arch != IH_CPU_ARM) {
-		printf ("Unsupported Architecture\n");
+#if defined(__PPC__)
+	if (hdr->ih_arch != IH_CPU_PPC)
+#elif defined(__ARM__)
+	if (hdr->ih_arch != IH_CPU_ARM)
+#elif defined(__I386__)
+	if (hdr->ih_arch != IH_CPU_I386)
+#else
+# error Unknown CPU type
+#endif
+	{
+		printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch);
 		SHOW_BOOT_PROGRESS (-4);
 		return 1;
 	}
@@ -201,7 +226,7 @@
 
 	switch (hdr->ih_comp) {
 	case IH_COMP_NONE:
-		if(hdr->ih_load == addr) {
+		if(ntohl(hdr->ih_load) == addr) {
 			printf ("   XIP %s ... ", name);
 		} else {
 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
@@ -294,7 +319,7 @@
 	return 1;
 }
 
-#ifndef CONFIG_ARM
+#ifdef CONFIG_PPC
 static void
 do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
 		int	argc, char *argv[],
diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c
index 8e6b735..e45b336 100644
--- a/common/cmd_fdc.c
+++ b/common/cmd_fdc.c
@@ -51,7 +51,7 @@
 #include <rtc.h>
 #endif
 
-#if (CONFIG_COMMANDS & CFG_CMD_FDC)
+#if ((CONFIG_COMMANDS & CFG_CMD_FDC) || (CONFIG_COMMANDS & CFG_CMD_FDOS))
 
 
 typedef struct {
@@ -192,7 +192,10 @@
 /* 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 * CFG_ISA_IO_STRIDE) + CFG_ISA_IO_OFFSET);
+	volatile unsigned char *val =
+		(volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS +
+					   (addr * CFG_ISA_IO_STRIDE) +
+					   CFG_ISA_IO_OFFSET);
         
 	return val [0];
 }
@@ -200,7 +203,10 @@
 /* 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 * CFG_ISA_IO_STRIDE) + CFG_ISA_IO_OFFSET);
+        volatile unsigned char *tmp =
+		(volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS +
+					   (addr * CFG_ISA_IO_STRIDE) +
+					   CFG_ISA_IO_OFFSET);
 	tmp[0]=val;
 }
 
@@ -279,7 +285,8 @@
 	head = sect / pFG->sect; /* head nr */
 	sect =  sect % pFG->sect; /* remaining blocks */
 	sect++; /* sectors are 1 based */
-	PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr);
+	PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",
+		pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr);
 
 	if(head|=0) { /* max heads = 2 */
 		pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */
@@ -588,7 +595,7 @@
 * setup the fdc according the datasheet
 * assuming in PS2 Mode
 */
-int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)
+int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
 {
 
 	int i;
@@ -601,7 +608,7 @@
 	for(i=0; i<255; i++) /* then we wait some time */
 		udelay(500);
 	/* then, we clear the reset in the DOR */
-	pCMD->drive=CFG_FDC_DRIVE_NUMBER;
+	pCMD->drive=drive;
 	select_fdc_drive(pCMD);
 	/* initialize the CCR */
 	write_fdc_reg(FDC_CCR,pFG->rate);
@@ -621,9 +628,8 @@
 			PRINTF("Sense Interrupt for drive %d failed\n",i);
 		}
 	}
-	/* assuming drive 0 for rest of configuration
-	 * issue the configure command */
-	pCMD->drive=CFG_FDC_DRIVE_NUMBER;
+	/* issue the configure command */
+	pCMD->drive=drive;
 	select_fdc_drive(pCMD);
 	pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE;
 	if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
@@ -644,7 +650,74 @@
 	/*	write_fdc_reg(FDC_DOR,0x04); */
 	return TRUE;
 }
+#endif /* ((CONFIG_COMMANDS & CFG_CMD_FDC)||(CONFIG_COMMANDS & CFG_CMD_FDOS))*/
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+
+/* Low level functions for the Floppy-DOS layer                              */
+
+/**************************************************************************
+* int fdc_fdos_init
+* initialize the FDC layer 
+* 
+*/
+int fdc_fdos_init (int drive)
+{
+	FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
+	FDC_COMMAND_STRUCT *pCMD = &cmd;
+    
+	/* setup FDC and scan for drives  */
+	if(fdc_setup(drive,pCMD,pFG)==FALSE) {
+		printf("\n** Error in setup FDC **\n");
+		return FALSE;
+	}
+	if(fdc_check_drive(pCMD,pFG)==FALSE) {
+		printf("\n** Error in check_drives **\n");
+		return FALSE;
+	}
+	if((pCMD->flags&(1<<drive))==0) {
+		/* drive not available */
+		printf("\n** Drive %d not available **\n",drive);
+		return FALSE;
+	}
+	if((pCMD->flags&(0x10<<drive))==0) {
+		/* no disk inserted */
+		printf("\n** No disk inserted in drive %d **\n",drive);
+		return FALSE;
+	}
+	/* ok, we have a valid source */
+	pCMD->drive=drive;
 
+	/* read first block */
+	pCMD->blnr=0;
+        return TRUE;
+}
+/**************************************************************************
+* int fdc_fdos_seek
+* parameter is a block number 
+*/
+int fdc_fdos_seek (int where)
+{
+	FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
+	FDC_COMMAND_STRUCT *pCMD = &cmd;
+
+        pCMD -> blnr = where ;
+        return (fdc_seek (pCMD, pFG));
+}
+/**************************************************************************
+* int fdc_fdos_read
+*  the length is in block number
+*/
+int fdc_fdos_read (void *buffer, int len)
+{
+	FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
+	FDC_COMMAND_STRUCT *pCMD = &cmd;
+
+        return (fdc_read_data (buffer, len, pCMD, pFG));
+}
+#endif  /* (CONFIG_COMMANDS & CFG_CMD_FDOS)                                  */
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDC)
 /****************************************************************************
  * main routine do_fdcboot
  */
@@ -677,7 +750,7 @@
 		return 1;
 	}
 	/* setup FDC and scan for drives  */
-	if(fdc_setup(pCMD,pFG)==FALSE) {
+	if(fdc_setup(boot_drive,pCMD,pFG)==FALSE) {
 		printf("\n** Error in setup FDC **\n");
 		return 1;
 	}
diff --git a/common/cmd_fdos.c b/common/cmd_fdos.c
new file mode 100644
index 0000000..763f418
--- /dev/null
+++ b/common/cmd_fdos.c
@@ -0,0 +1,145 @@
+/*
+ * (C) Copyright 2002
+ * Stäubli Faverges - <www.staubli.com>
+ * Pierre AUBERT  p.aubert@staubli.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
+ */
+
+/*
+ * Dos floppy support
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <fdc.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+
+/*-----------------------------------------------------------------------------
+ * do_fdosboot -- 
+ *-----------------------------------------------------------------------------
+ */
+int do_fdosboot(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+    char *name;
+    char *ep;
+    int size;
+    int rcode = 0;
+    char buf [10];
+    int drive = CFG_FDC_DRIVE_NUMBER;
+    
+    /* pre-set load_addr */
+    if ((ep = getenv("loadaddr")) != NULL) {
+        load_addr = simple_strtoul(ep, NULL, 16);
+    }
+
+    /* pre-set Boot file name */
+    if ((name = getenv("bootfile")) == NULL) {
+        name = "pImage";
+    }
+
+    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 */
+            name = argv [1];
+        } else {			/* load address	*/
+            load_addr = simple_strtoul(argv[1], NULL, 16);
+        }
+        break;
+    case 3:
+        load_addr = simple_strtoul(argv[1], NULL, 16);
+        name = argv [2];
+        break;
+    default:
+        printf ("Usage:\n%s\n", cmdtp->usage);
+        break;
+    }
+
+    /* Init physical layer                                                   */
+    if (!fdc_fdos_init (drive)) {
+        return (-1);
+    }
+    
+    /* Open file                                                             */
+    if (dos_open (name) < 0) {
+        printf ("Unable to open %s\n", name);
+        return 1;
+    }
+    if ((size = dos_read (load_addr)) < 0) {
+        printf ("boot error\n");
+        return 1;
+    }
+    flush_cache (load_addr, size);
+
+    sprintf(buf, "%x", size);
+    setenv("filesize", buf);
+
+    printf("Floppy DOS load complete: %d bytes loaded to 0x%lx\n",
+           size, load_addr);
+    
+    /* 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", load_addr);
+        rcode = do_bootm (cmdtp, 0, 1, local_args);
+    }
+    return rcode;
+}
+
+/*-----------------------------------------------------------------------------
+ * do_fdosls -- 
+ *-----------------------------------------------------------------------------
+ */
+int do_fdosls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+    char *path = "";
+    int drive = CFG_FDC_DRIVE_NUMBER;
+    
+    switch (argc) {
+    case 1:
+        break;
+    case 2:
+        path = argv [1];
+        break;
+    }
+
+    /* Init physical layer                                                   */
+    if (!fdc_fdos_init (drive)) {
+        return (-1);
+    }
+    /* Open directory                                                        */
+    if (dos_open (path) < 0) {
+        printf ("Unable to open %s\n", path);
+        return 1;
+    }
+    return (dos_dir ());
+}
+
+#endif
diff --git a/common/cmd_ide.c b/common/cmd_ide.c
index 9cbfe1b..e514cf7 100644
--- a/common/cmd_ide.c
+++ b/common/cmd_ide.c
@@ -44,6 +44,9 @@
 #ifdef CONFIG_STATUS_LED
 # include <status_led.h>
 #endif
+#ifdef __I386__
+#include <asm/io.h>
+#endif
 
 #ifdef CONFIG_SHOW_BOOT_PROGRESS
 # include <status_led.h>
@@ -114,7 +117,9 @@
 #endif
 };
 
+#ifdef __PPC__
 #define	ATA_CURR_BASE(dev)	(CFG_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)])
+#endif
 
 static int	    ide_bus_ok[CFG_IDE_MAXBUS];
 
@@ -142,9 +147,11 @@
 
 #define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
 
-static void __inline__ outb(int dev, int port, unsigned char val);
-static unsigned char __inline__ inb(int dev, int port);
+static void __inline__ ide_outb(int dev, int port, unsigned char val);
+static unsigned char __inline__ ide_inb(int dev, int port);
+#ifdef __PPC__
 static void input_swap_data(int dev, ulong *sect_buf, int words);
+#endif
 static void input_data(int dev, ulong *sect_buf, int words);
 static void output_data(int dev, ulong *sect_buf, int words);
 static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
@@ -517,14 +524,14 @@
 		/* Select device
 		 */
 		udelay (100000);		/* 100 ms */
-		outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
+		ide_outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
 		udelay (100000);		/* 100 ms */
 
 		i = 0;
 		do {
 			udelay (10000);		/* 10 ms */
 
-			c = inb (dev, ATA_STATUS);
+			c = ide_inb (dev, ATA_STATUS);
 			i++;
 			if (i > (ATA_RESET_TIME * 100)) {
 				puts ("** Timeout **\n");
@@ -679,30 +686,48 @@
 
 /* ------------------------------------------------------------------------- */
 
+#ifdef __PPC__
 static void __inline__
-outb(int dev, int port, unsigned char val)
+ide_outb(int dev, int port, unsigned char val)
 {
 	/* Ensure I/O operations complete */
 	__asm__ volatile("eieio");
 	*((uchar *)(ATA_CURR_BASE(dev)+port)) = val;
 #if 0
-	printf ("OUTB: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
+	printf ("ide_outb: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
 #endif
 }
+#else	/* ! __PPC__ */
+static void __inline__
+ide_outb(int dev, int port, unsigned char val)
+{
+	outb(val, port);
+}
+#endif	/* __PPC__ */
+
 
+#ifdef __PPC__
 static unsigned char __inline__
-inb(int dev, int port)
+ide_inb(int dev, int port)
 {
 	uchar val;
 	/* Ensure I/O operations complete */
 	__asm__ volatile("eieio");
 	val = *((uchar *)(ATA_CURR_BASE(dev)+port));
 #if 0
-	printf ("INB: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
+	printf ("ide_inb: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
 #endif
 	return (val);
 }
+#else	/* ! __PPC__ */
+static unsigned char __inline__
+ide_inb(int dev, int port)
+{
+	return inb(port);
+}
+#endif	/* __PPC__ */
 
+#ifdef __PPC__
 __inline__ unsigned ld_le16(const volatile unsigned short *addr)
 {
 	unsigned val;
@@ -722,7 +747,14 @@
 		*dbuf++ = ld_le16(pbuf);
 	}
 }
+#else	/* ! __PPC__ */
+#define input_swap_data(x,y,z) input_data(x,y,z)
+#endif	/* __PPC__ */
+
+
+
 
+#ifdef __PPC__
 static void
 output_data(int dev, ulong *sect_buf, int words)
 {
@@ -738,7 +770,15 @@
 		*pbuf = *dbuf++;
 	}
 }
+#else	/* ! __PPC__ */
+static void
+output_data(int dev, ulong *sect_buf, int words)
+{
+	outsw(ATA_DATA_REG, sect_buf, words<<1);
+}
+#endif	/* __PPC__ */
 
+#ifdef __PPC__
 static void
 input_data(int dev, ulong *sect_buf, int words)
 {
@@ -754,6 +794,14 @@
 		*dbuf++ = *pbuf;
 	}
 }
+#else	/* ! __PPC__ */
+static void
+input_data(int dev, ulong *sect_buf, int words)
+{
+	insw(ATA_DATA_REG, sect_buf, words << 1);
+}
+
+#endif	/* __PPC__ */
 
 /* -------------------------------------------------------------------------
  */
@@ -773,19 +821,19 @@
 	ide_led (DEVICE_LED(device), 1);	/* LED on	*/
 	/* Select device
 	 */
-	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
 	dev_desc->if_type=IF_TYPE_IDE;
 #ifdef CONFIG_ATAPI
 	/* check signature */
-	if ((inb(device,ATA_SECT_CNT)==0x01) &&
-		 (inb(device,ATA_SECT_NUM)==0x01) &&
-		 (inb(device,ATA_CYL_LOW)==0x14) &&
-		 (inb(device,ATA_CYL_HIGH)==0xEB)) {
+	if ((ide_inb(device,ATA_SECT_CNT) == 0x01) &&
+		 (ide_inb(device,ATA_SECT_NUM) == 0x01) &&
+		 (ide_inb(device,ATA_CYL_LOW)  == 0x14) &&
+		 (ide_inb(device,ATA_CYL_HIGH) == 0xEB)) {
 		/* ATAPI Signature found */
 		dev_desc->if_type=IF_TYPE_ATAPI;
 		/* Start Ident Command
 		 */
-		outb (device, ATA_COMMAND, ATAPI_CMD_IDENT);
+		ide_outb (device, ATA_COMMAND, ATAPI_CMD_IDENT);
 		/*
 		 * Wait for completion - ATAPI devices need more time
 		 * to become ready
@@ -797,7 +845,7 @@
 	{
 		/* Start Ident Command
 		 */
-		outb (device, ATA_COMMAND, ATA_CMD_IDENT);
+		ide_outb (device, ATA_COMMAND, ATA_CMD_IDENT);
 
 		/* Wait for completion
 		 */
@@ -867,15 +915,15 @@
 #if 0 	/* only used to test the powersaving mode,
 	 * if enabled, the drive goes after 5 sec
 	 * in standby mode */
-	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
 	c = ide_wait (device, IDE_TIME_OUT);
-	outb (device, ATA_SECT_CNT, 1);
-	outb (device, ATA_LBA_LOW,  0);
-	outb (device, ATA_LBA_MID,  0);
-	outb (device, ATA_LBA_HIGH, 0);
-	outb (device, ATA_DEV_HD,   ATA_LBA		|
+	ide_outb (device, ATA_SECT_CNT, 1);
+	ide_outb (device, ATA_LBA_LOW,  0);
+	ide_outb (device, ATA_LBA_MID,  0);
+	ide_outb (device, ATA_LBA_HIGH, 0);
+	ide_outb (device, ATA_DEV_HD,   ATA_LBA		|
 				    ATA_DEVICE(device));
-	outb (device, ATA_COMMAND,  0xe3);
+	ide_outb (device, ATA_COMMAND,  0xe3);
 	udelay (50);
 	c = ide_wait (device, IDE_TIME_OUT);	/* can't take over 500 ms */
 #endif
@@ -897,7 +945,7 @@
 
 	/* Select device
 	 */
-	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
 	c = ide_wait (device, IDE_TIME_OUT);
 
 	if (c & ATA_STAT_BUSY) {
@@ -907,7 +955,7 @@
 
 	/* first check if the drive is in Powersaving mode, if yes,
 	 * increase the timeout value */
-	outb (device, ATA_COMMAND,  ATA_CMD_CHK_PWR);
+	ide_outb (device, ATA_COMMAND,  ATA_CMD_CHK_PWR);
 	udelay (50);
 
 	c = ide_wait (device, IDE_TIME_OUT);	/* can't take over 500 ms */
@@ -919,7 +967,7 @@
 	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
 		printf ("No Powersaving mode %X\n", c);
 	} else {
-		c = inb(device,ATA_SECT_CNT);
+		c = ide_inb(device,ATA_SECT_CNT);
 		PRINTF("Powersaving %02X\n",c);
 		if(c==0)
 			pwrsave=1;
@@ -935,14 +983,14 @@
 			break;
 		}
 
-		outb (device, ATA_SECT_CNT, 1);
-		outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
-		outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
-		outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
-		outb (device, ATA_DEV_HD,   ATA_LBA		|
+		ide_outb (device, ATA_SECT_CNT, 1);
+		ide_outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
+		ide_outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
+		ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
+		ide_outb (device, ATA_DEV_HD,   ATA_LBA		|
 					    ATA_DEVICE(device)	|
 					    ((blknr >> 24) & 0xF) );
-		outb (device, ATA_COMMAND,  ATA_CMD_READ);
+		ide_outb (device, ATA_COMMAND,  ATA_CMD_READ);
 
 		udelay (50);
 
@@ -960,7 +1008,7 @@
 		}
 
 		input_data (device, buffer, ATA_SECTORWORDS);
-		(void) inb (device, ATA_STATUS);	/* clear IRQ */
+		(void) ide_inb (device, ATA_STATUS);	/* clear IRQ */
 
 		++n;
 		++blknr;
@@ -983,7 +1031,7 @@
 
 	/* Select device
 	 */
-	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
 
 	while (blkcnt-- > 0) {
 
@@ -994,14 +1042,14 @@
 			goto WR_OUT;
 		}
 
-		outb (device, ATA_SECT_CNT, 1);
-		outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
-		outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
-		outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
-		outb (device, ATA_DEV_HD,   ATA_LBA		|
+		ide_outb (device, ATA_SECT_CNT, 1);
+		ide_outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
+		ide_outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
+		ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
+		ide_outb (device, ATA_DEV_HD,   ATA_LBA		|
 					    ATA_DEVICE(device)	|
 					    ((blknr >> 24) & 0xF) );
-		outb (device, ATA_COMMAND,  ATA_CMD_WRITE);
+		ide_outb (device, ATA_COMMAND,  ATA_CMD_WRITE);
 
 		udelay (50);
 
@@ -1014,7 +1062,7 @@
 		}
 
 		output_data (device, buffer, ATA_SECTORWORDS);
-		c = inb (device, ATA_STATUS);	/* clear IRQ */
+		c = ide_inb (device, ATA_STATUS);	/* clear IRQ */
 		++n;
 		++blknr;
 		buffer += ATA_SECTORWORDS;
@@ -1063,7 +1111,7 @@
 	ulong delay = 10 * t;		/* poll every 100 us */
 	uchar c;
 
-	while ((c = inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
+	while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
 		udelay (100);
 		if (delay-- == 0) {
 			break;
@@ -1188,6 +1236,7 @@
 #define AT_PRINTF(fmt,args...)
 #endif
 
+#ifdef __PPC__
 /* since ATAPI may use commands with not 4 bytes alligned length
  * we have our own transfer functions, 2 bytes alligned */
 static void
@@ -1218,6 +1267,22 @@
 	}
 }
 
+#else	/* ! __PPC__ */
+static void
+output_data_shorts(int dev, ushort *sect_buf, int shorts)
+{
+	outsw(ATA_DATA_REG, sect_buf, shorts);
+}
+
+
+static void
+input_data_shorts(int dev, ushort *sect_buf, int shorts)
+{
+	insw(ATA_DATA_REG, sect_buf, shorts);
+}
+
+#endif	/* __PPC__ */
+
 /*
  * Wait until (Status & mask) == res, or timeout (in ms)
  * Return last status
@@ -1229,9 +1294,8 @@
 	ulong delay = 10 * t;		/* poll every 100 us */
 	uchar c;
 
-	c = inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */
-	while (((c = inb(dev, ATA_STATUS)) & mask)
-			!= res) {
+	c = ide_inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */
+	while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
 		/* break if error occurs (doesn't make sense to wait more) */
 		if((c & ATA_STAT_ERR)==ATA_STAT_ERR)
 			break;
@@ -1256,7 +1320,7 @@
 	 */
 	mask = ATA_STAT_BUSY|ATA_STAT_DRQ;
 	res = 0;
-	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
 	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
 	if ((c & mask) != res) {
 		printf ("ATAPI_ISSUE: device %d not ready status %X\n", device,c);
@@ -1264,12 +1328,12 @@
 		goto AI_OUT;
 	}
 	/* write taskfile */
-	outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
-	outb (device, ATA_CYL_LOW,  (unsigned char)(buflen & 0xFF));
-	outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xFF));
-	outb (device, ATA_DEV_HD,   ATA_LBA | ATA_DEVICE(device));
+	ide_outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
+	ide_outb (device, ATA_CYL_LOW,  (unsigned char)(buflen & 0xFF));
+	ide_outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xFF));
+	ide_outb (device, ATA_DEV_HD,   ATA_LBA | ATA_DEVICE(device));
 
-	outb (device, ATA_COMMAND,  ATAPI_CMD_PACKET);
+	ide_outb (device, ATA_COMMAND,  ATAPI_CMD_PACKET);
 	udelay (50);
 
 	mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR;
@@ -1295,7 +1359,7 @@
 	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
 	if ((c & mask) != res ) {
 		if (c & ATA_STAT_ERR) {
-			err=(inb(device,ATA_ERROR_REG))>>4;
+			err=(ide_inb(device,ATA_ERROR_REG))>>4;
 			AT_PRINTF("atapi_issue 1 returned sense key %X status %02X\n",err,c);
 		} else {
 			printf ("ATTAPI_ISSUE: (no DRQ) after sending ccb (%x)  status 0x%02x\n", ccb[0],c);
@@ -1303,9 +1367,9 @@
 		}
 		goto AI_OUT;
 	}
-	n=inb(device, ATA_CYL_HIGH);
+	n=ide_inb(device, ATA_CYL_HIGH);
 	n<<=8;
-	n+=inb(device, ATA_CYL_LOW);
+	n+=ide_inb(device, ATA_CYL_LOW);
 	if(n>buflen) {
 		printf("ERROR, transfer bytes %d requested only %d\n",n,buflen);
 		err=0xff;
@@ -1324,7 +1388,7 @@
 		 /* we transfer shorts */
 		n>>=1;
 		/* ok now decide if it is an in or output */
-		if ((inb(device, ATA_SECT_CNT)&0x02)==0) {
+		if ((ide_inb(device, ATA_SECT_CNT)&0x02)==0) {
 			AT_PRINTF("Write to device\n");
 			output_data_shorts(device,(unsigned short *)buffer,n);
 		} else {
@@ -1337,7 +1401,7 @@
 	res=0;
 	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
 	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
-		err=(inb(device,ATA_ERROR_REG) >> 4);
+		err=(ide_inb(device,ATA_ERROR_REG) >> 4);
 		AT_PRINTF("atapi_issue 2 returned sense key %X status %X\n",err,c);
 	} else {
 		err = 0;
diff --git a/common/command.c b/common/command.c
index f70cad8..cab68ab 100644
--- a/common/command.c
+++ b/common/command.c
@@ -70,6 +70,7 @@
 
 #include <cmd_vfd.h>		/* load a bitmap to the VFDs on TRAB */
 #include <cmd_log.h>
+#include <cmd_fdos.h>
 
 /*
  * HELP command
@@ -253,6 +254,8 @@
 	CMD_TBL_FCCINFO
 	CMD_TBL_FLERASE
 	CMD_TBL_FDC
+        CMD_TBL_FDOS_BOOT
+        CMD_TBL_FDOS_LS
 	CMD_TBL_FLINFO
 	CMD_TBL_FPGA
 	CMD_TBL_JFFS2_FSINFO