* Patch by Daniel Engström, 13 Nov 2002:
authorwdenk <wdenk>
Mon, 18 Nov 2002 00:14:45 +0000 (00:14 +0000)
committerwdenk <wdenk>
Mon, 18 Nov 2002 00:14:45 +0000 (00:14 +0000)
  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

82 files changed:
CHANGELOG
CREDITS
MAINTAINERS
Makefile
README
board/sc520_cdp/Makefile [new file with mode: 0644]
board/sc520_cdp/config.mk [new file with mode: 0644]
board/sc520_cdp/flash.c [new file with mode: 0644]
board/sc520_cdp/sc520_cdp.c [new file with mode: 0644]
board/sc520_cdp/sc520_cdp_asm.S [new file with mode: 0644]
board/sc520_cdp/sc520_cdp_asm16.S [new file with mode: 0644]
board/sc520_cdp/u-boot.lds [new file with mode: 0644]
common/Makefile
common/cmd_bootm.c
common/cmd_fdc.c
common/cmd_fdos.c [new file with mode: 0644]
common/cmd_ide.c
common/command.c
cpu/i386/Makefile [new file with mode: 0644]
cpu/i386/config.mk [new file with mode: 0644]
cpu/i386/cpu.c [new file with mode: 0644]
cpu/i386/interrupts.c [new file with mode: 0644]
cpu/i386/reset.S [new file with mode: 0644]
cpu/i386/serial.c [new file with mode: 0644]
cpu/i386/start.S [new file with mode: 0644]
cpu/i386/start16.S [new file with mode: 0644]
cpu/i386/timer.c [new file with mode: 0644]
doc/README-i386 [new file with mode: 0644]
doc/TODO-i386 [new file with mode: 0644]
drivers/pcnet.c
examples/syscall.S
fs/Makefile
fs/fdos/Makefile [new file with mode: 0644]
fs/fdos/dev.c [new file with mode: 0644]
fs/fdos/dos.h [new file with mode: 0644]
fs/fdos/fat.c [new file with mode: 0644]
fs/fdos/fdos.c [new file with mode: 0644]
fs/fdos/fdos.h [new file with mode: 0644]
fs/fdos/fs.c [new file with mode: 0644]
fs/fdos/subdir.c [new file with mode: 0644]
fs/fdos/vfat.c [new file with mode: 0644]
i386_config.mk [new file with mode: 0644]
include/asm-i386/bitops.h [new file with mode: 0644]
include/asm-i386/byteorder.h [new file with mode: 0644]
include/asm-i386/global_data.h [new file with mode: 0644]
include/asm-i386/i8254.h [new file with mode: 0644]
include/asm-i386/i8259.h [new file with mode: 0644]
include/asm-i386/ibmpc.h [new file with mode: 0644]
include/asm-i386/ic/ali512x.h [new file with mode: 0644]
include/asm-i386/ic/sc520.h [new file with mode: 0644]
include/asm-i386/io.h [new file with mode: 0644]
include/asm-i386/pci.h [new file with mode: 0644]
include/asm-i386/posix_types.h [new file with mode: 0644]
include/asm-i386/ppcboot-i386.h [new file with mode: 0644]
include/asm-i386/ptrace.h [new file with mode: 0644]
include/asm-i386/realmode.h [new file with mode: 0644]
include/asm-i386/string.h [new file with mode: 0644]
include/asm-i386/types.h [new file with mode: 0644]
include/asm-i386/u-boot.h [new file with mode: 0644]
include/asm-i386/zimage.h [new file with mode: 0644]
include/cmd_confdefs.h
include/cmd_fdos.h [new file with mode: 0644]
include/common.h
include/configs/LANTEC.h
include/configs/MPC8260ADS.h
include/configs/ep8260.h
include/configs/hymod.h
include/configs/sc520_cdp.h [new file with mode: 0644]
include/fdc.h [new file with mode: 0644]
include/linux/stat.h
lib_i386/Makefile [new file with mode: 0644]
lib_i386/bios.S [new file with mode: 0644]
lib_i386/bios_setup.c [new file with mode: 0644]
lib_i386/board.c [new file with mode: 0644]
lib_i386/i386_linux.c [new file with mode: 0644]
lib_i386/ic/ali512x.c [new file with mode: 0644]
lib_i386/ic/sc520.c [new file with mode: 0644]
lib_i386/ic/sc520_asm.S [new file with mode: 0644]
lib_i386/pci_type1.c [new file with mode: 0644]
lib_i386/realmode.c [new file with mode: 0644]
lib_i386/realmode_switch.S [new file with mode: 0644]
lib_i386/zimage.c [new file with mode: 0644]

index 0c0d3d06c4bad3fd8b811fbebd6a2e366d23f2a3..35c285db3702b43ba39601eceb018505eee9a058 100644 (file)
--- a/CHANGELOG
+++ b/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)
diff --git a/CREDITS b/CREDITS
index 235881766aaeaa2abf738b14f5520dadab2cb1e7..0f7d9656e532ec31b795edf5d5651c6dca351cb3 100644 (file)
--- a/CREDITS
+++ b/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
index ca5c78eb7812438c17c6d26cd260147efee99707..c924c6540375cff4293c5a26f701c58a57d7ceda 100644 (file)
@@ -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                                              #
 #########################################################################
index 6732a093ff2574807270f8a3c57cc8f9c54210e5..d3e92f41187a27d405b2c901883ea7a781f91559 100644 (file)
--- a/Makefile
+++ b/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:
diff --git a/README b/README
index 24ad20a980081820c46102b4438d0e11fc241f7a..894e193895fc7336d052381dd4736036f1d18296 100644 (file)
--- a/README
+++ b/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
diff --git a/board/sc520_cdp/Makefile b/board/sc520_cdp/Makefile
new file mode 100644 (file)
index 0000000..0f50393
--- /dev/null
@@ -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
+
+#########################################################################
diff --git a/board/sc520_cdp/config.mk b/board/sc520_cdp/config.mk
new file mode 100644 (file)
index 0000000..d4cd998
--- /dev/null
@@ -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
diff --git a/board/sc520_cdp/flash.c b/board/sc520_cdp/flash.c
new file mode 100644 (file)
index 0000000..e434512
--- /dev/null
@@ -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);
+}
diff --git a/board/sc520_cdp/sc520_cdp.c b/board/sc520_cdp/sc520_cdp.c
new file mode 100644 (file)
index 0000000..cc818d2
--- /dev/null
@@ -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);
+}
diff --git a/board/sc520_cdp/sc520_cdp_asm.S b/board/sc520_cdp/sc520_cdp_asm.S
new file mode 100644 (file)
index 0000000..1e255fa
--- /dev/null
@@ -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
+       
diff --git a/board/sc520_cdp/sc520_cdp_asm16.S b/board/sc520_cdp/sc520_cdp_asm16.S
new file mode 100644 (file)
index 0000000..a3cadcf
--- /dev/null
@@ -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
+       
diff --git a/board/sc520_cdp/u-boot.lds b/board/sc520_cdp/u-boot.lds
new file mode 100644 (file)
index 0000000..ac8d3db
--- /dev/null
@@ -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) );
+}
index 3f4ff0190917cf13f1e173ec4bc3cd37a4b98c49..67387ef64f1e96f4ffae9776362faef9729d8191 100644 (file)
@@ -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 \
index 70ca999c06e5d11735b5e4f41179f17a9522aed9..a0587d019f8b95cfe49d1e8850c85fbb0a1679ea 100644 (file)
@@ -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[],
index 8e6b7350c230d123fb6e69e5704256402b382849..e45b3361ca1b72c9e0227ab02ac227a2716c2604 100644 (file)
@@ -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;
        }
diff --git a/common/cmd_fdos.c b/common/cmd_fdos.c
new file mode 100644 (file)
index 0000000..763f418
--- /dev/null
@@ -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
index 9cbfe1bb04aea4b2161f212c1934c1f26718ca4e..e514cf71e3ea968ecd40703f8fd780dea0a2cbf5 100644 (file)
@@ -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;
index f70cad8cbc16c7a72d116b51a110dcaf55c4a918..cab68abf8e308f610960f22e5524b8e4728816bb 100644 (file)
@@ -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
diff --git a/cpu/i386/Makefile b/cpu/i386/Makefile
new file mode 100644 (file)
index 0000000..1482398
--- /dev/null
@@ -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
+
+#########################################################################
diff --git a/cpu/i386/config.mk b/cpu/i386/config.mk
new file mode 100644 (file)
index 0000000..70caeb2
--- /dev/null
@@ -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
diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c
new file mode 100644 (file)
index 0000000..669823f
--- /dev/null
@@ -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;
+}
+
diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c
new file mode 100644 (file)
index 0000000..81d6881
--- /dev/null
@@ -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
diff --git a/cpu/i386/reset.S b/cpu/i386/reset.S
new file mode 100644 (file)
index 0000000..57e32a8
--- /dev/null
@@ -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
+       
diff --git a/cpu/i386/serial.c b/cpu/i386/serial.c
new file mode 100644 (file)
index 0000000..c0d2e8a
--- /dev/null
@@ -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 */
+
diff --git a/cpu/i386/start.S b/cpu/i386/start.S
new file mode 100644 (file)
index 0000000..025555c
--- /dev/null
@@ -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                     
+
+
diff --git a/cpu/i386/start16.S b/cpu/i386/start16.S
new file mode 100644 (file)
index 0000000..590a5a6
--- /dev/null
@@ -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) */
diff --git a/cpu/i386/timer.c b/cpu/i386/timer.c
new file mode 100644 (file)
index 0000000..a23cd6e
--- /dev/null
@@ -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
diff --git a/doc/README-i386 b/doc/README-i386
new file mode 100644 (file)
index 0000000..99b3e19
--- /dev/null
@@ -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 }
+ };
diff --git a/doc/TODO-i386 b/doc/TODO-i386
new file mode 100644 (file)
index 0000000..0969cbc
--- /dev/null
@@ -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
index f69cd2ce79c6bf1a1b492658546e1127cff5239e..1ba7d817a5c401484c7a876f66e3882a78d13d1b 100644 (file)
@@ -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);
     }
index 9e8725edcd097412305848eb69a307819d0ce9c7..9934490433d5ad6a96778ec05be1254e2e693ec6 100644 (file)
@@ -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
 
index 9ed0f1e5a959a065074b52d966ea0aaafe471763..ad74942d08dbdf6e0b519b331f622784c8c81cad 100644 (file)
@@ -22,7 +22,7 @@
 #
 #
 
-SUBDIRS        := jffs2
+SUBDIRS        := jffs2 fdos
 
 .depend all:
        @for dir in $(SUBDIRS) ; do \
diff --git a/fs/fdos/Makefile b/fs/fdos/Makefile
new file mode 100644 (file)
index 0000000..af0fff1
--- /dev/null
@@ -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
+
+#########################################################################
diff --git a/fs/fdos/dev.c b/fs/fdos/dev.c
new file mode 100644 (file)
index 0000000..f38d07d
--- /dev/null
@@ -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
diff --git a/fs/fdos/dos.h b/fs/fdos/dos.h
new file mode 100644 (file)
index 0000000..71701c9
--- /dev/null
@@ -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
+
diff --git a/fs/fdos/fat.c b/fs/fdos/fat.c
new file mode 100644 (file)
index 0000000..42df755
--- /dev/null
@@ -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
diff --git a/fs/fdos/fdos.c b/fs/fdos/fdos.c
new file mode 100644 (file)
index 0000000..8963f42
--- /dev/null
@@ -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
diff --git a/fs/fdos/fdos.h b/fs/fdos/fdos.h
new file mode 100644 (file)
index 0000000..18076d8
--- /dev/null
@@ -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
+
diff --git a/fs/fdos/fs.c b/fs/fdos/fs.c
new file mode 100644 (file)
index 0000000..68bbde0
--- /dev/null
@@ -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
diff --git a/fs/fdos/subdir.c b/fs/fdos/subdir.c
new file mode 100644 (file)
index 0000000..5911f2e
--- /dev/null
@@ -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
diff --git a/fs/fdos/vfat.c b/fs/fdos/vfat.c
new file mode 100644 (file)
index 0000000..f828795
--- /dev/null
@@ -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
diff --git a/i386_config.mk b/i386_config.mk
new file mode 100644 (file)
index 0000000..9e6d37d
--- /dev/null
@@ -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__
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
new file mode 100644 (file)
index 0000000..a3063ca
--- /dev/null
@@ -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 */
diff --git a/include/asm-i386/byteorder.h b/include/asm-i386/byteorder.h
new file mode 100644 (file)
index 0000000..bbfb629
--- /dev/null
@@ -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 */
diff --git a/include/asm-i386/global_data.h b/include/asm-i386/global_data.h
new file mode 100644 (file)
index 0000000..324b435
--- /dev/null
@@ -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 */
diff --git a/include/asm-i386/i8254.h b/include/asm-i386/i8254.h
new file mode 100644 (file)
index 0000000..e13f04e
--- /dev/null
@@ -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
diff --git a/include/asm-i386/i8259.h b/include/asm-i386/i8259.h
new file mode 100644 (file)
index 0000000..0419e0e
--- /dev/null
@@ -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
diff --git a/include/asm-i386/ibmpc.h b/include/asm-i386/ibmpc.h
new file mode 100644 (file)
index 0000000..abdd1d7
--- /dev/null
@@ -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
diff --git a/include/asm-i386/ic/ali512x.h b/include/asm-i386/ic/ali512x.h
new file mode 100644 (file)
index 0000000..5bc1bd7
--- /dev/null
@@ -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
diff --git a/include/asm-i386/ic/sc520.h b/include/asm-i386/ic/sc520.h
new file mode 100644 (file)
index 0000000..9708504
--- /dev/null
@@ -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
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
new file mode 100644 (file)
index 0000000..d8c503c
--- /dev/null
@@ -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
diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h
new file mode 100644 (file)
index 0000000..15c165b
--- /dev/null
@@ -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
diff --git a/include/asm-i386/posix_types.h b/include/asm-i386/posix_types.h
new file mode 100644 (file)
index 0000000..5529f32
--- /dev/null
@@ -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
diff --git a/include/asm-i386/ppcboot-i386.h b/include/asm-i386/ppcboot-i386.h
new file mode 100644 (file)
index 0000000..704526e
--- /dev/null
@@ -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_ */
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
new file mode 100644 (file)
index 0000000..d99e464
--- /dev/null
@@ -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
diff --git a/include/asm-i386/realmode.h b/include/asm-i386/realmode.h
new file mode 100644 (file)
index 0000000..fcb76c3
--- /dev/null
@@ -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
diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h
new file mode 100644 (file)
index 0000000..c378222
--- /dev/null
@@ -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
diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h
new file mode 100644 (file)
index 0000000..bb100ec
--- /dev/null
@@ -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
+
diff --git a/include/asm-i386/u-boot.h b/include/asm-i386/u-boot.h
new file mode 100644 (file)
index 0000000..554bc85
--- /dev/null
@@ -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_ */
diff --git a/include/asm-i386/zimage.h b/include/asm-i386/zimage.h
new file mode 100644 (file)
index 0000000..6886826
--- /dev/null
@@ -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
index a5308b69324d397f95f6c60d9811c0f662d18f5e..25f386b95cc94d37ac4f7ec9470061f5132992e5 100644 (file)
@@ -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     | \
                        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
  */
diff --git a/include/cmd_fdos.h b/include/cmd_fdos.h
new file mode 100644 (file)
index 0000000..a444c7a
--- /dev/null
@@ -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 */
index 21101f105a638617031d6d425b0ddeb6c8f25884..a950cdcc40cbebddd60a74f5b31cc00ca74f2f1e 100644 (file)
@@ -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);
index c7c78ad0c69d3ff2430d1b27d7c9101a18ac797e..fe9ee228ee38791f0c5d27cdbaa9c08d27fbf653 100644 (file)
@@ -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     \
index 14ad3139445c210b077446b7f10d99ccb86b5777..b4d8406aa5d4432de1b5a190d8338a19fdf3bcd7 100644 (file)
                                 CFG_CMD_EEPROM | \
                                 CFG_CMD_ELF    | \
                                 CFG_CMD_FDC    | \
+                                CFG_CMD_FDOS   | \
                                 CFG_CMD_HWFLOW | \
                                 CFG_CMD_IDE    | \
                                 CFG_CMD_JFFS2  | \
index 5db1f13a14598611cb22fc40dc4f8b7d837c8bb3..1285326f4fcf4268e2cc3d84bdf59ced57f8b017 100644 (file)
                                        ~CFG_CMD_DOC    & \
                                        ~CFG_CMD_EEPROM & \
                                        ~CFG_CMD_FDC    & \
+                                       ~CFG_CMD_FDOS   & \
                                        ~CFG_CMD_HWFLOW & \
                                        ~CFG_CMD_IDE    & \
                                        ~CFG_CMD_JFFS2  & \
index af3ba686df49d3b0e3c4ae15712af05c4b68cc53..5d2bed6abc4a3f27abbe596b2d170593df0c1bda 100644 (file)
                                        CFG_CMD_DOC     | \
                                        CFG_CMD_ELF     | \
                                        CFG_CMD_FDC     | \
+                                       CFG_CMD_FDOS    | \
                                        CFG_CMD_HWFLOW  | \
                                        CFG_CMD_IDE     | \
                                        CFG_CMD_JFFS2   | \
diff --git a/include/configs/sc520_cdp.h b/include/configs/sc520_cdp.h
new file mode 100644 (file)
index 0000000..e7d6c79
--- /dev/null
@@ -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 */
diff --git a/include/fdc.h b/include/fdc.h
new file mode 100644 (file)
index 0000000..7892b0e
--- /dev/null
@@ -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
index 9fd32062d67da487b533ed10ba54449e45741dfb..13899c97c712e52c6be3851ad7b3cc497d73c3b9 100644 (file)
@@ -67,7 +67,7 @@ struct stat {
 
 #endif /* __PPC__ */
 
-#ifdef __ARM__
+#if defined (__ARM__) || defined (__I386__)
 
 struct stat {
        unsigned short st_dev;
diff --git a/lib_i386/Makefile b/lib_i386/Makefile
new file mode 100644 (file)
index 0000000..34994e5
--- /dev/null
@@ -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
+
+#########################################################################
diff --git a/lib_i386/bios.S b/lib_i386/bios.S
new file mode 100644 (file)
index 0000000..2f5ea8c
--- /dev/null
@@ -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
+
diff --git a/lib_i386/bios_setup.c b/lib_i386/bios_setup.c
new file mode 100644 (file)
index 0000000..94319af
--- /dev/null
@@ -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;
+}
+
diff --git a/lib_i386/board.c b/lib_i386/board.c
new file mode 100644 (file)
index 0000000..193860a
--- /dev/null
@@ -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 (;;);
+}
+
+
diff --git a/lib_i386/i386_linux.c b/lib_i386/i386_linux.c
new file mode 100644 (file)
index 0000000..c37a0d8
--- /dev/null
@@ -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);
+       
+}
+
+
diff --git a/lib_i386/ic/ali512x.c b/lib_i386/ic/ali512x.c
new file mode 100644 (file)
index 0000000..4537095
--- /dev/null
@@ -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; 
+}
+
diff --git a/lib_i386/ic/sc520.c b/lib_i386/ic/sc520.c
new file mode 100644 (file)
index 0000000..d202625
--- /dev/null
@@ -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
+
+
diff --git a/lib_i386/ic/sc520_asm.S b/lib_i386/ic/sc520_asm.S
new file mode 100644 (file)
index 0000000..72110c4
--- /dev/null
@@ -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
diff --git a/lib_i386/pci_type1.c b/lib_i386/pci_type1.c
new file mode 100644 (file)
index 0000000..e5577e8
--- /dev/null
@@ -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
diff --git a/lib_i386/realmode.c b/lib_i386/realmode.c
new file mode 100644 (file)
index 0000000..372147c
--- /dev/null
@@ -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;
+}
+
diff --git a/lib_i386/realmode_switch.S b/lib_i386/realmode_switch.S
new file mode 100644 (file)
index 0000000..9f212c2
--- /dev/null
@@ -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
diff --git a/lib_i386/zimage.c b/lib_i386/zimage.c
new file mode 100644 (file)
index 0000000..190d46e
--- /dev/null
@@ -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;
+}