Browse Source

* Patch by Daniel Engstrm, 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

wdenk 22 năm trước cách đây
mục cha
commit
2262cfeef9
82 tập tin đã thay đổi với 10257 bổ sung84 xóa
  1. 6 0
      CHANGELOG
  2. 4 0
      CREDITS
  3. 11 0
      MAINTAINERS
  4. 17 2
      Makefile
  5. 4 2
      README
  6. 47 0
      board/sc520_cdp/Makefile
  7. 25 0
      board/sc520_cdp/config.mk
  8. 449 0
      board/sc520_cdp/flash.c
  9. 288 0
      board/sc520_cdp/sc520_cdp.c
  10. 86 0
      board/sc520_cdp/sc520_cdp_asm.S
  11. 62 0
      board/sc520_cdp/sc520_cdp_asm16.S
  12. 85 0
      board/sc520_cdp/u-boot.lds
  13. 1 1
      common/Makefile
  14. 31 6
      common/cmd_bootm.c
  15. 83 10
      common/cmd_fdc.c
  16. 145 0
      common/cmd_fdos.c
  17. 119 55
      common/cmd_ide.c
  18. 3 0
      common/command.c
  19. 43 0
      cpu/i386/Makefile
  20. 26 0
      cpu/i386/config.mk
  21. 62 0
      cpu/i386/cpu.c
  22. 583 0
      cpu/i386/interrupts.c
  23. 38 0
      cpu/i386/reset.S
  24. 460 0
      cpu/i386/serial.c
  25. 198 0
      cpu/i386/start.S
  26. 112 0
      cpu/i386/start16.S
  27. 211 0
      cpu/i386/timer.c
  28. 74 0
      doc/README-i386
  29. 39 0
      doc/TODO-i386
  30. 3 3
      drivers/pcnet.c
  31. 14 0
      examples/syscall.S
  32. 1 1
      fs/Makefile
  33. 49 0
      fs/fdos/Makefile
  34. 195 0
      fs/fdos/dev.c
  35. 177 0
      fs/fdos/dos.h
  36. 145 0
      fs/fdos/fat.c
  37. 175 0
      fs/fdos/fdos.c
  38. 117 0
      fs/fdos/fdos.h
  39. 120 0
      fs/fdos/fs.c
  40. 348 0
      fs/fdos/subdir.c
  41. 357 0
      fs/fdos/vfat.c
  42. 24 0
      i386_config.mk
  43. 384 0
      include/asm-i386/bitops.h
  44. 47 0
      include/asm-i386/byteorder.h
  45. 60 0
      include/asm-i386/global_data.h
  46. 56 0
      include/asm-i386/i8254.h
  47. 88 0
      include/asm-i386/i8259.h
  48. 47 0
      include/asm-i386/ibmpc.h
  49. 54 0
      include/asm-i386/ic/ali512x.h
  50. 249 0
      include/asm-i386/ic/sc520.h
  51. 207 0
      include/asm-i386/io.h
  52. 31 0
      include/asm-i386/pci.h
  53. 80 0
      include/asm-i386/posix_types.h
  54. 53 0
      include/asm-i386/ppcboot-i386.h
  55. 66 0
      include/asm-i386/ptrace.h
  56. 31 0
      include/asm-i386/realmode.h
  57. 30 0
      include/asm-i386/string.h
  58. 51 0
      include/asm-i386/types.h
  59. 58 0
      include/asm-i386/u-boot.h
  60. 75 0
      include/asm-i386/zimage.h
  61. 4 3
      include/cmd_confdefs.h
  62. 55 0
      include/cmd_fdos.h
  63. 5 0
      include/common.h
  64. 1 0
      include/configs/LANTEC.h
  65. 1 0
      include/configs/MPC8260ADS.h
  66. 1 0
      include/configs/ep8260.h
  67. 1 0
      include/configs/hymod.h
  68. 210 0
      include/configs/sc520_cdp.h
  69. 41 0
      include/fdc.h
  70. 1 1
      include/linux/stat.h
  71. 45 0
      lib_i386/Makefile
  72. 443 0
      lib_i386/bios.S
  73. 178 0
      lib_i386/bios_setup.c
  74. 448 0
      lib_i386/board.c
  75. 174 0
      lib_i386/i386_linux.c
  76. 442 0
      lib_i386/ic/ali512x.c
  77. 348 0
      lib_i386/ic/sc520.c
  78. 530 0
      lib_i386/ic/sc520_asm.S
  79. 57 0
      lib_i386/pci_type1.c
  80. 69 0
      lib_i386/realmode.c
  81. 223 0
      lib_i386/realmode_switch.S
  82. 276 0
      lib_i386/zimage.c

+ 6 - 0
CHANGELOG

@@ -2,6 +2,12 @@
 Changes since for U-Boot 0.1.0:
 ======================================================================
 
+* 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
+
 * Patch by Jim Sandoz, 07 Nov 2002:
   Increase number of network RX buffers (PKTBUFSRX in
   "include/net.h") for EEPRO100 based boards (especially SP8240)

+ 4 - 0
CREDITS

@@ -83,6 +83,10 @@ N: Dave Ellis
 E: DGE@sixnetio.com
 D: EEPROM Speedup, SXNI855T port
 
+N: Daniel Engström
+E: daniel@omicron.se
+D: x86 port, Support for sc520_cdp board
+
 N: Dr. Wolfgang Grandegger
 E: wg@denx.de
 D: Support for Interphase 4539 T1/E1/J1 PMC, PN62, CCM, SCM boards

+ 11 - 0
MAINTAINERS

@@ -249,6 +249,17 @@ Alex Z
 	lart			SA1100
 	dnp1110			SA1110
 
+#########################################################################
+# x86 Systems:								#
+#									#
+# Maintainer Name, Email Address					#
+#	Board			CPU					#
+#########################################################################
+
+Daniel Engström <daniel@omicron.se>
+
+	sc520_cdp		x86
+
 #########################################################################
 # End of MAINTAINERS list						#
 #########################################################################

+ 17 - 2
Makefile

@@ -74,6 +74,9 @@ endif
 ifeq ($(ARCH),arm)
 CROSS_COMPILE = arm_920TDI-
 endif
+ifeq ($(ARCH),i386)
+#CROSS_COMPILE = i386-elf-
+endif
 endif
 endif
 
@@ -100,7 +103,10 @@ SUBDIRS	= tools \
 # U-Boot objects....order is important (i.e. start must be first)
 
 OBJS  =	cpu/$(CPU)/start.o
-
+ifeq ($(CPU),i386)
+OBJS +=	cpu/$(CPU)/start16.o
+OBJS +=	cpu/$(CPU)/reset.o
+endif
 ifeq ($(CPU),ppc4xx)
 OBJS +=	cpu/$(CPU)/resetvec.o
 endif
@@ -108,7 +114,7 @@ endif
 LIBS  =	board/$(BOARDDIR)/lib$(BOARD).a
 LIBS += cpu/$(CPU)/lib$(CPU).a
 LIBS += lib_$(ARCH)/lib$(ARCH).a
-LIBS += fs/jffs2/libjffs2.a
+LIBS += fs/jffs2/libjffs2.a fs/fdos/libfdos.a
 LIBS += net/libnet.a
 LIBS += disk/libdisk.a
 LIBS += rtc/librtc.a
@@ -627,6 +633,15 @@ cradle_config	:	unconfig
 csb226_config	:	unconfig
 	@./mkconfig $(@:_config=) arm xscale csb226
 
+#========================================================================
+# i386
+#========================================================================
+#########################################################################
+## AMD SC520 CDP 
+#########################################################################
+sc520_cdp_config	:	unconfig
+	@./mkconfig $(@:_config=) i386 i386 sc520_cdp
+
 #########################################################################
 
 clean:

+ 4 - 2
README

@@ -536,6 +536,7 @@ The following options need to be configured:
 		CFG_CMD_ELF	  bootelf, bootvx
 		CFG_CMD_ENV	  saveenv
 		CFG_CMD_FDC	* Floppy Disk Support
+		CFG_CMD_FDOS	* Dos diskette Support
 		CFG_CMD_FLASH	  flinfo, erase, protect
 		CFG_CMD_FPGA	  FPGA device initialization support
 		CFG_CMD_I2C	* I2C serial bus support
@@ -1127,6 +1128,7 @@ The following options need to be configured:
                 Define this to contain any number of null terminated
                 strings (variable = value pairs) that will be part of
                 the default enviroment compiled into the boot image.
+
                 For example, place something like this in your
                 board's config file:
 
@@ -1136,9 +1138,9 @@ The following options need to be configured:
 
                 Warning: This method is based on knowledge about the
                 internal format how the environment is stored by the
-                U-Boot code. This is NOT an official, expoerted
+                U-Boot code. This is NOT an official, exported
                 interface! Although it is unlikely that this format
-                will change soon, there is no guarantee either.
+                will change soon, but there is no guarantee either.
 		You better know what you are doing here.
 
                 Note: overly (ab)use of the default environment is

+ 47 - 0
board/sc520_cdp/Makefile

@@ -0,0 +1,47 @@
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	= lib$(BOARD).a
+
+OBJS	:= sc520_cdp.o flash.o 
+SOBJS	:= sc520_cdp_asm.o sc520_cdp_asm16.o
+
+$(LIB):	$(OBJS) $(SOBJS)
+	$(AR) crv $@ $^
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+		$(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+-include .depend
+
+#########################################################################

+ 25 - 0
board/sc520_cdp/config.mk

@@ -0,0 +1,25 @@
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+#
+# 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
+#
+
+
+TEXT_BASE = 0x387e0000

+ 449 - 0
board/sc520_cdp/flash.c

@@ -0,0 +1,449 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.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>
+
+ulong myflush(void);
+
+
+#define FLASH_BANK_SIZE 0x400000	/* 4 MB */
+#define MAIN_SECT_SIZE  0x20000		/* 128 KB */
+
+flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
+
+
+#define CMD_READ_ARRAY		0x00F000F0
+#define CMD_UNLOCK1		0x00AA00AA
+#define CMD_UNLOCK2		0x00550055
+#define CMD_ERASE_SETUP		0x00800080
+#define CMD_ERASE_CONFIRM	0x00300030
+#define CMD_PROGRAM		0x00A000A0
+#define CMD_UNLOCK_BYPASS	0x00200020
+
+#define MEM_FLASH_ADDR1		(*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2)))
+#define MEM_FLASH_ADDR2		(*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2)))
+
+#define BIT_ERASE_DONE		0x00800080
+#define BIT_RDY_MASK		0x00800080
+#define BIT_PROGRAM_ERROR	0x00200020
+#define BIT_TIMEOUT		0x80000000 /* our flag */
+
+#define READY 1
+#define ERR   2
+#define TMO   4
+
+/*-----------------------------------------------------------------------
+ */
+
+ulong flash_init(void)
+{
+    int i, j;
+    ulong size = 0;
+
+    for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
+    {
+	ulong flashbase = 0;
+	flash_info[i].flash_id =
+	  (AMD_MANUFACT & FLASH_VENDMASK) |
+	  (AMD_ID_LV160B & FLASH_TYPEMASK);
+	flash_info[i].size = FLASH_BANK_SIZE;
+	flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
+	memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
+	if (i == 0)
+	  flashbase = PHYS_FLASH_1;
+	else
+	  panic("configured to many flash banks!\n");
+	for (j = 0; j < flash_info[i].sector_count; j++)
+	{
+
+	    if (j <= 3)
+	    {
+		/* 1st one is 32 KB */
+		if (j == 0)
+		{
+			flash_info[i].start[j] = flashbase + 0;
+		}
+
+		/* 2nd and 3rd are both 16 KB */
+		if ((j == 1) || (j == 2))
+		{
+			flash_info[i].start[j] = flashbase + 0x8000 + (j-1)*0x4000;
+		}
+
+		/* 4th 64 KB */
+		if (j == 3)
+		{
+			flash_info[i].start[j] = flashbase + 0x10000;
+		}
+	    }
+	    else
+	    {
+		flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE;
+	    }
+	}
+	size += flash_info[i].size;
+    }
+
+    /*
+     * Protect monitor and environment sectors
+     */
+    flash_protect(FLAG_PROTECT_SET,
+		  i386boot_start-CFG_FLASH_BASE,
+		  i386boot_end-CFG_FLASH_BASE,
+		  &flash_info[0]);
+
+    flash_protect(FLAG_PROTECT_SET,
+		  CFG_ENV_ADDR,
+		  CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+		  &flash_info[0]);
+    return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+    int i;
+
+    switch (info->flash_id & FLASH_VENDMASK)
+    {
+    case (AMD_MANUFACT & FLASH_VENDMASK):
+	printf("AMD: ");
+	break;
+    default:
+	printf("Unknown Vendor ");
+	break;
+    }
+
+    switch (info->flash_id & FLASH_TYPEMASK)
+    {
+    case (AMD_ID_LV160B & FLASH_TYPEMASK):
+	printf("2x Amd29F160BB (16Mbit)\n");
+	break;
+    default:
+	printf("Unknown Chip Type\n");
+	goto Done;
+	break;
+    }
+
+    printf("  Size: %ld MB in %d Sectors\n",
+	   info->size >> 20, info->sector_count);
+
+    printf("  Sector Start Addresses:");
+    for (i = 0; i < info->sector_count; i++)
+    {
+	if ((i % 5) == 0)
+	{
+	    printf ("\n   ");
+	}
+	printf (" %08lX%s", info->start[i],
+		info->protect[i] ? " (RO)" : "     ");
+    }
+    printf ("\n");
+
+Done:
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int	flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    ulong result;
+    int iflag, cflag, prot, sect;
+    int rc = ERR_OK;
+    int chip1, chip2;
+
+    /* first look for protection bits */
+
+    if (info->flash_id == FLASH_UNKNOWN)
+	return ERR_UNKNOWN_FLASH_TYPE;
+
+    if ((s_first < 0) || (s_first > s_last)) {
+	return ERR_INVAL;
+    }
+
+    if ((info->flash_id & FLASH_VENDMASK) !=
+	(AMD_MANUFACT & FLASH_VENDMASK)) {
+	return ERR_UNKNOWN_FLASH_VENDOR;
+    }
+
+    prot = 0;
+    for (sect=s_first; sect<=s_last; ++sect) {
+	if (info->protect[sect]) {
+	    prot++;
+	}
+    }
+    if (prot)
+	return ERR_PROTECTED;
+
+    /*
+     * Disable interrupts which might cause a timeout
+     * here. Remember that our exception vectors are
+     * at address 0 in the flash, and we don't want a
+     * (ticker) exception to happen while the flash
+     * chip is in programming mode.
+     */
+    iflag = disable_interrupts();
+
+    /* Start erase on unprotected sectors */
+    for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
+    {
+	printf("Erasing sector %2d ... ", sect);
+
+	/* arm simple, non interrupt dependent timer */
+	reset_timer();
+
+	if (info->protect[sect] == 0)
+	{	/* not protected */
+	    vu_long *addr = (vu_long *)(info->start[sect]);
+
+	    MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+	    MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+	    MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
+
+	    MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+	    MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+	    *addr = CMD_ERASE_CONFIRM;
+
+	    /* wait until flash is ready */
+	    chip1 = chip2 = 0;
+
+	    do
+	    {
+		result = *addr;
+
+		/* check timeout */
+		if (get_timer(0) > CFG_FLASH_ERASE_TOUT)
+		{
+		    MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
+		    chip1 = TMO;
+		    break;
+		}
+
+		if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
+			chip1 = READY;
+
+		if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
+			chip1 = ERR;
+
+		if (!chip2 && (result >> 16) & BIT_ERASE_DONE)
+			chip2 = READY;
+
+		if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR)
+			chip2 = ERR;
+
+	    }  while (!chip1 || !chip2);
+
+	    MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
+
+	    if (chip1 == ERR || chip2 == ERR)
+	    {
+		rc = ERR_PROG_ERROR;
+		goto outahere;
+	    }
+	    if (chip1 == TMO)
+	    {
+		rc = ERR_TIMOUT;
+		goto outahere;
+	    }
+
+	    printf("ok.\n");
+	}
+	else /* it was protected */
+	{
+	    printf("protected!\n");
+	}
+    }
+
+    if (ctrlc())
+      printf("User Interrupt!\n");
+
+outahere:
+    /* allow flash to settle - wait 10 ms */
+    udelay(10000);
+
+    if (iflag)
+      enable_interrupts();
+
+
+    return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash
+ */
+
+volatile static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+    vu_long *addr = (vu_long *)dest;
+    ulong result;
+    int rc = ERR_OK;
+    int iflag;
+    int chip1, chip2;
+
+    /*
+     * Check if Flash is (sufficiently) erased
+     */
+    result = *addr;
+    if ((result & data) != data)
+        return ERR_NOT_ERASED;
+
+
+    /*
+     * Disable interrupts which might cause a timeout
+     * here. Remember that our exception vectors are
+     * at address 0 in the flash, and we don't want a
+     * (ticker) exception to happen while the flash
+     * chip is in programming mode.
+     */
+    iflag = disable_interrupts();
+
+    MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+    MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+    MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
+    *addr = CMD_PROGRAM;
+    *addr = data;
+
+    /* arm simple, non interrupt dependent timer */
+    reset_timer();
+
+    /* wait until flash is ready */
+    chip1 = chip2 = 0;
+    do
+    {
+	result = *addr;
+
+	/* check timeout */
+	if (get_timer(0) > CFG_FLASH_ERASE_TOUT)
+	{
+	    chip1 = ERR | TMO;
+	    break;
+	}
+	if (!chip1 && ((result & 0x80) == (data & 0x80)))
+		chip1 = READY;
+
+	if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR))
+	{
+		result = *addr;
+
+		if ((result & 0x80) == (data & 0x80))
+			chip1 = READY;
+		else
+			chip1 = ERR;
+	}
+
+	if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16))))
+		chip2 = READY;
+
+	if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR))
+	{
+		result = *addr;
+
+		if ((result & (0x80 << 16)) == (data & (0x80 << 16)))
+			chip2 = READY;
+		else
+			chip2 = ERR;
+	}
+
+    }  while (!chip1 || !chip2);
+
+    *addr = CMD_READ_ARRAY;
+
+    if (chip1 == ERR || chip2 == ERR || *addr != data)
+        rc = ERR_PROG_ERROR;
+
+    if (iflag)
+      enable_interrupts();
+
+
+    return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    ulong cp, wp, data;
+    int l;
+    int i, rc;
+
+    wp = (addr & ~3);	/* get lower word aligned address */
+
+    /*
+     * handle unaligned start bytes
+     */
+    if ((l = addr - wp) != 0) {
+	data = 0;
+	for (i=0, cp=wp; i<l; ++i, ++cp) {
+	    data = (data >> 8) | (*(uchar *)cp << 24);
+	}
+	for (; i<4 && cnt>0; ++i) {
+	    data = (data >> 8) | (*src++ << 24);
+	    --cnt;
+	    ++cp;
+	}
+	for (; cnt==0 && i<4; ++i, ++cp) {
+	    data = (data >> 8) | (*(uchar *)cp << 24);
+	}
+
+	if ((rc = write_word(info, wp, data)) != 0) {
+	    return (rc);
+	}
+	wp += 4;
+    }
+
+    /*
+     * handle word aligned part
+     */
+    while (cnt >= 4) {
+	data = *((vu_long*)src);
+	if ((rc = write_word(info, wp, data)) != 0) {
+	    return (rc);
+	}
+	src += 4;
+	wp  += 4;
+	cnt -= 4;
+    }
+
+    if (cnt == 0) {
+	return ERR_OK;
+    }
+
+    /*
+     * handle unaligned tail bytes
+     */
+    data = 0;
+    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+	data = (data >> 8) | (*src++ << 24);
+	--cnt;
+    }
+    for (; i<4; ++i, ++cp) {
+	data = (data >> 8) | (*(uchar *)cp << 24);
+    }
+
+    return write_word(info, wp, data);
+}

+ 288 - 0
board/sc520_cdp/sc520_cdp.c

@@ -0,0 +1,288 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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 <pci.h>
+#include <asm/io.h>
+#include <asm/ic/sc520.h>
+#include <asm/ic/ali512x.h>
+
+/* ------------------------------------------------------------------------- */
+
+static void irq_init(void)
+{
+	
+	/* disable global interrupt mode */
+	write_mmcr_byte(SC520_PICICR, 0x40); 
+	
+	/* set irq0-7 to edge */
+	write_mmcr_byte(SC520_MPICMODE, 0x00);
+	
+	/* set irq9-12 to level, all the other (8, 13-15) are edge */
+	write_mmcr_byte(SC520_SL1PICMODE, 0x1e);
+	
+	/* set irq16-24 (unused slave pic2) to level */
+	write_mmcr_byte(SC520_SL2PICMODE, 0xff);
+	
+	/* active low polarity on PIC interrupt pins, 
+	   active high polarity on all other irq pins */
+	write_mmcr_word(SC520_INTPINPOL, 0);
+
+	/* set irq number mapping */
+	write_mmcr_byte(SC520_GPTMR0MAP,0);            /* disable GP timer 0 INT */       
+	write_mmcr_byte(SC520_GPTMR1MAP,0);            /* disable GP timer 1 INT */
+	write_mmcr_byte(SC520_GPTMR2MAP,0);            /* disable GP timer 2 INT */
+	write_mmcr_byte(SC520_PIT0MAP,0x1);            /* Set PIT timer 0 INT to IRQ0 */ 
+	write_mmcr_byte(SC520_PIT1MAP,0);              /* diable PIT timer 1 INT */
+	write_mmcr_byte(SC520_PIT2MAP,0);              /* diable PIT timer 2 INT */
+	write_mmcr_byte(SC520_PCIINTAMAP,0x4);         /* Set PCI INT A to IRQ9 */
+	write_mmcr_byte(SC520_PCIINTBMAP,0x5);         /* Set PCI INT B to IRQ10 */
+	write_mmcr_byte(SC520_PCIINTCMAP,0x6);         /* Set PCI INT C to IRQ11 */
+	write_mmcr_byte(SC520_PCIINTDMAP,0x7);         /* Set PCI INT D to IRQ12 */
+	write_mmcr_byte(SC520_DMABCINTMAP,0);          /* disable DMA INT */ 
+	write_mmcr_byte(SC520_SSIMAP,0);               /* disable Synchronius serial INT */
+	write_mmcr_byte(SC520_WDTMAP,0);               /* disable Watchdor INT */
+	write_mmcr_byte(SC520_RTCMAP,0x3);             /* Set RTC int to 8 */
+	write_mmcr_byte(SC520_WPVMAP,0);               /* disable write protect INT */
+	write_mmcr_byte(SC520_ICEMAP,0x2);             /* Set ICE Debug Serielport INT to IRQ1 */
+	write_mmcr_byte(SC520_FERRMAP,0x8);            /* Set FP error INT to IRQ13 */
+	write_mmcr_byte(SC520_GP0IMAP,6);              /* Set GPIRQ0 (ISA IRQ2) to IRQ9 */
+	write_mmcr_byte(SC520_GP1IMAP,2);              /* Set GPIRQ1 (SIO IRQ1) to IRQ1 */
+	write_mmcr_byte(SC520_GP2IMAP,7);              /* Set GPIRQ2 (ISA IRQ12) to IRQ12 */
+	
+	if (CFG_USE_SIO_UART) {
+		write_mmcr_byte(SC520_UART1MAP,0);     /* disable internal UART1 INT */
+		write_mmcr_byte(SC520_UART2MAP,0);     /* disable internal UART2 INT */
+		write_mmcr_byte(SC520_GP3IMAP,11);     /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */ 
+		write_mmcr_byte(SC520_GP4IMAP,12);     /* Set GPIRQ4 (ISA IRQ4) to IRQ4 */
+	} else {
+		write_mmcr_byte(SC520_UART1MAP,12);    /* Set internal UART2 INT to IRQ4 */
+		write_mmcr_byte(SC520_UART2MAP,11);    /* Set internal UART2 INT to IRQ3 */
+		write_mmcr_byte(SC520_GP3IMAP,0);      /* disable GPIRQ3 (ISA IRQ3) */ 
+		write_mmcr_byte(SC520_GP4IMAP,0);      /* disable GPIRQ4 (ISA IRQ4) */
+	}
+	
+	write_mmcr_byte(SC520_GP5IMAP,13);             /* Set GPIRQ5 (ISA IRQ5) to IRQ5 */
+	write_mmcr_byte(SC520_GP6IMAP,21);             /* Set GPIRQ6 (ISA IRQ6) to IRQ6 */
+	write_mmcr_byte(SC520_GP7IMAP,22);             /* Set GPIRQ7 (ISA IRQ7) to IRQ7 */
+	write_mmcr_byte(SC520_GP8IMAP,3);              /* Set GPIRQ8 (SIO IRQ8) to IRQ8 */
+	write_mmcr_byte(SC520_GP9IMAP,4);              /* Set GPIRQ9 (ISA IRQ9) to IRQ9 */
+	write_mmcr_byte(SC520_GP10IMAP,9);             /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */          
+	write_mmcr_word(SC520_PCIHOSTMAP,0x11f);       /* Map PCI hostbridge INT to NMI */
+	write_mmcr_word(SC520_ECCMAP,0x100);           /* Map SDRAM ECC failure INT to NMI */
+ 
+}
+
+/* PCI stuff */
+static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+	char pin;
+	int irq;
+	
+	
+	pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
+	irq = pin-1;
+	
+	switch (PCI_DEV(dev)) {
+	case 20:
+		break;
+	case 19:
+		irq+=1;
+		break;
+	case 18:
+		irq+=2;
+		break;
+	case 17:
+		irq+=3;
+		break;
+	default: 
+		return;
+	}
+	
+	irq&=3; /* wrap around */
+	irq+=9; /* lowest IRQ is 9 */
+	
+	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, irq);
+#if 0	
+	printf("fixup_irq: device %d pin %c irq %d\n", 
+	       PCI_DEV(dev), 'A' + pin -1, irq);
+#endif
+}
+ 
+static struct pci_controller sc520_cdp_hose = {
+	fixup_irq: pci_sc520_cdp_fixup_irq,
+};
+
+void pci_init(void)
+{
+	pci_sc520_init(&sc520_cdp_hose);
+}
+
+
+static void silence_uart(int port)
+{
+	outb(0, port+1);
+}
+
+void setup_ali_sio(int uart_primary)
+{
+	ali512x_init();
+	
+	ali512x_set_fdc(ALI_ENABLED, 0x3f2, 6, 0);
+	ali512x_set_pp(ALI_ENABLED, 0x278, 7, 3);
+	ali512x_set_uart(ALI_ENABLED, ALI_UART1, uart_primary?0x3f8:0x3e8, 4);
+	ali512x_set_uart(ALI_ENABLED, ALI_UART2, uart_primary?0x2f8:0x2e8, 3);
+	ali512x_set_rtc(ALI_DISABLED, 0, 0);
+	ali512x_set_kbc(ALI_ENABLED, 1, 12);
+	ali512x_set_cio(ALI_ENABLED);
+	
+	/* IrDa pins */
+	ali512x_cio_function(12, 1, 0, 0);
+	ali512x_cio_function(13, 1, 0, 0);
+	
+	/* SSI chip select pins */
+	ali512x_cio_function(14, 0, 0, 0);  /* SSI_CS */
+	ali512x_cio_function(15, 0, 0, 0);  /* SSI_MV */					     
+	ali512x_cio_function(16, 0, 1, 0);  /* SSI_SPI# (inverted) */
+
+	/* Board REV pins */
+	ali512x_cio_function(20, 0, 0, 1);
+	ali512x_cio_function(21, 0, 0, 1);
+	ali512x_cio_function(22, 0, 0, 1);
+	ali512x_cio_function(23, 0, 0, 1);      
+}
+
+
+/* set up the ISA bus timing and system address mappings */
+static void bus_init(void)
+{
+
+	/* set up the GP IO pins */
+	write_mmcr_word(SC520_PIOPFS31_16, 0xf7ff); 	/* set the GPIO pin function 31-16 reg */		   
+	write_mmcr_word(SC520_PIOPFS15_0, 0xffff);  	/* set the GPIO pin function 15-0 reg */
+	write_mmcr_byte(SC520_CSPFS, 0xf8);  		/* set the CS pin function  reg */	
+	write_mmcr_byte(SC520_CLKSEL, 0x70);
+
+	
+	write_mmcr_byte(SC520_GPCSRT, 1);   /* set the GP CS offset */    	
+	write_mmcr_byte(SC520_GPCSPW, 3);   /* set the GP CS pulse width */
+	write_mmcr_byte(SC520_GPCSOFF, 1);  /* set the GP CS offset */
+	write_mmcr_byte(SC520_GPRDW, 3);    /* set the RD pulse width */
+	write_mmcr_byte(SC520_GPRDOFF, 1);  /* set the GP RD offset */
+        write_mmcr_byte(SC520_GPWRW, 3);    /* set the GP WR pulse width */
+	write_mmcr_byte(SC520_GPWROFF, 1);  /* set the GP WR offset */
+
+	write_mmcr_word(SC520_BOOTCSCTL, 0x1823);		/* set up timing of BOOTCS */ 
+	write_mmcr_word(SC520_ROMCS1CTL, 0x1823);		/* set up timing of ROMCS1 */
+	write_mmcr_word(SC520_ROMCS2CTL, 0x1823);		/* set up timing of ROMCS2 */ 
+	
+	/* adjust the memory map:
+	 * by default the first 256MB (0x00000000 - 0x0fffffff) is mapped to SDRAM
+	 * and 256MB to 1G-128k  (0x1000000 - 0x37ffffff) is mapped to PCI mmio
+	 * we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */ 
+	
+		
+	/* SRAM = GPCS3 128k @ d0000-effff*/
+	write_mmcr_long(SC520_PAR2,  0x4e00400d);		
+	
+	/* IDE0 = GPCS6 1f0-1f7 */
+	write_mmcr_long(SC520_PAR3,  0x380801f0);		
+
+	/* IDE1 = GPCS7 3f6 */
+	write_mmcr_long(SC520_PAR4,  0x3c0003f6);		
+	/* bootcs */
+	write_mmcr_long(SC520_PAR12, 0x8bffe800);		
+	/* romcs2 */
+	write_mmcr_long(SC520_PAR13, 0xcbfff000);		
+	/* romcs1 */
+	write_mmcr_long(SC520_PAR14, 0xabfff800);		
+	/* 680 LEDS */
+	write_mmcr_long(SC520_PAR15, 0x30000640);		
+	
+	asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */	
+
+	if (CFG_USE_SIO_UART) {
+		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS);	
+		setup_ali_sio(1);
+	} else {
+		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS));	
+		setup_ali_sio(0);
+		silence_uart(0x3e8);
+		silence_uart(0x2e8);
+	}
+
+}
+
+
+
+/*
+ * Miscelaneous platform dependent initialisations
+ */
+
+int board_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	
+	init_sc520();	
+	bus_init();
+	irq_init();
+		
+	/* max drive current on SDRAM */
+	write_mmcr_word(SC520_DSCTL, 0x0100);
+		
+	/* enter debug mode after next reset (only if jumper is also set) */
+	write_mmcr_byte(SC520_RESCFG, 0x08);
+	
+	/* configure the software timer to 33.333MHz */
+	write_mmcr_byte(SC520_SWTMRCFG, 0);
+	gd->bus_clk = 33333000;
+	
+	return 0;
+}
+
+int dram_init(void)
+{
+	init_sc520_dram();
+	return 0;
+}
+
+void show_boot_progress(int val)
+{
+	outb(val&0xff, 0x80);
+	outb((val&0xff00)>>8, 0x680);
+}
+
+
+int last_stage_init(void)
+{
+	int minor;
+	int major;
+	
+	major = minor = 0;
+	major |= ali512x_cio_in(23)?2:0;
+	major |= ali512x_cio_in(22)?1:0;
+	minor |= ali512x_cio_in(21)?2:0;
+	minor |= ali512x_cio_in(20)?1:0;
+	
+	printf("AMD SC520 CDP revision %d.%d\n", major, minor);
+}

+ 86 - 0
board/sc520_cdp/sc520_cdp_asm.S

@@ -0,0 +1,86 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+/* now setup the General purpose bus to give us access to the LEDs.
+ * We can then use the leds to display status information.
+ */ 
+
+sc520_cdp_registers:
+/* size    offset        value */
+.word 1 ; .word 0x040 ; .long 0x00       /* SDRAM buffer control */
+.word 2 ; .word 0xc08 ; .long 0x0001     /* GP CS offset */
+.word 2 ; .word 0xc09 ; .long 0x0003     /* GP CS width */
+.word 2 ; .word 0xc0a ; .long 0x0001     /* GP CS width */
+.word 2 ; .word 0xc0b ; .long 0x0003     /* GP RD pulse width */
+.word 2 ; .word 0xc0c ; .long 0x0001     /* GP RD offse */
+.word 2 ; .word 0xc0d ; .long 0x0003     /* GP WR pulse width */
+.word 2 ; .word 0xc0e ; .long 0x0001     /* GP WR offset */
+.word 2 ; .word 0xc2c ; .long 0x0000     /* GPIO directionreg */
+.word 2 ; .word 0xc2a ; .long 0x0000     /* GPIO directionreg */
+.word 2 ; .word 0xc22 ; .long 0xffff     /* GPIO pin function 31-16 reg */
+.word 2 ; .word 0xc20 ; .long 0xffff     /* GPIO pin function 15-0 reg */
+.word 2 ; .word 0x0c4 ; .long 0x28000680 /* PAR 15 for access to led 680 */
+.word 0 ; .word 0x000 ; .long 0x00
+
+/* board early intialization */
+.globl early_board_init
+early_board_init:
+        movl    $sc520_cdp_registers,%esi
+init_loop:	
+        movl    $0xfffef000,%edi     /* MMCR base to edi */					
+	movw	(%esi), %bx          /* load sizer to bx */
+	cmpw	$0, %bx              /* if sie is 0 we're done */
+	je	done 
+	xorl	%edx,%edx
+	movw	2(%esi), %dx        /* load MMCR offset to dx */
+	addl	%edx, %edi          /* add offset to base in edi */
+	movl	4(%esi), %eax       /* load value in eax */
+	cmpw	$1, %bx
+	je	byte                 /* byte op? */
+	cmpw	$2, %bx
+	je	word                 /* word op? */
+	movl	%eax, (%edi)         /* must be long, then */
+	jmp	next
+byte:   movb    %al,(%edi)        
+	jmp	next
+word:	movw	%ax,(%edi)
+next:	addl	$8, %esi             /* advance esi */
+	jmp	init_loop
+
+	/* the leds ad 0x80 and 0x680 should now work */
+done:   movb	$0x88, %al
+	out	%al, $0x80
+	movw	$0x680, %dx
+	out	%al, %dx
+
+	jmp 	*%ebp		     /* return to caller */
+
+
+.globl __show_boot_progress
+__show_boot_progress:
+	out	%al, $0x80
+	xchg	%al, %ah
+	movw	$0x680, %dx
+	out	%al, %dx
+	jmp	*%ebp
+	

+ 62 - 0
board/sc520_cdp/sc520_cdp_asm16.S

@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+/*
+ * 16bit initialization code.
+ * This code have to map the area of the boot flash
+ * that is used by U-boot to its final destination.
+ */
+
+.text
+.section .start16, "ax"
+.code16
+.globl board_init16
+board_init16:
+	/* Alias MMCR to 0xdf000 */
+	movw	$0xfffc, %dx
+	movl	$0x800df0cb, %eax	
+	outl	%eax, %dx		
+	
+	/* Set ds to point to MMCR alias */
+	movw	$0xdf00, %ax		
+	movw	%ax, %ds		 
+		
+	/* Map the entire flash at 0x38000000  
+	 * (with BOOTCS and PAR14, use 0xabfff800 for ROMCS1) */
+	movl    $0xc0, %edi
+        movl	$0x8bfff800, %eax
+        movl	%eax, (%di)		
+
+	/* Disable SDRAM write buffer */
+	movw    $0x40,%di
+        xorw    %ax,%ax
+        movb    %al, (%di)              
+
+	/* Disabe MMCR alias */
+	movw	$0xfffc, %dx
+	movl	$0x000000cb, %eax	
+	outl	%eax, %dx		
+	
+	/* the return address is tored in bp */
+	jmp	*%bp
+	

+ 85 - 0
board/sc520_cdp/u-boot.lds

@@ -0,0 +1,85 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{	
+	. = 0x387e0000;                     /* Where bootcode in the flash is mapped */
+	.text  : { *(.text); }
+	
+        . = ALIGN(4);
+        .rodata : { *(.rodata) }
+
+        . = 0x400000; 	                    /* Ram data segment to use */
+	_i386boot_romdata_dest = ABSOLUTE(.);
+        .data : AT ( LOADADDR(.rodata) + SIZEOF(.rodata) ) { *(.data) }
+	_i386boot_romdata_start = LOADADDR(.data); 	
+
+        . = ALIGN(4);
+        .got : AT ( LOADADDR(.data) + SIZEOF(.data) ) { *(.got) }
+	_i386boot_romdata_size = SIZEOF(.data) + SIZEOF(.got); 	
+
+
+        . = ALIGN(4);
+	_i386boot_bss_start = ABSOLUTE(.);
+        .bss : { *(.bss) }	
+	_i386boot_bss_size = SIZEOF(.bss);
+	
+	
+	/* 16bit realmode trampoline code */
+	.realmode 0x7c0 : AT ( LOADADDR(.got) + SIZEOF(.got) ) { *(.realmode) }
+    
+	_i386boot_realmode = LOADADDR(.realmode);
+	_i386boot_realmode_size = SIZEOF(.realmode);
+	
+	/* 16bit BIOS emulation code (just enough to boot Linux) */
+	.bios 0 : AT ( LOADADDR(.realmode) + SIZEOF(.realmode) ) { *(.bios) }
+    
+	_i386boot_bios = LOADADDR(.bios);
+	_i386boot_bios_size = SIZEOF(.bios);
+	
+
+	/* The load addresses below assumes that the flash
+	 * will be mapped so that 0x387f0000 == 0xffff0000
+	 * at reset time
+	 *
+	 * The fe00 and ff00 offsets of the start32 and start16 
+	 * segments are arbitrary, the just have to be mapped
+	 * at reset and the code have to fit.
+	 * The fff0 offset of reset is important, however.
+	 */
+	 
+	 
+	. = 0xfffffe00;
+	.start32 : AT (0x387ffe00) { *(.start32); } 
+	
+	. = 0xff00;
+	.start16 : AT (0x387fff00) { *(.start16); }  
+	
+	. = 0xfff0;
+	.reset : AT (0x387ffff0) { *(.reset); }  
+	_i386boot_end = (LOADADDR(.reset) + SIZEOF(.reset) );
+}

+ 1 - 1
common/Makefile

@@ -31,7 +31,7 @@ COBJS	= main.o altera.o bedbug.o \
 	  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 \

+ 31 - 6
common/cmd_bootm.c

@@ -70,6 +70,10 @@ static int image_info (unsigned long addr);
 #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 @@ typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag,
 			  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 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 	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 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 	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 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
 	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 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
 	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 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 	return 1;
 }
 
-#ifndef CONFIG_ARM
+#ifdef CONFIG_PPC
 static void
 do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
 		int	argc, char *argv[],

+ 83 - 10
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 @@ static FDC_COMMAND_STRUCT cmd; /* global command struct */
 /* 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 @@ unsigned char read_fdc_reg(unsigned int addr)
 /* 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 @@ int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
 	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 @@ int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
 * 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 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)
 	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 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)
 			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 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)
 	/*	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 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		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;
 	}

+ 145 - 0
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

+ 119 - 55
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 @@ ulong ide_bus_offset[CFG_IDE_MAXBUS] = {
 #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 @@ static uchar ide_wait  (int dev, ulong t);
 
 #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 @@ void ide_init (void)
 		/* 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 @@ set_pcmcia_timing (int pmode)
 
 /* ------------------------------------------------------------------------- */
 
+#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 @@ input_swap_data(int dev, ulong *sect_buf, int words)
 		*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 @@ output_data(int dev, ulong *sect_buf, int words)
 		*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 @@ input_data(int dev, ulong *sect_buf, int words)
 		*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 @@ static void ide_ident (block_dev_desc_t *dev_desc)
 	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 @@ static void ide_ident (block_dev_desc_t *dev_desc)
 	{
 		/* 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 @@ static void ide_ident (block_dev_desc_t *dev_desc)
 #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 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
 
 	/* 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 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
 
 	/* 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 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
 	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 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
 			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 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
 		}
 
 		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 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)
 
 	/* 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 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)
 			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 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)
 		}
 
 		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 @@ static uchar ide_wait (int dev, ulong t)
 	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 @@ static void ide_led (uchar led, uchar status)
 #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 @@ input_data_shorts(int dev, ushort *sect_buf, int shorts)
 	}
 }
 
+#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 @@ static uchar atapi_wait_mask (int dev, ulong t,uchar mask, uchar res)
 	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 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
 	 */
 	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 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
 		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 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
 	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 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
 		}
 		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 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
 		 /* 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 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
 	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;

+ 3 - 0
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_t cmd_tbl[] = {
 	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

+ 43 - 0
cpu/i386/Makefile

@@ -0,0 +1,43 @@
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	= lib$(CPU).a
+
+START	= start.o start16.o reset.o 
+OBJS	= serial.o interrupts.o cpu.o timer.o
+	  
+all:	.depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend:	Makefile $(START:.o=.S) $(OBJS:.o=.c)
+		$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################

+ 26 - 0
cpu/i386/config.mk

@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+#
+# 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
+#
+
+PLATFORM_RELFLAGS += # -pipe -mpreferred-stack-boundary=2 -fno-builtin -nostdinc -nostdlib
+
+PLATFORM_CPPFLAGS += -march=i386

+ 62 - 0
cpu/i386/cpu.c

@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ * 
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.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
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+
+int cpu_init(void)
+{
+	return 0;
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	extern void reset_cpu(ulong addr);
+
+	printf ("resetting ...\n");
+	udelay(50000);				/* wait 50 ms */
+	disable_interrupts();
+	reset_cpu(0);
+
+	/*NOTREACHED*/
+	return 0;
+}
+
+void  flush_cache (unsigned long dummy1, unsigned long dummy2)
+{
+	asm("wbinvd\n");
+	return;
+}
+

+ 583 - 0
cpu/i386/interrupts.c

@@ -0,0 +1,583 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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 <syscall.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include <asm/ibmpc.h>
+
+
+#if 0
+/* done */
+int	interrupt_init     (void);
+void	irq_install_handler(int, interrupt_handler_t *, void *);
+void	irq_free_handler   (int);
+void	enable_interrupts  (void);
+int	disable_interrupts (void);
+
+/* todo */
+void	timer_interrupt    (struct pt_regs *);
+void	external_interrupt (struct pt_regs *);
+void	reset_timer	   (void);
+ulong	get_timer	   (ulong base);
+void	set_timer	   (ulong t);
+
+#endif
+
+struct idt_entry {
+	u16	base_low;
+	u16	selector;
+	u8	res;
+	u8	access;
+	u16	base_high;
+} __attribute__ ((packed));
+
+
+struct idt_entry idt[256];
+
+
+#define MAX_IRQ 16
+
+typedef struct irq_handler { 
+	struct irq_handler *next;
+	interrupt_handler_t* isr_func;
+	void *isr_data;
+} irq_handler_t;
+
+#define IRQ_DISABLED   1
+
+typedef struct {
+	irq_handler_t *handler;
+	unsigned long status;
+} irq_desc_t;
+
+static irq_desc_t irq_table[MAX_IRQ];
+
+
+/* syscall stuff, very untested 
+ * the current approach which includes copying
+ * part of the stack will work badly for 
+ * varargs functions.
+ * if we were to store the top three words on the
+ * stack (eip, ss, eflags) somwhere and add 14 to
+ * %esp ....
+ */
+asm(".globl syscall_entry\n" \
+        "syscall_entry:\n" \
+        "movl   12(%esp), %eax\n" \
+	"movl   %esp, %ebx\n" \
+        "addl   $16, %ebx\n" \
+        "pushl  %ebx\n" \
+        "pushl  %eax\n" \
+        "call   do_syscall\n" \
+        "addl   $8, %esp\n" \
+        "iret\n");
+
+void __attribute__ ((regparm(0))) syscall_entry(void);
+
+int __attribute__ ((regparm(0))) do_syscall(u32 nr, u32 *stack)
+{
+	if (nr<NR_SYSCALLS) {
+		/* We copy 8 args of the syscall,
+		 * this will be a problem with the 
+		 * printf syscall .... */
+		int (*fp)(u32, u32, u32, u32,
+			  u32, u32, u32, u32);
+		fp = syscall_tbl[nr];
+		return fp(stack[0], stack[1], stack[2], stack[3],
+					     stack[4], stack[5], stack[6], stack[7]);
+	}
+	
+	return -1;
+}
+	
+
+asm ("irq_return:\n"
+     "     addl  $4, %esp\n"
+     "     popa\n"
+     "     iret\n");
+
+asm ("exp_return:\n"
+     "     addl  $12, %esp\n"
+     "     pop   %esp\n"
+     "     popa\n"
+     "     iret\n");
+
+char exception_stack[4096];
+
+#define DECLARE_INTERRUPT(x) \
+	asm(".globl irq_"#x"\n" \
+		    "irq_"#x":\n" \
+		    "pusha \n" \
+		    "pushl $"#x"\n" \
+		    "pushl $irq_return\n" \
+                    "jmp   do_irq\n"); \
+	void __attribute__ ((regparm(0))) irq_##x(void)
+
+#define DECLARE_EXCEPTION(x, f) \
+	asm(".globl exp_"#x"\n" \
+		    "exp_"#x":\n" \
+		    "pusha \n" \
+		    "movl     %esp, %ebx\n" \
+		    "movl     $exception_stack, %eax\n" \
+		    "movl     %eax, %esp \n" \
+		    "pushl    %ebx\n" \
+		    "movl     32(%esp), %ebx\n" \
+		    "xorl     %edx, %edx\n" \
+		    "movw     36(%esp), %dx\n" \
+		    "pushl    %edx\n" \
+		    "pushl    %ebx\n" \
+		    "pushl    $"#x"\n" \
+		    "pushl    $exp_return\n" \
+		    "jmp      "#f"\n"); \
+	void __attribute__ ((regparm(0))) exp_##x(void)
+
+DECLARE_EXCEPTION(0, divide_exception_entry);      /* Divide exception */
+DECLARE_EXCEPTION(1, debug_exception_entry);       /* Debug exception */
+DECLARE_EXCEPTION(2, nmi_entry);                   /* NMI */
+DECLARE_EXCEPTION(3, unknown_exception_entry);     /* Breakpoint/Coprocessor Error */
+DECLARE_EXCEPTION(4, unknown_exception_entry);     /* Overflow */
+DECLARE_EXCEPTION(5, unknown_exception_entry);     /* Bounds */
+DECLARE_EXCEPTION(6, invalid_instruction_entry);   /* Invalid instruction */
+DECLARE_EXCEPTION(7, unknown_exception_entry);     /* Device not present */
+DECLARE_EXCEPTION(8, double_fault_entry);          /* Double fault */
+DECLARE_EXCEPTION(9, unknown_exception_entry);     /* Co-processor segment overrun */
+DECLARE_EXCEPTION(10, invalid_tss_exception_entry);/* Invalid TSS */
+DECLARE_EXCEPTION(11, seg_fault_entry);            /* Segment not present */
+DECLARE_EXCEPTION(12, stack_fault_entry);          /* Stack overflow */
+DECLARE_EXCEPTION(13, gpf_entry);                  /* GPF */
+DECLARE_EXCEPTION(14, page_fault_entry);           /* PF */
+DECLARE_EXCEPTION(15, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(16, fp_exception_entry);         /* Floating point */
+DECLARE_EXCEPTION(17, alignment_check_entry);      /* alignment check */
+DECLARE_EXCEPTION(18, machine_check_entry);        /* machine check */
+DECLARE_EXCEPTION(19, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(20, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(21, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(22, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(23, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(24, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(25, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(26, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(27, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(28, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(29, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(30, unknown_exception_entry);    /* Reserved */
+DECLARE_EXCEPTION(31, unknown_exception_entry);    /* Reserved */
+
+DECLARE_INTERRUPT(0);
+DECLARE_INTERRUPT(1);
+DECLARE_INTERRUPT(3);
+DECLARE_INTERRUPT(4);
+DECLARE_INTERRUPT(5);
+DECLARE_INTERRUPT(6);
+DECLARE_INTERRUPT(7);
+DECLARE_INTERRUPT(8);
+DECLARE_INTERRUPT(9);
+DECLARE_INTERRUPT(10);
+DECLARE_INTERRUPT(11);
+DECLARE_INTERRUPT(12);
+DECLARE_INTERRUPT(13);
+DECLARE_INTERRUPT(14);
+DECLARE_INTERRUPT(15);
+  
+void __attribute__ ((regparm(0))) default_isr(void); 
+asm ("default_isr: iret\n");
+
+void disable_irq(int irq) 
+{
+	if (irq >= MAX_IRQ) {
+		return;
+	}
+	irq_table[irq].status |= IRQ_DISABLED;
+	
+}
+
+void enable_irq(int irq) 
+{
+	if (irq >= MAX_IRQ) {
+		return;
+	}
+	irq_table[irq].status &= ~IRQ_DISABLED;
+}
+
+/* masks one specific IRQ in the PIC */
+static void unmask_irq(int irq)
+{
+	int imr_port;
+	
+	if (irq >= MAX_IRQ) {
+		return;
+	}
+	if (irq > 7) {
+		imr_port = SLAVE_PIC + IMR;
+	} else {
+		imr_port = MASTER_PIC + IMR;
+	}
+	
+	outb(inb(imr_port)&~(1<<(irq&7)), imr_port);
+}
+
+
+/* unmasks one specific IRQ in the PIC */
+static void mask_irq(int irq)
+{
+	int imr_port;
+	
+	if (irq >= MAX_IRQ) {
+		return;
+	}
+	if (irq > 7) {
+		imr_port = SLAVE_PIC + IMR;
+	} else {
+		imr_port = MASTER_PIC + IMR;
+	}
+	
+	outb(inb(imr_port)|(1<<(irq&7)), imr_port); 
+}
+
+
+/* issue a Specific End Of Interrupt instruciton */
+static void specific_eoi(int irq)
+{
+	/* If it is on the slave PIC this have to be performed on
+	 * both the master and the slave PICs */
+	if (irq > 7) {
+		outb(OCW2_SEOI|(irq&7), SLAVE_PIC + OCW2);
+		irq = SEOI_IR2;               /* also do IR2 on master */
+	} 
+	outb(OCW2_SEOI|irq, MASTER_PIC + OCW2);
+}
+
+void __attribute__ ((regparm(0))) do_irq(int irq) 
+{
+	
+	mask_irq(irq);
+	
+	if (irq_table[irq].status & IRQ_DISABLED) {
+		unmask_irq(irq);
+		specific_eoi(irq);
+		return;
+	}
+	
+	
+	if (NULL != irq_table[irq].handler) {
+		irq_handler_t *handler;
+		for (handler = irq_table[irq].handler; 
+		     NULL!= handler; handler = handler->next) {
+			handler->isr_func(handler->isr_data);
+		}
+	} else {
+		if ((irq & 7) != 7) {				
+			printf("Spurious irq %d\n", irq);
+		}
+	}		
+	unmask_irq(irq);
+	specific_eoi(irq);	
+}
+
+
+void __attribute__ ((regparm(0))) unknown_exception_entry(int cause, int ip, int seg) 
+{
+	printf("Unknown Exception %d at %04x:%08x\n", cause, seg, ip);
+}
+
+void __attribute__ ((regparm(0))) divide_exception_entry(int cause, int ip, int seg) 
+{
+	printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip);
+	while(1);
+}
+
+void __attribute__ ((regparm(0))) debug_exception_entry(int cause, int ip, int seg) 
+{
+	printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip);
+}
+
+void __attribute__ ((regparm(0))) nmi_entry(int cause, int ip, int seg) 
+{
+	printf("NMI Interrupt at %04x:%08x\n", seg, ip);
+}
+		
+void __attribute__ ((regparm(0))) invalid_instruction_entry(int cause, int ip, int seg) 
+{
+	printf("Invalid Instruction at %04x:%08x\n", seg, ip);
+	while(1);
+}
+				
+void __attribute__ ((regparm(0))) double_fault_entry(int cause, int ip, int seg) 
+{
+	printf("Double fault at %04x:%08x\n", seg, ip);
+	while(1);
+}
+
+void __attribute__ ((regparm(0))) invalid_tss_exception_entry(int cause, int ip, int seg) 
+{
+	printf("Invalid TSS at %04x:%08x\n", seg, ip);
+}
+		
+void __attribute__ ((regparm(0))) seg_fault_entry(int cause, int ip, int seg) 
+{
+	printf("Segmentation fault at %04x:%08x\n", seg, ip);
+	while(1);
+}
+
+void __attribute__ ((regparm(0))) stack_fault_entry(int cause, int ip, int seg) 
+{
+	printf("Stack fault at %04x:%08x\n", seg, ip);
+	while(1);
+}
+
+void __attribute__ ((regparm(0))) gpf_entry(int cause, int ip, int seg) 
+{
+	printf("General protection fault at %04x:%08x\n", seg, ip);
+}
+
+void __attribute__ ((regparm(0))) page_fault_entry(int cause, int ip, int seg) 
+{
+	printf("Page fault at %04x:%08x\n", seg, ip);
+	while(1);
+}
+
+void __attribute__ ((regparm(0))) fp_exception_entry(int cause, int ip, int seg) 
+{
+	printf("Floating point exception at %04x:%08x\n", seg, ip);
+}
+
+void __attribute__ ((regparm(0))) alignment_check_entry(int cause, int ip, int seg) 
+{
+	printf("Alignment check at %04x:%08x\n", seg, ip);
+}
+       
+void __attribute__ ((regparm(0))) machine_check_entry(int cause, int ip, int seg) 
+{
+	printf("Machine check exception at %04x:%08x\n", seg, ip);
+}
+
+
+void irq_install_handler(int ino, interrupt_handler_t *func, void *pdata)
+{
+	int status;
+	
+	if (ino>MAX_IRQ) {
+		return;
+	}
+		
+	if (NULL != irq_table[ino].handler) {
+		return;
+	}
+	
+	status = disable_interrupts();
+	irq_table[ino].handler = malloc(sizeof(irq_handler_t));
+	if (NULL == irq_table[ino].handler) {
+		return;
+	}
+	
+	memset(irq_table[ino].handler, 0, sizeof(irq_handler_t));
+	
+	irq_table[ino].handler->isr_func = func;
+	irq_table[ino].handler->isr_data = pdata;
+	if (status) {
+		enable_interrupts();
+	}
+	
+	unmask_irq(ino);
+	
+	return;
+}
+
+void irq_free_handler(int ino)
+{
+	int status;
+	if (ino>MAX_IRQ) {
+		return;
+	}
+	
+	status = disable_interrupts();
+	mask_irq(ino);
+	if (NULL == irq_table[ino].handler) {
+		return;
+	}
+	free(irq_table[ino].handler);
+	irq_table[ino].handler=NULL;
+	if (status) {
+		enable_interrupts();
+	}
+	return;
+}
+
+
+asm ("idt_ptr:\n"
+	".word	0x800\n" /* size of the table 8*256 bytes */
+	".long	idt\n"	 /* offset */
+	".word	0x18\n");/* data segment */
+
+static void set_vector(int intnum, void *routine)
+{
+	idt[intnum].base_high = (u16)((u32)(routine)>>16);	
+	idt[intnum].base_low = (u16)((u32)(routine)&0xffff);	
+}
+
+
+int interrupt_init(void)
+{
+	int i;
+	
+	/* Just in case... */
+	disable_interrupts();
+		
+	/* Initialize the IDT and stuff */
+	
+	
+	memset(irq_table, 0, sizeof(irq_table));
+
+	/* Setup the IDT */
+	for (i=0;i<256;i++) {		
+		idt[i].access = 0x8e;
+		idt[i].res = 0;	
+		idt[i].selector = 0x10;	
+		set_vector(i, default_isr);
+	}	
+	
+	asm ("cs lidt idt_ptr\n");
+	
+	/* Setup exceptions */
+	set_vector(0x00, exp_0);
+	set_vector(0x01, exp_1);
+	set_vector(0x02, exp_2);
+	set_vector(0x03, exp_3);
+	set_vector(0x04, exp_4);
+	set_vector(0x05, exp_5);
+	set_vector(0x06, exp_6);
+	set_vector(0x07, exp_7);
+	set_vector(0x08, exp_8);
+	set_vector(0x09, exp_9);
+	set_vector(0x0a, exp_10);
+	set_vector(0x0b, exp_11);
+	set_vector(0x0c, exp_12);
+	set_vector(0x0d, exp_13);
+	set_vector(0x0e, exp_14);
+	set_vector(0x0f, exp_15);
+	set_vector(0x10, exp_16);
+	set_vector(0x11, exp_17);
+	set_vector(0x12, exp_18);
+	set_vector(0x13, exp_19);
+	set_vector(0x14, exp_20);
+	set_vector(0x15, exp_21);
+	set_vector(0x16, exp_22);
+	set_vector(0x17, exp_23);
+	set_vector(0x18, exp_24);
+	set_vector(0x19, exp_25);
+	set_vector(0x1a, exp_26);
+	set_vector(0x1b, exp_27);
+	set_vector(0x1c, exp_28);
+	set_vector(0x1d, exp_29);
+	set_vector(0x1e, exp_30);
+	set_vector(0x1f, exp_31);
+
+
+	/* Setup interrupts */
+	set_vector(0x20, irq_0);
+	set_vector(0x21, irq_1);
+	set_vector(0x23, irq_3);
+	set_vector(0x24, irq_4);
+	set_vector(0x25, irq_5);
+	set_vector(0x26, irq_6);
+	set_vector(0x27, irq_7);
+	set_vector(0x28, irq_8);
+	set_vector(0x29, irq_9);
+	set_vector(0x2a, irq_10);
+	set_vector(0x2b, irq_11);
+	set_vector(0x2c, irq_12);
+	set_vector(0x2d, irq_13);
+	set_vector(0x2e, irq_14);
+	set_vector(0x2f, irq_15);
+	/* vectors 0x30-0x3f are reserved for irq 16-31 */
+	set_vector(0x40, syscall_entry);
+
+	
+	/* Mask all interrupts */
+	outb(0xff, MASTER_PIC + IMR);
+	outb(0xff, SLAVE_PIC + IMR);
+	
+	/* Master PIC */
+	outb(ICW1_SEL|ICW1_EICW4, MASTER_PIC + ICW1);	
+	outb(0x20, MASTER_PIC + ICW2);          /* Place master PIC interrupts at INT20 */
+	outb(IR2, MASTER_PIC + ICW3);		/* ICW3, One slevc PIC is present */	
+	outb(ICW4_PM, MASTER_PIC + ICW4);
+	
+	for (i=0;i<8;i++) {
+		outb(OCW2_SEOI|i, MASTER_PIC + OCW2);
+	}
+	
+	/* Slave PIC */
+	outb(ICW1_SEL|ICW1_EICW4, SLAVE_PIC + ICW1);	
+	outb(0x28, SLAVE_PIC + ICW2);	        /* Place slave PIC interrupts at INT28 */
+	outb(0x02, SLAVE_PIC + ICW3);		/* Slave ID */
+	outb(ICW4_PM, SLAVE_PIC + ICW4);        
+	
+	for (i=0;i<8;i++) {
+		outb(OCW2_SEOI|i, SLAVE_PIC + OCW2);
+	}
+	
+	
+	/* enable cascade interrerupt */
+	outb(0xfb, MASTER_PIC + IMR);
+	outb(0xff, SLAVE_PIC + IMR);
+	
+	/* It is now safe to enable interrupts */
+	enable_interrupts(); 
+	
+	return 0;
+}
+
+void enable_interrupts(void)
+{
+	asm("sti\n");
+}
+
+int disable_interrupts(void)
+{
+	long flags;
+	
+	asm volatile ("pushfl ; popl %0 ; cli\n" : "=g" (flags) : );
+	
+	return (flags&0x200); /* IE flags is bit 9 */
+}
+
+
+#ifdef CFG_RESET_GENERIC
+
+void __attribute__ ((regparm(0))) generate_gpf(void);
+asm(".globl generate_gpf\n" 
+    "generate_gpf:\n" 
+    "ljmp   $0x70, $0x47114711\n"); /* segment 0x70 is an arbitrary segment which does not 
+				    * exist */
+void reset_cpu(ulong addr)
+{
+	set_vector(13, generate_gpf);  /* general protection fault handler */
+	set_vector(8, generate_gpf);   /* double fault handler */
+	generate_gpf();                /* start the show */
+}
+#endif

+ 38 - 0
cpu/i386/reset.S

@@ -0,0 +1,38 @@
+/*
+ *  U-boot - i386 Startup Code 
+ *
+ *  Copyright (c) 2002	Omicron Ceti AB, Daniel Engström <denaiel@omicron.se>
+ *
+ * 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
+ */
+
+/* Reset vector, jumps to start16.S */
+
+.extern start16
+
+.section .reset, "ax"
+.code16
+reset_vector: 
+        cli
+        cld
+        jmp start16 
+
+	.org 0xf
+	nop
+	

+ 460 - 0
cpu/i386/serial.c

@@ -0,0 +1,460 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * (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
+ */
+/*------------------------------------------------------------------------------+ */
+/*
+ * This source code has been made available to you by IBM on an AS-IS
+ * basis.  Anyone receiving this source is licensed under IBM
+ * copyrights to use it in any way he or she deems fit, including
+ * copying it, modifying it, compiling it, and redistributing it either
+ * with or without modifications.  No license under IBM patents or
+ * patent applications is to be implied by the copyright license.
+ *
+ * Any user of this software should understand that IBM cannot provide
+ * technical support for this software and will not be responsible for
+ * any consequences resulting from the use of this software.
+ *
+ * Any person who transfers this source code or any derivative work
+ * must include the IBM copyright notice, this paragraph, and the
+ * preceding two paragraphs in the transferred software.
+ *
+ * COPYRIGHT   I B M   CORPORATION 1995
+ * LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+ */
+/*------------------------------------------------------------------------------- */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <asm/ibmpc.h>
+
+#if CONFIG_SERIAL_SOFTWARE_FIFO
+#include <malloc.h>
+#endif
+
+#define UART_RBR    0x00
+#define UART_THR    0x00
+#define UART_IER    0x01
+#define UART_IIR    0x02
+#define UART_FCR    0x02
+#define UART_LCR    0x03
+#define UART_MCR    0x04
+#define UART_LSR    0x05
+#define UART_MSR    0x06
+#define UART_SCR    0x07
+#define UART_DLL    0x00
+#define UART_DLM    0x01
+
+/*-----------------------------------------------------------------------------+
+  | Line Status Register.
+  +-----------------------------------------------------------------------------*/
+#define asyncLSRDataReady1            0x01
+#define asyncLSROverrunError1         0x02
+#define asyncLSRParityError1          0x04
+#define asyncLSRFramingError1         0x08
+#define asyncLSRBreakInterrupt1       0x10
+#define asyncLSRTxHoldEmpty1          0x20
+#define asyncLSRTxShiftEmpty1         0x40
+#define asyncLSRRxFifoError1          0x80
+
+
+
+#if CONFIG_SERIAL_SOFTWARE_FIFO
+/*-----------------------------------------------------------------------------+
+  | Fifo
+  +-----------------------------------------------------------------------------*/
+typedef struct {
+	char *rx_buffer;
+	ulong rx_put;
+	ulong rx_get;
+} serial_buffer_t;
+
+volatile static serial_buffer_t buf_info;
+#endif
+
+
+static int serial_div (int baudrate )
+{
+	
+	switch (baudrate) {
+	case 1200:
+		return 96;
+	case 9600:
+		return 12;
+	case 19200:
+		return 6;
+	case 38400:
+		return 3;
+	case 57600:
+		return 2;
+	case 115200:
+		return 1;		
+	}
+	hang ();
+}
+
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+int serial_init (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	volatile char val;
+
+	int bdiv = serial_div(gd->baudrate);
+    
+
+	outb(0x80, UART0_BASE + UART_LCR);	/* set DLAB bit */
+	outb(bdiv, UART0_BASE + UART_DLL);	/* set baudrate divisor */
+	outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */
+	outb(0x03, UART0_BASE + UART_LCR);	/* clear DLAB; set 8 bits, no parity */
+	outb(0x00, UART0_BASE + UART_FCR);	/* disable FIFO */
+	outb(0x00, UART0_BASE + UART_MCR);	/* no modem control DTR RTS */
+	val = inb(UART0_BASE + UART_LSR);	/* clear line status */
+	val = inb(UART0_BASE + UART_RBR);	/* read receive buffer */
+	outb(0x00, UART0_BASE + UART_SCR);	/* set scratchpad */
+	outb(0x00, UART0_BASE + UART_IER);	/* set interrupt enable reg */
+
+	return (0);
+}
+
+
+void serial_setbrg (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	unsigned short bdiv;
+	
+	bdiv = serial_div (gd->baudrate);
+
+	outb(0x80, UART0_BASE + UART_LCR);	/* set DLAB bit */
+	outb(bdiv&0xff, UART0_BASE + UART_DLL);	/* set baudrate divisor */
+	outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */
+	outb(0x03, UART0_BASE + UART_LCR);	/* clear DLAB; set 8 bits, no parity */
+}
+
+
+void serial_putc (const char c)
+{
+	int i;
+
+	if (c == '\n')
+		serial_putc ('\r');
+
+	/* check THRE bit, wait for transmiter available */
+	for (i = 1; i < 3500; i++) {
+		if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20)
+			break;
+		udelay (100);
+	}
+	outb(c, UART0_BASE + UART_THR);	/* put character out */
+}
+
+
+void serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
+
+
+int serial_getc ()
+{
+	unsigned char status = 0;
+
+	while (1) {
+#if defined(CONFIG_HW_WATCHDOG)
+		WATCHDOG_RESET ();	/* Reset HW Watchdog, if needed */
+#endif	/* CONFIG_HW_WATCHDOG */
+		status = inb (UART0_BASE + UART_LSR);
+		if ((status & asyncLSRDataReady1) != 0x0) {
+			break;
+		}
+		if ((status & ( asyncLSRFramingError1 |
+				asyncLSROverrunError1 |
+				asyncLSRParityError1  |
+				asyncLSRBreakInterrupt1 )) != 0) {
+			outb(asyncLSRFramingError1 |
+			      asyncLSROverrunError1 |
+			      asyncLSRParityError1  |
+			      asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR);
+		}
+	}
+	return (0x000000ff & (int) inb (UART0_BASE));
+}
+
+
+int serial_tstc ()
+{
+	unsigned char status;
+
+	status = inb (UART0_BASE + UART_LSR);
+	if ((status & asyncLSRDataReady1) != 0x0) {
+		return (1);
+	}
+	if ((status & ( asyncLSRFramingError1 |
+			asyncLSROverrunError1 |
+			asyncLSRParityError1  |
+			asyncLSRBreakInterrupt1 )) != 0) {
+		outb(asyncLSRFramingError1 |
+		      asyncLSROverrunError1 |
+		      asyncLSRParityError1  |
+		      asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR);
+	}
+	return 0;
+}
+
+
+#if CONFIG_SERIAL_SOFTWARE_FIFO
+
+void serial_isr (void *arg)
+{
+	int space;
+	int c;
+	const int rx_get = buf_info.rx_get;
+	int rx_put = buf_info.rx_put;
+
+	if (rx_get <= rx_put) {
+		space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
+	} else {
+		space = rx_get - rx_put;
+	}
+	while (serial_tstc ()) {
+		c = serial_getc ();
+		if (space) {
+			buf_info.rx_buffer[rx_put++] = c;
+			space--;
+		}
+		if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO)
+			rx_put = 0;
+		if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
+			/* Stop flow by setting RTS inactive */
+			outb(inb (UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
+			      UART0_BASE + UART_MCR);
+		}
+	}
+	buf_info.rx_put = rx_put;
+}
+
+void serial_buffered_init (void)
+{
+	serial_puts ("Switching to interrupt driven serial input mode.\n");
+	buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
+	buf_info.rx_put = 0;
+	buf_info.rx_get = 0;
+
+	if (inb (UART0_BASE + UART_MSR) & 0x10) {
+		serial_puts ("Check CTS signal present on serial port: OK.\n");
+	} else {
+		serial_puts ("WARNING: CTS signal not present on serial port.\n");
+	}
+
+	irq_install_handler ( VECNUM_U0 /*UART0 *//*int vec */ ,
+			      serial_isr /*interrupt_handler_t *handler */ ,
+			      (void *) &buf_info /*void *arg */ );
+
+	/* Enable "RX Data Available" Interrupt on UART */
+	/* outb(inb(UART0_BASE + UART_IER) |0x01, UART0_BASE + UART_IER); */
+	outb(0x01, UART0_BASE + UART_IER);
+	/* Set DTR active */
+	outb(inb (UART0_BASE + UART_MCR) | 0x01, UART0_BASE + UART_MCR);
+	/* Start flow by setting RTS active */
+	outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR);
+	/* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */
+	outb((1 << 6) | 1, UART0_BASE + UART_FCR);
+}
+
+void serial_buffered_putc (const char c)
+{
+	/* Wait for CTS */
+#if defined(CONFIG_HW_WATCHDOG)
+	while (!(inb (UART0_BASE + UART_MSR) & 0x10))
+		WATCHDOG_RESET ();
+#else
+	while (!(inb (UART0_BASE + UART_MSR) & 0x10));
+#endif
+	serial_putc (c);
+}
+
+void serial_buffered_puts (const char *s)
+{
+	serial_puts (s);
+}
+
+int serial_buffered_getc (void)
+{
+	int space;
+	int c;
+	int rx_get = buf_info.rx_get;
+	int rx_put;
+
+#if defined(CONFIG_HW_WATCHDOG)
+	while (rx_get == buf_info.rx_put)
+		WATCHDOG_RESET ();
+#else
+	while (rx_get == buf_info.rx_put);
+#endif
+	c = buf_info.rx_buffer[rx_get++];
+	if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO)
+		rx_get = 0;
+	buf_info.rx_get = rx_get;
+
+	rx_put = buf_info.rx_put;
+	if (rx_get <= rx_put) {
+		space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
+	} else {
+		space = rx_get - rx_put;
+	}
+	if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) {
+		/* Start flow by setting RTS active */
+		outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR);
+	}
+
+	return c;
+}
+
+int serial_buffered_tstc (void)
+{
+	return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
+}
+
+#endif	/* CONFIG_SERIAL_SOFTWARE_FIFO */
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+/*
+  AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
+  number 0 or number 1
+  - if CONFIG_KGDB_SER_INDEX = 1 => serial port number 0 :
+  configuration has been already done
+  - if CONFIG_KGDB_SER_INDEX = 2 => serial port number 1 :
+  configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE
+*/
+#if (CONFIG_KGDB_SER_INDEX & 2)
+void kgdb_serial_init (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	volatile char val;
+	bdiv = serial_div (CONFIG_KGDB_BAUDRATE);
+
+	/*
+	 * Init onboard 16550 UART
+	 */
+	outb(0x80, UART1_BASE + UART_LCR);	/* set DLAB bit */
+	outb(bdiv & 0xff), UART1_BASE + UART_DLL);	/* set divisor for 9600 baud */
+	outb(bdiv >> 8), UART1_BASE + UART_DLM);	/* set divisor for 9600 baud */
+	outb(0x03, UART1_BASE + UART_LCR);	/* line control 8 bits no parity */
+	outb(0x00, UART1_BASE + UART_FCR);	/* disable FIFO */
+	outb(0x00, UART1_BASE + UART_MCR);	/* no modem control DTR RTS */
+	val = inb(UART1_BASE + UART_LSR);	/* clear line status */
+	val = inb(UART1_BASE + UART_RBR);	/* read receive buffer */
+	outb(0x00, UART1_BASE + UART_SCR);	/* set scratchpad */
+	outb(0x00, UART1_BASE + UART_IER);	/* set interrupt enable reg */
+}
+
+
+void putDebugChar (const char c)
+{
+	if (c == '\n')
+		serial_putc ('\r');
+
+	outb(c, UART1_BASE + UART_THR);	/* put character out */
+
+	/* check THRE bit, wait for transfer done */
+	while ((inb(UART1_BASE + UART_LSR) & 0x20) != 0x20);
+}
+
+
+void putDebugStr (const char *s)
+{
+	while (*s) {
+		serial_putc(*s++);
+	}
+}
+
+
+int getDebugChar (void)
+{
+	unsigned char status = 0;
+
+	while (1) {
+		status = inb(UART1_BASE + UART_LSR);
+		if ((status & asyncLSRDataReady1) != 0x0) {
+			break;
+		}
+		if ((status & ( asyncLSRFramingError1 |
+				asyncLSROverrunError1 |
+				asyncLSRParityError1  |
+				asyncLSRBreakInterrupt1 )) != 0) {
+			outb(asyncLSRFramingError1 |
+			     asyncLSROverrunError1 |
+			     asyncLSRParityError1  |
+			     asyncLSRBreakInterrupt1, UART1_BASE + UART_LSR);
+		}
+	}
+	return (0x000000ff & (int) inb(UART1_BASE));
+}
+
+
+void kgdb_interruptible (int yes)
+{
+	return;
+}
+
+#else	/* ! (CONFIG_KGDB_SER_INDEX & 2) */
+
+void kgdb_serial_init (void)
+{
+	serial_printf ("[on serial] ");
+}
+
+void putDebugChar (int c)
+{
+	serial_putc (c);
+}
+
+void putDebugStr (const char *str)
+{
+	serial_puts (str);
+}
+
+int getDebugChar (void)
+{
+	return serial_getc ();
+}
+
+void kgdb_interruptible (int yes)
+{
+	return;
+}
+#endif	/* (CONFIG_KGDB_SER_INDEX & 2) */
+#endif	/* CFG_CMD_KGDB */
+

+ 198 - 0
cpu/i386/start.S

@@ -0,0 +1,198 @@
+/*
+ *  U-boot - i386 Startup Code 
+ *
+ *  Copyright (c) 2002	Omicron Ceti AB, Daniel Engström <denaiel@omicron.se>
+ *
+ * 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 <config.h>
+#include <version.h>
+
+	
+.section .text
+.code32
+.globl _start
+.type _start, @function	
+.globl _i386boot_start
+_i386boot_start:
+_start:		
+        movl    $0x18,%eax         	/* Load our segement registes, the
+                                         * gdt have already been loaded by start16.S */
+        movw    %ax,%fs
+	movw	%ax,%ds
+        movw    %ax,%gs
+        movw    %ax,%es
+        movw    %ax,%ss
+	
+	/* We call a few functions in the board support package
+	 * since we have no stack yet we'll have to use %ebp
+	 * to store the return address */
+	
+	/* Early platform init (setup gpio, etc ) */
+	mov     $early_board_init_ret, %ebp
+	jmp	early_board_init
+early_board_init_ret:
+	
+	/* The __port80 entry-point should be usabe by now */
+	/* so we try to indicate progress */
+	movw	$0x01, %ax    
+	movl	$.progress0, %ebp
+	jmp	__show_boot_progress
+.progress0:  	
+
+	/* size memory */
+	mov	$mem_init_ret, %ebp
+	jmp     mem_init		
+mem_init_ret:
+	
+	/* check ammount of configured memory 
+	 * (we need atleast bss start+bss size+stack size) */		
+	movl	$_i386boot_bss_start, %ecx        /* BSS start */
+	addl	$_i386boot_bss_size, %ecx         /* BSS size */	
+	addl	$CFG_STACK_SIZE, %ecx
+	cmpl	%ecx, %eax 
+	jae	mem_ok
+	
+	/* indicate (lack of) progress */
+	movw	$0x81, %ax    
+	movl	$.progress0a, %ebp
+	jmp	__show_boot_progress
+.progress0a:  	
+	jmp 	die
+mem_ok:	
+
+	/* indicate progress */
+	movw	$0x02, %ax    
+	movl	$.progress1, %ebp
+	jmp	__show_boot_progress
+.progress1:  	
+
+	/* create a stack after the bss */
+        movl    $_i386boot_bss_start, %eax
+	addl	$_i386boot_bss_size, %eax
+	addl	$CFG_STACK_SIZE, %eax
+        movl    %eax, %esp
+	
+	pushl	$0
+	popl	%eax
+	cmpl	$0, %eax
+	jne	no_stack
+	push	$0x55aa55aa
+	popl	%ebx
+	cmpl	$0x55aa55aa, %ebx
+	je	stack_ok
+
+no_stack:
+	/* indicate (lack of) progress */
+	movw	$0x82, %ax    
+	movl	$.progress1a, %ebp
+	jmp	__show_boot_progress
+.progress1a:  	
+	jmp die
+	
+	
+stack_ok:	
+	/* indicate progress */
+	movw	$0x03, %ax    
+	movl	$.progress2, %ebp
+	jmp	__show_boot_progress
+.progress2:  	
+
+	/* copy data section to ram, size must be 4-byte aligned */
+	movl	$_i386boot_romdata_dest, %edi	  /* destination address */
+ 	movl	$_i386boot_romdata_start, %esi	  /* source address */
+	movl	$_i386boot_romdata_size, %ecx     /* number of bytes to copy */
+	movl	%ecx, %eax
+	andl	$3, %eax
+	jnz	data_fail
+	
+	shrl	$2, %ecx	                  /* copy 4 byte each time */
+	cld	 
+	cmpl	$0, %ecx
+	je	data_ok	
+data_segment:	
+	movsl		
+	loop	data_segment
+	jmp	data_ok
+data_fail:
+	/* indicate (lack of) progress */
+	movw	$0x83, %ax    
+	movl	$.progress2a, %ebp
+	jmp	__show_boot_progress
+.progress2a:  	
+	jmp 	die
+
+data_ok:	
+
+	/* indicate progress */
+	movw	$0x04, %ax    
+	movl	$.progress3, %ebp
+	jmp	__show_boot_progress
+.progress3:  	
+
+	/* clear bss section in ram, size must be 4-byte aligned  */
+	movl	$_i386boot_bss_start, %eax        /* BSS start */
+	movl	$_i386boot_bss_size, %ecx         /* BSS size */	
+	movl	%ecx, %eax
+	andl	$3, %eax
+	jnz	bss_fail
+	shrl	$2, %ecx	                  /* clear 4 byte each time */
+	cld		      
+	cmpl	$0, %ecx
+	je	bss_ok	
+bss:	
+	movl	$0, (%edi)
+	add	$4, %edi			
+	loop	bss
+	jmp 	bss_ok
+
+bss_fail:
+	/* indicate (lack of) progress */
+	movw	$0x84, %ax    
+	movl	$.progress3a, %ebp
+	jmp	__show_boot_progress
+.progress3a:  	
+	jmp 	die
+
+bss_ok:	
+
+	wbinvd	 
+
+
+	/* indicate progress */
+	movw	$0x05, %ax    
+	movl	$.progress4, %ebp
+	jmp	__show_boot_progress
+.progress4:
+
+	call	start_i386boot  /* Enter, U-boot! */
+
+	/* indicate (lack of) progress */
+	movw	$0x85, %ax    
+	movl	$.progress4a, %ebp
+	jmp	__show_boot_progress
+.progress4a:
+
+die:	hlt
+	jmp	die
+	hlt                     
+
+

+ 112 - 0
cpu/i386/start16.S

@@ -0,0 +1,112 @@
+/*
+ *  U-boot - i386 Startup Code 
+ *
+ *  Copyright (c) 2002	Omicron Ceti AB, Daniel Engström <denaiel@omicron.se>
+ *
+ * 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
+ */
+
+
+#define BOOT_SEG	0xffff0000	/* linear segment of boot code */
+#define a32		.byte 0x67;
+#define o32		.byte 0x66;
+
+.section .start16, "ax"
+.code16
+.globl start16
+start16: 
+	/* First we let the BSP do some early initialization
+	 * this code have to map the flash to its final position
+	 */
+	mov	$board_init16_ret, %bp
+	jmp	board_init16
+board_init16_ret:	
+	
+	/* Turn of cache (this might require a 486-class CPU) */
+        movl    %cr0, %eax
+        orl     $060000000,%eax
+        movl    %eax, %cr0
+        wbinvd  		     
+	
+	/* load the descriptor tables */
+o32 cs	lidt	idt_ptr
+o32 cs	lgdt    gdt_ptr		 
+
+
+	/* Now, we enter protected mode */
+        movl    %cr0, %eax               
+        orl     $1,%eax                  
+        movl    %eax, %cr0            
+	
+	/* Flush the prefetch queue */
+        jmp     ff        
+ff:
+
+	/* Finally jump to the 32bit initialization code */
+	movw	$code32start, %ax 
+        movw    %ax,%bp
+o32 cs	ljmp	*(%bp)
+
+	/* 48-bit far pointer */
+code32start:
+	.long	_start                          /* offset */
+	.word	0x10                            /* segment */
+
+idt_ptr:
+	.word	0				/* limit */
+	.long	0		       		/* base */
+	
+gdt_ptr:
+	.word	0x30			        /* limit (48 bytes = 6 GDT entries) */
+	.long	BOOT_SEG + gdt	        	/* base */
+
+	/* The GDT table ... 
+	 *
+	 *       Selector	Type 
+	 * 	 0x00		NULL
+	 * 	 0x08		Unused
+	 *	 0x10		32bit code 
+	 *	 0x18		32bit data/stack
+	 *	 0x20		16bit code
+	 *	 0x28	 	16bit data/stack
+	 */
+
+gdt:
+	.word	0, 0, 0, 0			/* NULL  */
+	.word	0, 0, 0, 0			/* unused */
+
+	.word	0xFFFF				/* 4Gb - (0x100000*0x1000 = 4Gb) */
+	.word	0				/* base address = 0 */
+	.word	0x9B00				/* code read/exec */
+	.word	0x00CF				/* granularity = 4096, 386 (+5th nibble of limit) */
+
+	.word	0xFFFF				/* 4Gb - (0x100000*0x1000 = 4Gb) */
+	.word	0x0				/* base address = 0 */
+	.word	0x9300				/* data read/write */
+	.word	0x00CF				/* granularity = 4096, 386 (+5th nibble of limit) */
+						
+	.word	0xFFFF				/* 64kb */
+	.word	0				/* base address = 0 */
+	.word	0x9b00				/* data read/write */
+	.word	0x0010				/* granularity = 1  (+5th nibble of limit) */
+	
+	.word	0xFFFF				/* 64kb */
+	.word	0				/* base address = 0 */
+	.word	0x9300				/* data read/write */
+	.word	0x0010				/* granularity = 1 (+5th nibble of limit) */

+ 211 - 0
cpu/i386/timer.c

@@ -0,0 +1,211 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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 <asm/io.h>
+#include <asm/i8254.h>
+#include <asm/ibmpc.h>
+
+
+static volatile unsigned long system_ticks;
+static int timer_init_done =0;
+
+static void timer_isr(void *unused)
+{
+	system_ticks++;
+}
+
+unsigned long get_system_ticks(void)
+{
+	return system_ticks;
+}
+
+#define TIMER0_VALUE 0x04aa /* 1kHz 1.9318MHz / 1000 */
+#define TIMER2_VALUE 0x0a8e /* 440Hz */
+
+int timer_init(void)
+{
+	system_ticks = 0;
+	
+	irq_install_handler(0, timer_isr, NULL);
+	
+	/* initialize timer 0 and 2 
+	 * 
+	 * Timer 0 is used to increment system_tick 1000 times/sec
+	 * Timer 1 was used for DRAM refresh in early PC's
+	 * Timer 2 is used to drive the speaker
+	 * (to stasrt a beep: write 3 to port 0x61,
+	 * to stop it again: write 0)
+	 */
+		
+        outb(PIT_CMD_CTR0|PIT_CMD_BOTH|PIT_CMD_MODE2, PIT_BASE + PIT_COMMAND);
+	outb(TIMER0_VALUE&0xff, PIT_BASE + PIT_T0);
+	outb(TIMER0_VALUE>>8, PIT_BASE + PIT_T0);
+
+        outb(PIT_CMD_CTR2|PIT_CMD_BOTH|PIT_CMD_MODE3, PIT_BASE + PIT_COMMAND);
+	outb(TIMER2_VALUE&0xff, PIT_BASE + PIT_T2);
+	outb(TIMER2_VALUE>>8, PIT_BASE + PIT_T2);
+
+	timer_init_done = 1;
+	
+	return 0;
+}
+
+
+#ifdef CFG_TIMER_GENERIC
+
+/* the unit for these is CFG_HZ */
+
+/* FixMe: implement these */
+void reset_timer (void)
+{
+	system_ticks = 0;
+}
+
+ulong get_timer (ulong base)
+{
+	return (system_ticks - base);
+}
+
+void set_timer (ulong t)	
+{
+	system_ticks = t;
+}
+
+static u16 read_pit(void)
+{
+	u8 low;
+	outb(PIT_CMD_LATCH, PIT_BASE + PIT_COMMAND);
+	low = inb(PIT_BASE + PIT_T0);
+	return ((inb(PIT_BASE + PIT_T0) << 8) | low);
+}
+
+/* this is not very exact */
+void udelay (unsigned long usec)
+{	
+	int counter;
+	int wraps;
+	
+	if (!timer_init_done) {
+		return;
+	}
+	counter = read_pit();
+	wraps = usec/1000;
+	usec = usec%1000;
+	
+	usec*=1194;
+	usec/=1000;
+	usec+=counter; 
+	if (usec > 1194) {
+		usec-=1194;
+		wraps++;
+	}
+
+	while (1) {
+		int new_count = read_pit();
+		
+		if (((new_count < usec) && !wraps) || wraps < 0) {
+			break;
+		}
+		
+		if (new_count > counter) {
+			wraps--;
+		}
+		counter = new_count;
+	}
+	
+}
+
+#if 0
+/* this is a version with debug output */
+void _udelay (unsigned long usec)
+{	
+	int counter;
+	int wraps;
+	
+	int usec1, usec2, usec3;
+	int wraps1, wraps2, wraps3, wraps4;
+	int ctr1, ctr2, ctr3, nct1, nct2;
+	int i;
+	usec1=usec;
+	if (!timer_init_done) {
+		return;
+	}
+	counter = read_pit();
+	ctr1 = counter;
+	wraps = usec/1000;
+	usec = usec%1000;
+	
+	usec2 = usec;
+	wraps1 = wraps;
+	
+	usec*=1194;
+	usec/=1000;
+	usec+=counter; 
+	if (usec > 1194) {
+		usec-=1194;
+		wraps++;
+	}
+
+	usec3 = usec;
+	wraps2 = wraps;
+	
+	ctr2 = wraps3 = nct1 = 4711;
+	ctr3 = wraps4 = nct2 = 4711;
+	i=0;
+	while (1) {
+		int new_count = read_pit();
+		i++;
+		if ((new_count < usec && !wraps) || wraps < 0) {
+			break;
+		}
+		
+		if (new_count > counter) {
+			wraps--;
+		}
+		if (ctr2==4711) {
+			ctr2 = counter;
+			wraps3 = wraps;
+			nct1 = new_count;
+		} else {
+			ctr3 = counter;
+			wraps4 = wraps;
+			nct2 = new_count;
+		}
+		
+		counter = new_count;
+	}
+	
+	printf("udelay(%d)\n", usec1);
+	printf("counter %d\n", ctr1);
+	printf("1: wraps %d, usec %d\n", wraps1, usec2);
+	printf("2: wraps %d, usec %d\n", wraps2, usec3);
+	printf("new_count[0] %d counter %d wraps %d\n", nct1, ctr2, wraps3);
+	printf("new_count[%d] %d counter %d wraps %d\n", i, nct2, ctr3, wraps4);
+
+	printf("%d %d %d %d %d\n",
+	       read_pit(), read_pit(), read_pit(),
+	       read_pit(), read_pit());
+}
+#endif
+#endif

+ 74 - 0
doc/README-i386

@@ -0,0 +1,74 @@
+This is my attempt to port PPCBoot to the i386 platform. This
+work was sponsored by my emplyer, Omicron Ceti AB. http://www.omicron.se
+
+It is currently capable of booting a linux bzImage from flash on
+the AMD SC520 CDP platform.
+
+It was originally based on PPCBoot taken from the CVS October 28 2002.  
+
+To compile:
+
+1) Unpack the source tree, either from the complete tarball or
+   from the virgin snapshot + the patch
+   
+2) Configure the source
+   $ make sc520_cdp_comfig
+   $ make
+   
+To use this code on the CDP:
+1) Make a suitable kernel, I used 2.4.19 with the mtd-support updated
+   from the MTD CVS and a patch to allow root=/dev/mtdblock1 which I
+   included at the end of this file. 
+   The following options in the MTD section might be useful:
+   
+   CONFIG_MTD_PHYSMAP=y
+   CONFIG_MTD_PHYSMAP_START=38100000
+   CONFIG_MTD_PHYSMAP_LEN=7a0000
+   CONFIG_MTD_PHYSMAP_BUSWIDTH=2
+
+
+2) Program it in to the CDP flashbank with remon
+   ppcboot.bin should be programmed att offset 0x7e000 and the kernel at
+   offset 0. If you want to use a jffs2 root file system (not included here), 
+   it should be  programmed to offset 0x100000.
+   
+   remon> z
+   remon> yi
+   remon> ns ppcboot.bin 7e0000
+   remon> ns bzImage 0
+   remon> ns image.jffs2 100000
+
+3) Connect a terminal to the 25pin serial port at 9600bps, and start the CDP.
+   
+   remon> z
+   remon> g
+
+4) PPCboot should output some message and a prompt on the terminal, to
+   start the kernel issue the following command:
+   
+   BOOT> bootm
+   
+5) The kernel should boot, and mount the root filesystem if present.
+
+We hope you find this stuff useful
+Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+
+
+
+--- linux-2.4.19-orig/init/do_mounts.c	Sat Aug  3 02:39:46 2002
++++ linux-2.4.19/init/do_mounts.c	Mon Sep 23 16:21:33 2002
+@@ -224,6 +224,14 @@
+ 	{ "ftlc", 0x2c10 },
+ 	{ "ftld", 0x2c18 },
+ 	{ "mtdblock", 0x1f00 },
++	{ "mtdblock0", 0x1f00 },
++	{ "mtdblock1", 0x1f01 },
++	{ "mtdblock2", 0x1f02 },
++	{ "mtdblock3", 0x1f03 },
++	{ "mtdblock4", 0x1f04 },
++	{ "mtdblock5", 0x1f05 },
++	{ "mtdblock6", 0x1f06 },
++	{ "mtdblock7", 0x1f07 },
+ 	{ NULL, 0 }
+ };
+ 

+ 39 - 0
doc/TODO-i386

@@ -0,0 +1,39 @@
+i386 port missing features:
+* i386 cleaness (wbinvld is 486+ ... )
+* Pentium TSC timer/udelay
+* setup the BIOS data area and BIOS equipment word to reflect machine config. 
+* Make reset work (from Linux and from the boot prompt)
+* DMA, FDC, RTC, KBC initialization
+* video card support (call BIOS to initialize, use helper routrine in BSP to shadow 
+  video rom if on pci) and PC keyboard
+* split of part of cpu/i386/interrupt.c to cpu/i385/entry.c?
+* re-entry of protected mode from real mode, should be added to realmode_switch.S 
+  (and used by INT 10h and INT 16h handlers for console I/O during early
+   linux boot...) 
+* missing functions in lib_i386 and cpu/i386
+* speaker beep interface
+
+i386 port bugs:
+* IDE does not work 
+
+SC520 missing features:
+* Watchdog
+* SC520 timer/udelay
+* SC520 3rd PIC
+* SC520 ICE serial
+* SC520 MMCR reset 
+
+SC520 CDP board support missing features:
+* Synchronius serial port and seriel EEPROM
+* environment in SEEP
+* environment in flash
+* environment in sram
+* status LED ?
+* flash driver
+
+SC520 CDP board support bugs:
+* 0x680 LEDS dos not work for me
+* is it possible to make both the internal serial ports and the 
+  ports on the sio work at the same time?
+* ali sio cio lines?
+* On-borad ethernet does not work from Linux

+ 3 - 3
drivers/pcnet.c

@@ -288,8 +288,8 @@ static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr)
 	unsigned int val;
 	val = pcnet_read_csr(dev, i+12) & 0x0ffff;
 	/* There may be endianness issues here. */
-	dev->dev_addr[2*i] = val & 0x0ff;
-	dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff;
+	dev->enetaddr[2*i  ] =  val       & 0x0ff;
+	dev->enetaddr[2*i+1] = (val >> 8) & 0x0ff;
     }
 #endif /* PCNET_HAS_PROM */
 
@@ -349,7 +349,7 @@ static int pcnet_init(struct eth_device* dev, bd_t *bis)
 	lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]);
 	lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ);
 	lp->rx_ring[i].status = cpu_to_le16(0x8000);
-	DEBUG1("Rx%d: base=0x%x buf_length=0x%x status=0x%x\n",
+	DEBUG1("Rx%d: base=0x%x buf_length=0x%hx status=0x%hx\n",
 	       i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length,
 	       lp->rx_ring[i].status);
     }

+ 14 - 0
examples/syscall.S

@@ -38,12 +38,26 @@ mon_free:
 	sub     fp, ip, #4
 	ldmea   fp, {fp, sp, pc}
 #else /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+#ifdef CONFIG_I386 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+#define SYMBOL_NAME(X) 	X
+#define SYMBOL_NAME_LABEL(X) 	X##:
+	
+#define SYSCALL(name,n) \
+	.globl SYMBOL_NAME(name) ; \
+SYMBOL_NAME_LABEL(name)     		 ; \
+	ret
+
+#endif	/* CONFIG_I386 */
+
+#ifdef CONFIG_PPC
 #define SYSCALL(name,n) \
 	.globl name		; \
 name:				; \
 	li r0,n			; \
 	sc			; \
 	blr
+#endif	/* CONFIG_PPC */
 
 	.text
 

+ 1 - 1
fs/Makefile

@@ -22,7 +22,7 @@
 #
 #
 
-SUBDIRS	:= jffs2
+SUBDIRS	:= jffs2 fdos
 
 .depend all:
 	@for dir in $(SUBDIRS) ; do \

+ 49 - 0
fs/fdos/Makefile

@@ -0,0 +1,49 @@
+#
+# (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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= libfdos.a
+
+AOBJS	=
+COBJS	= fat.o vfat.o dev.o fdos.o fs.o subdir.o 
+OBJS	= $(AOBJS) $(COBJS)
+
+#CPPFLAGS +=
+
+all:	$(LIB) $(AOBJS)
+
+$(LIB):	.depend $(OBJS)
+	$(AR) crv $@ $(OBJS)
+
+
+#########################################################################
+
+.depend:	Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c)
+		$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################

+ 195 - 0
fs/fdos/dev.c

@@ -0,0 +1,195 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <config.h>
+
+#include "dos.h"
+#include "fdos.h"
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+
+#define NB_HEADS        2
+#define NB_TRACKS       80
+#define NB_SECTORS      18
+
+
+static int lastwhere;
+
+/*-----------------------------------------------------------------------------
+ * dev_open -- 
+ *-----------------------------------------------------------------------------
+ */
+int dev_open (void)
+{
+    lastwhere = 0;
+    return (0);
+}
+
+/*-----------------------------------------------------------------------------
+ * dev_read -- len and where are sectors number
+ *-----------------------------------------------------------------------------
+ */
+int dev_read (void *buffer, int where, int len)
+{
+    PRINTF ("dev_read (len = %d, where = %d)\n", len, where);
+
+    /* Si on ne desire pas lire a la position courante, il faut un seek      */
+    if (where != lastwhere) {
+        if (!fdc_fdos_seek (where)) {
+            PRINTF ("seek error in dev_read");
+            lastwhere = -1;
+            return (-1);
+        }
+    }
+    
+    if (!fdc_fdos_read (buffer, len)) {
+        PRINTF ("read error\n");
+        lastwhere = -1;
+        return (-1);
+    }
+    lastwhere = where + len;
+    return (0);
+}
+/*-----------------------------------------------------------------------------
+ * check_dev -- verify the diskette format
+ *-----------------------------------------------------------------------------
+ */
+int check_dev (BootSector_t *boot, Fs_t *fs)
+{
+    unsigned int heads, sectors, tracks;
+    int BootP, Infp0, InfpX, InfTm;
+    int sect_per_track;
+
+    /* Display Boot header                                                   */
+    PRINTF ("Jump to boot code                  0x%02x 0x%02x 0x%02x\n",
+            boot -> jump [0], boot -> jump [1], boot -> jump[2]);
+    PRINTF ("OEM name & version                 '%*.*s'\n",
+            BANNER_LG, BANNER_LG, boot -> banner );
+    PRINTF ("Bytes per sector hopefully 512     %d\n",
+            __le16_to_cpu (boot -> secsiz));
+    PRINTF ("Cluster size in sectors            %d\n",
+            boot -> clsiz);
+    PRINTF ("Number of reserved (boot) sectors  %d\n",
+            __le16_to_cpu (boot -> nrsvsect));
+    PRINTF ("Number of FAT tables hopefully 2   %d\n",
+            boot -> nfat);
+    PRINTF ("Number of directory slots          %d\n",
+            __le16_to_cpu (boot -> dirents));
+    PRINTF ("Total sectors on disk              %d\n",
+            __le16_to_cpu (boot -> psect));
+    PRINTF ("Media descriptor=first byte of FAT %d\n",
+            boot -> descr);
+    PRINTF ("Sectors in FAT                     %d\n",
+            __le16_to_cpu (boot -> fatlen));
+    PRINTF ("Sectors/track                      %d\n",
+            __le16_to_cpu (boot -> nsect));
+    PRINTF ("Heads                              %d\n",
+            __le16_to_cpu (boot -> nheads));
+    PRINTF ("number of hidden sectors           %d\n",
+            __le32_to_cpu (boot -> nhs));
+    PRINTF ("big total sectors                  %d\n",
+            __le32_to_cpu (boot -> bigsect));
+    PRINTF ("physical drive ?                   %d\n",
+            boot -> physdrive);
+    PRINTF ("reserved                           %d\n",
+            boot -> reserved);
+    PRINTF ("dos > 4.0 diskette                 %d\n",
+            boot -> dos4);
+    PRINTF ("serial number                      %d\n",
+            __le32_to_cpu (boot -> serial));
+    PRINTF ("disk label                         %*.*s\n",
+            LABEL_LG, LABEL_LG, boot -> label);
+    PRINTF ("FAT type                           %8.8s\n",
+            boot -> fat_type);
+    PRINTF ("reserved by 2M                     %d\n",
+            boot -> res_2m);
+    PRINTF ("2M checksum (not used)             %d\n",
+            boot -> CheckSum);
+    PRINTF ("2MF format version                 %d\n",
+            boot -> fmt_2mf);
+    PRINTF ("1 if write track after format      %d\n",
+            boot -> wt);
+    PRINTF ("data transfer rate on track 0      %d\n",
+            boot -> rate_0);
+    PRINTF ("data transfer rate on track<>0     %d\n",
+            boot -> rate_any);
+    PRINTF ("offset to boot program             %d\n",
+            __le16_to_cpu (boot -> BootP));
+    PRINTF ("T1: information for track 0        %d\n",
+            __le16_to_cpu (boot -> Infp0));
+    PRINTF ("T2: information for track<>0       %d\n",
+            __le16_to_cpu (boot -> InfpX));
+    PRINTF ("T3: track sectors size table       %d\n",
+            __le16_to_cpu (boot -> InfTm));
+    PRINTF ("Format date                        0x%04x\n",
+            __le16_to_cpu (boot -> DateF));
+    PRINTF ("Format time                        0x%04x\n",
+            __le16_to_cpu (boot -> TimeF));
+    
+
+    /* informations are extracted from boot sector                           */
+    heads = __le16_to_cpu (boot -> nheads);
+    sectors = __le16_to_cpu (boot -> nsect);
+    fs -> tot_sectors = __le32_to_cpu (boot -> bigsect);
+    if (__le16_to_cpu (boot -> psect) != 0) {
+        fs -> tot_sectors = __le16_to_cpu (boot -> psect);
+    }
+    
+    sect_per_track = heads * sectors;
+    tracks = (fs -> tot_sectors + sect_per_track - 1) / sect_per_track;
+    
+    BootP = __le16_to_cpu (boot -> BootP);
+    Infp0 = __le16_to_cpu (boot -> Infp0);
+    InfpX = __le16_to_cpu (boot -> InfpX);
+    InfTm = __le16_to_cpu (boot -> InfTm);
+    
+    if (boot -> dos4 == EXTENDED_BOOT &&
+        strncmp( boot->banner,"2M", 2 ) == 0 &&
+        BootP < SZ_STD_SECTOR &&
+        Infp0 < SZ_STD_SECTOR &&
+        InfpX < SZ_STD_SECTOR &&
+        InfTm < SZ_STD_SECTOR &&
+        BootP >= InfTm + 2 &&
+        InfTm >= InfpX &&
+        InfpX >= Infp0 && 
+        Infp0 >= 76 ) {
+
+        return (-1);
+    }
+
+    if (heads != NB_HEADS ||
+        tracks != NB_TRACKS ||
+        sectors != NB_SECTORS ||
+        __le16_to_cpu (boot -> secsiz) != SZ_STD_SECTOR ||
+        fs -> tot_sectors == 0 ||
+        (fs -> tot_sectors % sectors) != 0) {
+        return (-1);
+    }
+    
+    return (0);
+}
+
+
+#endif

+ 177 - 0
fs/fdos/dos.h

@@ -0,0 +1,177 @@
+/*
+ * (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
+ */
+
+#ifndef _DOS_H_
+#define _DOS_H_
+
+/* Definitions for Dos diskettes                                             */
+
+/* General definitions                                                       */
+#define SZ_STD_SECTOR   512             /* Standard sector size              */
+#define MDIR_SIZE	32		/* Direntry size                     */
+#define FAT_BITS        12              /* Diskette use 12 bits fat          */
+
+#define MAX_PATH	128		/* Max size of the MSDOS PATH        */
+#define MAX_DIR_SECS	64		/* Taille max d'un repertoire (en    */
+                                        /* secteurs)                         */
+/* Misc. definitions                                                         */
+#define DELMARK         '\xe5'
+#define EXTENDED_BOOT   (0x29)
+#define MEDIA_STD       (0xf0)
+#define JUMP_0_1        (0xe9)
+#define JUMP_0_2        (0xeb)
+
+/* Boot size is 256 bytes, but we need to read almost a sector, then
+   assume bootsize is 512                                                    */
+#define BOOTSIZE        512
+
+/* Fat definitions for 12 bits fat                                           */
+#define FAT12_MAX_NB    4086
+#define FAT12_LAST      0x0ff6
+#define FAT12_END       0x0fff
+
+/* file attributes                                                           */
+#define ATTR_READONLY           0x01
+#define ATTR_HIDDEN             0x02
+#define ATTR_SYSTEM             0x04
+#define ATTR_VOLUME             0x08
+#define ATTR_DIRECTORY          0x10
+#define ATTR_ARCHIVE            0x20
+#define ATTR_VSE                0x0f
+
+/* Name format                                                               */
+#define EXTCASE                 0x10
+#define BASECASE                0x8
+
+/* Definition of the boot sector                                             */
+#define BANNER_LG               8
+#define LABEL_LG                11
+
+typedef struct bootsector
+{
+    unsigned char jump [3];	/* 0  Jump to boot code                      */
+    char banner [BANNER_LG];	/* 3  OEM name & version                     */
+    unsigned short secsiz;	/* 11 Bytes per sector hopefully 512         */
+    unsigned char clsiz;	/* 13 Cluster size in sectors                */
+    unsigned short nrsvsect;	/* 14 Number of reserved (boot) sectors      */
+    unsigned char nfat;		/* 16 Number of FAT tables hopefully 2       */
+    unsigned short dirents;	/* 17 Number of directory slots              */
+    unsigned short psect;	/* 19 Total sectors on disk                  */
+    unsigned char descr;	/* 21 Media descriptor=first byte of FAT     */
+    unsigned short fatlen;	/* 22 Sectors in FAT                         */
+    unsigned short nsect;	/* 24 Sectors/track                          */
+    unsigned short nheads;	/* 26 Heads                                  */
+    unsigned int nhs;	        /* 28 number of hidden sectors               */
+    unsigned int bigsect;	/* 32 big total sectors                      */
+    unsigned char physdrive;	/* 36 physical drive ?                       */
+    unsigned char reserved;	/* 37 reserved                               */
+    unsigned char dos4;		/* 38 dos > 4.0 diskette                     */
+    unsigned int serial;        /* 39 serial number                          */
+    char label [LABEL_LG];	/* 43 disk label                             */
+    char fat_type [8];		/* 54 FAT type                               */
+    unsigned char res_2m;	/* 62 reserved by 2M                         */
+    unsigned char CheckSum;	/* 63 2M checksum (not used)                 */
+    unsigned char fmt_2mf;	/* 64 2MF format version                     */
+    unsigned char wt;		/* 65 1 if write track after format          */
+    unsigned char rate_0;	/* 66 data transfer rate on track 0          */
+    unsigned char rate_any;	/* 67 data transfer rate on track<>0         */
+    unsigned short BootP;	/* 68 offset to boot program                 */
+    unsigned short Infp0;	/* 70 T1: information for track 0            */
+    unsigned short InfpX;	/* 72 T2: information for track<>0           */
+    unsigned short InfTm;	/* 74 T3: track sectors size table           */
+    unsigned short DateF;	/* 76 Format date                            */
+    unsigned short TimeF;	/* 78 Format time                            */
+    unsigned char junk [BOOTSIZE - 80];	/* 80 remaining data                 */
+} __attribute__ ((packed)) BootSector_t;
+
+/* Structure d'une entree de repertoire                                      */
+typedef struct directory {
+    char name [8];		/* file name                                 */
+    char ext [3];		/* file extension                            */
+    unsigned char attr;		/* attribute byte                            */
+    unsigned char Case;		/* case of short filename                    */
+    unsigned char reserved [9];	/* ??                                        */
+    unsigned char time [2];	/* time stamp                                */
+    unsigned char date [2];	/* date stamp                                */
+    unsigned short start;	/* starting cluster number                   */
+    unsigned int size;	        /* size of the file                          */
+} __attribute__ ((packed))  Directory_t;
+
+
+
+#define MAX_VFAT_SUBENTRIES 20
+#define VSE_NAMELEN 13
+
+#define VSE1SIZE 5
+#define VSE2SIZE 6
+#define VSE3SIZE 2
+
+#define VBUFSIZE ((MAX_VFAT_SUBENTRIES * VSE_NAMELEN) + 1)
+
+#define MAX_VNAMELEN (255)
+
+#define VSE_PRESENT 0x01
+#define VSE_LAST 0x40
+#define VSE_MASK 0x1f
+
+/* Flag used by vfat_lookup                                                  */
+#define DO_OPEN         1
+#define ACCEPT_PLAIN    0x20
+#define ACCEPT_DIR      0x10
+#define ACCEPT_LABEL    0x08
+#define SINGLE          2
+#define MATCH_ANY       0x40
+
+struct vfat_subentry {
+    unsigned char id;		        /* VSE_LAST pour la fin, VSE_MASK    */
+                                        /* pour un VSE                       */
+    char text1 [VSE1SIZE * 2];          /* Caracteres encodes sur 16 bits    */
+    unsigned char attribute;	        /* 0x0f pour les VFAT                */
+    unsigned char hash1;		/* toujours 0                        */
+    unsigned char sum;		        /* Checksum du nom court             */
+    char text2 [VSE2SIZE * 2];          /* Caracteres encodes sur 16 bits    */
+    unsigned char sector_l;             /* 0 pour les VFAT                   */
+    unsigned char sector_u;		/* 0 pour les VFAT                   */
+    char text3 [VSE3SIZE * 2];          /* Caracteres encodes sur 16 bits    */
+} __attribute__ ((packed)) ;
+
+struct vfat_state {
+    char name [VBUFSIZE];
+    int status;             /* is now a bit map of 32 bits                   */
+    int subentries;
+    unsigned char sum;      /* no need to remember the sum for each          */
+                            /*   entry, it is the same anyways               */
+} __attribute__ ((packed)) ;
+
+/* Conversion macros                                                         */
+#define	DOS_YEAR(dir) (((dir)->date[1] >> 1) + 1980)
+#define	DOS_MONTH(dir) (((((dir)->date[1]&0x1) << 3) + ((dir)->date[0] >> 5)))
+#define	DOS_DAY(dir) ((dir)->date[0] & 0x1f)
+#define	DOS_HOUR(dir) ((dir)->time[1] >> 3)
+#define	DOS_MINUTE(dir) (((((dir)->time[1]&0x7) << 3) + ((dir)->time[0] >> 5)))
+#define	DOS_SEC(dir) (((dir)->time[0] & 0x1f) * 2)
+
+
+#endif
+

+ 145 - 0
fs/fdos/fat.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
+ */
+
+#include <common.h>
+#include <config.h>
+#include <malloc.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+
+#include "dos.h"
+#include "fdos.h"
+
+
+/*-----------------------------------------------------------------------------
+ * fat_decode -- 
+ *-----------------------------------------------------------------------------
+ */
+unsigned int fat_decode (Fs_t *fs, unsigned int num)
+{
+    unsigned int start = num * 3 / 2;
+    unsigned char *address = fs -> fat_buf + start;
+    
+    if (num < 2 || start + 1 > (fs -> fat_len * SZ_STD_SECTOR))
+        return 1;
+    
+    if (num & 1)
+        return ((address [1] & 0xff) << 4) | ((address [0] & 0xf0 ) >> 4);
+    else
+        return ((address [1] & 0xf) << 8) | (address [0] & 0xff );
+}
+/*-----------------------------------------------------------------------------
+ * check_fat -- 
+ *-----------------------------------------------------------------------------
+ */
+static int check_fat (Fs_t *fs)
+{
+    int i, f;
+
+    /* Cluster verification                                                  */
+    for (i = 3 ; i < fs -> num_clus; i++){
+        f = fat_decode (fs, i);
+        if (f < FAT12_LAST && f > fs -> num_clus){
+            /* Wrong cluster number detected                                 */
+            return (-1);
+        }
+    }
+    return (0);
+}
+/*-----------------------------------------------------------------------------
+ * read_one_fat -- 
+ *-----------------------------------------------------------------------------
+ */
+static int read_one_fat (BootSector_t *boot, Fs_t *fs, int nfat)
+{
+    if (dev_read (fs -> fat_buf,
+                  (fs -> fat_start + nfat * fs -> fat_len),
+                  fs -> fat_len) < 0) {
+        return (-1);
+    }
+
+    if (fs -> fat_buf [0] || fs -> fat_buf [1] || fs -> fat_buf [2]) {
+        if ((fs -> fat_buf [0] != boot -> descr &&
+             (fs -> fat_buf [0] != 0xf9 || boot -> descr != MEDIA_STD)) ||
+            fs -> fat_buf [0] < MEDIA_STD){
+            /* Unknown Media                                                 */
+            return (-1);
+        }
+        if (fs -> fat_buf [1] != 0xff || fs -> fat_buf [2] != 0xff){
+            /* FAT doesn't start with good values                            */
+            return (-1);
+        }
+    }
+
+    if (fs -> num_clus >= FAT12_MAX_NB) {
+        /* Too much clusters                                                 */
+        return (-1);
+    }
+
+    return check_fat (fs);
+}
+/*-----------------------------------------------------------------------------
+ * read_fat -- 
+ *-----------------------------------------------------------------------------
+ */
+int read_fat (BootSector_t *boot, Fs_t *fs)
+{
+    unsigned int buflen;
+    int i;
+
+    /* Allocate Fat Buffer                                                   */
+    buflen = fs -> fat_len * SZ_STD_SECTOR;
+    if (fs -> fat_buf) {
+        free (fs -> fat_buf);
+    }
+
+    if ((fs -> fat_buf = malloc (buflen)) == NULL) {
+        return (-1);
+    }
+
+    /* Try to read each Fat                                                  */
+    for (i = 0; i< fs -> nb_fat; i++){
+        if (read_one_fat (boot, fs, i) == 0) {
+            /* Fat is OK                                                     */
+            fs -> num_fat = i;
+            break;
+        }
+    }
+
+    if (i == fs -> nb_fat){
+        return (-1);
+    }
+    
+    if (fs -> fat_len > (((fs -> num_clus + 2) *
+                          (FAT_BITS / 4) -1 ) / 2 /
+                         SZ_STD_SECTOR + 1)) {
+        return (-1);
+    }
+    return (0);
+}
+
+
+ 
+
+#endif

+ 175 - 0
fs/fdos/fdos.c

@@ -0,0 +1,175 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <config.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+#include <malloc.h>
+#include "dos.h"
+#include "fdos.h"
+
+
+const char *month [] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+Fs_t    fs;
+File_t  file;
+
+/*-----------------------------------------------------------------------------
+ * dos_open -- 
+ *-----------------------------------------------------------------------------
+ */
+int dos_open(char *name)
+{
+    int lg;
+    int entry;
+    char *fname;
+    
+    /* We need to suppress the " char around the name                        */
+    if (name [0] == '"') {
+        name ++;
+    }
+    lg = strlen (name);
+    if (name [lg - 1] == '"') {
+        name [lg - 1] = '\0';
+    }
+
+    /* Open file system                                                      */
+    if (fs_init (&fs) < 0) {
+        return -1;
+    }
+
+    /* Init the file descriptor                                              */
+    file.name = name;
+    file.fs = &fs;
+    
+    /* find the subdirectory containing the file                             */
+    if (open_subdir (&file) < 0) {
+        return (-1);
+    }
+
+    fname = basename (name);
+
+    /* if we try to open root directory                                      */
+    if (*fname == '\0') {
+        file.file = file.subdir;
+        return (0);
+    }
+    
+    /* find the file in the subdir                                           */
+    entry = 0;
+    if (vfat_lookup (&file.subdir,
+                     file.fs,
+                     &file.file.dir,
+                     &entry,
+                     0,
+                     fname,
+                     ACCEPT_DIR | ACCEPT_PLAIN | SINGLE | DO_OPEN,
+                     0,
+                     &file.file) != 0) {
+        /* File not found                                                    */
+        printf ("File not found\n");
+        return (-1);
+    }
+
+    return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * dos_read -- 
+ *-----------------------------------------------------------------------------
+ */
+int dos_read (ulong addr)
+{
+    int read = 0, nb;
+
+    /* Try to boot a directory ?                                             */
+    if (file.file.dir.attr & (ATTR_DIRECTORY | ATTR_VOLUME)) {
+        printf ("Unable to boot %s !!\n", file.name);
+        return (-1);
+    }
+    while (read < file.file.FileSize) {
+        PRINTF ("read_file (%ld)\n", (file.file.FileSize - read));
+        nb = read_file (&fs,
+                        &file.file,
+                        (char *)addr + read,
+                        read,
+                        (file.file.FileSize - read));
+        PRINTF ("read_file -> %d\n", nb);
+        if (nb < 0) {
+            printf ("read error\n");
+            return (-1);
+        }
+        read += nb;
+    }
+    return (read);
+}
+/*-----------------------------------------------------------------------------
+ * dos_dir -- 
+ *-----------------------------------------------------------------------------
+ */
+int dos_dir (void)
+{
+    int entry;
+    Directory_t dir;
+    char *name;
+    
+    
+    if ((file.file.dir.attr & ATTR_DIRECTORY) == 0) {
+        printf ("%s: not a directory !!\n", file.name);
+        return (1);
+    }
+    entry = 0;
+    if ((name = malloc (MAX_VNAMELEN + 1)) == NULL) {
+        PRINTF ("Allcation error\n");
+        return (1);
+    }
+    
+    while (vfat_lookup (&file.file,
+                        file.fs,
+                        &dir,
+                        &entry,
+                        0,
+                        NULL,
+                        ACCEPT_DIR | ACCEPT_PLAIN | MATCH_ANY,
+                        name,
+                        NULL) == 0) {
+        /* Display file info                                                 */
+        printf ("%3.3s %9d %s %02d %04d %02d:%02d:%02d %s\n",
+                (dir.attr & ATTR_DIRECTORY) ? "dir" : "   ",
+                __le32_to_cpu (dir.size),
+                month [DOS_MONTH (&dir) - 1],
+                DOS_DAY (&dir),
+                DOS_YEAR (&dir),
+                DOS_HOUR (&dir),
+                DOS_MINUTE (&dir),
+                DOS_SEC (&dir),
+                name);
+        
+    }
+    free (name);
+    return (0);
+}
+
+#endif

+ 117 - 0
fs/fdos/fdos.h

@@ -0,0 +1,117 @@
+/*
+ * (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
+ */
+
+#ifndef _FDOS_H_
+#define _FDOS_H_
+
+
+#undef	FDOS_DEBUG
+
+#ifdef	FDOS_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Data structure describing media                                           */
+typedef struct fs
+{
+    unsigned long       tot_sectors;
+
+    int                 cluster_size;
+    int                 num_clus;
+    
+    int                 fat_start;
+    int                 fat_len;
+    int                 nb_fat;
+    int                 num_fat;
+    
+    int                 dir_start;
+    int                 dir_len;
+
+    unsigned char       *fat_buf;
+    
+} Fs_t;
+
+/* Data structure describing one file system slot                            */
+typedef struct slot {
+    int (*map) (struct fs *fs,
+                struct slot *file,
+                int where,
+                int *len);
+    unsigned long FileSize;
+
+    unsigned short int FirstAbsCluNr;
+    unsigned short int PreviousAbsCluNr;
+    unsigned short int PreviousRelCluNr;
+
+    Directory_t dir;
+} Slot_t;
+
+typedef struct file {
+    char                *name;
+    int                 Case;
+    Fs_t                *fs;
+    Slot_t              subdir;
+    Slot_t              file;
+} File_t;
+
+
+/* dev.c                                                                     */
+int dev_read (void *buffer, int where, int len);
+int dev_open (void);
+int check_dev (BootSector_t *boot, Fs_t *fs);
+
+/* fat.c                                                                     */
+unsigned int fat_decode (Fs_t *fs, unsigned int num);
+int read_fat (BootSector_t *boot, Fs_t *fs);
+
+/* vfat.c                                                                    */
+int vfat_lookup (Slot_t *dir,
+                 Fs_t *fs,
+                 Directory_t *dirent,
+                 int *entry,
+                 int *vfat_start,
+                 char *filename, 
+                 int flags,
+                 char *outname,
+                 Slot_t *file);
+
+/* subdir.c                                                                  */
+char *basename (char *name);
+int open_subdir (File_t *desc);
+int open_file (Slot_t *file, Directory_t *dir);
+int read_file (Fs_t *fs,
+               Slot_t *file,
+               char *buf,
+               int where,
+               int len);
+void init_subdir (void);
+
+/* fs.c                                                                      */
+int fs_init (Fs_t *fs);
+
+
+#endif
+

+ 120 - 0
fs/fdos/fs.c

@@ -0,0 +1,120 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <config.h>
+#include <malloc.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+
+#include "dos.h"
+#include "fdos.h"
+
+
+/*-----------------------------------------------------------------------------
+ * fill_fs -- Read info on file system 
+ *-----------------------------------------------------------------------------
+ */
+static int fill_fs (BootSector_t *boot, Fs_t *fs)
+{
+    
+    fs -> fat_start = __le16_to_cpu (boot -> nrsvsect);
+    fs -> fat_len = __le16_to_cpu (boot -> fatlen);
+    fs -> nb_fat = boot -> nfat;
+    
+    fs -> dir_start = fs -> fat_start + fs -> nb_fat * fs -> fat_len;
+    fs -> dir_len = __le16_to_cpu (boot -> dirents) * MDIR_SIZE / SZ_STD_SECTOR;
+    fs -> cluster_size = boot -> clsiz;
+    fs -> num_clus = (fs -> tot_sectors - fs -> dir_start - fs -> dir_len) / fs -> cluster_size;
+
+    return (0);
+}
+
+/*-----------------------------------------------------------------------------
+ * fs_init -- 
+ *-----------------------------------------------------------------------------
+ */
+int fs_init (Fs_t *fs)
+{
+    BootSector_t *boot;
+
+    /* Initialize physical device                                            */
+    if (dev_open () < 0) {
+        PRINTF ("Unable to initialize the fdc\n");
+        return (-1);
+    }
+    init_subdir ();
+    
+    /* Allocate space for read the boot sector                               */
+    if ((boot = (BootSector_t *)malloc (sizeof (BootSector_t))) == NULL) {
+        PRINTF ("Unable to allocate space for boot sector\n");
+        return (-1);
+    }
+    
+    /* read boot sector                                                      */
+    if (dev_read (boot, 0, 1)){
+        PRINTF ("Error during boot sector read\n");
+        free (boot);
+        return (-1);
+    }
+
+    /* we verify it'a a DOS diskette                                         */
+    if (boot -> jump [0] !=  JUMP_0_1 && boot -> jump [0] !=  JUMP_0_2) {
+        PRINTF ("Not a DOS diskette\n");
+        free (boot);
+        return (-1);
+    }
+
+    if (boot -> descr < MEDIA_STD) {
+        /* We handle only recent medias (type F0)                            */
+        PRINTF ("unrecognized diskette type\n");
+        free (boot);
+        return (-1);
+    }
+
+    if (check_dev (boot, fs) < 0) {
+        PRINTF ("Bad diskette\n");
+        free (boot);
+        return (-1);
+    }
+    
+    if (fill_fs (boot, fs) < 0) {
+        free (boot);
+
+        return (-1);
+    }
+
+    /* Read FAT                                                              */
+    if (read_fat (boot, fs) < 0) {
+        free (boot);
+        return (-1);
+    }
+
+    free (boot);
+    return (0);
+}
+
+
+
+#endif

+ 348 - 0
fs/fdos/subdir.c

@@ -0,0 +1,348 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <config.h>
+#include <malloc.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+
+#include "dos.h"
+#include "fdos.h"
+
+static int cache_sect;
+static unsigned char cache [SZ_STD_SECTOR];
+
+
+#define min(x,y) ((x)<(y)?(x):(y))
+
+static int descend (Slot_t *parent,
+             Fs_t *fs,
+                    char *path);
+
+/*-----------------------------------------------------------------------------
+ * init_subdir -- 
+ *-----------------------------------------------------------------------------
+ */
+void init_subdir (void)
+{
+    cache_sect = -1;
+}
+/*-----------------------------------------------------------------------------
+ * basename -- 
+ *-----------------------------------------------------------------------------
+ */
+char *basename (char *name)
+{
+    register char *cptr;
+
+    if (!name || !*name) {
+        return ("");
+    }
+    
+    for (cptr= name; *cptr++; );
+    while (--cptr >= name) {
+	if (*cptr == '/')    {
+            return (cptr + 1);
+	}
+    }
+    return(name);
+}
+/*-----------------------------------------------------------------------------
+ * root_map -- 
+ *-----------------------------------------------------------------------------
+ */
+static int root_map (Fs_t *fs, Slot_t *file, int where, int *len)
+{
+    *len = min (*len, fs -> dir_len * SZ_STD_SECTOR - where);
+    if (*len < 0 ) {
+        *len = 0;
+        return (-1);
+    }
+    return fs -> dir_start * SZ_STD_SECTOR + where;
+}
+/*-----------------------------------------------------------------------------
+ * normal_map -- 
+ *-----------------------------------------------------------------------------
+ */
+static int normal_map (Fs_t *fs, Slot_t *file, int where, int *len)
+{
+    int offset;
+    int NrClu;
+    unsigned short RelCluNr;
+    unsigned short CurCluNr;
+    unsigned short NewCluNr;
+    unsigned short AbsCluNr;
+    int clus_size;
+
+    clus_size = fs -> cluster_size * SZ_STD_SECTOR;
+    offset = where % clus_size;
+
+    *len = min (*len, file -> FileSize - where);
+
+    if (*len < 0 ) {
+        *len = 0;
+        return (0);
+    }
+
+    if (file -> FirstAbsCluNr < 2){
+        *len = 0;
+        return (0);
+    }
+
+    RelCluNr = where / clus_size;
+	
+    if (RelCluNr >= file -> PreviousRelCluNr){
+        CurCluNr = file -> PreviousRelCluNr;
+        AbsCluNr = file -> PreviousAbsCluNr;
+    } else {
+        CurCluNr = 0;
+        AbsCluNr = file -> FirstAbsCluNr;
+    }
+
+
+    NrClu = (offset + *len - 1) / clus_size;
+    while (CurCluNr <= RelCluNr + NrClu) {
+        if (CurCluNr == RelCluNr){
+            /* we have reached the beginning of our zone. Save
+             * coordinates */
+            file -> PreviousRelCluNr = RelCluNr;
+            file -> PreviousAbsCluNr = AbsCluNr;
+        }
+        NewCluNr = fat_decode (fs, AbsCluNr);
+        if (NewCluNr == 1 || NewCluNr == 0) {
+            PRINTF("Fat problem while decoding %d %x\n", 
+                    AbsCluNr, NewCluNr);
+            return (-1);
+        }
+        if (CurCluNr == RelCluNr + NrClu) {
+            break;
+        }
+
+        if (CurCluNr < RelCluNr && NewCluNr == FAT12_END) {
+            *len = 0;
+            return 0;
+        }
+
+        if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1)
+            break;
+        CurCluNr++;
+        AbsCluNr = NewCluNr;
+    }
+
+    *len = min (*len, (1 + CurCluNr - RelCluNr) * clus_size - offset);
+
+    return (((file -> PreviousAbsCluNr - 2) * fs -> cluster_size +
+             fs -> dir_start + fs -> dir_len) *
+            SZ_STD_SECTOR + offset);
+}
+/*-----------------------------------------------------------------------------
+ * open_subdir -- open the subdir containing the file
+ *-----------------------------------------------------------------------------
+ */
+int open_subdir (File_t *desc)
+{
+    char *pathname;
+    char *tmp, *s, *path;
+    char terminator;
+    
+    if ((pathname = (char *)malloc (MAX_PATH)) == NULL) {
+        return (-1);
+    }
+    
+    strcpy (pathname, desc -> name);
+    
+    /* Suppress file name                                                    */
+    tmp = basename (pathname);
+    *tmp = '\0';
+
+    /* root directory  init                                                  */
+    desc -> subdir.FirstAbsCluNr = 0;
+    desc -> subdir.FileSize = -1;
+    desc -> subdir.map = root_map;
+    desc -> subdir.dir.attr = ATTR_DIRECTORY;
+    
+    tmp = pathname;
+    for (s = tmp; ; ++s) {
+        if (*s == '/' || *s == '\0') {
+            path = tmp;
+            terminator = *s;
+            *s = '\0';
+            if (s != tmp && strcmp (path,".")) {
+                if (descend (&desc -> subdir, desc -> fs, path) < 0) {
+                    free (pathname);
+                    return (-1);
+                }
+            }
+            if (terminator == 0) {
+                break;
+            }
+            tmp = s + 1;
+        }
+    }
+    free (pathname);
+    return (0);
+}
+/*-----------------------------------------------------------------------------
+ * descend -- 
+ *-----------------------------------------------------------------------------
+ */
+static int descend (Slot_t *parent,
+             Fs_t *fs,
+             char *path)
+{
+    int entry;
+    Slot_t SubDir;
+
+    if(path[0] == '\0' || strcmp (path, ".") == 0) {
+        return (0);
+    }
+    
+
+    entry = 0;
+    if (vfat_lookup (parent,
+                     fs,
+                     &(SubDir.dir),
+                     &entry,
+                     0,
+                     path,
+                     ACCEPT_DIR | SINGLE | DO_OPEN,
+                     0,
+                     &SubDir) == 0) {
+        *parent = SubDir;
+        return (0);
+    }
+
+    if (strcmp(path, "..") == 0) {
+        parent -> FileSize = -1;
+        parent -> FirstAbsCluNr = 0;
+        parent -> map = root_map;
+        return (0);
+    }
+    return (-1);
+}
+/*-----------------------------------------------------------------------------
+ * open_file -- 
+ *-----------------------------------------------------------------------------
+ */
+int open_file (Slot_t *file, Directory_t *dir)
+{
+    int first;
+    unsigned long size;
+
+    first = __le16_to_cpu (dir -> start);
+
+    if(first == 0 &&
+       (dir -> attr & ATTR_DIRECTORY) != 0) {
+        file -> FirstAbsCluNr = 0;
+        file -> FileSize = -1;
+        file -> map = root_map;
+        return (0);
+    }
+	
+    if ((dir -> attr & ATTR_DIRECTORY) != 0) {
+        size = (1UL << 31) - 1;
+    }
+    else {
+        size = __le32_to_cpu (dir -> size);
+    }
+
+    file -> map = normal_map;
+    file -> FirstAbsCluNr = first;
+    file -> PreviousRelCluNr = 0xffff;
+    file -> FileSize = size;
+    return (0);
+}
+/*-----------------------------------------------------------------------------
+ * read_file -- 
+ *-----------------------------------------------------------------------------
+ */
+int read_file (Fs_t *fs,
+               Slot_t *file,
+               char *buf,
+               int where,
+               int len)
+{
+    int pos;
+    int read, nb, sect, offset;
+    
+    pos = file -> map (fs, file, where, &len);
+    if  (pos < 0) {
+        return -1;
+    }
+    if (len == 0) {
+        return (0);
+    }
+
+    /* Compute sector number                                                 */
+    sect = pos / SZ_STD_SECTOR;
+    offset = pos % SZ_STD_SECTOR;
+    read = 0;
+    
+    if (offset) {
+        /* Read doesn't start at the sector beginning. We need to use our    */
+        /* cache                                                             */
+        if (sect != cache_sect) {
+            if (dev_read (cache, sect, 1) < 0) {
+                return (-1);
+            }
+            cache_sect = sect;
+        }
+        nb = min (len, SZ_STD_SECTOR - offset);
+        
+        memcpy (buf, cache + offset, nb);
+        read += nb;
+        len -= nb;
+        sect += 1;
+    }
+
+    if (len > SZ_STD_SECTOR) {
+        nb = (len - 1) / SZ_STD_SECTOR;
+        if (dev_read (buf + read, sect, nb) < 0) {
+            return ((read) ? read : -1);
+        }
+        /* update sector position                                            */
+        sect += nb;
+
+        /* Update byte position                                              */
+        nb *= SZ_STD_SECTOR;
+        read += nb;
+        len -= nb;
+    }
+
+    if (len) {
+        if (sect != cache_sect) {
+            if (dev_read (cache, sect, 1) < 0) {
+                return ((read) ? read : -1);
+                cache_sect = -1;
+            }
+            cache_sect = sect;
+        }
+        
+        memcpy (buf + read, cache, len);
+        read += len;
+    }
+    return (read);
+}
+#endif

+ 357 - 0
fs/fdos/vfat.c

@@ -0,0 +1,357 @@
+/*
+ * (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
+ */
+
+#include <common.h>
+#include <config.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+#include <linux/ctype.h>
+
+#include "dos.h"
+#include "fdos.h"
+
+static int dir_read (Fs_t *fs,
+                     Slot_t *dir,
+                     Directory_t *dirent,
+                     int num,
+                     struct vfat_state *v);
+
+static int unicode_read (char *in, char *out, int num);
+static int match (const char *s, const char *p);
+static unsigned char sum_shortname (char *name);
+static int check_vfat (struct vfat_state *v, Directory_t *dir);
+static char *conv_name (char *name, char *ext, char Case, char *ans);
+
+
+/*-----------------------------------------------------------------------------
+ * clear_vfat -- 
+ *-----------------------------------------------------------------------------
+ */
+static void clear_vfat (struct vfat_state *v)
+{
+    v -> subentries = 0;
+    v -> status = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * vfat_lookup -- 
+ *-----------------------------------------------------------------------------
+ */
+int vfat_lookup (Slot_t *dir,
+                 Fs_t *fs,
+                 Directory_t *dirent,
+                 int *entry,
+                 int *vfat_start,
+                 char *filename, 
+                 int flags,
+                 char *outname,
+                 Slot_t *file)
+{
+    int found;
+    struct vfat_state vfat;
+    char newfile [VSE_NAMELEN];
+    int vfat_present = 0;
+
+    if (*entry == -1) {
+        return -1;
+    }
+
+    found = 0;
+    clear_vfat (&vfat);
+    while (1) {
+        if (dir_read (fs, dir, dirent, *entry, &vfat) < 0) {
+            if (vfat_start) {
+                *vfat_start = *entry;
+            }
+            break;
+        }
+        (*entry)++;
+
+        /* Empty slot                                                        */
+        if (dirent -> name[0] == '\0'){
+            if (vfat_start == 0) {
+                break;
+            }
+            continue;
+        }
+
+        if (dirent -> attr == ATTR_VSE) {
+            /* VSE entry, continue                                           */
+            continue;
+        }
+        if ( (dirent -> name [0] == DELMARK) ||
+             ((dirent -> attr & ATTR_DIRECTORY) != 0 &&
+              (flags & ACCEPT_DIR) == 0) ||
+             ((dirent -> attr & ATTR_VOLUME) != 0 &&
+              (flags & ACCEPT_LABEL) == 0) ||
+             (((dirent -> attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0) &&
+              (flags & ACCEPT_PLAIN) == 0)) {
+            clear_vfat (&vfat);
+            continue;
+        }
+
+        vfat_present = check_vfat (&vfat, dirent);
+        if (vfat_start) {
+            *vfat_start = *entry - 1;
+            if (vfat_present) {
+                *vfat_start -= vfat.subentries;
+            }
+        }
+
+        if (dirent -> attr & ATTR_VOLUME) {
+            strncpy (newfile, dirent -> name, 8);
+            newfile [8] = '\0';
+            strncat (newfile, dirent -> ext, 3);
+            newfile [11] = '\0';
+        }
+        else {
+            conv_name (dirent -> name, dirent -> ext, dirent -> Case, newfile);
+        }
+
+        if (flags & MATCH_ANY) {
+            found = 1;
+            break;
+        }
+
+        if ((vfat_present && match (vfat.name, filename)) ||
+            (match (newfile, filename))) {
+            found = 1;
+            break;
+        }
+        clear_vfat (&vfat);
+    }
+
+    if (found) {
+        if ((flags & DO_OPEN) && file) {
+            if (open_file (file, dirent) < 0) {
+                return (-1);
+            }
+        }
+        if (outname) {
+            if (vfat_present) {
+                strcpy (outname, vfat.name);
+            }
+            else {
+                strcpy (outname, newfile);
+            }
+        }
+        return (0);                    /* File found                         */
+    } else {
+        *entry = -1;
+        return -1;                      /* File not found                    */
+    }
+}
+
+/*-----------------------------------------------------------------------------
+ * dir_read -- Read one directory entry
+ *-----------------------------------------------------------------------------
+ */
+static int dir_read (Fs_t *fs,
+              Slot_t *dir,
+              Directory_t *dirent,
+              int num,
+              struct vfat_state *v)
+{
+
+    /* read the directory entry                                              */
+    if (read_file (fs,
+                   dir,
+                   (char *)dirent,
+                   num * MDIR_SIZE,
+                   MDIR_SIZE) != MDIR_SIZE) {
+        return (-1);
+    }
+
+    if (v && (dirent -> attr == ATTR_VSE)) {
+        struct vfat_subentry *vse;
+        unsigned char id, last_flag;
+        char *c;
+
+        vse = (struct vfat_subentry *) dirent;
+        id = vse -> id & VSE_MASK;
+        last_flag = (vse -> id & VSE_LAST);
+        if (id > MAX_VFAT_SUBENTRIES) {
+            /* Invalid VSE entry                                             */
+            return (-1);
+        }
+
+
+        /* Decode VSE                                                        */
+        if(v -> sum != vse -> sum) {
+            clear_vfat (v);
+            v -> sum = vse -> sum;
+        }
+
+        
+        v -> status |= 1 << (id - 1);
+        if (last_flag) {
+            v -> subentries = id;
+        }
+
+        c = &(v -> name [VSE_NAMELEN * (id - 1)]);
+        c += unicode_read (vse->text1, c, VSE1SIZE);
+        c += unicode_read (vse->text2, c, VSE2SIZE);
+        c += unicode_read (vse->text3, c, VSE3SIZE);
+		
+        if (last_flag) {
+            *c = '\0';	        /* Null terminate long name                  */
+        }
+        
+    }
+    return (0);
+}
+
+/*-----------------------------------------------------------------------------
+ * unicode_read -- 
+ *-----------------------------------------------------------------------------
+ */
+static int unicode_read (char *in, char *out, int num)
+{
+    int j;
+    
+    for (j = 0; j < num; ++j) {
+        if (in [1])
+            *out = '_';
+        else
+            *out = in [0];
+        out ++;
+        in += 2;
+    }
+    return num;
+}
+
+/*-----------------------------------------------------------------------------
+ * match -- 
+ *-----------------------------------------------------------------------------
+ */
+static int match (const char *s, const char *p)
+{
+
+    for (; *p != '\0'; ) {
+        if (toupper (*s) != toupper (*p)) {
+            return (0);
+        }
+        p++;
+        s++;
+    }
+    
+    if (*s != '\0') {
+        return (0);
+    }
+    else {
+        return (1);
+    }
+}
+/*-----------------------------------------------------------------------------
+ * sum_shortname -- 
+ *-----------------------------------------------------------------------------
+ */
+static unsigned char sum_shortname (char *name)
+{
+    unsigned char sum;
+    int j;
+    
+    for (j = sum = 0; j < 11; ++j) {
+        sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) +
+            (name [j] ? name [j] : ' ');
+    }
+    return (sum);
+}
+/*-----------------------------------------------------------------------------
+ * check_vfat -- 
+ * Return 1 if long name is valid, 0 else
+ *-----------------------------------------------------------------------------
+ */
+static int check_vfat (struct vfat_state *v, Directory_t *dir)
+{
+    char name[12];
+    
+    if (v -> subentries == 0) {
+        return 0;
+    }
+    
+    strncpy (name, dir -> name, 8);
+    strncpy (name + 8, dir -> ext, 3);
+    name [11] = '\0';
+    
+    if (v -> sum != sum_shortname (name)) {
+        return 0;
+    }
+    
+    if( (v -> status & ((1 << v -> subentries) - 1)) !=
+        (1 << v -> subentries) - 1) {
+        return 0;
+    }
+    v->name [VSE_NAMELEN * v -> subentries] = 0;
+    
+    return 1;
+}
+/*-----------------------------------------------------------------------------
+ * conv_name -- 
+ *-----------------------------------------------------------------------------
+ */
+static char *conv_name (char *name, char *ext, char Case, char *ans)
+{
+    char tname [9], text [4];
+    int i;
+
+    i = 0;
+    while (i < 8 && name [i] != ' ' && name [i] != '\0') {
+        tname [i] = name [i];
+        i++;
+    }
+    tname [i] = '\0';
+    
+    if (Case & BASECASE) {
+        for (i = 0; i < 8 && tname [i]; i++) {
+            tname [i] = tolower (tname [i]);
+        }
+    }
+
+    i = 0;
+    while (i < 3 && ext [i] != ' ' && ext [i] != '\0') {
+        text [i] = ext [i];
+        i++;
+    }
+    text [i] = '\0';
+
+    if (Case & EXTCASE){
+        for (i = 0; i < 3 && text [i]; i++) {
+            text [i] = tolower (text [i]);
+        }
+    }
+
+    if (*text) {
+        strcpy (ans, tname);
+        strcat (ans, ".");
+        strcat (ans, text);
+    }
+    else {
+        strcpy(ans, tname);
+    }
+    return (ans);
+}
+
+
+#endif

+ 24 - 0
i386_config.mk

@@ -0,0 +1,24 @@
+#
+# (C) Copyright 2000-2002
+# 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
+#
+
+PLATFORM_CPPFLAGS += -DCONFIG_I386 -D__I386__

+ 384 - 0
include/asm-i386/bitops.h

@@ -0,0 +1,384 @@
+#ifndef _I386_BITOPS_H
+#define _I386_BITOPS_H
+
+/*
+ * Copyright 1992, Linus Torvalds.
+ */
+
+#include <linux/config.h>
+
+/*
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+#ifdef CONFIG_SMP
+#define LOCK_PREFIX "lock ; "
+#else
+#define LOCK_PREFIX ""
+#endif
+
+#define ADDR (*(volatile long *) addr)
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static __inline__ void set_bit(int nr, volatile void * addr)
+{
+	__asm__ __volatile__( LOCK_PREFIX
+		"btsl %1,%0"
+		:"=m" (ADDR)
+		:"Ir" (nr));
+}
+
+/**
+ * __set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike set_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static __inline__ void __set_bit(int nr, volatile void * addr)
+{
+	__asm__(
+		"btsl %1,%0"
+		:"=m" (ADDR)
+		:"Ir" (nr));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static __inline__ void clear_bit(int nr, volatile void * addr)
+{
+	__asm__ __volatile__( LOCK_PREFIX
+		"btrl %1,%0"
+		:"=m" (ADDR)
+		:"Ir" (nr));
+}
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+
+/**
+ * __change_bit - Toggle a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike change_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static __inline__ void __change_bit(int nr, volatile void * addr)
+{
+	__asm__ __volatile__(
+		"btcl %1,%0"
+		:"=m" (ADDR)
+		:"Ir" (nr));
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static __inline__ void change_bit(int nr, volatile void * addr)
+{
+	__asm__ __volatile__( LOCK_PREFIX
+		"btcl %1,%0"
+		:"=m" (ADDR)
+		:"Ir" (nr));
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__( LOCK_PREFIX
+		"btsl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr) : "memory");
+	return oldbit;
+}
+
+/**
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.  
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__(
+		"btsl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr));
+	return oldbit;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__( LOCK_PREFIX
+		"btrl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr) : "memory");
+	return oldbit;
+}
+
+/**
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.  
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__(
+		"btrl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr));
+	return oldbit;
+}
+
+/* WARNING: non atomic and it can be reordered! */
+static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__(
+		"btcl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr) : "memory");
+	return oldbit;
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its new value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_change_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__( LOCK_PREFIX
+		"btcl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr) : "memory");
+	return oldbit;
+}
+
+#if 0 /* Fool kernel-doc since it doesn't do macros yet */
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static int test_bit(int nr, const volatile void * addr);
+#endif
+
+static __inline__ int constant_test_bit(int nr, const volatile void * addr)
+{
+	return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
+}
+
+static __inline__ int variable_test_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__(
+		"btl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit)
+		:"m" (ADDR),"Ir" (nr));
+	return oldbit;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
+/**
+ * find_first_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first zero bit, not the number of the byte
+ * containing a bit.
+ */
+static __inline__ int find_first_zero_bit(void * addr, unsigned size)
+{
+	int d0, d1, d2;
+	int res;
+
+	if (!size)
+		return 0;
+	/* This looks at memory. Mark it volatile to tell gcc not to move it around */
+	__asm__ __volatile__(
+		"movl $-1,%%eax\n\t"
+		"xorl %%edx,%%edx\n\t"
+		"repe; scasl\n\t"
+		"je 1f\n\t"
+		"xorl -4(%%edi),%%eax\n\t"
+		"subl $4,%%edi\n\t"
+		"bsfl %%eax,%%edx\n"
+		"1:\tsubl %%ebx,%%edi\n\t"
+		"shll $3,%%edi\n\t"
+		"addl %%edi,%%edx"
+		:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
+	return res;
+}
+
+/**
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+{
+	unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+	int set = 0, bit = offset & 31, res;
+	
+	if (bit) {
+		/*
+		 * Look for zero in first byte
+		 */
+		__asm__("bsfl %1,%0\n\t"
+			"jne 1f\n\t"
+			"movl $32, %0\n"
+			"1:"
+			: "=r" (set)
+			: "r" (~(*p >> bit)));
+		if (set < (32 - bit))
+			return set + offset;
+		set = 32 - bit;
+		p++;
+	}
+	/*
+	 * No zero yet, search remaining full bytes for a zero
+	 */
+	res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
+	return (offset + set + res);
+}
+
+/**
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static __inline__ unsigned long ffz(unsigned long word)
+{
+	__asm__("bsfl %1,%0"
+		:"=r" (word)
+		:"r" (~word));
+	return word;
+}
+
+#ifdef __KERNEL__
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static __inline__ int ffs(int x)
+{
+	int r;
+
+	__asm__("bsfl %1,%0\n\t"
+		"jnz 1f\n\t"
+		"movl $-1,%0\n"
+		"1:" : "=r" (r) : "g" (x));
+	return r+1;
+}
+
+/**
+ * hweightN - returns the hamming weight of a N-bit word
+ * @x: the word to weigh
+ *
+ * The Hamming Weight of a number is the total number of bits set in it.
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
+
+#ifdef __KERNEL__
+
+#define ext2_set_bit                 __test_and_set_bit
+#define ext2_clear_bit               __test_and_clear_bit
+#define ext2_test_bit                test_bit
+#define ext2_find_first_zero_bit     find_first_zero_bit
+#define ext2_find_next_zero_bit      find_next_zero_bit
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
+#define minix_set_bit(nr,addr) __set_bit(nr,addr)
+#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* _I386_BITOPS_H */

+ 47 - 0
include/asm-i386/byteorder.h

@@ -0,0 +1,47 @@
+#ifndef _I386_BYTEORDER_H
+#define _I386_BYTEORDER_H
+
+#include <asm/types.h>
+
+#ifdef __GNUC__
+
+/* For avoiding bswap on i386 */
+#ifdef __KERNEL__
+#include <linux/config.h>
+#endif
+
+static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+{
+#ifdef CONFIG_X86_BSWAP
+	__asm__("bswap %0" : "=r" (x) : "0" (x));
+#else
+	__asm__("xchgb %b0,%h0\n\t"	/* swap lower bytes	*/
+		"rorl $16,%0\n\t"	/* swap words		*/
+		"xchgb %b0,%h0"		/* swap higher bytes	*/
+		:"=q" (x)
+		: "0" (x));
+#endif
+	return x;
+}
+
+static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+	__asm__("xchgb %b0,%h0"		/* swap bytes		*/ \
+		: "=q" (x) \
+		:  "0" (x)); \
+		return x;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#endif /* __GNUC__ */
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _I386_BYTEORDER_H */

+ 60 - 0
include/asm-i386/global_data.h

@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2002
+ * 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
+ */
+
+#ifndef	__ASM_GBL_DATA_H
+#define __ASM_GBL_DATA_H
+/*
+ * The following data structure is placed in some memory wich is
+ * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
+ * some locked parts of the data cache) to allow for a minimum set of
+ * global variables during system initialization (until we have set
+ * up the memory controller so that we can use RAM).
+ *
+ * Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t)
+ */
+
+typedef	struct {
+	bd_t		*bd;
+	unsigned long	flags;
+	unsigned long	baudrate;
+	unsigned long	have_console;	/* serial_init() was called */
+	unsigned long	reloc_off;	/* Relocation Offset */
+	unsigned long	env_addr;	/* Address  of Environment struct */
+	unsigned long	env_valid;	/* Checksum of Environment valid? */
+	unsigned long	cpu_clk;	/* CPU clock in Hz!		*/
+	unsigned long	bus_clk;
+	unsigned long	ram_size;	/* RAM size */
+	unsigned long	reset_status;	/* reset status register at boot */
+} gd_t;
+
+/*
+ * Global Data Flags
+ */
+#define	GD_FLG_RELOC	0x00001		/* Code was relocated to RAM		*/
+#define	GD_FLG_DEVINIT	0x00002		/* Devices have been initialized	*/
+
+extern gd_t *global_data;
+
+#define DECLARE_GLOBAL_DATA_PTR     gd_t *gd = global_data
+
+#endif /* __ASM_GBL_DATA_H */

+ 56 - 0
include/asm-i386/i8254.h

@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+
+/* i8254.h Intel 8254 PIT registers */
+
+
+#ifndef _ASMI386_I8254_H_
+#define _ASMI386_I8954_H_       1
+
+
+
+#define PIT_T0		0x00		/* PIT channel 0 count/status */
+#define PIT_T1		0x01		/* PIT channel 1 count/status */
+#define PIT_T2		0x02		/* PIT channel 2 count/status */
+#define PIT_COMMAND	0x03		/* PIT mode control, latch and read back */
+
+/* PIT Command Register Bit Definitions */
+
+#define PIT_CMD_CTR0	0x00		/* Select PIT counter 0 */
+#define PIT_CMD_CTR1	0x40		/* Select PIT counter 1 */
+#define PIT_CMD_CTR2	0x80		/* Select PIT counter 2 */
+
+#define PIT_CMD_LATCH	0x00		/* Counter Latch Command */
+#define PIT_CMD_LOW	0x10		/* Access counter bits 7-0 */
+#define PIT_CMD_HIGH	0x20		/* Access counter bits 15-8 */
+#define PIT_CMD_BOTH	0x30		/* Access counter bits 15-0 in two accesses */
+
+#define PIT_CMD_MODE0	0x00		/* Select mode 0 */
+#define PIT_CMD_MODE1	0x02		/* Select mode 1 */
+#define PIT_CMD_MODE2	0x04		/* Select mode 2 */
+#define PIT_CMD_MODE3	0x06		/* Select mode 3 */
+#define PIT_CMD_MODE4	0x08		/* Select mode 4 */
+#define PIT_CMD_MODE5	0x0A		/* Select mode 5 */
+
+#endif

+ 88 - 0
include/asm-i386/i8259.h

@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+/* i8259.h i8259 PIC Registers */
+
+#ifndef _ASMI386_I8259_H_
+#define _ASMI386_I8959_H_       1
+
+
+/* PIC I/O mapped registers */
+
+#define IRR		0x0	/* Interrupt Request Register */
+#define ISR		0x0	/* In-Service Register */
+#define ICW1		0x0	/* Initialization Control Word 1 */
+#define OCW2		0x0	/* Operation Control Word 2 */
+#define OCW3		0x0	/* Operation Control Word 3 */
+#define ICW2		0x1	/* Initialization Control Word 2 */
+#define ICW3		0x1	/* Initialization Control Word 3 */
+#define ICW4		0x1	/* Initialization Control Word 4 */
+#define IMR		0x1	/* Interrupt Mask Register */
+
+/* bits for IRR, IMR, ISR and ICW3 */
+#define	IR7		0x80	/* IR7 */
+#define	IR6		0x40	/* IR6 */
+#define	IR5		0x20	/* IR5 */
+#define	IR4		0x10	/* IR4 */
+#define	IR3		0x08	/* IR3 */
+#define	IR2		0x04	/* IR2 */
+#define	IR1		0x02	/* IR1 */
+#define	IR0		0x01	/* IR0 */
+
+/* bits for SEOI */
+#define	SEOI_IR7	0x07	/* IR7 */
+#define	SEOI_IR6	0x06	/* IR6 */
+#define	SEOI_IR5	0x05	/* IR5 */
+#define	SEOI_IR4	0x04	/* IR4 */
+#define	SEOI_IR3	0x03	/* IR3 */
+#define	SEOI_IR2	0x02	/* IR2 */
+#define	SEOI_IR1	0x01	/* IR1 */
+#define	SEOI_IR0	0x00	/* IR0 */
+
+/* OCW2 bits */
+#define OCW2_RCLR	0x00	/* Rotate/clear */
+#define OCW2_NEOI	0x20	/* Non specific EOI */
+#define OCW2_NOP	0x40	/* NOP */
+#define OCW2_SEOI	0x60	/* Specific EOI */
+#define OCW2_RSET	0x80	/* Rotate/set */
+#define OCW2_REOI	0xA0	/* Rotate on non specific EOI */
+#define OCW2_PSET	0xC0	/* Priority Set Command */
+#define OCW2_RSEOI	0xE0	/* Rotate on specific EOI */
+
+/* ICW1 bits */
+#define ICW1_SEL	0x10	/* Select ICW1 */
+#define ICW1_LTIM	0x08	/* Level-Triggered Interrupt Mode */
+#define ICW1_ADI	0x04	/* Address Interval */
+#define ICW1_SNGL	0x02	/* Single PIC */
+#define ICW1_EICW4	0x01	/* Expect initilization ICW4 */
+
+/* ICW2 is the starting vector number */
+
+/* ICW2 is bit-mask of present slaves for a master device, 
+ * or the slave ID for a slave device */
+
+/* ICW4 bits */
+#define	ICW4_AEOI	0x02	/* Automatic EOI Mode */
+#define ICW4_PM		0x01	/* Microprocessor Mode */
+
+#endif

+ 47 - 0
include/asm-i386/ibmpc.h

@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * 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
+ */
+
+#ifndef __ASM_IBMPC_H_
+#define __ASM_IBMPC_H_ 1
+
+/* misc ports in an ibm compatible pc */
+
+#define MASTER_PIC      0x20
+#define PIT_BASE	0x40
+#define KBDDATA         0x60
+#define SYSCTLB         0x62
+#define KBDCMD          0x64
+#define SYSCTLA         0x92
+#define SLAVE_PIC       0xa0
+
+#if 1
+#define UART0_BASE     0x3f8
+#define UART1_BASE     0x2f8
+#else
+/* FixMe: uarts swapped */
+#define UART0_BASE     0x2f8
+#define UART1_BASE     0x3f8
+#endif
+
+
+#endif

+ 54 - 0
include/asm-i386/ic/ali512x.h

@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+#ifndef __ASM_IC_ALI512X_H_
+#define __ASM_IC_ALI512X_H_
+
+# define ALI_INDEX    0x3f0
+# define ALI_DATA     0x3f1
+
+# define ALI_ENABLED  1
+# define ALI_DISABLED 0
+
+# define ALI_UART1    0
+# define ALI_UART2    1
+
+/* setup functions */
+void ali512x_init(void);
+void ali512x_set_fdc(int enabled, u16 io, u8 irq, u8 dma_channel);
+void ali512x_set_pp(int enabled, u16 io, u8 irq, u8 dma_channel);
+void ali512x_set_uart(int enabled, int index, u16 io, u8 irq);
+void ali512x_set_rtc(int enabled, u16 io, u8 irq);
+void ali512x_set_kbc(int enabled, u8 kbc_irq, u8 mouse_irq);
+void ali512x_set_cio(int enabled);
+
+
+/* common I/O functions */
+void ali512x_cio_function(int pin, int special, int inv, int input);
+void ali512x_cio_out(int pin, int value);
+int ali512x_cio_in(int pin);
+
+/* misc features */
+void ali512x_set_uart2_irda(int enabled);
+
+#endif

+ 249 - 0
include/asm-i386/ic/sc520.h

@@ -0,0 +1,249 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+#ifndef _ASM_IC_SC520_H_
+#define _ASM_IC_SC520_H_ 1
+
+/* Memory mapped configuration registers, MMCR */
+#define SC520_REVID		0x0000		/* ElanSC520 Microcontroller Revision ID Register */
+#define SC520_CPUCTL		0x0002		/* Am5x86 CPU Control Register */
+#define SC520_DRCCTL            0x0010          /* SDRAM Control Register */
+#define SC520_DRCTMCTL		0x0012		/* SDRAM Timing Control Register */
+#define SC520_DRCCFG		0x0014		/* SDRAM Bank Configuration Register*/
+#define SC520_DRCBENDADR	0x0018		/* SDRAM Bank 0-3 Ending Address Register*/
+#define SC520_ECCCTL		0x0020		/* ECC Control Register */
+#define SC520_ECCSTA		0x0021		/* ECC Status Register */
+#define SC520_ECCCKBPOS		0x0022		/* ECC Check Bit Position Register */
+#define SC520_ECCSBADD		0x0024		/* ECC Single-Bit Error Address Register */
+#define SC520_DBCTL		0x0040		/* SDRAM Buffer Control Register */
+#define SC520_BOOTCSCTL		0x0050		/* /BOOTCS Control Register */
+#define SC520_ROMCS1CTL		0x0054		/* /ROMCS1 Control Register */
+#define SC520_ROMCS2CTL		0x0056		/* /ROMCS2 Control Register */
+#define SC520_HBCTL		0x0060 		/* Host Bridge Control Register */
+#define SC520_HBTGTIRQCTL	0x0062		/* Host Bridge Target Interrupt Control Register */
+#define SC520_HBTGTIRQSTA	0x0064		/* Host Bridge Target Interrupt Status Register */
+#define SC520_HBMSTIRQCTL	0x0066		/* Host Bridge Target Interrupt Control Register */
+#define SC520_HBMSTIRQSTA	0x0068		/* Host Bridge Master Interrupt Status Register */
+#define SC520_MSTINTADD		0x006c		/* Host Bridge Master Interrupt Address Register */
+#define SC520_SYSARBCTL		0x0070		/* System Arbiter Control Register */
+#define SC520_PCIARBSTA		0x0071		/* PCI Bus Arbiter Status Register */
+#define SC520_SYSARBMENB	0x0072		/* System Arbiter Master Enable Register */
+#define SC520_ARBPRICTL		0x0074		/* Arbiter Priority Control Register */
+#define SC520_ADDDECCTL     	0x0080 		/* Address Decode Control Register */
+#define SC520_WPVSTA        	0x0082		/* Write-Protect Violation Status Register */
+#define SC520_PAR0          	0x0088		/* Programmable Address Region 0 Register */
+#define SC520_PAR1          	0x008c       	/* Programmable Address Region 1 Register */
+#define SC520_PAR2          	0x0090       	/* Programmable Address Region 2 Register */
+#define SC520_PAR3          	0x0094      	/* Programmable Address Region 3 Register */
+#define SC520_PAR4          	0x0098       	/* Programmable Address Region 4 Register */
+#define SC520_PAR5          	0x009c       	/* Programmable Address Region 5 Register */
+#define SC520_PAR6         	0x00a0      	/* Programmable Address Region 6 Register */
+#define SC520_PAR7          	0x00a4       	/* Programmable Address Region 7 Register */
+#define SC520_PAR8          	0x00a8       	/* Programmable Address Region 8 Register */
+#define SC520_PAR9          	0x00ac       	/* Programmable Address Region 9 Register */
+#define SC520_PAR10         	0x00b0       	/* Programmable Address Region 10 Register */
+#define SC520_PAR11         	0x00b4       	/* Programmable Address Region 11 Register */
+#define SC520_PAR12         	0x00b8       	/* Programmable Address Region 12 Register */
+#define SC520_PAR13         	0x00bc       	/* Programmable Address Region 13 Register */
+#define SC520_PAR14         	0x00c0       	/* Programmable Address Region 14 Register */
+#define SC520_PAR15		0x00c4		/* Programmable Address Region 15 Register */
+#define SC520_GPECHO		0x0c00		/* GP Echo Mode Register */
+#define SC520_GPCSDW		0x0c01		/* GP Chip Select Data Width Register */
+#define SC520_GPCSQUAL		0x0c02		/* GP Chip Select Qualification Register */
+#define SC520_GPCSRT		0x0c08		/* GP Chip Select Recovery Time Register */
+#define SC520_GPCSPW		0x0c09		/* GP Chip Select Pulse Width Register */
+#define SC520_GPCSOFF		0x0c0a		/* GP Chip Select Offset Register */
+#define SC520_GPRDW		0x0c0b		/* GP Read Pulse Width Register */
+#define SC520_GPRDOFF		0x0c0c		/* GP Read Offset Register */
+#define SC520_GPWRW		0x0c0d		/* GP Write Pulse Width Register */
+#define SC520_GPWROFF		0x0c0e		/* GP Write Offset Register */
+#define SC520_GPALEW		0x0c0f		/* GP ALE Pulse Width Register */
+#define SC520_GPALEOFF		0x0c10		/* GP ALE Offset Register */
+#define SC520_PIOPFS15_0	0x0c20		/* PIO15-PIO0 Pin Function Select */
+#define SC520_PIOPFS31_16	0x0c22		/* PIO31-PIO16 Pin Function Select */
+#define SC520_CSPFS		0x0c24		/* Chip Select Pin Function Select */
+#define SC520_CLKSEL		0x0c26		/* Clock Select */
+#define SC520_DSCTL		0x0c28		/* Drive Strength Control */
+#define SC520_PIODIR15_0	0x0c2a		/* PIO15-PIO0 Direction */
+#define SC520_PIODIR31_16	0x0c2c		/* PIO31-PIO16 Direction */
+#define SC520_PIODATA15_0	0x0c30		/* PIO15-PIO0 Data */
+#define SC520_PIODATA31_16	0x0c32		/* PIO31-PIO16 Data */
+#define SC520_PIOSET15_0	0x0c34		/* PIO15-PIO0 Set */
+#define SC520_PIOSET31_16	0x0c36		/* PIO31-PIO16 Set */
+#define SC520_PIOCLR15_0	0x0c38		/* PIO15-PIO0 Clear */
+#define SC520_PIOCLR31_16	0x0c3a		/* PIO31-PIO16 Clear */
+#define SC520_SWTMRMILLI 	0x0c60		/* Software Timer Millisecond Count */
+#define SC520_SWTMRMICRO 	0x0c62		/* Software Timer Microsecond Count */
+#define SC520_SWTMRCFG   	0x0c64		/* Software Timer Configuration */
+#define SC520_GPTMRSTA		0x0c70		/* GP Timers Status Register */
+#define SC520_GPTMR0CTL		0x0c72		/* GP Timer 0 Mode/Control Register */
+#define SC520_GPTMR0CNT		0x0c74		/* GP Timer 0 Count Register */
+#define SC520_GPTMR0MAXCMPA	0x0c76		/* GP Timer 0 Maxcount Compare A Register */
+#define SC520_GPTMR0MAXCMPB	0x0c78		/* GP Timer 0 Maxcount Compare B Register */
+#define SC520_GPTMR1CTL		0x0c7a		/* GP Timer 1 Mode/Control Register */
+#define SC520_GPTMR1CNT		0x0c7c		/* GP Timer 1 Count Register */
+#define SC520_GPTMR1MAXCMPA	0x0c7e		/* GP Timer 1 Maxcount Compare Register A */
+#define SC520_GPTMR1MAXCMPB	0x0c80		/* GP Timer 1 Maxcount Compare B Register */
+#define SC520_GPTMR2CTL		0x0c82		/* GP Timer 2 Mode/Control Register */
+#define SC520_GPTMR2CNT		0x0c84		/* GP Timer 2 Count Register */
+#define SC520_GPTMR2MAXCMPA	0x0c8e		/* GP Timer 2 Maxcount Compare A Register */
+#define SC520_WDTMRCTL		0x0cb0		/* Watchdog Timer Control Register */
+#define SC520_WDTMRCNTL		0x0cb2		/* Watchdog Timer Count Low Register */
+#define SC520_WDTMRCNTH		0x0cb4		/* Watchdog Timer Count High Register */
+#define SC520_UART1CTL		0x0cc0	        /* UART 1 General Control Register */
+#define SC520_UART1STA		0x0cc1	        /* UART 1 General Status Register */
+#define SC520_UART1FCRSHAD	0x0cc2	        /* UART 1 FIFO Control Shadow Register */
+#define SC520_UART2CTL		0x0cc4	        /* UART 2 General Control Register */
+#define SC520_UART2STA		0x0cc5	        /* UART 2 General Status Register */
+#define SC520_UART2FCRSHAD	0x0cc6	        /* UART 2 FIFO Control Shadow Register */
+#define SC520_PICICR		0x0d00		/* Interrupt Control Register */
+#define SC520_MPICMODE		0x0d02		/* Master PIC Interrupt Mode Register */
+#define SC520_SL1PICMODE	0x0d03		/* Slave 1 PIC Interrupt Mode Register */
+#define SC520_SL2PICMODE	0x0d04		/* Slave 2 PIC Interrupt Mode Register */
+#define SC520_SWINT16_1		0x0d08		/* Software Interrupt 16-1 Control Register */
+#define SC520_SWINT22_17	0x0d0a		/* Software Interrupt 22-17/NMI Control Register */
+#define SC520_INTPINPOL		0x0d10		/* Interrupt Pin Polarity Register */
+#define SC520_PCIHOSTMAP	0x0d14		/* PCI Host Bridge Interrupt Mappin Register */
+#define SC520_ECCMAP		0x0d18		/* ECC Interrupt Mapping Register */
+#define SC520_GPTMR0MAP		0x0d1a		/* GP Timer 0 Interrupt Mapping Register */
+#define SC520_GPTMR1MAP		0x0d1b		/* GP Timer 1 Interrupt Mapping Register */
+#define SC520_GPTMR2MAP		0x0d1c		/* GP Timer 2 Interrupt Mapping Register */
+#define SC520_PIT0MAP		0x0d20		/* PIT0 Interrupt Mapping Register */
+#define SC520_PIT1MAP		0x0d21		/* PIT1 Interrupt Mapping Register */
+#define SC520_PIT2MAP		0x0d22		/* PIT2 Interrupt Mapping Register */
+#define SC520_UART1MAP		0x0d28		/* UART 1 Interrupt Mapping Register */
+#define SC520_UART2MAP		0x0d29		/* UART 2 Interrupt Mapping Register */
+#define SC520_PCIINTAMAP	0x0d30		/* PCI Interrupt A Mapping Register */
+#define SC520_PCIINTBMAP	0x0d31		/* PCI Interrupt B Mapping Register */
+#define SC520_PCIINTCMAP	0x0d32		/* PCI Interrupt C Mapping Register */
+#define SC520_PCIINTDMAP	0x0d33		/* PCI Interrupt D Mapping Register */
+#define SC520_DMABCINTMAP	0x0d40		/* DMA Buffer Chaining Interrupt Mapping Register */
+#define SC520_SSIMAP		0x0d41		/* SSI Interrupt Mapping Register */
+#define SC520_WDTMAP		0x0d42		/* Watchdog Timer Interrupt Mapping Register */
+#define SC520_RTCMAP		0x0d43		/* RTC Interrupt Mapping Register */
+#define SC520_WPVMAP		0x0d44		/* Write-Protect Interrupt Mapping Register */
+#define SC520_ICEMAP		0x0d45		/* AMDebug JTAG RX/TX Interrupt Mapping Register */
+#define SC520_FERRMAP		0x0d46		/* Floating Point Error Interrupt Mapping Register */
+#define SC520_GP0IMAP		0x0d50		/* GPIRQ0 Interrupt Mapping Register */
+#define SC520_GP1IMAP		0x0d51		/* GPIRQ1 Interrupt Mapping Register */
+#define SC520_GP2IMAP		0x0d52		/* GPIRQ2 Interrupt Mapping Register */
+#define SC520_GP3IMAP		0x0d53		/* GPIRQ3 Interrupt Mapping Register */
+#define SC520_GP4IMAP		0x0d54		/* GPIRQ4 Interrupt Mapping Register */
+#define SC520_GP5IMAP		0x0d55		/* GPIRQ5 Interrupt Mapping Register */
+#define SC520_GP6IMAP		0x0d56		/* GPIRQ6 Interrupt Mapping Register */
+#define SC520_GP7IMAP		0x0d57		/* GPIRQ7 Interrupt Mapping Register */
+#define SC520_GP8IMAP		0x0d58		/* GPIRQ8 Interrupt Mapping Register */
+#define SC520_GP9IMAP		0x0d59		/* GPIRQ9 Interrupt Mapping Register */
+#define SC520_GP10IMAP		0x0d5a		/* GPIRQ10 Interrupt Mapping Register */
+#define SC520_SYSINFO		0x0d70		/* System Board Information Register */
+#define SC520_RESCFG		0x0d72		/* Reset Configuration Register */
+#define SC520_RESSTA		0x0d74		/* Reset Status Register */
+#define SC520_GPDMAMMIO		0x0d81		/* GP-DMA Memory-Mapped I/O Register */
+#define SC520_GPDMAEXTCHMAPA	0x0d82		/* GP-DMA Resource Channel Map A */
+#define SC520_GPDMAEXTCHMAPB	0x0d84		/* GP-DMA Resource Channel Map B */
+#define SC520_GPDMAEXTPG0	0x0d86		/* GP-DMA Channel 0 Extended Page */
+#define SC520_GPDMAEXTPG1	0x0d87		/* GP-DMA Channel 1 Extended Page */
+#define SC520_GPDMAEXTPG2	0x0d88		/* GP-DMA Channel 2 Extended Page */
+#define SC520_GPDMAEXTPG3	0x0d89		/* GP-DMA Channel 3 Extended Page */
+#define SC520_GPDMAEXTPG5	0x0d8a		/* GP-DMA Channel 5 Extended Page */
+#define SC520_GPDMAEXTPG6	0x0d8b		/* GP-DMA Channel 6 Extended Page */
+#define SC520_GPDMAEXTPG7	0x0d8c		/* GP-DMA Channel 7 Extended Page */
+#define SC520_GPDMAEXTTC3	0x0d90		/* GP-DMA Channel 3 Extender Transfer count */
+#define SC520_GPDMAEXTTC5	0x0d91		/* GP-DMA Channel 5 Extender Transfer count */
+#define SC520_GPDMAEXTTC6	0x0d92		/* GP-DMA Channel 6 Extender Transfer count */
+#define SC520_GPDMAEXTTC7	0x0d93		/* GP-DMA Channel 7 Extender Transfer count */
+#define SC520_GPDMABCCTL	0x0d98		/* Buffer Chaining Control */
+#define SC520_GPDMABCSTA	0x0d99		/* Buffer Chaining Status */
+#define SC520_GPDMABSINTENB	0x0d9a		/* Buffer Chaining Interrupt Enable */
+#define SC520_GPDMABCVAL	0x0d9b		/* Buffer Chaining Valid */
+#define SC520_GPDMANXTADDL3	0x0da0		/* GP-DMA Channel 3 Next Address Low */
+#define SC520_GPDMANXTADDH3	0x0da2		/* GP-DMA Channel 3 Next Address High */
+#define SC520_GPDMANXTADDL5	0x0da4		/* GP-DMA Channel 5 Next Address Low */
+#define SC520_GPDMANXTADDH5	0x0da6		/* GP-DMA Channel 5 Next Address High */
+#define SC520_GPDMANXTADDL6	0x0da8		/* GP-DMA Channel 6 Next Address Low */
+#define SC520_GPDMANXTADDH6	0x0daa		/* GP-DMA Channel 6 Next Address High */
+#define SC520_GPDMANXTADDL7	0x0dac		/* GP-DMA Channel 7 Next Address Low */
+#define SC520_GPDMANXTADDH7	0x0dae		/* GP-DMA Channel 7 Next Address High */
+#define SC520_GPDMANXTTCL3	0x0db0		/* GP-DMA Channel 3 Next Transfer Count Low */
+#define SC520_GPDMANXTTCH3	0x0db2		/* GP-DMA Channel 3 Next Transfer Count High */
+#define SC520_GPDMANXTTCL5	0x0db4		/* GP-DMA Channel 5 Next Transfer Count Low */
+#define SC520_GPDMANXTTCH5	0x0db6		/* GP-DMA Channel 5 Next Transfer Count High */
+#define SC520_GPDMANXTTCL6	0x0db8		/* GP-DMA Channel 6 Next Transfer Count Low */
+#define SC520_GPDMANXTTCH6	0x0dba		/* GP-DMA Channel 6 Next Transfer Count High */
+#define SC520_GPDMANXTTCL7	0x0dbc		/* GP-DMA Channel 7 Next Transfer Count Low */
+#define SC520_GPDMANXTTCH7	0x0dbe		/* GP-DMA Channel 7 Next Transfer Count High */
+
+/* MMCR Register bits (not all of them :) ) */
+
+/* BITS for SC520_ADDDECCTL: */
+#define WPV_INT_ENB		0x80		/* Write-Protect Violation Interrupt Enable */
+#define IO_HOLE_DEST		0x10		/* I/O Hole Access Destination */
+#define RTC_DIS			0x04		/* RTC Disable */
+#define UART2_DIS		0x02		/* UART2 Disable */
+#define UART1_DIS		0x01		/* UART1 Disable */
+
+/* bus mapping constants (used for PCI core initialization) */																																																 /* bus mapping constants */
+#define SC520_REG_ADDR		0x00000cf8     
+#define SC520_REG_DATA		0x00000cfc
+
+
+#define SC520_ISA_MEM_PHYS	0x00000000
+#define SC520_ISA_MEM_BUS	0x00000000
+#define SC520_ISA_MEM_SIZE	0x01000000
+
+#define SC520_ISA_IO_PHYS	0x00000000
+#define SC520_ISA_IO_BUS	0x00000000
+#define SC520_ISA_IO_SIZE	0x00001000
+
+/* PCI I/O space from 0x1000 to 0xfdff */
+#define SC520_PCI_IO_PHYS	0x00001000
+#define SC520_PCI_IO_BUS	0x00001000
+#define SC520_PCI_IO_SIZE	0x0000ee00
+
+/* system memory from 0x00000000 to 0x0fffffff */
+#define	SC520_PCI_MEMORY_PHYS	0x00000000
+#define	SC520_PCI_MEMORY_BUS	0x00000000
+#define SC520_PCI_MEMORY_SIZE	0x10000000
+
+/* PCI bus memory from 0x10000000 to 0x27ffffff */
+#define SC520_PCI_MEM_PHYS	0x10000000
+#define SC520_PCI_MEM_BUS       0x10000000
+#define SC520_PCI_MEM_SIZE	0x18000000
+
+/* 0x28000000 - 0x3fffffff is used by the flash banks */
+
+/* 0x40000000 - 0xffffffff is not adressable by the SC520 */
+
+/* utility functions */
+void write_mmcr_byte(u16 mmcr, u8 data);
+void write_mmcr_word(u16 mmcr, u16 data);
+void write_mmcr_long(u16 mmcr, u32 data);
+u8 read_mmcr_byte(u16 mmcr);
+u16 read_mmcr_word(u16 mmcr);
+u32 read_mmcr_long(u16 mmcr);
+
+void init_sc520(void);
+unsigned long init_sc520_dram(void);
+void pci_sc520_init(struct pci_controller *hose);
+
+#endif

+ 207 - 0
include/asm-i386/io.h

@@ -0,0 +1,207 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#include <linux/config.h>
+
+/*
+ * This file contains the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl and the "string versions" of the same
+ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
+ * versions of the single-IO instructions (inb_p/inw_p/..).
+ *
+ * This file is not meant to be obfuscating: it's just complicated
+ * to (a) handle it all in a way that makes gcc able to optimize it
+ * as well as possible and (b) trying to avoid writing the same thing
+ * over and over again with slight variations and possibly making a
+ * mistake somewhere.
+ */
+
+/*
+ * Thanks to James van Artsdalen for a better timing-fix than
+ * the two short jumps: using outb's to a nonexistent port seems
+ * to guarantee better timings even on fast machines.
+ *
+ * On the other hand, I'd like to be sure of a non-existent port:
+ * I feel a bit unsafe about using 0x80 (should be safe, though)
+ *
+ *		Linus
+ */
+
+ /*
+  *  Bit simplified and optimized by Jan Hubicka
+  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
+  *
+  *  isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
+  *  isa_read[wl] and isa_write[wl] fixed
+  *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+  */
+
+#define IO_SPACE_LIMIT 0xffff
+
+
+#ifdef __KERNEL__
+
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+
+#define readb(addr) (*(volatile unsigned char *) (addr))
+#define readw(addr) (*(volatile unsigned short *) (addr))
+#define readl(addr) (*(volatile unsigned int *) (addr))
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
+#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
+#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define memset_io(a,b,c)	memset((a),(b),(c))
+#define memcpy_fromio(a,b,c)	memcpy((a),(b),(c))
+#define memcpy_toio(a,b,c)	memcpy((a),(b),(c))
+
+/*
+ * ISA space is 'always mapped' on a typical x86 system, no need to
+ * explicitly ioremap() it. The fact that the ISA IO space is mapped
+ * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
+ * are physical addresses. The following constant pointer can be
+ * used as the IO-area pointer (it can be iounmapped as well, so the
+ * analogy with PCI is quite large):
+ */
+#define isa_readb(a) readb((a))
+#define isa_readw(a) readw((a))
+#define isa_readl(a) readl((a))
+#define isa_writeb(b,a) writeb(b,(a))
+#define isa_writew(w,a) writew(w,(a))
+#define isa_writel(l,a) writel(l,(a))
+#define isa_memset_io(a,b,c)		memset_io((a),(b),(c))
+#define isa_memcpy_fromio(a,b,c)	memcpy_fromio((a),(b),(c))
+#define isa_memcpy_toio(a,b,c)		memcpy_toio((a),(b),(c))
+
+
+ 
+static inline int check_signature(unsigned long io_addr,
+	const unsigned char *signature, int length)
+{
+	int retval = 0;
+	do {
+		if (readb(io_addr) != *signature)
+			goto out;
+		io_addr++;
+		signature++;
+		length--;
+	} while (length);
+	retval = 1;
+out:
+	return retval;
+}
+
+/**
+ *	isa_check_signature		-	find BIOS signatures
+ *	@io_addr: mmio address to check 
+ *	@signature:  signature block
+ *	@length: length of signature
+ *
+ *	Perform a signature comparison with the ISA mmio address io_addr.
+ *	Returns 1 on a match.
+ *
+ *	This function is deprecated. New drivers should use ioremap and
+ *	check_signature.
+ */
+ 
+
+static inline int isa_check_signature(unsigned long io_addr,
+	const unsigned char *signature, int length)
+{
+	int retval = 0;
+	do {
+		if (isa_readb(io_addr) != *signature)
+			goto out;
+		io_addr++;
+		signature++;
+		length--;
+	} while (length);
+	retval = 1;
+out:
+	return retval;
+}
+
+#endif /* __KERNEL__ */
+
+#ifdef SLOW_IO_BY_JUMPING
+#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
+#else
+#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+#endif
+
+#ifdef REALLY_SLOW_IO
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+#else
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+
+
+/*
+ * Talk about misusing macros..
+ */
+#define __OUT1(s,x) \
+static inline void out##s(unsigned x value, unsigned short port) {
+
+#define __OUT2(s,s1,s2) \
+__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
+
+
+#define __OUT(s,s1,x) \
+__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
+__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} 
+
+#define __IN1(s) \
+static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
+
+#define __IN2(s,s1,s2) \
+__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
+
+#define __IN(s,s1,i...) \
+__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
+__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } 
+
+#define __INS(s) \
+static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+{ __asm__ __volatile__ ("rep ; ins" #s \
+: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
+
+#define __OUTS(s) \
+static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+{ __asm__ __volatile__ ("rep ; outs" #s \
+: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
+
+#define RETURN_TYPE unsigned char
+__IN(b,"")
+#undef RETURN_TYPE
+#define RETURN_TYPE unsigned short
+__IN(w,"")
+#undef RETURN_TYPE
+#define RETURN_TYPE unsigned int
+__IN(l,"")
+#undef RETURN_TYPE
+
+__OUT(b,"b",char)
+__OUT(w,"w",short)
+__OUT(l,,int)
+
+__INS(b)
+__INS(w)
+__INS(l)
+
+__OUTS(b)
+__OUTS(w)
+__OUTS(l)
+
+#endif

+ 31 - 0
include/asm-i386/pci.h

@@ -0,0 +1,31 @@
+
+
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+#ifndef _PCI_I386_H_
+#define _PCI_I386_H_	1
+
+void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data);
+
+#endif

+ 80 - 0
include/asm-i386/posix_types.h

@@ -0,0 +1,80 @@
+#ifndef __ARCH_I386_POSIX_TYPES_H
+#define __ARCH_I386_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short	__kernel_dev_t;
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned short	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
+typedef unsigned short	__kernel_uid_t;
+typedef unsigned short	__kernel_gid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+
+typedef unsigned short	__kernel_old_uid_t;
+typedef unsigned short	__kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long	__kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+	int	val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+	int	__val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef	__FD_SET
+#define __FD_SET(fd,fdsetp) \
+		__asm__ __volatile__("btsl %1,%0": \
+			"=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef	__FD_CLR
+#define __FD_CLR(fd,fdsetp) \
+		__asm__ __volatile__("btrl %1,%0": \
+			"=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef	__FD_ISSET
+#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
+		unsigned char __result; \
+		__asm__ __volatile__("btl %1,%2 ; setb %0" \
+			:"=q" (__result) :"r" ((int) (fd)), \
+			"m" (*(__kernel_fd_set *) (fdsetp))); \
+		__result; }))
+
+#undef	__FD_ZERO
+#define __FD_ZERO(fdsetp) \
+do { \
+	int __d0, __d1; \
+	__asm__ __volatile__("cld ; rep ; stosl" \
+			:"=m" (*(__kernel_fd_set *) (fdsetp)), \
+			  "=&c" (__d0), "=&D" (__d1) \
+			:"a" (0), "1" (__FDSET_LONGS), \
+			"2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
+} while (0)
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif

+ 53 - 0
include/asm-i386/ppcboot-i386.h

@@ -0,0 +1,53 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+#ifndef _PPCBOOT_I386_H_
+#define _PPCBOOT_I386_H_	1
+
+/* for the following variables, see start.S */
+extern ulong i386boot_start;	    /* code start (in flash) */
+extern ulong i386boot_end;	    /* code end (in flash) */
+extern ulong i386boot_romdata_start;/* datasegment in flash (also code+rodata end) */
+extern ulong i386boot_romdata_dest; /* data location segment in ram */
+extern ulong i386boot_romdata_size; /* size of data segment */
+extern ulong i386boot_bss_start;    /* bss start */
+extern ulong i386boot_bss_size;     /* bss size */
+extern ulong i386boot_stack_end;    /* first usable RAM address after bss and stack */
+extern ulong i386boot_ram_end;      /* end of ram */
+
+extern ulong i386boot_realmode;     /* start of realmode entry code */
+extern ulong i386boot_realmode_size;/* size of realmode entry code */
+extern ulong i386boot_bios;         /* start of BIOS emulation code */
+extern ulong i386boot_bios_size;    /* size of BIOS emulation code */
+
+
+/* cpu/.../cpu.c */
+int cpu_init(void);
+int timer_init(void);
+
+/* board/.../... */
+int	board_init(void);
+int	dram_init (void);
+
+
+#endif	/* _PPCBOOT_I386_H_ */

+ 66 - 0
include/asm-i386/ptrace.h

@@ -0,0 +1,66 @@
+#ifndef _I386_PTRACE_H
+#define _I386_PTRACE_H
+
+#define EBX 0
+#define ECX 1
+#define EDX 2
+#define ESI 3
+#define EDI 4
+#define EBP 5
+#define EAX 6
+#define DS 7
+#define ES 8
+#define FS 9
+#define GS 10
+#define ORIG_EAX 11
+#define EIP 12
+#define CS  13
+#define EFL 14
+#define UESP 15
+#define SS   16
+#define FRAME_SIZE 17
+
+/* this struct defines the way the registers are stored on the 
+   stack during a system call. */
+
+struct pt_regs {
+	long ebx;
+	long ecx;
+	long edx;
+	long esi;
+	long edi;
+	long ebp;
+	long eax;
+	int  xds;
+	int  xes;
+	int  xfs;
+	int  xgs;
+	long orig_eax;
+	long eip;
+	int  xcs;
+	long eflags;
+	long esp;
+	int  xss;
+}  __attribute__ ((packed));
+
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_GETFPXREGS         18
+#define PTRACE_SETFPXREGS         19
+
+#define PTRACE_SETOPTIONS         21
+
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD     0x00000001
+
+#ifdef __KERNEL__
+#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
+#define instruction_pointer(regs) ((regs)->eip)
+extern void show_regs(struct pt_regs *);
+#endif
+
+#endif

+ 31 - 0
include/asm-i386/realmode.h

@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * 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
+ */
+
+#ifndef __ASM_REALMODE_H_
+#define __ASM_REALMODE_H_
+#include <asm/ptrace.h>
+
+int bios_setup(void);
+int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out);
+
+#endif

+ 30 - 0
include/asm-i386/string.h

@@ -0,0 +1,30 @@
+#ifndef __ASM_I386_STRING_H
+#define __ASM_I386_STRING_H
+
+/*
+ * We don't do inline string functions, since the
+ * optimised inline asm versions are not small.
+ */
+
+#define __HAVE_ARCH_STRRCHR
+extern char * strrchr(const char * s, int c);
+
+#define __HAVE_ARCH_STRCHR
+extern char * strchr(const char * s, int c);
+
+#define __HAVE_ARCH_MEMCPY
+extern void * memcpy(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMMOVE
+extern void * memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMCHR
+extern void * memchr(const void *, int, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMSET
+extern void * memset(void *, int, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMZERO
+extern void memzero(void *ptr, __kernel_size_t n);
+
+#endif

+ 51 - 0
include/asm-i386/types.h

@@ -0,0 +1,51 @@
+#ifndef __ASM_I386_TYPES_H
+#define __ASM_I386_TYPES_H
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide.  */
+
+typedef u32 dma_addr_t;
+
+#endif /* __KERNEL__ */
+
+#endif
+

+ 58 - 0
include/asm-i386/u-boot.h

@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ * 
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.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
+ */
+
+#ifndef _U_BOOT_H_
+#define _U_BOOT_H_	1
+
+typedef struct bd_info {
+	unsigned long	bi_memstart;	/* start of DRAM memory */
+	unsigned long	bi_memsize;	/* size	 of DRAM memory in bytes */
+	unsigned long	bi_flashstart;	/* start of FLASH memory */
+	unsigned long	bi_flashsize;	/* size	 of FLASH memory */
+	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
+	unsigned long	bi_sramstart;	/* start of SRAM memory */
+	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
+	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */
+	unsigned long	bi_ip_addr;	/* IP Address */
+	unsigned char	bi_enetaddr[6];	/* Ethernet adress */
+	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps */
+	unsigned long	bi_intfreq;	/* Internal Freq, in MHz */
+	unsigned long	bi_busfreq;	/* Bus Freq, in MHz */
+	unsigned long	bi_baudrate;	/* Console Baudrate */
+	struct environment_s	       *bi_env;
+	struct				/* RAM configuration */
+	{ 
+		ulong start;
+		ulong size;
+	}bi_dram[CONFIG_NR_DRAM_BANKS];
+} bd_t;
+
+#define bi_env_data bi_env->data
+#define bi_env_crc  bi_env->crc
+
+#endif	/* _U_BOOT_H_ */

+ 75 - 0
include/asm-i386/zimage.h

@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * 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
+ */
+
+#ifndef _ASM_ZIMAGE_H_
+#define _ASM_ZIMAGE_H_
+
+/* linux i386 zImage/bzImage header. Offsets relative to 
+ * the start of the image */
+
+#define CMD_LINE_MAGIC_OFF  0x020 /* Magic 0xa33f if the offset below is valid */
+#define CMD_LINE_OFFSET_OFF 0x022 /* Offset to comandline */
+#define SETUP_SECTS_OFF     0x1F1 /* The size of the setup in sectors */
+#define ROOT_FLAGS_OFF      0x1F2 /* If set, the root is mounted readonly */
+#define VID_MODE_OFF        0x1FA /* Video mode control */
+#define ROOT_DEV_OFF        0x1FC /* Default root device number */
+#define BOOT_FLAG_OFF       0x1FE /* 0xAA55 magic number */
+#define HEADER_OFF          0x202 /* Magic signature "HdrS" */
+#define VERSION_OFF         0x206 /* Boot protocol version supported */
+#define REALMODE_SWTCH_OFF  0x208 /* Boot loader hook (see below) */
+#define START_SYS_OFF       0x20C /* Points to kernel version string */
+#define TYPE_OF_LOADER_OFF  0x210 /* Boot loader identifier */
+#define LOADFLAGS_OFF       0x211 /* Boot protocol option flags */
+#define SETUP_MOVE_SIZE_OFF 0x212 /* Move to high memory size (used with hooks) */
+#define CODE32_START_OFF    0x214 /* Boot loader hook (see below) */
+#define RAMDISK_IMAGE_OFF   0x218 /* initrd load address (set by boot loader) */
+#define RAMDISK_SIZE_OFF    0x21C /* initrd size (set by boot loader) */
+#define HEAP_END_PTR_OFF    0x224 /* Free memory after setup end */
+#define CMD_LINE_PTR_OFF    0x228 /* 32-bit pointer to the kernel command line */
+
+
+#define HEAP_FLAG           0x80
+#define BIG_KERNEL_FLAG     0x01
+
+/* magic numbers */
+#define KERNEL_MAGIC        0xaa55
+#define KERNEL_V2_MAGIC     0x53726448
+#define COMMAND_LINE_MAGIC  0xA33F
+
+/* limits */
+#define BZIMAGE_MAX_SIZE   15*1024*1024     /* 15MB */
+#define ZIMAGE_MAX_SIZE    512*1024         /* 512k */
+#define SETUP_MAX_SIZE     32768
+
+#define SETUP_START_OFFSET 0x200
+#define BZIMAGE_LOAD_ADDR  0x100000 
+#define ZIMAGE_LOAD_ADDR   0x10000
+	
+void *load_zimage(char *image, unsigned long kernel_size, 
+		  unsigned long initrd_addr, unsigned long initrd_size,
+		  int auto_boot);
+
+void boot_zimage(void *setup_base);
+image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size);
+
+#endif

+ 4 - 3
include/cmd_confdefs.h

@@ -75,8 +75,8 @@
 #define CFG_CMD_FPGA	0x0000010000000000	/* FPGA configuration Support   */
 #define CFG_CMD_HWFLOW	0x0000020000000000	/* RTS/CTS hw flow control	*/
 #define CFG_CMD_SAVES	0x0000040000000000	/* save S record dump		*/
-#define CFG_CMD_VFD	0x0000080000000000	/* Display bitmap on VFD display*/
 #define CFG_CMD_SPI	0x0000100000000000	/* SPI utility			*/
+#define CFG_CMD_FDOS    0x0000200000000000      /* Floppy DOS support           */
 
 #define CFG_CMD_ALL	0xFFFFFFFFFFFFFFFF	/* ALL commands			*/
 
@@ -96,6 +96,7 @@
 			CFG_CMD_EEPROM	| \
 			CFG_CMD_ELF	| \
 			CFG_CMD_FDC	| \
+                        CFG_CMD_FDOS    | \
 			CFG_CMD_HWFLOW	| \
 			CFG_CMD_I2C	| \
 			CFG_CMD_IDE	| \
@@ -110,9 +111,9 @@
 			CFG_CMD_SAVES	| \
 			CFG_CMD_SCSI	| \
 			CFG_CMD_SDRAM	| \
+			CFG_CMD_SPI	| \
 			CFG_CMD_USB	| \
-			CFG_CMD_VFD	| \
-			CFG_CMD_SPI	)
+			CFG_CMD_VFD	)
 
 /* Default configuration
  */

+ 55 - 0
include/cmd_fdos.h

@@ -0,0 +1,55 @@
+/*
+ * (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
+ */
+#ifndef	_CMD_FDOS_H
+#define	_CMD_FDOS_H
+
+#include <common.h>
+#include <command.h>
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
+
+#define CMD_TBL_FDOS_BOOT	MK_CMD_TBL_ENTRY(       \
+	"fdosboot", 5,	3,	0,	do_fdosboot,    \
+	"fdosboot- boot from a dos floppy file\n",     \
+	"[loadAddr] [filename]\n"                       \
+),
+#define CMD_TBL_FDOS_LS	        MK_CMD_TBL_ENTRY(       \
+	"fdosls", 5,	2,	0,	do_fdosls,      \
+	"fdosls  - list files in a directory\n",       \
+	"[directory]\n"                                 \
+),
+int do_fdosboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+int do_fdosls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+#else
+#define CMD_TBL_FDOS_BOOT
+#define CMD_TBL_FDOS_LS
+#endif
+
+#endif	/* _CMD_FDOS_H */

+ 5 - 0
include/common.h

@@ -130,10 +130,15 @@ int	getenv_r     (uchar *name, uchar *buf, unsigned len);
 int	saveenv      (void);
 #ifdef CONFIG_PPC		/* ARM version to be fixed! */
 void inline setenv   (char *, char *);
+#else
+void    setenv       (char *, char *);
 #endif /* CONFIG_PPC */
 #ifdef CONFIG_ARM
 # include <asm/u-boot-arm.h>	/* ARM version to be fixed! */
 #endif /* CONFIG_ARM */
+#ifdef CONFIG_I386		/* x86 version to be fixed! */
+# include <asm/ppcboot-i386.h>  
+#endif /* CONFIG_I386 */
 
 void    pci_init      (void);
 void    pciinfo       (int, int);

+ 1 - 0
include/configs/LANTEC.h

@@ -90,6 +90,7 @@
 					     & ~CFG_CMD_EEPROM	\
 					     & ~CFG_CMD_ELF	\
 					     & ~CFG_CMD_FDC	\
+					     & ~CFG_CMD_FDOS	\
 					     & ~CFG_CMD_HWFLOW	\
 					     & ~CFG_CMD_I2C	\
 					     & ~CFG_CMD_IDE	\

+ 1 - 0
include/configs/MPC8260ADS.h

@@ -112,6 +112,7 @@
 				 CFG_CMD_EEPROM | \
 				 CFG_CMD_ELF    | \
 				 CFG_CMD_FDC	| \
+				 CFG_CMD_FDOS	| \
 				 CFG_CMD_HWFLOW	| \
 				 CFG_CMD_IDE	| \
 				 CFG_CMD_JFFS2	| \

+ 1 - 0
include/configs/ep8260.h

@@ -276,6 +276,7 @@
 					~CFG_CMD_DOC    & \
 					~CFG_CMD_EEPROM & \
 					~CFG_CMD_FDC    & \
+					~CFG_CMD_FDOS	& \
 					~CFG_CMD_HWFLOW	& \
 					~CFG_CMD_IDE    & \
 					~CFG_CMD_JFFS2	& \

+ 1 - 0
include/configs/hymod.h

@@ -141,6 +141,7 @@
 					CFG_CMD_DOC	| \
 					CFG_CMD_ELF	| \
 					CFG_CMD_FDC	| \
+					CFG_CMD_FDOS	| \
 					CFG_CMD_HWFLOW	| \
 					CFG_CMD_IDE	| \
 					CFG_CMD_JFFS2	| \

+ 210 - 0
include/configs/sc520_cdp.h

@@ -0,0 +1,210 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_X86		1	/* This is a X86 CPU		*/
+
+#define CFG_SDRAM_PRECHARGE_DELAY 6     /* 6T */	
+#define CFG_SDRAM_REFRESH_RATE    78    /* 7.8uS (choices are 7.8, 15.6, 31.2 or 62.5uS) */
+#define CFG_SDRAM_RAS_CAS_DELAY   3     /* 3T */
+
+/* define at most one of these */
+#undef CFG_SDRAM_CAS_LATENCY_2T
+#define CFG_SDRAM_CAS_LATENCY_3T
+
+#define CFG_SC520_HIGH_SPEED    0       /* 100 or 133MHz */
+#define CFG_RESET_GENERIC       1       /* use tripple-fault to reset cpu */
+#undef  CFG_RESET_SC520                 /* use SC520 MMCR's to reset cpu */
+#undef  CFG_TIMER_SC520                 /* use SC520 swtimers */
+#define CFG_TIMER_GENERIC       1       /* use the i8254 PIT timers */
+#undef  CFG_TIMER_TSC                   /* use the Pentium TSC timers */
+#define  CFG_USE_SIO_UART       0       /* prefer the uarts on the SIO to those
+					 * in the SC520 on the CDP */
+
+#define CFG_STACK_SIZE          0x8000  /* Size of bootloader stack */
+
+#define CONFIG_SHOW_BOOT_PROGRESS 1
+#define CONFIG_LAST_STAGE_INIT    1
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_MALLOC_SIZE	(CFG_ENV_SIZE + 128*1024)
+
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CFG_ENV_IS_NOWHERE 1
+#undef CFG_ENV_IS_IN_FLASH 
+#undef CFG_ENV_IS_IN_NVRAM 
+#undef CFG_ENV_IS_INEEPROM
+
+#define CONFIG_BAUDRATE		9600
+
+#define CONFIG_COMMANDS         (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_JFFS2 | CFG_CMD_IDE | CFG_CMD_NET)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#define CONFIG_BOOTDELAY	15
+#define CONFIG_BOOTARGS    	"root=/dev/mtdblock0 console=ttyS0,9600"
+/* #define CONFIG_BOOTCOMMAND	"bootm 38000000" */
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE	115200		/* speed to run kgdb serial port */
+#define CONFIG_KGDB_SER_INDEX	2		/* which serial port to use */
+#endif
+
+#define CFG_JFFS2_FIRST_BANK    0           /* use for JFFS2 */
+#define CFG_JFFS2_NUM_BANKS     1           /*  */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define	CFG_LONGHELP				/* undef to save memory		*/
+#define	CFG_PROMPT		"boot > "	/* Monitor Command Prompt	*/
+#define	CFG_CBSIZE		256		/* Console I/O Buffer Size	*/
+#define	CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define	CFG_MAXARGS		16		/* max number of command args	*/
+#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size	*/
+
+#define CFG_MEMTEST_START	0x00100000	/* memtest works on	*/
+#define CFG_MEMTEST_END		0x01000000	/* 1 ... 16 MB in DRAM	*/
+
+#undef  CFG_CLKS_IN_HZ		/* everything, incl board info, in Hz */
+
+#define	CFG_LOAD_ADDR		0x38000000	/* default load address	*/
+
+#define	CFG_HZ			1024		/* incrementer freq: 1kHz */
+
+						/* valid baudrates */
+#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS	4	   /* we have 4 banks of DRAM */
+
+
+#define PHYS_FLASH_1		0x38000000 /* Flash Bank #1 */
+#define PHYS_FLASH_SIZE		0x00800000 /* 8 MB */
+
+#define CFG_FLASH_BASE		PHYS_FLASH_1
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+#define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks		*/
+#define CFG_MAX_FLASH_SECT	64	/* max number of sectors on one chip	*/
+
+/* timeout values are in ticks */
+#define CFG_FLASH_ERASE_TOUT	(2*CFG_HZ) /* Timeout for Flash Erase */
+#define CFG_FLASH_WRITE_TOUT	(2*CFG_HZ) /* Timeout for Flash Write */
+
+#define	CFG_ENV_IS_IN_FLASH	1
+#define CFG_ENV_ADDR		(PHYS_FLASH_1 + 0x7a0000)	/* Addr of Environment Sector	*/
+#define CFG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/
+
+
+/*-----------------------------------------------------------------------
+ * Device drivers
+ */
+#define CONFIG_NET_MULTI        /* Multi ethernet cards support */
+#define CONFIG_PCNET
+#define CONFIG_PCNET_79C973
+#define CONFIG_PCNET_79C975
+#define PCNET_HAS_PROM         1
+/************************************************************
+ * IDE/ATA stuff
+ ************************************************************/
+#define CFG_IDE_MAXBUS		2   /* max. 2 IDE busses	*/
+#define CFG_IDE_MAXDEVICE	(CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */
+
+#define CFG_ATA_IDE0_OFFSET	0x01F0	/* ide0 offste */
+#define CFG_ATA_IDE1_OFFSET	0x0170	/* ide1 offset */
+#define CFG_ATA_DATA_OFFSET	0	/* data reg offset	*/
+#define CFG_ATA_REG_OFFSET	0	/* reg offset */
+#define CFG_ATA_ALT_OFFSET	0x200	/* alternate register offset */
+
+#undef	CONFIG_IDE_8xx_DIRECT		/* no pcmcia interface required */
+#undef	CONFIG_IDE_LED			/* no led for ide supported	*/
+#undef  CONFIG_IDE_RESET		/* reset for ide unsupported...	*/
+#undef  CONFIG_IDE_RESET_ROUTINE	/* no special reset function */
+
+/************************************************************
+ * ATAPI support (experimental)
+ ************************************************************/
+#define CONFIG_ATAPI			/* enable ATAPI Support */
+
+/************************************************************
+ * DISK Partition support
+ ************************************************************/
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION /* Experimental */
+
+/************************************************************
+ * Keyboard support
+ ************************************************************/
+#define CONFIG_ISA_KEYBOARD
+
+#if 0
+/************************************************************
+ * Video support
+ ************************************************************/
+#define CONFIG_VIDEO			/*To enable video controller support */
+#define CONFIG_VIDEO_CT69000
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_CONSOLE_EXTRA_INFO
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_VIDEO_SW_CURSOR
+#define CONFIG_VIDEO_ONBOARD		/* Video controller is on-board */
+#endif
+
+/************************************************************
+ * RTC
+ ***********************************************************/
+#define CONFIG_RTC_MC146818
+#undef CONFIG_WATCHDOG			/* watchdog disabled		*/
+
+/*
+ * PCI stuff
+ */
+#define CONFIG_PCI                                /* include pci support */
+#define CONFIG_PCI_PNP                            /* pci plug-and-play */
+#define CONFIG_PCI_SCAN_SHOW
+
+#endif	/* __CONFIG_H */

+ 41 - 0
include/fdc.h

@@ -0,0 +1,41 @@
+/*
+ * (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
+ */
+
+#ifndef _FDC_H_
+#define _FDC_H_
+
+
+
+/* Functions prototype                                                       */
+int fdc_fdos_init (int drive);
+int fdc_fdos_seek (int where);
+int fdc_fdos_read (void *buffer, int len);
+
+int dos_open(char *name);
+int dos_read (ulong addr);
+int dos_dir (void);
+
+
+
+#endif

+ 1 - 1
include/linux/stat.h

@@ -67,7 +67,7 @@ struct stat {
 
 #endif	/* __PPC__ */
 
-#ifdef	__ARM__
+#if defined (__ARM__) || defined (__I386__)
 
 struct stat {
 	unsigned short st_dev;

+ 45 - 0
lib_i386/Makefile

@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2002
+# 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 $(TOPDIR)/config.mk
+
+LIB	= lib$(ARCH).a
+
+AOBJS	= bios.o realmode_switch.o ic/sc520_asm.o
+
+COBJS	= board.o bios_setup.o i386_linux.o zimage.o realmode.o \
+	  pci_type1.o ic/sc520.o ic/ali512x.o
+
+OBJS	= $(AOBJS) $(COBJS)
+
+$(LIB):	.depend $(OBJS)
+	$(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend:	Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c)
+		$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################

+ 443 - 0
lib_i386/bios.S

@@ -0,0 +1,443 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * 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
+ */
+
+/*
+ * Based on msbios.c from rolo 1.6:
+ *----------------------------------------------------------------------
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions GmbH
+ * Klein-Winternheim, Germany
+ *----------------------------------------------------------------------
+ */
+
+/*
+ * During it's initialization phase, before switching to protected
+ * mode, the Linux Kernel makes a few BIOS calls. This won't work
+ * if the board does not have a BIOS.
+ *
+ * This is a very minimalisic BIOS that supplies just enough
+ * functionality to keep the Linux Kernel happy. It is NOT
+ * a general purpose replacement for a real BIOS !!
+ */
+
+#define OFFS_ES      0
+#define OFFS_GS      2
+#define OFFS_DS      4
+#define OFFS_DI      6
+#define OFFS_SI      8
+#define OFFS_BP      10
+#define OFFS_SP      12
+#define OFFS_BX      14
+#define OFFS_DX      16
+#define OFFS_CX      18
+#define OFFS_AX      20
+#define OFFS_VECTOR  22
+#define OFFS_IP      24
+#define OFFS_CS      26
+#define OFFS_FLAGS   28
+
+#define SEGMENT      0x40
+#define STACK	     0x800  			/* stack at 0x40:0x800 -> 0x800 */
+
+.section .bios, "ax"
+.code16
+.org 0
+
+.globl rm_int00
+rm_int00:
+	pushw	$0
+	jmp	any_interrupt16
+.globl rm_int01
+rm_int01:
+	pushw	$1
+	jmp	any_interrupt16
+.globl rm_int02
+rm_int02:
+	pushw	$2
+	jmp	any_interrupt16
+.globl rm_int03
+rm_int03:
+	pushw	$3
+	jmp	any_interrupt16
+.globl rm_int04
+rm_int04:
+	pushw	$4
+	jmp	any_interrupt16
+.globl rm_int05
+rm_int05:
+	pushw	$5
+	jmp	any_interrupt16
+.globl rm_int06
+rm_int06:
+	pushw	$6
+	jmp	any_interrupt16
+.globl rm_int07
+rm_int07:
+	pushw	$7
+	jmp	any_interrupt16
+.globl rm_int08
+rm_int08:
+	pushw	$8
+	jmp	any_interrupt16
+.globl rm_int09
+rm_int09:
+	pushw	$9
+	jmp	any_interrupt16
+.globl rm_int0a
+rm_int0a:
+	pushw	$10
+	jmp	any_interrupt16
+.globl rm_int0b
+rm_int0b:
+	pushw	$11
+	jmp	any_interrupt16
+.globl rm_int0c
+rm_int0c:
+	pushw	$12
+	jmp	any_interrupt16
+.globl rm_int0d
+rm_int0d:
+	pushw	$13
+	jmp	any_interrupt16
+.globl rm_int0e
+rm_int0e:
+	pushw	$14
+	jmp	any_interrupt16
+.globl rm_int0f
+rm_int0f:
+	pushw	$15
+	jmp	any_interrupt16
+.globl rm_int10
+rm_int10:
+	pushw	$16
+	jmp	any_interrupt16
+.globl rm_int11
+rm_int11:
+	pushw	$17
+	jmp	any_interrupt16
+.globl rm_int12
+rm_int12:
+	pushw	$18
+	jmp	any_interrupt16
+.globl rm_int13
+rm_int13:
+	pushw	$19
+	jmp	any_interrupt16
+.globl rm_int14
+rm_int14:
+	pushw	$20
+	jmp	any_interrupt16
+.globl rm_int15
+rm_int15:
+	pushw	$21
+	jmp	any_interrupt16
+.globl rm_int16
+rm_int16:
+	pushw	$22
+	jmp	any_interrupt16
+.globl rm_int17
+rm_int17:
+	pushw	$23
+	jmp	any_interrupt16
+.globl rm_int18
+rm_int18:
+	pushw	$24
+	jmp	any_interrupt16
+.globl rm_int19
+rm_int19:
+	pushw	$25
+	jmp	any_interrupt16
+.globl rm_int1a
+rm_int1a:
+	pushw	$26
+	jmp	any_interrupt16
+.globl rm_int1b
+rm_int1b:
+	pushw	$27
+	jmp	any_interrupt16
+.globl rm_int1c
+rm_int1c:
+	pushw	$28
+	jmp	any_interrupt16
+.globl rm_int1d
+rm_int1d:
+	pushw	$29
+	jmp	any_interrupt16
+.globl rm_int1e
+rm_int1e:
+	pushw	$30
+	jmp	any_interrupt16
+.globl rm_int1f
+rm_int1f:
+	pushw	$31
+	jmp	any_interrupt16
+.globl rm_def_int
+rm_def_int:
+	iret
+
+ 
+	/*
+	 * All interrupt jumptable entries jump to here
+	 * after pushing the interrupt vector number onto the
+	 * stack.
+	 */
+any_interrupt16:
+	pusha					/* save general registers */
+	pushw	%ds				/* save some segments     */
+	pushw	%gs
+	pushw	%es
+	pushw	%ss				/* save callers stack segment .. */
+	popw	%gs				/* ... in gs */
+	movw	$SEGMENT,%ax			/* setup my segments */
+	movw	%ax,%ds
+	movw	%ax,%es
+	movw	%ax,%ss
+	movw	%sp,%bp
+	movw	$STACK,%sp			/* setup BIOS stackpointer */
+
+gs	movw	OFFS_VECTOR(%bp), %ax
+	cmpw	$0x10, %ax
+	je	Lint_10h         
+	cmpw	$0x11, %ax
+	je	Lint_11h
+	cmpw	$0x13, %ax
+	je	Lint_13h
+	cmpw	$0x15, %ax
+	je	Lint_15h
+	cmpw	$0x16, %ax
+	je	Lint_16h
+	movw	$0xffff, %ax
+	jmp	Lout
+Lint_10h:					/* VGA BIOS services */
+	call	bios_10h
+	jmp	Lout
+Lint_11h:	
+	call	bios_11h
+	jmp	Lout
+Lint_13h:					/* BIOS disk services */
+	call	bios_13h
+	jmp	Lout
+Lint_15h:					/* Misc. BIOS services */
+	call	bios_15h
+	jmp	Lout
+Lint_16h:					/* keyboard services */
+	call	bios_16h
+	jmp	Lout
+Lout:	
+	cmpw	$0, %ax
+	je	Lhandeled
+	
+	/* Insert code for unhandeled INTs here.
+	 *
+	 * ROLO prints a message to the console 
+	 * (we could do that but then we're in 16bit mode
+	 * so we'll have to get back into 32bit mode
+	 * to use the console I/O routines (if we do this
+	 * we shuls make int 0x10 and int 0x16 work as well))
+	 */
+Lhandeled:
+
+	pushw	%gs				/* restore callers stack segment */
+	popw	%ss
+	movw	%bp,%sp				/* restore stackpointer */
+
+	popw	%es				/* restore segment selectors */
+	popw	%gs
+	popw	%ds
+	
+	popa					/* restore GP registers */
+	addw	$2,%sp				/* dump vector number */
+	iret					/* return from interrupt */
+
+
+/*
+ ************************************************************
+ * BIOS 	interrupt 10h -- VGA services
+ ************************************************************
+ */
+bios_10h:
+gs	movw	OFFS_AX(%bp), %ax
+	shrw	$8, %ax
+	cmpw	$0x3, %ax
+	je	Lcur_pos
+	cmpw	$0xf, %ax
+	je	Lvid_state
+	cmpw	$0x12, %ax
+	je	Lvid_cfg
+	movw	$0xffff, %ax
+	ret
+Lcur_pos:					/* Read Cursor Position and Size */
+gs	movw	$0, OFFS_CX(%bp)
+gs	movw	$0, OFFS_DX(%bp)
+	xorw	%ax, %ax
+	ret
+Lvid_state:					/* Get Video State */
+gs	movw	$(80 << 8|0x03), OFFS_AX(%bp)	/* 80 columns, 80x25, 16 colors */
+gs	movw	$0, OFFS_BX(%bp)
+	xorw	%ax, %ax
+	ret
+Lvid_cfg:	/* Video Subsystem Configuration (EGA/VGA) */
+gs	movw	$0x10, OFFS_BX(%bp)		/* indicate CGA/MDA/HGA */
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 11h -- Equipment determination
+ ************************************************************
+ */
+
+bios_11h:
+	movw	bios_equipment, %ax
+gs	movw	%ax, OFFS_AX(%bp)  
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 13h -- Disk services
+ ************************************************************
+ */
+bios_13h:
+gs	movw	OFFS_AX(%bp), %ax
+	shrw	$8, %ax
+	cmpw	$0x15, %ax
+	je	Lfunc_15h
+	movw	$0xffff, %ax
+	ret
+Lfunc_15h:	
+gs	movw	OFFS_AX(%bp), %ax
+	andw	$0xff, %ax			/* return AH=0->drive not present */
+gs	movw	%ax, OFFS_AX(%bp)
+	xorw	%ax, %ax
+	ret
+	
+	
+
+/*
+ ***********************************************************
+ * BIOS interrupt 15h -- Miscellaneous services
+ ***********************************************************
+ */
+bios_15h:
+gs	movw	OFFS_AX(%bp), %ax
+	shrw	$8, %ax
+	cmpw	$0xc0, %ax
+	je	Lfunc_c0h
+	cmpw	$0xe8, %ax
+	je	Lfunc_e8h
+	cmpw	$0x88, %ax
+	je	Lfunc_88h
+	movw	$0xffff, %ax
+	ret
+
+Lfunc_c0h: 					/* Return System Configuration Parameters (PS2 only) */
+gs	movw	OFFS_FLAGS(%bp), %ax
+	orw	$1, %ax				/* return carry -- function not supported */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+	ret
+	
+Lfunc_e8h:
+gs	movw	OFFS_AX(%bp), %ax
+	andw	$0xff, %ax
+	cmpw	$1, %ax
+	je	Lfunc_e801h
+gs	movw	OFFS_FLAGS(%bp), %ax
+	orw	$1, %ax				/* return carry -- function not supported */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+	ret
+	
+Lfunc_e801h:					/* Get memory size for >64M Configurations */
+	movw	$ram_in_64kb_chunks, %ax
+	cmpw	$256, %ax
+	ja	Lmore_than_16mb
+	shlw	$6, %ax				/* multiply by 64 */	
+gs	movw	%ax, OFFS_AX(%bp)   		/* return memory size in 1kb chunks in AX and CX */
+gs	movw	%ax, OFFS_CX(%bp)
+	xorw	%ax, %ax
+gs	movw	%ax, OFFS_BX(%bp)		/* set BX and DX to 0*/
+gs	movw	%ax, OFFS_DX(%bp)	
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+	ret
+	
+Lmore_than_16mb:
+	subw	$0x100, %ax			/* subtract 16MB */	
+	
+gs	movw	$0x3c00, OFFS_AX(%bp)		/* return 0x3c00 (16MB-384k) in AX and CX */
+gs	movw	$0x3c00, OFFS_CX(%bp)
+gs	movw	%ax, OFFS_BX(%bp)		/* set BX and DX to number of 64kb chunks - 256 */
+gs	movw	%ax, OFFS_DX(%bp)	
+
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+	xorw	%ax, %ax
+	ret
+
+Lfunc_88h:
+	movw	ram_in_64kb_chunks, %ax
+	subw	$16, %ax
+	shlw	$6, %ax
+	
+gs	movw	%ax, OFFS_AX(%bp)		/* return number of kilobytes in ax */
+
+gs	movw	OFFS_FLAGS(%bp), %ax
+	andw	$0xfffe, %ax			/* clear carry -- function succeeded */
+gs	movw	%ax, OFFS_FLAGS(%bp)
+
+	xorw	%ax, %ax
+	ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 16h -- keyboard services
+ ************************************************************
+ */
+bios_16h:
+gs	movw	OFFS_AX(%bp), %ax
+	shrw	$8, %ax
+	cmpw	$0x03, %ax
+	je	Lfunc_03h
+	movw	$0xffff, %ax
+	ret
+Lfunc_03h:
+	xorw	%ax, %ax			/* do nothing -- function not supported */
+	ret
+
+
+.globl ram_in_64kb_chunks
+ram_in_64kb_chunks:
+	.word 	0
+
+.globl bios_equipment
+bios_equipment:
+	.word 	0
+

+ 178 - 0
lib_i386/bios_setup.c

@@ -0,0 +1,178 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * 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
+ */
+
+
+/*
+ * Partly based on msbios.c from rolo 1.6:
+ *----------------------------------------------------------------------
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions GmbH
+ * Klein-Winternheim, Germany
+ *----------------------------------------------------------------------
+ */
+
+#include <common.h>
+#include <asm/realmode.h>
+#include <asm/io.h>
+
+#define NUMVECTS	256
+
+#define BIOS_DATA        ((char*)0x400)
+#define BIOS_DATA_SIZE   256
+#define BIOS_BASE        ((char*)0xf0000)
+#define BIOS_CS          0xf000
+
+extern u16 ram_in_64kb_chunks;
+extern u16 bios_equipment;
+extern void *rm_int00;
+extern void *rm_int01;
+extern void *rm_int02;
+extern void *rm_int03;
+extern void *rm_int04;
+extern void *rm_int05;
+extern void *rm_int06;
+extern void *rm_int07;
+extern void *rm_int08;
+extern void *rm_int09;
+extern void *rm_int0a;
+extern void *rm_int0b;
+extern void *rm_int0c;
+extern void *rm_int0d;
+extern void *rm_int0e;
+extern void *rm_int0f;
+extern void *rm_int10;
+extern void *rm_int11;
+extern void *rm_int12;
+extern void *rm_int13;
+extern void *rm_int14;
+extern void *rm_int15;
+extern void *rm_int16;
+extern void *rm_int17;
+extern void *rm_int18;
+extern void *rm_int19;
+extern void *rm_int1a;
+extern void *rm_int1b;
+extern void *rm_int1c;
+extern void *rm_int1d;
+extern void *rm_int1e;
+extern void *rm_int1f;
+extern void *rm_def_int;
+
+/*
+ ************************************************************
+ * Install an interrupt vector
+ ************************************************************
+ */
+
+static void setvector(int vector, u16 segment, void *handler)
+{
+	u16 *ptr = (u16*)(vector*4);
+	ptr[0] = ((u32)handler - (segment << 4))&0xffff;
+	ptr[1] = segment;
+	
+#if 0	
+	printf("setvector: int%02x -> %04x:%04x\n",
+	       vector, ptr[1], ptr[0]);
+#endif	
+}
+
+int bios_setup(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	static int done=0;	
+	int vector;
+	
+	if (done) {
+		return 0;
+	}
+	done = 1;
+	
+	if (i386boot_bios_size > 65536) {
+		printf("BIOS too large (%ld bytes, max is 65536)\n", 
+		       i386boot_bios_size);
+		return -1;
+	}
+	
+	memcpy(BIOS_BASE, (void*)i386boot_bios, i386boot_bios_size);
+
+	/* clear bda */
+	memset(BIOS_DATA, 0, BIOS_DATA_SIZE);
+	
+	/* enter some values to the bda */
+	writew(0x3f8, BIOS_DATA);   /* com1 addr */
+	writew(0x2f8, BIOS_DATA+2); /* com2 addr */
+	writew(0x3e8, BIOS_DATA+4); /* com3 addr */
+	writew(0x2e8, BIOS_DATA+6); /* com4 addr */
+	writew(0x278, BIOS_DATA+8); /* lpt1 addr */
+	/*
+	 * The kernel wants to read the base memory size
+	 * from 40:13. Put a zero there to avoid an error message
+	 */
+	writew(0, BIOS_DATA+0x13);  /* base memory size */
+
+	
+	/* setup realmode interrupt vectors */	
+	for (vector = 0; vector < NUMVECTS; vector++) {
+		setvector(vector, BIOS_CS, &rm_def_int);
+	}
+	
+	setvector(0x00, BIOS_CS, &rm_int00);
+	setvector(0x01, BIOS_CS, &rm_int01);
+	setvector(0x02, BIOS_CS, &rm_int02);
+	setvector(0x03, BIOS_CS, &rm_int03);
+	setvector(0x04, BIOS_CS, &rm_int04);
+	setvector(0x05, BIOS_CS, &rm_int05);
+	setvector(0x06, BIOS_CS, &rm_int06);
+	setvector(0x07, BIOS_CS, &rm_int07);
+	setvector(0x08, BIOS_CS, &rm_int08);
+	setvector(0x09, BIOS_CS, &rm_int09);
+	setvector(0x0a, BIOS_CS, &rm_int0a);
+	setvector(0x0b, BIOS_CS, &rm_int0b);
+	setvector(0x0c, BIOS_CS, &rm_int0c);
+	setvector(0x0d, BIOS_CS, &rm_int0d);
+	setvector(0x0e, BIOS_CS, &rm_int0e);
+	setvector(0x0f, BIOS_CS, &rm_int0f);
+	setvector(0x10, BIOS_CS, &rm_int10);
+	setvector(0x11, BIOS_CS, &rm_int11);
+	setvector(0x12, BIOS_CS, &rm_int12);
+	setvector(0x13, BIOS_CS, &rm_int13);
+	setvector(0x14, BIOS_CS, &rm_int14);
+	setvector(0x15, BIOS_CS, &rm_int15);
+	setvector(0x16, BIOS_CS, &rm_int16);
+	setvector(0x17, BIOS_CS, &rm_int17);
+	setvector(0x18, BIOS_CS, &rm_int18);
+	setvector(0x19, BIOS_CS, &rm_int19);
+	setvector(0x1a, BIOS_CS, &rm_int1a);
+	setvector(0x1b, BIOS_CS, &rm_int1b);
+	setvector(0x1c, BIOS_CS, &rm_int1c);
+	setvector(0x1d, BIOS_CS, &rm_int1d);
+	setvector(0x1e, BIOS_CS, &rm_int1e);
+	setvector(0x1f, BIOS_CS, &rm_int1f);
+
+	/* fill in data area */
+	ram_in_64kb_chunks = gd->ram_size >> 16;
+	bios_equipment = 0; /* FixMe */
+	
+	return 0;
+}
+

+ 448 - 0
lib_i386/board.c

@@ -0,0 +1,448 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * 
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.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 <watchdog.h>
+#include <command.h>
+#include <devices.h>
+#include <version.h>
+#include <malloc.h>
+#include <syscall.h>
+#include <net.h>
+#include <ide.h>
+
+extern long _i386boot_start;	    
+extern long _i386boot_end;	    
+extern long _i386boot_romdata_start;
+extern long _i386boot_romdata_dest; 
+extern long _i386boot_romdata_size; 
+extern long _i386boot_bss_start;   
+extern long _i386boot_bss_size;    
+
+extern long _i386boot_realmode;    
+extern long _i386boot_realmode_size;
+extern long _i386boot_bios;         
+extern long _i386boot_bios_size;    
+
+/* The symbols defined by the linker script becomes pointers
+ * which is somewhat inconveient ... */
+ulong i386boot_start         = (ulong)&_i386boot_start;         /* code start (in flash) defined in start.S */
+ulong i386boot_end           = (ulong)&_i386boot_end;	        /* code end (in flash) */
+ulong i386boot_romdata_start = (ulong)&_i386boot_romdata_start; /* datasegment in flash (also code+rodata end) */
+ulong i386boot_romdata_dest  = (ulong)&_i386boot_romdata_dest;  /* data location segment in ram */
+ulong i386boot_romdata_size  = (ulong)&_i386boot_romdata_size;  /* size of data segment */
+ulong i386boot_bss_start     = (ulong)&_i386boot_bss_start;     /* bss start */
+ulong i386boot_bss_size      = (ulong)&_i386boot_bss_size;      /* bss size */
+
+ulong i386boot_realmode      = (ulong)&_i386boot_realmode;      /* start of realmode entry code */
+ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size; /* size of realmode entry code */
+ulong i386boot_bios          = (ulong)&_i386boot_bios;          /* start of BIOS emulation code */
+ulong i386boot_bios_size     = (ulong)&_i386boot_bios_size;     /* size of BIOS emulation code */
+
+
+const char version_string[] =
+	U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")";
+
+
+/*
+ * Begin and End of memory area for malloc(), and current "brk"
+ */
+static ulong mem_malloc_start = 0;
+static ulong mem_malloc_end = 0;
+static ulong mem_malloc_brk = 0;
+
+static int mem_malloc_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+        
+#if 1	
+	/* start malloc area right after the stack */
+	mem_malloc_start = i386boot_bss_start + 
+		i386boot_bss_size + CFG_STACK_SIZE;
+	mem_malloc_start = (mem_malloc_start+3)&~3;
+#else
+	mem_malloc_start = 0x400000;
+#endif	
+#if 1
+	/* Use all available RAM for malloc() */
+	mem_malloc_end = gd->ram_size;
+#else	
+	/* Use only  CONFIG_MALLOC_SIZE bytes of RAM for malloc() */
+	mem_malloc_end = mem_malloc_start + CONFIG_MALLOC_SIZE;
+#endif	
+	mem_malloc_brk = mem_malloc_start;
+
+	return 0;
+}
+
+void *sbrk (ptrdiff_t increment)
+{
+	ulong old = mem_malloc_brk;
+	ulong new = old + increment;
+
+	if ((new < mem_malloc_start) || (new > mem_malloc_end)) {
+		return (NULL);
+	}
+	mem_malloc_brk = new;
+
+	return ((void *) old);
+}
+
+char *strmhz (char *buf, long hz)
+{
+	long l, n;
+	long m;
+
+	n = hz / 1000000L;
+	l = sprintf (buf, "%ld", n);
+	m = (hz % 1000000L) / 1000L;
+	if (m != 0)
+		sprintf (buf + l, ".%03ld", m);
+	return (buf);
+}
+
+/************************************************************************
+ * Init Utilities							*
+ ************************************************************************
+ * Some of this code should be moved into the core functions,
+ * or dropped completely,
+ * but let's get it working (again) first...
+ */
+static void syscalls_init (void)
+{
+	syscall_tbl[SYSCALL_MALLOC] = (void *) malloc;
+	syscall_tbl[SYSCALL_FREE] = (void *) free;
+
+	syscall_tbl[SYSCALL_INSTALL_HDLR] = (void *) irq_install_handler;
+	syscall_tbl[SYSCALL_FREE_HDLR] = (void *) irq_free_handler;
+
+}
+
+static int init_baudrate (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	uchar tmp[64];	/* long enough for environment variables */
+	int i = getenv_r ("baudrate", tmp, sizeof (tmp));
+
+	gd->baudrate = (i > 0)
+			? (int) simple_strtoul (tmp, NULL, 10)
+			: CONFIG_BAUDRATE;
+
+	return (0);
+}
+
+static int display_banner (void)
+{
+
+	printf ("\n\n%s\n\n", version_string);
+	printf ("U-Boot code: %08lX -> %08lX  data: %08lX -> %08lX\n"
+		"        BSS: %08lX -> %08lX stack: %08lX -> %08lX\n",
+		i386boot_start, i386boot_romdata_start-1,
+		i386boot_romdata_dest, i386boot_romdata_dest+i386boot_romdata_size-1,
+		i386boot_bss_start, i386boot_bss_start+i386boot_bss_size-1,
+		i386boot_bss_start+i386boot_bss_size, 
+		i386boot_bss_start+i386boot_bss_size+CFG_STACK_SIZE-1);
+	
+
+	return (0);
+}
+
+/*
+ * WARNING: this code looks "cleaner" than the PowerPC version, but
+ * has the disadvantage that you either get nothing, or everything.
+ * On PowerPC, you might see "DRAM: " before the system hangs - which
+ * gives a simple yet clear indication which part of the
+ * initialization if failing.
+ */
+static int display_dram_config (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	int i;
+
+	puts ("DRAM Configuration:\n");
+
+	for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
+		printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
+		print_size (gd->bd->bi_dram[i].size, "\n");
+	}
+	
+	return (0);
+}
+
+static void display_flash_config (ulong size)
+{
+	puts ("Flash: ");
+	print_size (size, "\n");
+}
+
+
+
+/*
+ * Breath some life into the board...
+ *
+ * Initialize an SMC for serial comms, and carry out some hardware
+ * tests.
+ *
+ * The first part of initialization is running from Flash memory;
+ * its main purpose is to initialize the RAM so that we
+ * can relocate the monitor code to RAM.
+ */
+
+/*
+ * All attempts to come up with a "common" initialization sequence
+ * that works for all boards and architectures failed: some of the
+ * requirements are just _too_ different. To get rid of the resulting
+ * mess of board dependend #ifdef'ed code we now make the whole
+ * initialization sequence configurable to the user.
+ *
+ * The requirements for any new initalization function is simple: it
+ * receives a pointer to the "global data" structure as it's only
+ * argument, and returns an integer return code, where 0 means
+ * "continue" and != 0 means "fatal error, hang the system".
+ */
+typedef int (init_fnc_t) (void);
+
+init_fnc_t *init_sequence[] = {
+	cpu_init,		/* basic cpu dependent setup */
+	board_init,		/* basic board dependent setup */
+	dram_init,		/* configure available RAM banks */
+	mem_malloc_init,        /* dependant on dram_init */
+	interrupt_init,		/* set up exceptions */
+	timer_init,	
+	env_init,		/* initialize environment */
+	init_baudrate,		/* initialze baudrate settings */
+	serial_init,		/* serial communications setup */
+	display_banner,
+	display_dram_config,
+
+	NULL,
+};
+
+gd_t *global_data;
+
+void start_i386boot (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	char *s;
+	int i;
+	ulong size;
+	static gd_t gd_data;
+	static bd_t bd_data;
+	init_fnc_t **init_fnc_ptr;
+	
+	show_boot_progress(0x21);
+
+	gd = global_data = &gd_data;
+	
+	memset (gd, 0, sizeof (gd_t));
+	gd->bd = &bd_data;
+	memset (gd->bd, 0, sizeof (bd_t));
+	show_boot_progress(0x22);
+
+	
+	for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) {
+		show_boot_progress(0xa130|i);
+
+		if ((*init_fnc_ptr)() != 0) {
+			hang ();
+		}
+	}
+	show_boot_progress(0x23);
+
+	/* configure available FLASH banks */
+	size = flash_init();
+	display_flash_config(size);
+	show_boot_progress(0x24);
+
+	show_boot_progress(0x25);
+
+	/* initialize environment */
+	env_relocate ();
+	show_boot_progress(0x26);
+
+
+	/* IP Address */
+	bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+	/* MAC Address */
+	{
+		int i;
+		ulong reg;
+		char *s, *e;
+		uchar tmp[64];
+
+		i = getenv_r ("ethaddr", tmp, sizeof (tmp));
+		s = (i > 0) ? tmp : NULL;
+
+		for (reg = 0; reg < 6; ++reg) {
+			bd_data.bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
+			if (s)
+				s = (*e) ? e + 1 : e;
+		}
+	}
+
+#if defined(CONFIG_PCI)
+	/*
+	 * Do pci configuration
+	 */
+	pci_init();
+#endif
+
+	show_boot_progress(0x27);
+
+
+	devices_init ();
+
+	/* allocate syscalls table (console_init_r will fill it in */
+	syscall_tbl = (void **) malloc (NR_SYSCALLS * sizeof (void *));
+
+	/* Initialize the console (after the relocation and devices init) */
+	console_init_r();
+	syscalls_init();
+
+#ifdef CONFIG_MISC_INIT_R
+	/* miscellaneous platform dependent initialisations */
+	misc_init_r();
+#endif
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && (0)
+	WATCHDOG_RESET();
+# ifdef DEBUG
+	puts ("Reset Ethernet PHY\n");
+# endif
+	reset_phy();
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) && !(CONFIG_COMMANDS & CFG_CMD_IDE)
+	WATCHDOG_RESET();
+	puts ("PCMCIA:");
+	pcmcia_init();
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+	WATCHDOG_RESET();
+	puts("KGDB:  ");
+	kgdb_init();
+#endif
+
+	/* enable exceptions */
+	enable_interrupts ();
+	show_boot_progress(0x28);
+
+	/* Must happen after interrupts are initialized since
+	 * an irq handler gets installed
+	 */
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+	serial_buffered_init();
+#endif
+    
+#ifdef CONFIG_STATUS_LED
+	status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
+#endif
+
+	udelay (20);
+
+	set_timer (0);
+
+	/* Initialize from environment */
+	if ((s = getenv ("loadaddr")) != NULL) {
+		load_addr = simple_strtoul (s, NULL, 16);
+	}
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+	if ((s = getenv ("bootfile")) != NULL) {
+		copy_filename (BootFile, s, sizeof (BootFile));
+	}
+#endif /* CFG_CMD_NET */
+
+	WATCHDOG_RESET();
+
+#if (CONFIG_COMMANDS & CFG_CMD_IDE)
+	WATCHDOG_RESET();
+	puts("IDE:   ");
+	ide_init();
+#endif /* CFG_CMD_IDE */
+
+#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
+	WATCHDOG_RESET();
+	puts("SCSI:  ");
+	scsi_init();
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_DOC)
+	WATCHDOG_RESET();
+	puts ("DOC:   ");
+	doc_init();
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI)
+	WATCHDOG_RESET();
+	puts("Net:   ");
+	eth_initialize(gd->bd);
+#endif
+
+#ifdef CONFIG_LAST_STAGE_INIT
+	WATCHDOG_RESET();
+	/*
+	 * Some parts can be only initialized if all others (like
+	 * Interrupts) are up and running (i.e. the PC-style ISA
+	 * keyboard).
+	 */
+	last_stage_init();
+#endif
+
+
+
+#ifdef CONFIG_POST
+	post_run (NULL, POST_RAM | post_bootmode_get(0));
+	if (post_bootmode_get(0) & POST_POWERFAIL) {
+		post_bootmode_clear();
+		board_poweroff();
+	}
+#endif
+
+	show_boot_progress(0x29);
+	
+	/* main_loop() can return to retry autoboot, if so just run it again. */
+	for (;;) {
+		main_loop ();
+	}
+
+	/* NOTREACHED - no way out of command loop except booting */
+}
+
+void hang (void)
+{
+	puts ("### ERROR ### Please RESET the board ###\n");
+	for (;;);
+}
+
+

+ 174 - 0
lib_i386/i386_linux.c

@@ -0,0 +1,174 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * 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 <command.h>
+#include <cmd_boot.h>
+#include <image.h>
+#include <zlib.h>
+#include <asm/byteorder.h>
+#include <asm/zimage.h>
+
+
+extern image_header_t header;           /* from cmd_bootm.c */
+
+
+image_header_t *fake_header(image_header_t *hdr, void *ptr, int size)
+{
+	/* try each supported image type in order */
+	if (NULL != fake_zimage_header(hdr, ptr, size)) {
+		return hdr;
+	}
+	
+	return NULL;
+}
+
+
+void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
+		ulong addr, ulong *len_ptr, int   verify)
+{
+	ulong base_ptr;
+	
+	ulong len = 0, checksum;
+	ulong initrd_start, initrd_end;
+	ulong data;
+	image_header_t *hdr = &header;
+	
+	/*
+	 * Check if there is an initrd image
+	 */
+	if (argc >= 3) {
+		addr = simple_strtoul(argv[2], NULL, 16);
+		
+		printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
+		
+		/* Copy header so we can blank CRC field for re-calculation */
+		memcpy (&header, (char *)addr, sizeof(image_header_t));
+		
+		if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+			printf ("Bad Magic Number\n");
+			do_reset (cmdtp, flag, argc, argv);
+		}
+		
+		data = (ulong)&header;
+		len  = sizeof(image_header_t);
+		
+		checksum = ntohl(hdr->ih_hcrc);
+		hdr->ih_hcrc = 0;
+		
+		if (crc32 (0, (char *)data, len) != checksum) {
+			printf ("Bad Header Checksum\n");
+			do_reset (cmdtp, flag, argc, argv);
+		}
+		
+		print_image_hdr (hdr);
+		
+		data = addr + sizeof(image_header_t);
+		len  = ntohl(hdr->ih_size);
+		
+		if (verify) {
+			ulong csum = 0;
+			
+			printf ("   Verifying Checksum ... ");
+			csum = crc32 (0, (char *)data, len);
+			if (csum != ntohl(hdr->ih_dcrc)) {
+				printf ("Bad Data CRC\n");
+				do_reset (cmdtp, flag, argc, argv);
+			}
+			printf ("OK\n");
+		}
+		
+		if ((hdr->ih_os   != IH_OS_LINUX)	||
+		    (hdr->ih_arch != IH_CPU_I386)	||
+		    (hdr->ih_type != IH_TYPE_RAMDISK)	) {
+			printf ("No Linux i386 Ramdisk Image\n");
+			do_reset (cmdtp, flag, argc, argv);
+		}
+		
+		/*
+		 * Now check if we have a multifile image
+		 */
+	} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
+		ulong tail    = ntohl(len_ptr[0]) % 4;
+		int i;
+		
+		/* skip kernel length and terminator */
+		data = (ulong)(&len_ptr[2]);
+		/* skip any additional image length fields */
+		for (i=1; len_ptr[i]; ++i)
+			data += 4;
+		/* add kernel length, and align */
+		data += ntohl(len_ptr[0]);
+		if (tail) {
+			data += 4 - tail;
+		}
+		
+		len   = ntohl(len_ptr[1]);
+		
+	} else {
+		/*
+		 * no initrd image
+		 */
+		data = 0;
+	}
+	
+#ifdef	DEBUG
+	if (!data) {
+		printf ("No initrd\n");
+	}
+#endif
+	
+	if (data) {
+		initrd_start = data;
+		initrd_end   = initrd_start + len;
+		printf ("   Loading Ramdisk to %08lx, end %08lx ... ",
+			initrd_start, initrd_end);
+		memmove ((void *)initrd_start, (void *)data, len);
+		printf ("OK\n");
+	} else {
+		initrd_start = 0;
+		initrd_end = 0;
+	}
+	
+	base_ptr = load_zimage(addr + sizeof(image_header_t), ntohl(hdr->ih_size), 
+			       initrd_start, initrd_end-initrd_start, 0);
+
+	if (NULL == base_ptr) {
+		printf ("## Kernel loading failed ...\n");
+		do_reset(cmdtp, flag, argc, argv);
+		
+	}
+		
+#ifdef DEBUG
+	printf ("## Transferring control to Linux (at address %08x) ...\n",
+		(u32)base_ptr);
+#endif
+		
+	/* we assume that the kernel is in place */
+	printf("\nStarting kernel ...\n\n");
+		
+	boot_zimage(base_ptr);
+	
+}
+
+

+ 442 - 0
lib_i386/ic/ali512x.c

@@ -0,0 +1,442 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+/*
+ * Based on sc520cdp.c from rolo 1.6:
+ *----------------------------------------------------------------------
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions GmbH
+ * Klein-Winternheim, Germany
+ *----------------------------------------------------------------------
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ic/ali512x.h>
+
+
+/* ALI M5123 Logical device numbers:
+ * 0 FDC
+ * 1 unused?
+ * 2 unused?
+ * 3 lpt
+ * 4 UART1
+ * 5 UART2
+ * 6 RTC
+ * 7 mouse/kbd
+ * 8 CIO
+ */
+
+/*
+ ************************************************************
+ *  Some access primitives for the ALi chip:                *
+ ************************************************************
+ */
+
+static void ali_write(u8 index, u8 value)
+{	
+	/* write an arbirary register */
+	outb(index, ALI_INDEX);
+	outb(value, ALI_DATA);
+}
+
+static int ali_read(u8 index)
+{
+	outb(index, ALI_INDEX);
+	return inb(ALI_DATA);
+}
+
+#define ALI_OPEN() \
+	outb(0x51, ALI_DATA); \
+	outb(0x23, ALI_DATA)	
+
+
+#define ALI_CLOSE() \
+	outb(0xbb, ALI_DATA)
+
+/* Select a logical device */
+#define ALI_SELDEV(dev)	\
+	ali_write(0x07, dev)	
+
+
+void ali512x_init(void)
+{
+	ALI_OPEN();
+
+	ali_write(0x02, 0x01);	/* soft reset */
+	ali_write(0x03, 0x03);	/* disable access to CIOs */
+	ali_write(0x22, 0x00);	/* disable direct powerdown */
+	ali_write(0x23, 0x00);	/* disable auto powerdown */
+	ali_write(0x24, 0x00);	/* IR 8 is active hi, pin26 is PDIR */
+
+	ALI_CLOSE();
+}
+
+void ali512x_set_fdc(int enabled, u16 io, u8 irq, u8 dma_channel)
+{
+	ALI_OPEN();
+	ALI_SELDEV(0);
+	
+	ali_write(0x30, enabled?1:0);
+	if (enabled) {
+		ali_write(0x60, io >> 8);
+		ali_write(0x61, io & 0xff);
+		ali_write(0x70, irq);
+		ali_write(0x74, dma_channel);
+		
+		/* AT mode, no drive swap */
+		ali_write(0xf0, 0x08);
+		ali_write(0xf1, 0x00);
+		ali_write(0xf2, 0xff);
+		ali_write(0xf4, 0x00);
+	}
+	ALI_CLOSE();
+}
+
+
+void ali512x_set_pp(int enabled, u16 io, u8 irq, u8 dma_channel)
+{
+	ALI_OPEN();
+	ALI_SELDEV(3);
+	
+	ali_write(0x30, enabled?1:0);
+	if (enabled) {
+		ali_write(0x60, io >> 8);
+		ali_write(0x61, io & 0xff);
+		ali_write(0x70, irq);
+		ali_write(0x74, dma_channel);
+		
+		/* mode: EPP 1.9, ECP FIFO threshold = 7, IRQ active low */
+		ali_write(0xf0, 0xbc);
+		/* 12 MHz, Burst DMA in ECP */
+		ali_write(0xf1, 0x05);
+	}
+	ALI_CLOSE();
+
+}
+
+void ali512x_set_uart(int enabled, int index, u16 io, u8 irq)
+{
+	ALI_OPEN();
+	ALI_SELDEV(index?5:4);
+	
+	ali_write(0x30, enabled?1:0);
+	if (enabled) {
+		ali_write(0x60, io >> 8);
+		ali_write(0x61, io & 0xff);
+		ali_write(0x70, irq);
+		
+		ali_write(0xf0, 0x00);
+		ali_write(0xf1, 0x00);
+		
+		/* huh? write 0xf2 twice - a typo in rolo
+		 * or some secret ali errata? Who knows? 
+		 */
+		if (index) {
+			ali_write(0xf2, 0x00);
+		}
+		ali_write(0xf2, 0x0c);
+	}
+	ALI_CLOSE();
+
+}
+
+void ali512x_set_uart2_irda(int enabled)
+{
+	ALI_OPEN();
+	ALI_SELDEV(5);
+	
+	ali_write(0xf1, enabled?0x48:0x00); /* fullduplex IrDa */
+	ALI_CLOSE();
+
+}
+
+void ali512x_set_rtc(int enabled, u16 io, u8 irq)
+{
+	ALI_OPEN();
+	ALI_SELDEV(6);
+	
+	ali_write(0x30, enabled?1:0);
+	if (enabled) {
+		ali_write(0x60, io >> 8);
+		ali_write(0x61, io & 0xff);
+		ali_write(0x70, irq);
+
+		ali_write(0xf0, 0x00);
+	}
+	ALI_CLOSE();
+}
+
+void ali512x_set_kbc(int enabled, u8 kbc_irq, u8 mouse_irq)
+{
+	ALI_OPEN();
+	ALI_SELDEV(7);
+	
+	ali_write(0x30, enabled?1:0);
+	if (enabled) {
+		ali_write(0x70, kbc_irq);
+		ali_write(0x72, mouse_irq);		
+		
+		ali_write(0xf0, 0x00);
+	}
+	ALI_CLOSE();
+}
+
+
+/* Common I/O
+ * 
+ * (This descripotsion is base on several incompete sources
+ *  since I have not been able to obtain any datasheet for the device
+ *  there may be some mis-understandings burried in here. 
+ *  -- Daniel daniel@omicron.se)
+ * 
+ * There are 22 CIO pins numbered
+ * 10-17
+ * 20-25
+ * 30-37
+ * 
+ * 20-24 are dedicated CIO pins, the other 17 are muliplexed with
+ * other functions.
+ * 
+ *           Secondary 
+ * CIO Pin   Function    Decription
+ * =======================================================
+ * CIO10     IRQIN1      Interrupt input 1?
+ * CIO11     IRQIN2      Interrupt input 2?
+ * CIO12     IRRX        IrDa Receive
+ * CIO13     IRTX        IrDa Transmit
+ * CIO14     P21         KBC P21 fucntion
+ * CIO15     P20         KBC P21 fucntion
+ * CIO16     I2C_CLK     I2C Clock
+ * CIO17     I2C_DAT     I2C Data
+ * 
+ * CIO20     -
+ * CIO21     -
+ * CIO22     -
+ * CIO23     -
+ * CIO24     -
+ * CIO25     LOCK        Keylock
+ * 
+ * CIO30     KBC_CLK     Keybaord Clock
+ * CIO31     CS0J        General Chip Select decoder CS0J
+ * CIO32     CS1J        General Chip Select decoder CS1J
+ * CIO33     ALT_KCLK    Alternative Keyboard Clock
+ * CIO34     ALT_KDAT    Alternative Keyboard Data
+ * CIO35     ALT_MCLK    Alternative Mouse Clock
+ * CIO36     ALT_MDAT    Alternative Mouse Data
+ * CIO37     ALT_KBC     Alternative KBC select
+ *
+ * The CIO use a double indirect address scheme. 
+ * 
+ * Reigster 3 in the SIO is used to selectg where the CIO 
+ * I/O registers show up under function 8. Note that these
+ * registers clash with the CIO function select regsters,
+ * below.
+ * 
+ * SIO reigster 3 (CIO Address Selection) bit definitions:
+ * bit 7   CIO data register enabled
+ * bit 1-0 CIO indirect registers select
+ *     	 0  index = 0xE0 data = 0xE1
+ *       1  index = 0xE2 data = 0xE3
+ *       2  index = 0xE4 data = 0xE5
+ *       3  index = 0xEA data = 0xEB
+ * 
+ * There are three CIO I/O register accessed via CIO index and CIO data
+ * 0x01     CIO 10-17 data
+ * 0x02     CIO 20-25 data (bits 7-6 unused)
+ * 0x03     CIO 30-37 data
+ * 
+ * 
+ * The pin function is accessed through normal 
+ * SIO registers, each register have the same format:
+ * 
+ * Bit   Function                     Value
+ * 0     Input/output                 1=input 
+ * 1     Polarity of signal           1=inverted
+ * 2     Unused                       ??
+ * 3     Function (normal or special) 1=special
+ * 7-4   Unused
+ * 
+ * SIO REG
+ * 0xe0     CIO 10 Config
+ * 0xe1     CIO 11 Config
+ * 0xe2     CIO 12 Config
+ * 0xe3     CIO 13 Config
+ * 0xe4     CIO 14 Config
+ * 0xe5     CIO 15 Config
+ * 0xe6     CIO 16 Config
+ * 0xe7     CIO 16 Config
+ *
+ * 0xe8     CIO 20 Config
+ * 0xe9     CIO 21 Config
+ * 0xea     CIO 22 Config
+ * 0xeb     CIO 23 Config
+ * 0xec     CIO 24 Config
+ * 0xed     CIO 25 Config
+ *
+ * 0xf5     CIO 30 Config
+ * 0xf6     CIO 31 Config
+ * 0xf7     CIO 32 Config
+ * 0xf8     CIO 33 Config
+ * 0xf9     CIO 34 Config
+ * 0xfa     CIO 35 Config
+ * 0xfb     CIO 36 Config
+ * 0xfc     CIO 37 Config
+ * 
+ */
+
+void ali512x_set_cio(int enabled)
+{
+	int i;
+	
+	ALI_OPEN();
+	ali_write(0x3, 3);    /* Disable CIO data register */
+	
+	ALI_SELDEV(8);
+	ali_write(0x30, enabled?1:0);
+	
+	/* set all pins to input to start with */
+	for (i=0xe0;i<0xee;i++) {
+		ali_write(i, 1);
+	}
+	for (i=0xf5;i<0xfe;i++) {
+		ali_write(i, 1);
+	}
+			
+	ALI_CLOSE();
+}
+
+void ali512x_cio_function(int pin, int special, int inv, int input)
+{
+	u8 data;
+	u8 addr;
+	
+	
+	/* valid pins are 10-17, 20-25 and 30-37 */
+	if (pin >= 10 && pin <= 17) { 
+		addr = 0xe0+(pin-10);
+	} else if (pin >= 20 && pin <= 25) {
+		addr = 0xe8+(pin-20);
+	} else if (pin >= 30 && pin <= 37) { 
+		addr = 0xf5+(pin-30);
+	} else {
+		return;
+	}
+	
+	ALI_OPEN();
+	ALI_SELDEV(8);
+	
+	ali_write(0x03, 0x03);    /* Disable CIO data register */
+	
+	data=0;
+	if (special) {
+		data |= 0x08;
+	} else {
+		if (inv) {
+			data |= 0x02;
+		}
+		if (input) {
+			data |= 0x01;
+		}
+	}
+	
+	ali_write(addr, data);
+	
+	ALI_CLOSE();
+}
+
+void ali512x_cio_out(int pin, int value) 
+{
+	u8 reg;
+	u8 data;
+	u8 bit;
+	
+	/* valid pins are 10-17, 20-25 and 30-37 */
+	if (pin >= 10 && pin <= 17) { 
+		reg = 1;
+		pin -= 10;
+	} else if (pin >= 20 && pin <= 25) {
+		reg = 2;
+		pin -= 20;
+	} else if (pin >= 30 && pin <= 37) { 
+		reg = 3;
+		pin -= 30;
+	} else {
+		return;
+	}
+	bit = 1 << pin;
+	
+	ALI_OPEN();
+	ALI_SELDEV(8);
+	
+	ali_write(0x03, 0x83);    /* Enable CIO data register, use data port at 0xea */
+	
+	ali_write(0xea, reg);     /* select I/O register */
+	data = ali_read(0xeb);
+	if (value) {
+		data |= bit;
+	} else {
+		data &= ~bit;
+	}
+	ali_write(0xeb, data);
+	ali_write(0xea, 0);       /* select register 0 */
+	ali_write(0x03, 0x03);    /* Disable CIO data register */
+	ALI_CLOSE();
+}
+
+int ali512x_cio_in(int pin)
+{
+	u8 reg;
+	u8 data;
+	u8 bit;
+	
+	/* valid pins are 10-17, 20-25 and 30-37 */
+	if (pin >= 10 && pin <= 17) { 
+		reg = 1;
+		pin -= 10;
+	} else if (pin >= 20 && pin <= 25) {
+		reg = 2;
+		pin -= 20;
+	} else if (pin >= 30 && pin <= 37) { 
+		reg = 3;
+		pin -= 30;
+	} else {
+		return -1; 
+	}
+	bit = 1 << pin;
+	
+	ALI_OPEN();
+	ALI_SELDEV(8);
+	
+	ali_write(0x03, 0x83);    /* Enable CIO data register, use data port at 0xea */
+	
+	ali_write(0xea, reg);     /* select I/O register */
+	data = ali_read(0xeb);
+	ali_write(0xea, 0);       /* select register 0 */
+	ali_write(0x03, 0x03);    /* Disable CIO data register */
+	ALI_CLOSE();
+	
+	return data & bit; 
+}
+
+ 

+ 348 - 0
lib_i386/ic/sc520.c

@@ -0,0 +1,348 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+/* stuff specific for the sc520,
+ * but idependent of implementation */
+
+
+#include <common.h>
+#include <config.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/ic/sc520.h>
+
+/* 
+ * utility functions for boards based on the AMD sc520 
+ * 
+ * void write_mmcr_byte(u16 mmcr, u8 data)
+ * void write_mmcr_word(u16 mmcr, u16 data)
+ * void write_mmcr_long(u16 mmcr, u32 data)
+ * 
+ * u8   read_mmcr_byte(u16 mmcr)
+ * u16  read_mmcr_word(u16 mmcr)
+ * u32  read_mmcr_long(u16 mmcr)
+ * 
+ * void init_sc520(void)
+ * unsigned long init_sc520_dram(void)
+ * void pci_sc520_init(struct pci_controller *hose)
+ * 
+ * void reset_timer(void)
+ * ulong get_timer(ulong base)
+ * void set_timer(ulong t)
+ * void udelay(unsigned long usec)
+ * 
+ */
+
+static u32 mmcr_base= 0xfffef000;
+
+void write_mmcr_byte(u16 mmcr, u8 data)
+{
+	writeb(data, mmcr+mmcr_base);
+}
+
+void write_mmcr_word(u16 mmcr, u16 data)
+{
+	writew(data, mmcr+mmcr_base);	
+}
+
+void write_mmcr_long(u16 mmcr, u32 data)
+{
+	writel(data, mmcr+mmcr_base);
+}
+
+u8 read_mmcr_byte(u16 mmcr)
+{
+	return readb(mmcr+mmcr_base);
+}
+
+u16 read_mmcr_word(u16 mmcr)
+{
+	return readw(mmcr+mmcr_base);	
+}
+
+u32 read_mmcr_long(u16 mmcr)
+{
+	return readl(mmcr+mmcr_base);
+}
+
+
+void init_sc520(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	
+	/* Set the UARTxCTL register at it's slower,
+	 * baud clock giving us a 1.8432 MHz reference 
+	 */
+	write_mmcr_byte(SC520_UART1CTL, 7);
+	write_mmcr_byte(SC520_UART2CTL, 7);
+	
+	/* first set the timer pin mapping */
+	write_mmcr_byte(SC520_CLKSEL, 0x72);	/* no clock frequency selected, use 1.1892MHz */
+	
+	/* enable PCI bus arbitrer */
+	write_mmcr_byte(SC520_SYSARBCTL,0x02);  /* enable concurrent mode */
+	
+	write_mmcr_word(SC520_SYSARBMENB,0x1f); /* enable external grants */
+	write_mmcr_word(SC520_HBCTL,0x04);      /* enable posted-writes */
+
+
+	if (CFG_SC520_HIGH_SPEED) {
+		write_mmcr_byte(SC520_CPUCTL, 0x2);	/* set it to 133 MHz and write back */
+		gd->cpu_clk = 133000000;
+		printf("## CPU Speed set to 133MHz\n");
+	} else {
+		write_mmcr_byte(SC520_CPUCTL, 1);	/* set CPU to 100 MHz and write back cache */
+		printf("## CPU Speed set to 100MHz\n");
+		gd->cpu_clk = 100000000;
+	}
+	
+
+	/* wait at least one millisecond */
+        asm("movl	$0x2000,%%ecx\n"
+	    "wait_loop:	pushl %%ecx\n"
+	    "popl	%%ecx\n"
+	    "loop wait_loop\n": : : "ecx");
+
+	/* turn on the SDRAM write buffer */
+	write_mmcr_byte(SC520_DBCTL, 0x11);
+
+	/* turn on the cache and disable write through */
+	asm("movl	%%cr0, %%eax\n"
+	    "andl	$0x9fffffff, %%eax\n"
+	    "movl	%%eax, %%cr0\n"  : : : "eax");
+}
+
+unsigned long init_sc520_dram(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	bd_t *bd = gd->bd;
+	
+	u32 dram_present=0;
+	u32 dram_ctrl;
+
+	int val;
+	
+	int cas_precharge_delay = CFG_SDRAM_PRECHARGE_DELAY;	
+	int refresh_rate        = CFG_SDRAM_REFRESH_RATE;	
+	int ras_cas_delay       = CFG_SDRAM_RAS_CAS_DELAY;
+	
+	/* set SDRAM speed here */
+	
+	refresh_rate/=78;	
+	if (refresh_rate<=1) {
+		val = 0;  /* 7.8us */
+	} else if (refresh_rate==2) {
+		val = 1;  /* 15.6us */
+	} else if (refresh_rate==3 || refresh_rate==4) {
+		val = 2;  /* 31.2us */
+	} else {
+		val = 3;  /* 62.4us */
+	}
+	write_mmcr_byte(SC520_DRCCTL, (read_mmcr_byte(SC520_DRCCTL) & 0xcf) | (val<<4));
+	
+	val = read_mmcr_byte(SC520_DRCTMCTL);
+	val &= 0xf0;
+	
+	if (cas_precharge_delay==3) {		
+		val |= 0x04;   /* 3T */
+	} else if (cas_precharge_delay==4) {		
+		val |= 0x08;   /* 4T */
+	} else if (cas_precharge_delay>4) {		
+		val |= 0x0c;
+	} 
+	
+	if (ras_cas_delay > 3) {
+		val |= 2; 
+	} else {
+		val |= 1; 
+	}
+	write_mmcr_byte(SC520_DRCTMCTL, val);
+
+
+	/* We read-back the configuration of the dram
+	 * controller that the assembly code wrote */
+	dram_ctrl = read_mmcr_long(SC520_DRCBENDADR);
+	
+
+	bd->bi_dram[0].start = 0;
+	if (dram_ctrl & 0x80) {
+		/* bank 0 enabled */
+		dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
+		bd->bi_dram[0].size = bd->bi_dram[1].start; 
+
+	} else {
+		bd->bi_dram[0].size = 0;
+		bd->bi_dram[1].start = bd->bi_dram[0].start;
+	}
+	
+	if (dram_ctrl & 0x8000) {
+		/* bank 1 enabled */
+		dram_present = bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
+		bd->bi_dram[1].size = bd->bi_dram[2].start -  bd->bi_dram[1].start; 
+	} else {
+		bd->bi_dram[1].size = 0;
+		bd->bi_dram[2].start = bd->bi_dram[1].start;
+	}
+	
+	if (dram_ctrl & 0x800000) {
+		/* bank 2 enabled */
+		dram_present = bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
+		bd->bi_dram[2].size = bd->bi_dram[3].start -  bd->bi_dram[2].start; 
+	} else {
+		bd->bi_dram[2].size = 0;
+		bd->bi_dram[3].start = bd->bi_dram[2].start;
+	} 
+	
+	if (dram_ctrl & 0x80000000) {
+		/* bank 3 enabled */
+		dram_present  = (dram_ctrl & 0x7f000000) >> 2;
+		bd->bi_dram[3].size = dram_present -  bd->bi_dram[3].start;
+	} else {
+		bd->bi_dram[3].size = 0;
+	}
+
+	
+#if 0	
+	printf("Configured %d bytes of dram\n", dram_present);
+#endif	
+	gd->ram_size = dram_present;
+	
+	return dram_present;
+}
+
+
+#ifdef CONFIG_PCI
+
+
+
+void pci_sc520_init(struct pci_controller *hose)
+{
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	/* System memory space */
+	pci_set_region(hose->regions + 0, 
+		       SC520_PCI_MEMORY_BUS,
+		       SC520_PCI_MEMORY_PHYS,
+		       SC520_PCI_MEMORY_SIZE,
+		       PCI_REGION_MEM | PCI_REGION_MEMORY);
+
+	/* PCI memory space */
+	pci_set_region(hose->regions + 1, 
+		       SC520_PCI_MEM_BUS,
+		       SC520_PCI_MEM_PHYS,
+		       SC520_PCI_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	/* ISA/PCI memory space */
+	pci_set_region(hose->regions + 2, 
+		       SC520_ISA_MEM_BUS,
+		       SC520_ISA_MEM_PHYS,
+		       SC520_ISA_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	/* PCI I/O space */
+	pci_set_region(hose->regions + 3, 
+		       SC520_PCI_IO_BUS,
+		       SC520_PCI_IO_PHYS,
+		       SC520_PCI_IO_SIZE,
+		       PCI_REGION_IO);
+
+	/* ISA/PCI I/O space */
+	pci_set_region(hose->regions + 4, 
+		       SC520_ISA_IO_BUS,
+		       SC520_ISA_IO_PHYS,
+		       SC520_ISA_IO_SIZE,
+		       PCI_REGION_IO);
+
+	hose->region_count = 5;
+
+	pci_setup_type1(hose,
+			SC520_REG_ADDR,
+			SC520_REG_DATA);
+
+	pci_register_hose(hose);
+
+	hose->last_busno = pci_hose_scan(hose);
+	
+	/* enable target memory acceses on host brige */
+	pci_write_config_word(0, PCI_COMMAND, 
+			      PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+}
+
+
+#endif
+
+#ifdef CFG_TIMER_SC520
+
+
+void reset_timer(void)
+{
+	write_mmcr_word(SC520_GPTMR0CNT, 0);
+	write_mmcr_word(SC520_GPTMR0CTL, 0x6001);
+	
+}
+
+ulong get_timer(ulong base)
+{
+	/* fixme: 30 or 33 */
+	return 	read_mmcr_word(SC520_GPTMR0CNT) / 33;
+}
+
+void set_timer(ulong t)
+{
+	/* FixMe: use two cascade coupled timers */
+	write_mmcr_word(SC520_GPTMR0CTL, 0x4001);
+	write_mmcr_word(SC520_GPTMR0CNT, t*33);
+	write_mmcr_word(SC520_GPTMR0CTL, 0x6001);
+}
+
+
+void udelay(unsigned long usec)
+{
+	int m=0;
+	long u;
+	
+	read_mmcr_word(SC520_SWTMRMILLI);
+	read_mmcr_word(SC520_SWTMRMICRO);
+	     
+#if 0
+	/* do not enable this line, udelay is used in the serial driver -> recursion */
+	printf("udelay: %ld m.u %d.%d  tm.tu %d.%d\n", usec, m, u, tm, tu);
+#endif	
+	while (1) {
+		
+		m += read_mmcr_word(SC520_SWTMRMILLI);
+		u = read_mmcr_word(SC520_SWTMRMICRO) + (m * 1000);
+		
+		if (usec <= u) {
+			break;
+		}
+	}
+}
+
+#endif
+
+

+ 530 - 0
lib_i386/ic/sc520_asm.S

@@ -0,0 +1,530 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+/* This file is largely based on code obtned from AMD. AMD's original
+ * copyright is included below 
+ */
+
+/*
+ *  =============================================================================
+ *                                                                              
+ *   Copyright 1999 Advanced Micro Devices, Inc.                                
+ *                                                                              
+ *  This software is the property of Advanced Micro Devices, Inc  (AMD)  which 
+ *  specifically grants the user the right to modify, use and distribute this 
+ *  software provided this COPYRIGHT NOTICE is not removed or altered.  All 
+ *  other rights are reserved by AMD.                                                       
+ *                                                                             
+ *  THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY 
+ *  OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF 
+ *  THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE.
+ *  IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+ *  (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+ *  INTERRUPTION, LOSS OF INFORMAITON) ARISING OUT OF THE USE OF OR INABILITY
+ *  TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF
+ *  SUCH DAMAGES.  BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR
+ *  LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
+ *  LIMITATION MAY NOT APPLY TO YOU.
+ * 
+ *  AMD does not assume any responsibility for any errors that may appear in
+ *  the Materials nor any responsibility to support or update the Materials.
+ *  AMD retains the right to make changes to its test specifications at any
+ *  time, without notice.
+ * 
+ *  So that all may benefit from your experience, please report  any  problems 
+ *  or suggestions about this software back to AMD.  Please include your name, 
+ *  company,  telephone number,  AMD product requiring support and question or 
+ *  problem encountered.                                                       
+ *                                                                             
+ *  Advanced Micro Devices, Inc.         Worldwide support and contact           
+ *  Embedded Processor Division            information available at:               
+ *  Systems Engineering                       epd.support@amd.com
+ *  5204 E. Ben White Blvd.                          -or-
+ *  Austin, TX 78741                http://www.amd.com/html/support/techsup.html
+ *  ============================================================================
+ */
+
+
+/*******************************************************************************
+ *	 AUTHOR      : Buddy Fey - Original. 
+ *******************************************************************************
+ */
+
+
+/*******************************************************************************
+ *       FUNCTIONAL DESCRIPTION:
+ * This routine is called to autodetect the geometry of the DRAM.
+ *
+ * This routine is called to determine the number of column bits for the DRAM
+ * devices in this external bank. This routine assumes that the external bank
+ * has been configured for an 11-bit column and for 4 internal banks. This gives
+ * us the maximum address reach in memory. By writing a test value to the max
+ * address and locating where it aliases to, we can determine the number of valid
+ * column bits.
+ *
+ * This routine is called to determine the number of internal banks each DRAM
+ * device has. The external bank (under test) is configured for maximum reach
+ * with 11-bit columns and 4 internal banks. This routine will write to a max
+ * address (BA1 and BA0 = 1) and then read from an address with BA1=0 to see if
+ * that column is a "don't care". If BA1 does not affect write/read of data,
+ * then this device has only 2 internal banks.
+ *
+ * This routine is called to determine the ending address for this external
+ * bank of SDRAM. We write to a max address with a data value and then disable
+ * row address bits looking for "don't care" locations. Each "don't care" bit
+ * represents a dividing of the maximum density (128M) by 2. By dividing the
+ * maximum of 32 4M chunks in an external bank down by all the "don't care" bits
+ * determined during sizing, we set the proper density.
+ *
+ * WARNINGS.
+ * bp must be preserved because it is used for return linkage.
+ *
+ * EXIT
+ * nothing returned - but the memory subsystem is enabled
+ *******************************************************************************
+ */
+
+.section .text
+.equ            DRCCTL,     0x0fffef010   /* DRAM control register */
+.equ            DRCTMCTL,   0x0fffef012   /* DRAM timing control register */
+.equ            DRCCFG,     0x0fffef014   /* DRAM bank configuration register */
+.equ            DRCBENDADR, 0x0fffef018   /* DRAM bank ending address register */
+.equ            ECCCTL,     0x0fffef020   /* DRAM ECC control register */
+.equ            DBCTL,      0x0fffef040   /* DRAM buffer control register */
+
+.equ            CACHELINESZ, 0x00000010   /* size of our cache line (read buffer) */
+.equ            COL11_ADR,  0x0e001e00    /* 11 col addrs */
+.equ            COL10_ADR,  0x0e000e00    /* 10 col addrs */
+.equ            COL09_ADR,  0x0e000600    /*  9 col addrs */
+.equ            COL08_ADR,  0x0e000200    /*  8 col addrs */
+.equ            ROW14_ADR,  0x0f000000    /* 14 row addrs */
+.equ            ROW13_ADR,  0x07000000    /* 13 row addrs */
+.equ            ROW12_ADR,  0x03000000    /* 12 row addrs */
+.equ            ROW11_ADR,  0x01000000    /* 11 row addrs/also bank switch */
+.equ            ROW10_ADR,  0x00000000    /* 10 row addrs/also bank switch */
+.equ            COL11_DATA, 0x0b0b0b0b    /* 11 col addrs */
+.equ            COL10_DATA, 0x0a0a0a0a    /* 10 col data */
+.equ            COL09_DATA, 0x09090909    /*  9 col data */
+.equ            COL08_DATA, 0x08080808    /*  8 col data */
+.equ            ROW14_DATA, 0x3f3f3f3f    /* 14 row data (MASK) */
+.equ            ROW13_DATA, 0x1f1f1f1f    /* 13 row data (MASK) */
+.equ            ROW12_DATA, 0x0f0f0f0f    /* 12 row data (MASK) */
+.equ            ROW11_DATA, 0x07070707    /* 11 row data/also bank switch (MASK) */
+.equ            ROW10_DATA, 0xaaaaaaaa    /* 10 row data/also bank switch (MASK) */
+
+
+ /*
+  * initialize dram controller registers
+  */
+.globl mem_init
+mem_init: 
+        xorw    %ax,%ax
+        movl    $DBCTL, %edi             
+fs	movb     %al, (%edi)             /* disable write buffer */
+
+        movl    $ECCCTL, %edi            
+fs	movb     %al, (%edi)             /* disable ECC */
+
+        movl    $DRCTMCTL, %edi           
+        movb    $0x1E,%al                /* Set SDRAM timing for slowest */
+fs	movb     %al, (%edi)
+
+ /*
+  * setup loop to do 4 external banks starting with bank 3
+  */
+        movl    $0xff000000,%eax         /* enable last bank and setup */
+        movl    $DRCBENDADR, %edi        /* ending address register */
+fs	movl     %eax, (%edi)
+
+        movl    $DRCCFG, %edi            /* setup */
+        movw    $0xbbbb,%ax              /* dram config register for  */
+fs	movw    %ax, (%edi)
+
+ /*
+  * issue a NOP to all DRAMs
+  */
+        movl    $DRCCTL, %edi            /* setup DRAM control register with */
+        movb    $0x1,%al                 /* Disable refresh,disable write buffer */ 
+fs	movb     %al, (%edi)
+        movl    $CACHELINESZ, %esi       /* just a dummy address to write for */ 
+fs	movw     %ax, (%esi)
+ /*
+  * delay for 100 usec? 200?
+  * ******this is a cludge for now *************
+  */
+        movw    $100,%cx
+sizdelay: 
+        loop    sizdelay                 /* we need 100 usec here */
+ /***********************************************/
+
+ /*
+  * issue all banks precharge
+  */
+        movb    $0x2,%al                 /* All banks precharge */
+fs	movb     %al, (%edi)
+fs	movw     %ax, (%esi)
+
+ /*
+  * issue 2 auto refreshes to all banks 
+  */
+        movb    $0x4,%al                 /* Auto refresh cmd */
+fs	movb     %al, (%edi)
+        movw    $2,%cx
+refresh1: 
+fs	movw     %ax, (%esi)
+        loop    refresh1
+
+ /*
+  * issue LOAD MODE REGISTER command
+  */
+        movb    $0x3,%al                 /* Load mode register cmd */
+fs	movb     %al, (%edi)
+fs	movw     %ax, (%esi)
+
+ /*
+  * issue 8 more auto refreshes to all banks 
+  */ 
+        movb    $0x4,%al                 /* Auto refresh cmd */
+fs	movb     %al, (%edi)
+        movw    $8,%cx
+refresh2: 
+fs	movw     %ax, (%esi)
+        loop    refresh2
+
+ /*
+  * set control register to NORMAL mode 
+  */
+        movb    $0x0,%al                 /* Normal mode value */
+fs	movb     %al, (%edi)
+
+ /*
+  * size dram starting with external bank 3 moving to external bank 0
+  */
+        movl    $0x3,%ecx                /* start with external bank 3 */
+
+nextbank: 
+
+ /*
+  * write col 11 wrap adr
+  */
+        movl    $COL11_ADR, %esi         /* set address to max col (11) wrap addr */
+        movl    $COL11_DATA, %eax        /* pattern for max supported columns(11) */
+fs      movl    %eax, (%esi)             /* write max col pattern at max col adr */
+fs      movl    (%esi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * write col 10 wrap adr
+  */
+
+        movl    $COL10_ADR, %esi         /* set address to 10 col wrap address */
+        movl    $COL10_DATA, %eax        /* pattern for 10 col wrap */
+fs      movl    %eax, (%esi)             /* write 10 col pattern @ 10 col wrap adr */
+fs      movl    (%esi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * write col 9 wrap adr
+  */
+        movl    $COL09_ADR, %esi         /* set address to 9 col wrap address */
+        movl    $COL09_DATA, %eax        /* pattern for 9 col wrap */
+fs      movl    %eax, (%esi)             /* write 9 col pattern @ 9 col wrap adr */
+fs      movl    (%esi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * write col 8 wrap adr
+  */
+        movl    $COL08_ADR, %esi         /* set address to min(8) col wrap address */
+        movl    $COL08_DATA, %eax        /* pattern for min (8) col wrap */
+fs      movl    %eax, (%esi)             /* write min col pattern @ min col adr */
+fs      movl    (%esi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * write row 14 wrap adr
+  */
+        movl    $ROW14_ADR, %esi         /* set address to max row (14) wrap addr */
+        movl    $ROW14_DATA, %eax        /* pattern for max supported rows(14) */
+fs      movl    %eax, (%esi)             /* write max row pattern at max row adr */
+fs      movl    (%esi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * write row 13 wrap adr
+  */
+        movl    $ROW13_ADR, %esi         /* set address to 13 row wrap address */
+        movl    $ROW13_DATA, %eax        /* pattern for 13 row wrap */
+fs      movl    %eax, (%esi)             /* write 13 row pattern @ 13 row wrap adr */
+fs      movl    (%esi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * write row 12 wrap adr
+  */
+        movl    $ROW12_ADR, %esi         /* set address to 12 row wrap address */
+        movl    $ROW12_DATA, %eax        /* pattern for 12 row wrap */
+fs      movl    %eax, (%esi)             /* write 12 row pattern @ 12 row wrap adr */
+fs      movl    (%esi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * write row 11 wrap adr
+  */
+        movl    $ROW11_ADR, %edi         /* set address to 11 row wrap address */
+        movl    $ROW11_DATA, %eax        /* pattern for 11 row wrap */
+fs      movl    %eax, (%edi)             /* write 11 row pattern @ 11 row wrap adr */
+fs      movl    (%edi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * write row 10 wrap adr --- this write is really to determine number of banks
+  */
+        movl    $ROW10_ADR, %edi         /* set address to 10 row wrap address */
+        movl    $ROW10_DATA, %eax        /* pattern for 10 row wrap (AA) */
+fs      movl    %eax, (%edi)             /* write 10 row pattern @ 10 row wrap adr */
+fs      movl    (%edi), %ebx             /* optional read */
+        cmpl    %ebx,%eax                /* to verify write */
+        jnz     bad_ram                  /* this ram is bad */
+ /*
+  * read data @ row 12 wrap adr to determine  * banks, 
+  * and read data @ row 14 wrap adr to determine  * rows.
+  * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
+  * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4 
+  * if data @ row 12 wrap == 11 or 12, we have 4 banks,
+  */
+        xorw    %di,%di                  /* value for 2 banks in DI */
+fs      movl    (%esi), %ebx             /* read from 12 row wrap to check banks 
+                                          * (esi is setup from the write to row 12 wrap) */
+        cmpl    %ebx,%eax                /* check for AA pattern  (eax holds the aa pattern) */
+        jz      only2                    /* if pattern == AA, we only have 2 banks */
+
+	/* 4 banks */
+	
+        movw    $8,%di                   /* value for 4 banks in DI (BNK_CNT bit) */
+        cmpl    $ROW11_DATA, %ebx        /* only other legitimate values are 11 */
+        jz      only2
+        cmpl    $ROW12_DATA, %ebx        /* and 12 */
+        jnz     bad_ram                  /* its bad if not 11 or 12! */
+	
+	/* fall through */
+only2: 
+ /*
+  * validate row mask
+  */
+        movl    $ROW14_ADR, %esi         /* set address back to max row wrap addr */
+fs      movl    (%esi), %eax             /* read actual number of rows @ row14 adr */
+
+        cmpl    $ROW11_DATA, %eax        /* row must be greater than 11 pattern */
+        jb      bad_ram
+
+        cmpl    $ROW14_DATA, %eax        /* and row must be less than 14 pattern */
+        ja      bad_ram
+
+        cmpb    %ah,%al                  /* verify all 4 bytes of dword same */
+        jnz     bad_ram
+        movl    %eax,%ebx
+        shrl    $16,%ebx
+        cmpw    %bx,%ax
+        jnz     bad_ram
+ /*
+  * read col 11 wrap adr for real column data value
+  */
+        movl    $COL11_ADR, %esi         /* set address to max col (11) wrap addr */
+fs      movl    (%esi), %eax             /* read real col number at max col adr */
+ /*
+  * validate column data
+  */
+        cmpl    $COL08_DATA, %eax        /* col must be greater than 8 pattern */
+        jb      bad_ram
+
+        cmpl    $COL11_DATA, %eax        /* and row must be less than 11 pattern */
+        ja      bad_ram
+
+        subl    $COL08_DATA, %eax        /* normalize column data to zero */
+        jc      bad_ram
+        cmpb    %ah,%al                  /* verify all 4 bytes of dword equal */
+        jnz     bad_ram
+        movl    %eax,%edx
+        shrl    $16,%edx
+        cmpw    %dx,%ax
+        jnz     bad_ram
+ /*
+  * merge bank and col data together
+  */
+        addw    %di,%dx                  /* merge of bank and col info in dl */
+ /*
+  * fix ending addr mask based upon col info
+  */
+        movb    $3,%al
+        subb    %dh,%al                  /* dh contains the overflow from the bank/col merge  */
+        movb    %bl,%dh                  /* bl contains the row mask (aa, 07, 0f, 1f or 3f) */
+        xchgw   %cx,%ax                  /* cx = ax = 3 or 2 depending on 2 or 4 bank device */
+        shrb    %cl,%dh	                 /*  */
+        incb    %dh                      /* ending addr is 1 greater than real end */
+        xchgw   %cx,%ax                  /* cx is bank number again */
+ /*
+  * issue all banks precharge
+  */
+bad_reint: 
+        movl    $DRCCTL, %esi            /* setup DRAM control register with */
+        movb    $0x2,%al                 /* All banks precharge */
+fs	movb     %al, (%esi)
+        movl    $CACHELINESZ, %esi       /* address to init read buffer */
+fs	movw     %ax, (%esi)
+
+ /*
+  * update ENDING ADDRESS REGISTER
+  */
+        movl    $DRCBENDADR, %edi        /* DRAM ending address register */
+        movl    %ecx,%ebx
+	addl	%ebx, %edi
+fs	movb    %dh, (%edi)
+ /*
+  * update CONFIG REGISTER
+  */
+        xorb    %dh,%dh
+        movw    $0x00f,%bx
+        movw    %cx,%ax
+        shlw    $2,%ax
+        xchgw   %cx,%ax
+        shlw    %cl,%dx
+        shlw    %cl,%bx
+        notw    %bx
+        xchgw   %cx,%ax
+        movl    $DRCCFG, %edi
+fs	mov     (%edi), %ax
+        andw    %bx,%ax
+        orw     %dx,%ax
+fs      movw    %ax, (%edi)
+        jcxz    cleanup
+
+        decw    %cx
+        movl    %ecx,%ebx
+        movl    $DRCBENDADR, %edi        /* DRAM ending address register */
+        movb    $0xff,%al
+	addl	%ebx, %edi
+fs	movb    %al, (%edi)
+ /*
+  * set control register to NORMAL mode 
+  */
+        movl    $DRCCTL, %esi            /* setup DRAM control register with */
+        movb    $0x0,%al                 /* Normal mode value */
+fs	movb    %al, (%esi)
+        movl    $CACHELINESZ, %esi       /* address to init read buffer */
+fs	movw    %ax, (%esi)
+        jmp     nextbank
+
+cleanup: 
+        movl    $DRCBENDADR, %edi        /* DRAM ending address register  */
+        movw    $4,%cx
+        xorw    %ax,%ax
+cleanuplp: 
+fs	movb   (%edi), %al
+        orb     %al,%al
+        jz      emptybank
+
+        addb    %ah,%al
+        jns     nottoomuch
+
+        movb    $0x7f,%al
+nottoomuch: 
+        movb    %al,%ah
+        orb     $0x80,%al
+fs	movb    %al, (%edi)
+emptybank: 
+        incl    %edi
+        loop    cleanuplp
+
+#if defined(CFG_SDRAM_CAS_LATENCY_2T) || defined(CFG_SDRAM_CAS_LATENCY_3T)
+	/* set the CAS latency now since it is hard to do
+	 * when we run from the RAM */
+	movl    $DRCTMCTL, %edi          /* DRAM timing register */
+	movb    (%edi), %al	
+#ifdef CFG_SDRAM_CAS_LATENCY_2T
+	andb    $0xef, %al
+#endif
+#ifdef CFG_SDRAM_CAS_LATENCY_3T
+	orb     $0x10, %al
+#endif	 
+	movb    %al, (%edi)
+#endif
+        movl    $DRCCTL, %edi            /* DRAM Control register */
+        movb    $0x3,%al                 /* Load mode register cmd */
+fs	movb     %al, (%edi)
+fs	movw     %ax, (%esi)
+
+
+        movl    $DRCCTL, %edi            /* DRAM Control register */
+        movb    $0x18,%al                /*  Enable refresh and NORMAL mode */
+fs	movb    %al, (%edi)
+
+        jmp     dram_done
+
+bad_ram: 
+        xorl    %edx,%edx
+        xorl    %edi,%edi
+        jmp     bad_reint
+
+dram_done: 
+	
+	/* readback DRCBENDADR and return the number
+	 * of available ram bytes in %eax */ 
+
+        movl    $DRCBENDADR, %edi        /* DRAM ending address register  */
+	
+	movl	(%edi), %eax
+	movl	%eax, %ecx
+	andl	$0x80000000, %ecx
+	jz	bank2
+	andl	$0x7f000000, %eax
+	shrl	$2, %eax 
+	movl	%eax, %ebx
+
+bank2: 	movl	(%edi), %eax
+	movl	%eax, %ecx
+	andl	$0x00800000, %ecx
+	jz	bank1
+	andl	$0x007f0000, %eax
+	shll	$6, %eax 
+	movl	%eax, %ebx
+
+bank1: 	movl	(%edi), %eax
+	movl	%eax, %ecx
+	andl	$0x00008000, %ecx
+	jz	bank0
+	andl	$0x00007f00, %eax
+	shll	$14, %eax 
+	movl	%eax, %ebx
+
+bank0: 	movl	(%edi), %eax
+	movl	%eax, %ecx
+	andl	$0x00000080, %ecx
+	jz	done
+	andl	$0x0000007f, %eax
+	shll	$22, %eax 
+	movl	%eax, %ebx
+
+done:	movl	%ebx, %eax
+
+	jmp	*%ebp

+ 57 - 0
lib_i386/pci_type1.c

@@ -0,0 +1,57 @@
+/*
+ * Support for type PCI configuration cycles.
+ * based on pci_indirect.c
+ *
+ * Copyright (C) 2002 Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op)	op((val), (type *)(addr))
+
+#define TYPE1_PCI_OP(rw, size, type, op, mask)			 \
+static int								 \
+type1_##rw##_config_##size(struct pci_controller *hose, 		 \
+			      pci_dev_t dev, int offset, type val)	 \
+{									 \
+	outl(dev | (offset & 0xfc) | 0x80000000, hose->cfg_addr); 	 \
+	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);	 \
+	return 0;    					 		 \
+}
+
+
+TYPE1_PCI_OP(read, byte, u8 *, inb, 3)
+TYPE1_PCI_OP(read, word, u16 *, inw, 2)
+TYPE1_PCI_OP(read, dword, u32 *, inl, 0)
+
+TYPE1_PCI_OP(write, byte, u8, outb, 3)
+TYPE1_PCI_OP(write, word, u16, outw, 2)
+TYPE1_PCI_OP(write, dword, u32, outl, 0)
+
+void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+	pci_set_ops(hose,
+		    type1_read_config_byte,
+		    type1_read_config_word,
+		    type1_read_config_dword,
+		    type1_write_config_byte,
+		    type1_write_config_word,
+		    type1_write_config_dword);
+
+	hose->cfg_addr = (unsigned int *) cfg_addr;
+	hose->cfg_data = (unsigned char *) cfg_data;
+}
+
+#endif

+ 69 - 0
lib_i386/realmode.c

@@ -0,0 +1,69 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * 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 <asm/io.h>
+#include <asm/ptrace.h>
+
+
+#define REALMODE_BASE    ((char*)0x7c0)
+#define REALMODE_MAILBOX ((char*)0xe00)
+
+
+extern char realmode_enter;
+
+
+int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
+{
+	
+	/* setup out thin bios emulation */
+	if (bios_setup()) {
+		return -1;
+	}
+		
+	/* copy the realmode switch code */
+	if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
+		printf("realmode switch too large (%ld bytes, max is %d)\n", 
+		       i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE));
+		return -1;
+	}
+	
+	memcpy(REALMODE_BASE, i386boot_realmode, i386boot_realmode_size);
+		
+	
+	in->eip = off;
+	in->xcs = seg;
+	if (3>in->esp & 0xffff) {
+		printf("Warning: entering realmode with sp < 4 will fail\n");
+	}
+	
+	memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs));
+	
+	__asm__ volatile ( 
+		 "lcall $0x20,%0\n"  : :  "i" (&realmode_enter) );
+
+	memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs));
+
+	return out->eax;
+}
+

+ 223 - 0
lib_i386/realmode_switch.S

@@ -0,0 +1,223 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * 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
+ */
+
+
+/* 32bit -> 16bit -> 32bit mode switch code */
+
+/*
+ * Stack frame at 0xe00
+ *      e00 ebx;
+ *	e04 ecx;
+ *	e08 edx;
+ *	e0c esi;
+ *	e10 edi;
+ *	e14 ebp; 
+ *	e18 eax;
+ *	e1c ds;  
+ *	e20 es;
+ *	e24 fs;  
+ *	e28 gs;
+ *	e2c orig_eax;
+ *	e30 eip;
+ *	e34 cs;
+ *	e38 eflags;
+ *	e3c esp;
+ *	e40 ss;
+ */
+
+#define a32		.byte 0x67;		/* address size prefix 32 */
+#define o32		.byte 0x66;		/* operand size prefix 32 */ 
+
+.section .realmode, "ax"
+.code16
+
+						/* 16bit protected mode code here */
+.globl realmode_enter
+realmode_enter:
+o32	pusha
+o32	pushf
+	cli
+        sidt   	saved_idt
+        sgdt    saved_gdt
+        movl    %esp, %eax
+        movl    %eax, saved_protected_mode_esp
+	
+	movl	$0x10, %eax
+	movl    %eax, %esp
+	movw	$0x28, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %fs
+	movw	%ax, %gs
+
+	lidt	realmode_idt_ptr
+	movl	%cr0, %eax                	/* Go back into real mode by */
+	andl	$0x7ffffffe, %eax         	/* clearing PE to 0 */
+	movl	%eax, %cr0
+	ljmp	$0x0,$do_realmode             	/* switch to real mode */
+						
+do_realmode:					/* realmode code from here */ 
+	movw	%cs,%ax
+	movw	%ax,%ds
+	movw	%ax,%es
+	movw	%ax,%fs
+	movw	%ax,%gs
+	
+						/* create a temporary stack */
+	                               
+	movw	$0xc0, %ax             
+	movw	%ax, %ss                
+	movw	$0x200, %ax           
+	movw	%ax, %sp 
+	
+	popl	%ebx
+	popl	%ecx
+	popl	%edx
+	popl	%esi
+	popl	%edi
+	popl	%ebp
+	popl	%eax
+	movl	%eax, temp_eax
+	popl	%eax
+	movw	%ax, %ds
+	popl	%eax
+	movw	%ax, %es
+	popl	%eax
+	movw	%ax, %fs
+	popl	%eax
+	movw	%ax, %gs
+	popl	%eax				/* orig_eax */
+	popl	%eax
+cs	movw	%ax, temp_ip
+	popl	%eax
+cs	movw	%ax, temp_cs
+o32	popf
+	popl	%eax
+	popw	%ss
+	movl	%eax, %esp
+cs	movl	temp_eax, %eax
+	wbinvd                                  /* self-modifying code,
+						 * better flush the cache */
+	
+	.byte	0x9a				/* lcall */
+temp_ip:
+	.word	0	     			/* new ip */
+temp_cs:	
+	.word   0				/* new cs */
+realmode_ret:
+						/* save eax, esp and ss */
+cs	movl	%eax, saved_eax
+	movl	%esp, %eax
+cs	movl	%eax, saved_esp
+	movw    %ss, %ax
+cs	movw	%ax, saved_ss
+	
+	/* restore the stack, note that we set sp to 0x244;
+	 * pt_regs is 0x44 bytes long and we push the structure
+	 * backwards on to the stack, bottom first */
+	 
+	movw	$0xc0, %ax             
+	movw	%ax, %ss                
+	movw	$0x244, %ax           
+	movw	%ax, %sp 
+	
+	xorl	%eax,%eax
+cs	movw	saved_ss, %ax
+	pushl	%eax
+cs	movl	saved_esp, %eax
+	pushl	%eax
+o32	pushf
+	xorl	%eax,%eax
+cs	movw	temp_cs, %ax
+	pushl	%eax
+cs	movw	temp_ip, %ax
+	pushl	%eax
+	pushl	$0
+	movw	%gs, %ax
+	pushl	%eax
+	movw	%fs, %ax
+	pushl	%eax
+	movw	%es, %ax
+	pushl	%eax
+	movw	%ds, %ax
+	pushl	%eax
+	movl	saved_eax, %eax
+	pushl	%eax
+	pushl	%ebp
+	pushl	%edi
+	pushl	%esi
+	pushl	%edx
+	pushl	%ecx
+	pushl	%ebx
+
+o32 cs	lidt	saved_idt
+o32 cs	lgdt    saved_gdt			/* Set GDTR */
+
+        movl    %cr0, %eax              	/* Go back into protected mode */
+        orl     $1,%eax                 	/* reset PE to 1 */
+        movl    %eax, %cr0               
+        jmp     next_line               	/* flush prefetch queue */
+next_line:    
+        movw	$return_ptr, %ax          
+        movw    %ax,%bp
+o32 cs	ljmp	*(%bp)
+
+.code32
+protected_mode:
+        movl    $0x18,%eax         		/* reload GDT[3] */
+        movw    %ax,%fs                 	/* reset FS */
+	movw	%ax,%ds                		/* reset DS */
+        movw    %ax,%gs                 	/* reset GS */
+        movw    %ax,%es                 	/* reset ES */
+        movw    %ax,%ss                 	/* reset SS */
+        movl    saved_protected_mode_esp, %eax
+	movl	%eax, %esp
+	popf
+	popa
+        ret
+
+temp_eax:
+	.long	0
+
+saved_ss:
+	.word   0
+saved_esp:
+	.long	0
+saved_eax:
+	.long	0
+	
+realmode_idt_ptr:
+	.word	0x400			       
+	.word	0x0, 0x0		
+	
+saved_gdt:  
+  	.word 	0, 0, 0, 0
+saved_idt:
+  	.word 	0, 0, 0, 0
+
+saved_protected_mode_esp:
+	.long 	0
+	
+return_ptr:
+	.long	protected_mode
+	.word	0x10

+ 276 - 0
lib_i386/zimage.c

@@ -0,0 +1,276 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ * 
+ * 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
+ */
+
+/* 
+ * Linux i386 zImage and bzImage loading
+ * 
+ * based on the procdure described in 
+ * linux/Documentation/i386/boot.txt
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/zimage.h>
+#include <asm/realmode.h>
+#include <asm/byteorder.h>
+
+/*
+ * Memory lay-out:
+ * 
+ * relative to setup_base (which is 0x90000 currently)
+ * 
+ *	0x0000-0x7FFF	Real mode kernel   
+ *	0x8000-0x8FFF	Stack and heap
+ *	0x9000-0x90FF	Kernel command line
+ */
+#define DEFAULT_SETUP_BASE  0x90000
+#define COMMAND_LINE_OFFSET 0x9000
+#define HEAP_END_OFFSET     0x8e00
+
+#define COMMAND_LINE_SIZE   2048
+
+static void build_command_line(char *command_line, int auto_boot)
+{
+	char *env_command_line;
+	
+	command_line[0] = '\0';
+	
+	env_command_line =  getenv("bootargs");
+	
+	/* set console= argument if we use a serial console */
+	if (NULL == strstr(env_command_line, "console=")) {
+		if (0==strcmp(getenv("stdout"), "serial")) {
+			
+			/* We seem to use serial console */
+			sprintf(command_line, "console=ttyS0,%s ", 
+				 getenv("baudrate"));
+		}
+	}
+	
+	if (auto_boot) {
+		strcat(command_line, "auto ");
+	}
+		
+	if (NULL != env_command_line) {
+		strcat(command_line, env_command_line);
+	} 
+	
+	
+	printf("Kernel command line: \"%s\"\n", command_line);
+}
+
+void *load_zimage(char *image, unsigned long kernel_size, 
+		  unsigned long initrd_addr, unsigned long initrd_size,
+		  int auto_boot)
+{
+        void *setup_base;
+	int setup_size;
+	int bootproto;
+	int big_image;
+	void *load_address;
+	
+	
+	setup_base = (void*)DEFAULT_SETUP_BASE;	/* base address for real-mode segment */
+	
+ 	if (KERNEL_MAGIC != *(u16*)(image + BOOT_FLAG_OFF)) {
+		printf("Error: Invalid kernel magic (found 0x%04x, expected 0xaa55)\n",
+		       *(u16*)(image + BOOT_FLAG_OFF));
+		return 0;
+	}
+	
+	
+	/* determine boot protocol version */
+	if (KERNEL_V2_MAGIC == *(u32*)(image+HEADER_OFF)) {
+		bootproto = *(u16*)(image+VERSION_OFF);
+	} else {
+		/* Very old kernel */
+		bootproto = 0x0100;
+	}
+	
+	/* determine size of setup */
+	if (0 == *(u8*)(image + SETUP_SECTS_OFF)) {
+		setup_size = 5 * 512;
+	} else {
+		setup_size = (*(u8*)(image + SETUP_SECTS_OFF) + 1) * 512;
+	}
+	
+	if (setup_size > SETUP_MAX_SIZE) {
+		printf("Error: Setup is too large (%d bytes)\n", setup_size);
+	}
+	
+	/* Determine image type */
+  	big_image = (bootproto >= 0x0200) && (*(u8*)(image + LOADFLAGS_OFF) & BIG_KERNEL_FLAG);
+	
+	/* Derermine load address */
+	load_address = (void*)(big_image ? BZIMAGE_LOAD_ADDR:ZIMAGE_LOAD_ADDR);
+			
+	/* load setup */
+	memmove(setup_base, image, setup_size);
+	
+	printf("Using boot protocol version %x.%02x\n", 
+	       (bootproto & 0xff00) >> 8, bootproto & 0xff);
+	
+	
+	if (bootproto == 0x0100) {		
+	
+		*(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC;
+		*(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET; 
+		
+		/* A very old kernel MUST have its real-mode code
+		 * loaded at 0x90000 */
+		
+		if ((u32)setup_base != 0x90000) {
+			/* Copy the real-mode kernel */
+			memmove((void*)0x90000, setup_base, setup_size);
+			/* Copy the command line */
+			memmove((void*)0x99000, setup_base+COMMAND_LINE_OFFSET, 
+			       COMMAND_LINE_SIZE);
+			
+			setup_base = (void*)0x90000;		 /* Relocated */
+		}
+		
+		/* It is recommended to clear memory up to the 32K mark */
+		memset((void*)0x90000 + setup_size, 0, SETUP_MAX_SIZE-setup_size);
+	}
+	
+	if (bootproto >= 0x0200) {
+		*(u8*)(setup_base + TYPE_OF_LOADER_OFF) = 0xff;
+		printf("Linux kernel version %s\n", 
+		       (char*)(setup_base + SETUP_START_OFFSET + 
+			       *(u16*)(setup_base + START_SYS_OFF + 2)));
+		
+		if (initrd_addr) {
+			printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n",
+			       initrd_addr, initrd_size);
+			
+			*(u32*)(setup_base + RAMDISK_IMAGE_OFF) = initrd_addr;
+			*(u32*)(setup_base + RAMDISK_SIZE_OFF)=initrd_size;
+		}
+	}
+	
+	if (bootproto >= 0x0201) {
+		*(u16*)(setup_base + HEAP_END_PTR_OFF) = HEAP_END_OFFSET;
+		
+		/* CAN_USE_HEAP */
+		*(u8*)(setup_base + LOADFLAGS_OFF) = 
+			*(u8*)(setup_base + LOADFLAGS_OFF) | HEAP_FLAG;
+	}
+	
+	if (bootproto >= 0x0202) {
+		*(u32*)(setup_base + CMD_LINE_PTR_OFF) = (u32)setup_base + COMMAND_LINE_OFFSET;
+	} else if (bootproto >= 0x0200) {
+		*(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC;
+		*(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET; 
+		*(u16*)(setup_base + SETUP_MOVE_SIZE_OFF) = 0x9100;
+	}
+	
+
+	
+	if (big_image) {
+		if ((kernel_size - setup_size) > BZIMAGE_MAX_SIZE) { 
+			printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n",
+			       kernel_size - setup_size, BZIMAGE_MAX_SIZE);
+			return 0;
+		}
+		
+	} else if ((kernel_size - setup_size) > ZIMAGE_MAX_SIZE) {
+		printf("Error: zImage kernel too big! (size: %ld, max: %d)\n",
+		       kernel_size - setup_size, ZIMAGE_MAX_SIZE);
+		return 0;
+	}
+	
+	/* build command line at COMMAND_LINE_OFFSET */
+	build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot);
+	
+        printf("Loading %czImage at address 0x%08x (%ld bytes)\n", big_image ? 'b' : ' ', 
+	       (u32)load_address, kernel_size - setup_size);
+
+	       
+	memmove(load_address, image + setup_size, kernel_size - setup_size);
+	
+	/* ready for booting */
+	return setup_base;
+}
+
+
+void boot_zimage(void *setup_base)
+{
+	struct pt_regs regs;
+	
+	memset(&regs, 0, sizeof(struct pt_regs));
+	regs.xds = (u32)setup_base >> 4;
+	regs.xss = 0x8e00;
+	regs.esp = 0x200;
+	regs.eflags = 0;
+	enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, &regs, &regs);
+}
+
+
+image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size)
+{	
+	/* There is no way to know the size of a zImage ... *
+	 * so we assume that 2MB will be enough for now */
+#define ZIMAGE_SIZE 0x200000
+	
+	/* load a 1MB, the loaded will have to be moved to its final
+	 * position again later... */
+#define ZIMAGE_LOAD 0x100000
+	
+	ulong checksum;
+	
+ 	if (KERNEL_MAGIC != *(u16*)(ptr + BOOT_FLAG_OFF)) {
+		/* not a zImage or bzImage */
+		return NULL;
+	}
+
+	if (-1 == size) {
+		size = ZIMAGE_SIZE;
+	}
+#if 0	
+	checksum = crc32 (0, ptr, size);
+#else
+	checksum = 0;
+#endif		
+	memset(hdr, 0, sizeof(image_header_t));
+	
+	/* Build new header */
+	hdr->ih_magic = htonl(IH_MAGIC);
+	hdr->ih_time  = 0;
+	hdr->ih_size  = htonl(size);
+	hdr->ih_load  = htonl(ZIMAGE_LOAD);
+	hdr->ih_ep    = 0;
+	hdr->ih_dcrc  = htonl(checksum);
+	hdr->ih_os    = IH_OS_LINUX;
+	hdr->ih_arch  = IH_CPU_I386;
+	hdr->ih_type  = IH_TYPE_KERNEL;
+	hdr->ih_comp  = IH_COMP_NONE;
+
+	strncpy((char *)hdr->ih_name, "(none)", IH_NMLEN);
+
+	checksum = crc32(0,(const char *)hdr,sizeof(image_header_t));
+
+	hdr->ih_hcrc = htonl(checksum);
+	
+	return hdr;
+}