diff -Nurd u-boot-1.1.2/board/oxnas/config.mk u-boot-1.1.2-oxe810/board/oxnas/config.mk
--- u-boot-1.1.2/board/oxnas/config.mk	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/board/oxnas/config.mk	2008-06-11 17:55:18.000000000 +0200
@@ -0,0 +1,26 @@
+TEXT_BASE = 0x48d00000
+CROSS_COMPILE = arm-linux-
+
+PLL400 ?= 733333333
+RPSCLK ?=  25000000
+
+NAS_VERSION ?= 810
+FPGA ?= 0
+FPGA_ARM_CLK ?= 25000000
+
+PROBE_MEM_SIZE ?= 1
+MEM_SIZE ?= 64	# Memory size in megabytes if probing is not enabled
+MEM_ODT ?= 150
+
+USE_SATA ?= 1
+USE_SATA_ENV ?= 1
+USE_FLASH ?= 1
+
+LINUX_ROOT_RAIDED ?= 1
+
+USE_EXTERNAL_UART ?= 0
+INTERNAL_UART ?= 2
+
+TEST_BRD ?= 0	# Only significant for OX800
+
+PLATFORM_CPPFLAGS += -DLINUX_ROOT_RAIDED=$(LINUX_ROOT_RAIDED) -DMEM_ODT=$(MEM_ODT) -DPROBE_MEM_SIZE=$(PROBE_MEM_SIZE) -DNAS_VERSION=$(NAS_VERSION) -DFPGA=$(FPGA) -DFPGA_ARM_CLK=$(FPGA_ARM_CLK) -DINTERNAL_UART=$(INTERNAL_UART) -DUSE_EXTERNAL_UART=$(USE_EXTERNAL_UART) -DMEM_SIZE=$(MEM_SIZE) -DPLL400=$(PLL400) -DRPSCLK=$(RPSCLK) -DTEST_BRD=$(TEST_BRD) -DUSE_SATA=$(USE_SATA) -DUSE_SATA_ENV=$(USE_SATA_ENV) -DUSE_FLASH=$(USE_FLASH)
diff -Nurd u-boot-1.1.2/board/oxnas/eth.c u-boot-1.1.2-oxe810/board/oxnas/eth.c
--- u-boot-1.1.2/board/oxnas/eth.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/board/oxnas/eth.c	2008-06-11 17:55:18.000000000 +0200
@@ -0,0 +1,1666 @@
+/*
+ * (C) Copyright 2005
+ * Oxford Semiconductor Ltd
+ *
+ * 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 <malloc.h>
+#include <net.h>
+#include <asm/barrier.h>
+
+//#define DEBUG_GMAC_INIT
+
+// The number of bytes wasted at the start of a received packet buffer in order
+// to ensure the IP header will be aligned to a 32-bit boundary
+static const int ETHER_FRAME_ALIGN_WASTAGE = 2;
+static const int EXTRA_RX_SKB_SPACE = 32;   // Otherwise GMAC spans over >1 skb
+static const int ETHER_MTU  = 1500;
+
+static const u32 MAC_BASE_OFFSET = 0x0000;
+static const u32 DMA_BASE_OFFSET = 0x1000;
+
+static const int NUM_TX_DMA_DESCRIPTORS = 1;
+static const int NUM_RX_DMA_DESCRIPTORS = 32;
+
+/* Generic MII registers. */
+#define MII_BMCR            0x00	/* Basic mode control register */
+#define MII_BMSR            0x01	/* Basic mode status register  */
+#define MII_PHYSID1         0x02	/* PHYS ID 1                   */
+#define MII_PHYSID2         0x03	/* PHYS ID 2                   */
+#define MII_ADVERTISE       0x04	/* Advertisement control reg   */
+#define MII_LPA             0x05	/* Link partner ability reg    */
+#define MII_EXPANSION       0x06	/* Expansion register          */
+#define MII_CTRL1000        0x09	/* 1000BASE-T control          */
+#define MII_STAT1000        0x0a	/* 1000BASE-T status           */
+#define MII_ESTATUS         0x0f	/* Extended Status */
+
+/* Basic mode control register. */
+#define BMCR_RESV          0x003f  /* Unused...                   */
+#define BMCR_SPEED1000		0x0040  /* MSB of Speed (1000)         */
+#define BMCR_CTST          0x0080  /* Collision test              */
+#define BMCR_FULLDPLX      0x0100  /* Full duplex                 */
+#define BMCR_ANRESTART     0x0200  /* Auto negotiation restart    */
+#define BMCR_ISOLATE       0x0400  /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN         0x0800  /* Powerdown the DP83840       */
+#define BMCR_ANENABLE      0x1000  /* Enable auto negotiation     */
+#define BMCR_SPEED100      0x2000  /* Select 100Mbps              */
+#define BMCR_LOOPBACK      0x4000  /* TXD loopback bits           */
+#define BMCR_RESET         0x8000  /* Reset the DP83840           */
+
+/* Basic mode status register. */
+#define BMSR_ERCAP         0x0001  /* Ext-reg capability          */
+#define BMSR_JCD           0x0002  /* Jabber detected             */
+#define BMSR_LSTATUS       0x0004  /* Link status                 */
+#define BMSR_ANEGCAPABLE   0x0008  /* Able to do auto-negotiation */
+#define BMSR_RFAULT        0x0010  /* Remote fault detected       */
+#define BMSR_ANEGCOMPLETE  0x0020  /* Auto-negotiation complete   */
+#define BMSR_RESV          0x00c0  /* Unused...                   */
+#define BMSR_ESTATEN		0x0100	/* Extended Status in R15 */
+#define BMSR_100FULL2		0x0200	/* Can do 100BASE-T2 HDX */
+#define BMSR_100HALF2		0x0400	/* Can do 100BASE-T2 FDX */
+#define BMSR_10HALF        0x0800  /* Can do 10mbps, half-duplex  */
+#define BMSR_10FULL        0x1000  /* Can do 10mbps, full-duplex  */
+#define BMSR_100HALF       0x2000  /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL       0x4000  /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4      0x8000  /* Can do 100mbps, 4k packets  */
+
+/* 1000BASE-T Status register */
+#define LPA_1000LOCALRXOK	0x2000  /* Link partner local receiver status */
+#define LPA_1000REMRXOK  	0x1000  /* Link partner remote receiver status */
+#define LPA_1000FULL     	0x0800  /* Link partner 1000BASE-T full duplex */
+#define LPA_1000HALF     	0x0400  /* Link partner 1000BASE-T half duplex */
+#define PHY_TYPE_NONE					0
+#define PHY_TYPE_MICREL_KS8721BL		0x00221619
+#define PHY_TYPE_VITESSE_VSC8201XVZ	0x000fc413
+#define PHY_TYPE_REALTEK_RTL8211BGR	0x001cc912
+#define PHY_TYPE_LSI_ET1011C			0x0282f013
+
+/* Specific PHY values */
+#define VSC8201_MII_ACSR			0x1c	// Vitesse VCS8201 gigabit PHY Auxillary Control and Status register
+#define VSC8201_MII_ACSR_MDPPS_BIT	2		// Mode/Duplex Pin Priority Select
+
+#define ET1011C_MII_CONFIG	0x16
+#define ET1011C_MII_CONFIG_IFMODESEL	0
+#define ET1011C_MII_CONFIG_IFMODESEL_NUM_BITS	3
+#define ET1011C_MII_CONFIG_SYSCLKEN	4
+#define ET1011C_MII_CONFIG_TXCLKEN		5
+#define ET1011C_MII_CONFIG_TBI_RATESEL	8
+#define ET1011C_MII_CONFIG_CRS_TX_EN	15
+
+#define ET1011C_MII_CONFIG_IFMODESEL_GMII_MII		0
+#define ET1011C_MII_CONFIG_IFMODESEL_TBI			1
+#define ET1011C_MII_CONFIG_IFMODESEL_GMII_MII_GTX	2
+
+#define ET1011C_MII_LED2 0x1c
+#define ET1011C_MII_LED2_LED_TXRX		12
+#define ET1011C_MII_LED2_LED_NUM_BITS	4
+
+#define ET1011C_MII_LED2_LED_TXRX_ON		0xe
+#define ET1011C_MII_LED2_LED_TXRX_ACTIVITY	0x7
+
+// Some typedefs to cope with std Linux types
+typedef void sk_buff_t;
+
+// The in-memory descriptor structures
+typedef struct gmac_dma_desc
+{
+    /** The encoded status field of the GMAC descriptor */
+    u32 status;
+    /** The encoded length field of GMAC descriptor */
+    u32 length;
+    /** Buffer 1 pointer field of GMAC descriptor */
+    u32 buffer1;
+    /** Buffer 2 pointer or next descriptor pointer field of GMAC descriptor */
+    u32 buffer2;
+    /** Not used for U-Boot */
+    u32 skb;
+} __attribute ((packed)) gmac_dma_desc_t;
+
+typedef struct gmac_desc_list_info
+{
+    gmac_dma_desc_t* base_ptr;
+    int              num_descriptors;
+    int              empty_count;
+    int              full_count;
+    int              r_index;
+    int              w_index;
+} gmac_desc_list_info_t;
+
+// Private data structure for the GMAC driver
+typedef struct gmac_priv
+{
+    /** Base address of GMAC MAC registers */
+    u32                     macBase;
+    /** Base address of GMAC DMA registers */
+    u32                     dmaBase;
+
+    /** The number of descriptors in the gmac_dma_desc_t array holding both the
+     *  TX and RX descriptors. The TX descriptors reside at the start of the
+     *  array */
+    unsigned                total_num_descriptors;
+
+    /** The address of the start of the descriptor array */
+    gmac_dma_desc_t        *desc_base_addr;
+
+    /** Descriptor list management */
+    gmac_desc_list_info_t   tx_gmac_desc_list_info;
+    gmac_desc_list_info_t   rx_gmac_desc_list_info;
+
+	/** PHY info */
+	u32						 phy_type;
+	u32						 phy_addr;
+	int						 phy_id;
+	int						 link_is_1000M;
+} gmac_priv_t;
+
+/**
+ * MAC register indices
+ */
+typedef enum gmac_mac_regs {
+    MAC_CONFIG_REG       = 0,
+    MAC_FRAME_FILTER_REG = 1,
+    MAC_HASH_HIGH_REG    = 2,
+    MAC_HASH_LOW_REG     = 3,
+    MAC_GMII_ADR_REG     = 4,
+    MAC_GMII_DATA_REG    = 5,
+    MAC_FLOW_CNTL_REG    = 6,
+    MAC_VLAN_TAG_REG     = 7,
+    MAC_VERSION_REG      = 8,
+    MAC_ADR0_HIGH_REG    = 16,
+    MAC_ADR0_LOW_REG     = 17,
+    MAC_ADR1_HIGH_REG    = 18,
+    MAC_ADR1_LOW_REG     = 19,
+    MAC_ADR2_HIGH_REG    = 20,
+    MAC_ADR2_LOW_REG     = 21,
+    MAC_ADR3_HIGH_REG    = 22,
+    MAC_ADR3_LOW_REG     = 23,
+    MAC_ADR4_HIGH_REG    = 24,
+    MAC_ADR4_LOW_REG     = 25,
+    MAC_ADR5_HIGH_REG    = 26,
+    MAC_ADR5_LOW_REG     = 27,
+    MAC_ADR6_HIGH_REG    = 28,
+    MAC_ADR6_LOW_REG     = 29,
+    MAC_ADR7_HIGH_REG    = 30,
+    MAC_ADR7_LOW_REG     = 31,
+    MAC_ADR8_HIGH_REG    = 32,
+    MAC_ADR8_LOW_REG     = 33,
+    MAC_ADR9_HIGH_REG    = 34,
+    MAC_ADR9_LOW_REG     = 35,
+    MAC_ADR10_HIGH_REG   = 36,
+    MAC_ADR10_LOW_REG    = 37,
+    MAC_ADR11_HIGH_REG   = 38,
+    MAC_ADR11_LOW_REG    = 39,
+    MAC_ADR12_HIGH_REG   = 40,
+    MAC_ADR12_LOW_REG    = 41,
+    MAC_ADR13_HIGH_REG   = 42,
+    MAC_ADR13_LOW_REG    = 43,
+    MAC_ADR14_HIGH_REG   = 44,
+    MAC_ADR14_LOW_REG    = 45,
+    MAC_ADR15_HIGH_REG   = 46,
+    MAC_ADR15_LOW_REG    = 47
+} gmac_mac_regs_t;
+
+
+/**
+ * MAC register field definitions
+ */
+typedef enum gmac_config_reg {
+    MAC_CONFIG_WD_BIT  = 23,
+    MAC_CONFIG_JD_BIT  = 22,
+    MAC_CONFIG_BE_BIT  = 21,
+    MAC_CONFIG_JE_BIT  = 20,
+    MAC_CONFIG_IFG_BIT = 17,
+    MAC_CONFIG_PS_BIT  = 15,
+    MAC_CONFIG_DO_BIT  = 13,
+    MAC_CONFIG_LM_BIT  = 12,
+    MAC_CONFIG_DM_BIT  = 11,
+    MAC_CONFIG_IPC_BIT = 10,
+    MAC_CONFIG_DR_BIT  = 9,
+    MAC_CONFIG_ACS_BIT = 7,
+    MAC_CONFIG_BL_BIT  = 5,
+    MAC_CONFIG_DC_BIT  = 4,
+    MAC_CONFIG_TE_BIT  = 3,
+    MAC_CONFIG_RE_BIT  = 2
+} gmac_config_reg_t;
+
+#define MAC_CONFIG_IFG_NUM_BITS 3
+#define MAC_CONFIG_BL_NUM_BITS 2
+
+typedef enum gmac_frame_filter_reg {
+    MAC_FRAME_FILTER_RA_BIT   = 31,
+    MAC_FRAME_FILTER_SAF_BIT  = 9,
+    MAC_FRAME_FILTER_SAIF_BIT = 8,
+    MAC_FRAME_FILTER_PCF_BIT  = 6,
+    MAC_FRAME_FILTER_DBF_BIT  = 5,
+    MAC_FRAME_FILTER_PM_BIT   = 4,
+    MAC_FRAME_FILTER_DAIF_BIT = 3,
+    MAC_FRAME_FILTER_HMC_BIT  = 2,
+    MAC_FRAME_FILTER_HUC_BIT  = 1,
+    MAC_FRAME_FILTER_PR_BIT   = 0
+} gmac_frame_filter_reg_t;
+
+#define MAC_FRAME_FILTER_PCF_NUM_BITS 2
+
+typedef enum gmac_hash_table_high_reg {
+    MAC_HASH_HIGH_HTH_BIT = 0
+} gmac_hash_table_high_reg_t;
+
+typedef enum gmac_hash_table_low_reg {
+    MAC_HASH_LOW_HTL_BIT = 0
+} gmac_hash_table_low_reg_t;
+
+typedef enum gmac_gmii_address_reg {
+    MAC_GMII_ADR_PA_BIT = 11,
+    MAC_GMII_ADR_GR_BIT = 6,
+    MAC_GMII_ADR_CR_BIT = 2,
+    MAC_GMII_ADR_GW_BIT = 1,
+    MAC_GMII_ADR_GB_BIT = 0
+} gmac_gmii_address_reg_t;
+
+#define MAC_GMII_ADR_PA_NUM_BITS 5
+#define MAC_GMII_ADR_GR_NUM_BITS 5
+#define MAC_GMII_ADR_CR_NUM_BITS 3
+
+typedef enum gmac_gmii_data_reg {
+    MAC_GMII_DATA_GD_BIT = 0
+} gmac_gmii_data_reg_t;
+
+#define MAC_GMII_DATA_GD_NUM_BITS 16
+
+typedef enum gmac_flow_control_reg {
+    MAC_FLOW_CNTL_PT_BIT      = 16,
+    MAC_FLOW_CNTL_PLT_BIT     = 4,
+    MAC_FLOW_CNTL_UP_BIT      = 3,
+    MAC_FLOW_CNTL_RFE_BIT     = 2,
+    MAC_FLOW_CNTL_TFE_BIT     = 1,
+    MAC_FLOW_CNTL_FCB_BPA_BIT = 0
+} gmac_flow_control_reg_t;
+
+#define MAC_FLOW_CNTL_PT_NUM_BITS 16
+#define MAC_FLOW_CNTL_PLT_NUM_BITS 2
+
+typedef enum gmac_vlan_tag_reg {
+    MAC_VLAN_TAG_LV_BIT = 0
+} gmac_vlan_tag_reg_t;
+
+#define MAC_VLAN_TAG_LV_NUM_BITS 16
+
+typedef enum gmac_version_reg {
+    MAC_VERSION_UD_BIT = 8,
+    MAC_VERSION_SD_BIT = 0
+} gmac_version_reg_t;
+
+#define MAC_VERSION_UD_NUM_BITS 8
+#define MAC_VERSION_SD_NUM_BITS 8
+
+typedef enum gmac_mac_adr_0_high_reg {
+    MAC_ADR0_HIGH_MO_BIT = 31,
+    MAC_ADR0_HIGH_A_BIT  = 0
+} gmac_mac_adr_0_high_reg_t;
+
+#define MAC_ADR0_HIGH_A_NUM_BITS 16
+
+typedef enum gmac_mac_adr_0_low_reg {
+    MAC_ADR0_LOW_A_BIT = 0
+} gmac_mac_adr_0_low_reg_t;
+
+typedef enum gmac_mac_adr_1_high_reg {
+    MAC_ADR1_HIGH_AE_BIT  = 31,
+    MAC_ADR1_HIGH_SA_BIT  = 30,
+    MAC_ADR1_HIGH_MBC_BIT = 24,
+    MAC_ADR1_HIGH_A_BIT   = 0
+} gmac_mac_adr_1_high_reg_t;
+
+#define MAC_ADR1_HIGH_MBC_NUM_BITS 6
+#define MAC_ADR1_HIGH_A_NUM_BITS 16
+
+typedef enum gmac_mac_adr_1_low_reg {
+    MAC_ADR1_LOW_A_BIT = 0
+} gmac_mac_adr_1_low_reg_t;
+
+
+/**
+ * MMC register indices - registers accessed via the MAC accessor functions
+ */
+typedef enum gmac_mmc_regs {
+    MMC_CONTROL_REG = 64,
+    MMC_RX_INT_REG  = 65,
+    MMC_TX_INT_REG  = 66,
+    MMC_RX_MASK_REG = 67,
+    MMC_TX_MASK_REG = 68
+} gmac_mmc_regs_t;
+
+/**
+ * DMA register indices
+ */
+typedef enum gmac_dma_regs {
+    DMA_BUS_MODE_REG        = 0,
+    DMA_TX_POLL_REG         = 1,
+    DMA_RX_POLL_REG         = 2,
+    DMA_RX_DESC_ADR_REG     = 3,
+    DMA_TX_DESC_ADR_REG     = 4,
+    DMA_STATUS_REG          = 5,
+    DMA_OP_MODE_REG         = 6,
+    DMA_INT_ENABLE_REG      = 7,
+    DMA_MISSED_OVERFLOW_REG = 8,
+    DMA_CUR_TX_DESC_REG     = 18,
+    DMA_CUR_RX_DESC_REG     = 19,
+    DMA_CUR_TX_ADR_REG      = 20,
+    DMA_CUR_RX_ADR_REG      = 21
+} gmac_dma_regs_t;
+
+/**
+ * DMA register field definitions
+ */
+
+typedef enum gmac_dma_bus_mode_reg {
+    DMA_BUS_MODE_FB_BIT  = 16,
+    DMA_BUS_MODE_PR_BIT  = 14,
+    DMA_BUS_MODE_PBL_BIT = 8,
+    DMA_BUS_MODE_DSL_BIT = 2,
+    DMA_BUS_MODE_DA_BIT  = 1,
+    DMA_BUS_MODE_SWR_BIT = 0
+} gmac_dma_bus_mode_reg_t;
+
+#define DMA_BUS_MODE_PR_NUM_BITS 2
+#define DMA_BUS_MODE_PBL_NUM_BITS 6
+#define DMA_BUS_MODE_DSL_NUM_BITS 5
+
+typedef enum gmac_dma_tx_poll_demand_reg {
+    DMA_TX_POLL_TPD_BIT = 0
+} gmac_dma_tx_poll_demand_reg_t;
+
+typedef enum gmac_dma_rx_poll_demand_reg {
+    DMA_RX_POLL_RPD_BIT = 0
+} gmac_dma_rx_poll_demand_reg_t;
+
+typedef enum gmac_dma_rx_desc_list_adr_reg {
+    DMA_RX_DESC_ADR_SRL_BIT = 0
+} gmac_dma_rx_desc_list_adr_reg_t;
+
+typedef enum gmac_dma_tx_desc_list_adr_reg {
+    DMA_TX_DESC_ADR_STL_BIT = 0
+} gmac_dma_tx_desc_list_adr_reg_t;
+
+typedef enum gmac_dma_status_reg {
+    DMA_STATUS_GPI_BIT = 28,
+    DMA_STATUS_GMI_BIT = 27,
+    DMA_STATUS_GLI_BIT = 26,
+    DMA_STATUS_EB_BIT  = 23,
+    DMA_STATUS_TS_BIT  = 20,
+    DMA_STATUS_RS_BIT  = 17,
+    DMA_STATUS_NIS_BIT = 16,
+    DMA_STATUS_AIS_BIT = 15,
+    DMA_STATUS_ERI_BIT = 14,
+    DMA_STATUS_FBE_BIT = 13,
+    DMA_STATUS_ETI_BIT = 10,
+    DMA_STATUS_RWT_BIT = 9,
+    DMA_STATUS_RPS_BIT = 8,
+    DMA_STATUS_RU_BIT  = 7,
+    DMA_STATUS_RI_BIT  = 6,
+    DMA_STATUS_UNF_BIT = 5,
+    DMA_STATUS_OVF_BIT = 4,
+    DMA_STATUS_TJT_BIT = 3,
+    DMA_STATUS_TU_BIT  = 2,
+    DMA_STATUS_TPS_BIT = 1,
+    DMA_STATUS_TI_BIT  = 0
+} gmac_dma_status_reg_t;
+
+#define DMA_STATUS_EB_NUM_BITS 3
+#define DMA_STATUS_TS_NUM_BITS 3
+#define DMA_STATUS_RS_NUM_BITS 3
+
+typedef enum gmac_dma_op_mode_reg {
+    DMA_OP_MODE_SF_BIT  = 21,
+    DMA_OP_MODE_FTF_BIT = 20,
+    DMA_OP_MODE_TTC_BIT = 14,
+    DMA_OP_MODE_ST_BIT  = 13,
+    DMA_OP_MODE_RFD_BIT = 11,
+    DMA_OP_MODE_RFA_BIT = 9,
+    DMA_OP_MODE_EFC_BIT = 8,
+    DMA_OP_MODE_FEF_BIT = 7,
+    DMA_OP_MODE_FUF_BIT = 6,
+    DMA_OP_MODE_RTC_BIT = 3,
+    DMA_OP_MODE_OSF_BIT = 2,
+    DMA_OP_MODE_SR_BIT  = 1
+} gmac_dma_op_mode_reg_t;
+
+#define DMA_OP_MODE_TTC_NUM_BITS 3
+#define DMA_OP_MODE_RFD_NUM_BITS 2
+#define DMA_OP_MODE_RFA_NUM_BITS 2
+#define DMA_OP_MODE_RTC_NUM_BITS 2
+
+typedef enum gmac_dma_intr_enable_reg {
+    DMA_INT_ENABLE_NI_BIT  = 16,
+    DMA_INT_ENABLE_AI_BIT  = 15,
+    DMA_INT_ENABLE_ERE_BIT = 14,
+    DMA_INT_ENABLE_FBE_BIT = 13,
+    DMA_INT_ENABLE_ETE_BIT = 10,
+    DMA_INT_ENABLE_RW_BIT  = 9,
+    DMA_INT_ENABLE_RS_BIT  = 8,
+    DMA_INT_ENABLE_RU_BIT  = 7,
+    DMA_INT_ENABLE_RI_BIT  = 6,
+    DMA_INT_ENABLE_UN_BIT  = 5,
+    DMA_INT_ENABLE_OV_BIT  = 4,
+    DMA_INT_ENABLE_TJ_BIT  = 3,
+    DMA_INT_ENABLE_TU_BIT  = 2,
+    DMA_INT_ENABLE_TS_BIT  = 1,
+    DMA_INT_ENABLE_TI_BIT  = 0
+} gmac_dma_intr_enable_reg_t;
+
+typedef enum gmac_dma_missed_overflow_reg {
+    DMA_MISSED_OVERFLOW_OFOC_BIT  = 28,    // Overflow bit for FIFO Overflow Counter
+    DMA_MISSED_OVERFLOW_AMFC_BIT  = 17,    // Application Missed Frames Count
+    DMA_MISSED_OVERFLOW_OAMFO_BIT = 16,    // Overflow bit for Application Missed Frames Count
+    DMA_MISSED_OVERFLOW_CMFC_BIT  = 0      // Controller Missed Frames Count
+} gmac_dma_missed_overflow_reg_t;
+
+#define DMA_MISSED_OVERFLOW_OAMFO_NUM_BITS 11
+#define DMA_MISSED_OVERFLOW_CMFC_NUM_BITS 16
+
+typedef enum gmac_dma_current_tx_desc_reg {
+    DMA_CUR_TX_DESC_A_BIT = 0
+} gmac_dma_current_tx_desc_reg_t;
+
+typedef enum gmac_dma_current_rx_desc_reg {
+    DMA_CUR_RX_DESC_A_BIT = 0
+} gmac_dma_current_rx_desc_reg_t;
+
+typedef enum gmac_dma_current_tx_adr_reg {
+    DMA_CUR_TX_ADR_A_BIT = 0
+} gmac_dma_current_tx_adr_reg_t;
+
+typedef enum gmac_dma_current_rx_adr_reg {
+    DMA_CUR_RX_ADR_A_BIT = 0
+} gmac_dma_current_rx_adr_reg_t;
+
+/**
+ * Descriptor support
+ */
+/** Descriptor status word field definitions */
+typedef enum desc_status {
+  descOwnByDma          = 0x80000000,   /* descriptor is owned by DMA engine  */
+
+  descFrameLengthMask   = 0x3FFF0000,   /* Receive descriptor frame length */
+  descFrameLengthShift  = 16,
+
+  descError             = 0x00008000,   /* Error summary bit  - OR of the following bits:    v  */
+
+  descRxTruncated       = 0x00004000,   /* Rx - no more descriptors for receive frame        E  */
+
+  descRxLengthError     = 0x00001000,   /* Rx - frame size not matching with length field */
+  descRxDamaged         = 0x00000800,   /* Rx - frame was damaged due to buffer overflow     E  */
+  descRxFirst           = 0x00000200,   /* Rx - first descriptor of the frame                   */
+  descRxLast            = 0x00000100,   /* Rx - last descriptor of the frame                    */
+  descRxLongFrame       = 0x00000080,   /* Rx - frame is longer than 1518 bytes              E  */
+  descRxCollision       = 0x00000040,   /* Rx - late collision occurred during reception     E  */
+  descRxFrameEther      = 0x00000020,   /* Rx - Frame type - Ethernet, otherwise 802.3          */
+  descRxWatchdog        = 0x00000010,   /* Rx - watchdog timer expired during reception      E  */
+  descRxMiiError        = 0x00000008,   /* Rx - error reported by MII interface              E  */
+  descRxDribbling       = 0x00000004,   /* Rx - frame contains noninteger multiple of 8 bits    */
+  descRxCrc             = 0x00000002,   /* Rx - CRC error                                    E  */
+
+  descTxTimeout         = 0x00004000,   /* Tx - Transmit jabber timeout                      E  */
+  descTxLostCarrier     = 0x00000800,   /* Tx - carrier lost during tramsmission             E  */
+  descTxNoCarrier       = 0x00000400,   /* Tx - no carrier signal from the tranceiver        E  */
+  descTxLateCollision   = 0x00000200,   /* Tx - transmission aborted due to collision        E  */
+  descTxExcCollisions   = 0x00000100,   /* Tx - transmission aborted after 16 collisions     E  */
+  descTxVLANFrame       = 0x00000080,   /* Tx - VLAN-type frame                                 */
+  descTxCollMask        = 0x00000078,   /* Tx - Collision count                                 */
+  descTxCollShift       = 3,
+  descTxExcDeferral     = 0x00000004,   /* Tx - excessive deferral                           E  */
+  descTxUnderflow       = 0x00000002,   /* Tx - late data arrival from the memory            E  */
+  descTxDeferred        = 0x00000001,   /* Tx - frame transmision deferred                      */
+} desc_status_t;
+
+/** Descriptor length word field definitions */
+typedef enum desc_length {
+  descTxIntEnable       = 0x80000000,   /* Tx - interrupt on completion                         */
+  descTxLast            = 0x40000000,   /* Tx - Last segment of the frame                       */
+  descTxFirst           = 0x20000000,   /* Tx - First segment of the frame                      */
+  descTxDisableCrc      = 0x04000000,   /* Tx - Add CRC disabled (first segment only)           */
+
+  descEndOfRing         = 0x02000000,   /* End of descriptors ring                              */
+  descChain             = 0x01000000,   /* Second buffer address is chain address               */
+  descTxDisablePadd     = 0x00800000,   /* disable padding, added by - reyaz */
+
+  descSize2Mask         = 0x003FF800,   /* Buffer 2 size                                        */
+  descSize2Shift        = 11,
+  descSize1Mask         = 0x000007FF,   /* Buffer 1 size                                        */
+  descSize1Shift        = 0,
+} desc_length_t;
+
+typedef enum rx_desc_status {
+    RX_DESC_STATUS_OWN_BIT  = 31,
+    RX_DESC_STATUS_AFM_BIT  = 30,
+    RX_DESC_STATUS_FL_BIT   = 16,
+    RX_DESC_STATUS_ES_BIT   = 15,
+    RX_DESC_STATUS_DE_BIT   = 14,
+    RX_DESC_STATUS_SAF_BIT  = 13,
+    RX_DESC_STATUS_LE_BIT   = 12,
+    RX_DESC_STATUS_OE_BIT   = 11,
+    RX_DESC_STATUS_IPC_BIT  = 10,
+    RX_DESC_STATUS_FS_BIT   = 9,
+    RX_DESC_STATUS_LS_BIT   = 8,
+    RX_DESC_STATUS_VLAN_BIT = 7,
+    RX_DESC_STATUS_LC_BIT   = 6,
+    RX_DESC_STATUS_FT_BIT   = 5,
+    RX_DESC_STATUS_RWT_BIT  = 4,
+    RX_DESC_STATUS_RE_BIT   = 3,
+    RX_DESC_STATUS_DRE_BIT  = 2,
+    RX_DESC_STATUS_CE_BIT   = 1,
+    RX_DESC_STATUS_MAC_BIT  = 0
+} rx_desc_status_t;
+
+#define RX_DESC_STATUS_FL_NUM_BITS 14
+
+typedef enum rx_desc_length {
+    RX_DESC_LENGTH_DIC_BIT  = 31,
+    RX_DESC_LENGTH_RER_BIT  = 25,
+    RX_DESC_LENGTH_RCH_BIT  = 24,
+    RX_DESC_LENGTH_RBS2_BIT = 11,
+    RX_DESC_LENGTH_RBS1_BIT = 0,
+} rx_desc_length_t;
+
+#define RX_DESC_LENGTH_RBS2_NUM_BITS 11
+#define RX_DESC_LENGTH_RBS1_NUM_BITS 11
+
+typedef enum tx_desc_status {
+    TX_DESC_STATUS_OWN_BIT  = 31,
+    TX_DESC_STATUS_ES_BIT   = 15,
+    TX_DESC_STATUS_JT_BIT   = 14,
+    TX_DESC_STATUS_FF_BIT   = 13,
+    TX_DESC_STATUS_LOC_BIT  = 11,
+    TX_DESC_STATUS_NC_BIT   = 10,
+    TX_DESC_STATUS_LC_BIT   = 9,
+    TX_DESC_STATUS_EC_BIT   = 8,
+    TX_DESC_STATUS_VF_BIT   = 7,
+    TX_DESC_STATUS_CC_BIT   = 3,
+    TX_DESC_STATUS_ED_BIT   = 2,
+    TX_DESC_STATUS_UF_BIT   = 1,
+    TX_DESC_STATUS_DB_BIT   = 0
+} tx_desc_status_t;
+
+#define TX_DESC_STATUS_CC_NUM_BITS 4
+
+typedef enum tx_desc_length {
+    TX_DESC_LENGTH_IC_BIT   = 31,
+    TX_DESC_LENGTH_LS_BIT   = 30,
+    TX_DESC_LENGTH_FS_BIT   = 29,
+    TX_DESC_LENGTH_DC_BIT   = 26,
+    TX_DESC_LENGTH_TER_BIT  = 25,
+    TX_DESC_LENGTH_TCH_BIT  = 24,
+    TX_DESC_LENGTH_DP_BIT   = 23,
+    TX_DESC_LENGTH_TBS2_BIT = 11,
+    TX_DESC_LENGTH_TBS1_BIT = 0
+} tx_desc_length_t;
+
+#define TX_DESC_LENGTH_TBS2_NUM_BITS 11
+#define TX_DESC_LENGTH_TBS1_NUM_BITS 11
+
+/** Return the number of descriptors available for the CPU to fill with new
+ *  packet info */
+static inline int available_for_write(gmac_desc_list_info_t* desc_list)
+{
+    return desc_list->empty_count;
+}
+
+/** Return non-zero if there is a descriptor available with a packet with which
+ *  the GMAC DMA has finished */
+static inline int tx_available_for_read(gmac_desc_list_info_t* desc_list)
+{
+    return desc_list->full_count &&
+           !((desc_list->base_ptr + desc_list->r_index)->status & (1UL << TX_DESC_STATUS_OWN_BIT));
+}
+
+/** Return non-zero if there is a descriptor available with a packet with which
+ *  the GMAC DMA has finished */
+static inline int rx_available_for_read(gmac_desc_list_info_t* desc_list)
+{
+    return desc_list->full_count &&
+           !((desc_list->base_ptr + desc_list->r_index)->status & (1UL << RX_DESC_STATUS_OWN_BIT));
+}
+
+/**
+ * @param A u32 containing the status from a received frame's DMA descriptor
+ * @return An int which is non-zero if a valid received frame is fully contained
+ *  within the descriptor from whence the status came
+ */
+static inline int is_rx_valid(u32 status)
+{
+    return !(status & descError)  &&
+           (status & descRxFirst) &&
+           (status & descRxLast);
+}
+
+static inline int is_rx_dribbling(u32 status)
+{
+    return status & descRxDribbling;
+}
+
+static inline u32 get_rx_length(u32 status)
+{
+    return (status & descFrameLengthMask) >> descFrameLengthShift;
+}
+
+static inline int is_rx_collision_error(u32 status)
+{
+    return status & (descRxDamaged | descRxCollision);
+}
+
+static inline int is_rx_crc_error(u32 status)
+{
+    return status & descRxCrc;
+}
+
+static inline int is_rx_frame_error(u32 status)
+{
+    return status & descRxDribbling;
+}
+
+static inline int is_rx_length_error(u32 status)
+{
+    return status & descRxLengthError;
+}
+
+static inline int is_rx_long_frame(u32 status)
+{
+    return status & descRxLongFrame;
+}
+
+static inline int is_tx_valid(u32 status)
+{
+    return !(status & descError);
+}
+
+static inline int is_tx_collision_error(u32 status)
+{
+    return (status & descTxCollMask) >> descTxCollShift;
+}
+
+static inline int is_tx_aborted(u32 status)
+{
+    return status & (descTxLateCollision | descTxExcCollisions);
+}
+
+static inline int is_tx_carrier_error(u32 status)
+{
+    return status & (descTxLostCarrier | descTxNoCarrier);
+}
+
+/**
+ * GMAC private metadata
+ */
+static gmac_priv_t priv_data;
+static gmac_priv_t* priv = &priv_data;
+
+/**
+ * Descriptor list management
+ */
+
+static void init_rx_descriptor(
+    gmac_dma_desc_t* desc,
+    int              end_of_ring,
+    int              disable_ioc)
+{
+    desc->status = 0;
+    desc->length = 0;
+    if (disable_ioc) {
+        desc->length |= (1UL << RX_DESC_LENGTH_DIC_BIT);
+    }
+    if (end_of_ring) {
+        desc->length |= (1UL << RX_DESC_LENGTH_RER_BIT);
+    }
+    desc->buffer1 = 0;
+    desc->buffer2 = 0;
+    desc->skb = 0;
+}
+
+static void init_tx_descriptor(
+    gmac_dma_desc_t* desc,
+    int              end_of_ring,
+    int              enable_ioc,
+    int              disable_crc,
+    int              disable_padding)
+{
+    desc->status = 0;
+    desc->length = 0;
+    if (enable_ioc) {
+        desc->length |= (1UL << TX_DESC_LENGTH_IC_BIT);
+    }
+    if (disable_crc) {
+        desc->length |= (1UL << TX_DESC_LENGTH_DC_BIT);
+    }
+    if (disable_padding) {
+        desc->length |= (1UL << TX_DESC_LENGTH_DP_BIT);
+    }
+    if (end_of_ring) {
+        desc->length |= (1UL << TX_DESC_LENGTH_TER_BIT);
+    }
+    desc->buffer1 = 0;
+    desc->buffer2 = 0;
+    desc->skb = 0;
+}
+
+static void init_rx_desc_list(
+    gmac_desc_list_info_t* desc_list,
+    gmac_dma_desc_t*       base_ptr,
+    int                    num_descriptors)
+{
+    int i;
+    
+    desc_list->base_ptr = base_ptr;
+    desc_list->num_descriptors = num_descriptors;
+    desc_list->empty_count = num_descriptors;
+    desc_list->full_count = 0;
+    desc_list->r_index = 0;
+    desc_list->w_index = 0;
+
+    for (i=0; i < (num_descriptors - 1); i++) {
+        init_rx_descriptor(base_ptr + i, 0, 0);
+    }
+    init_rx_descriptor(base_ptr + i, 1, 0);
+}
+
+static void init_tx_desc_list(
+    gmac_desc_list_info_t* desc_list,
+    gmac_dma_desc_t*       base_ptr,
+    int                    num_descriptors)
+{
+    int i;
+    
+    desc_list->base_ptr = base_ptr;
+    desc_list->num_descriptors = num_descriptors;
+    desc_list->empty_count = num_descriptors;
+    desc_list->full_count = 0;
+    desc_list->r_index = 0;
+    desc_list->w_index = 0;
+
+    for (i=0; i < (num_descriptors - 1); i++) {
+        init_tx_descriptor(base_ptr + i, 0, 1, 0, 0);
+    }
+    init_tx_descriptor(base_ptr + i, 1, 1, 0, 0);
+}
+
+static void rx_take_ownership(gmac_desc_list_info_t* desc_list)
+{
+    int i;
+    for (i=0; i < desc_list->num_descriptors; i++) {
+        (desc_list->base_ptr + i)->status &= ~(1UL << RX_DESC_STATUS_OWN_BIT);
+    }
+}
+
+static void tx_take_ownership(gmac_desc_list_info_t* desc_list)
+{
+    int i;
+    for (i=0; i < desc_list->num_descriptors; i++) {
+        (desc_list->base_ptr + i)->status &= ~(1UL << TX_DESC_STATUS_OWN_BIT);
+    }
+}
+
+static int set_tx_descriptor(
+    gmac_priv_t* priv,
+    dma_addr_t   dma_address,
+    u32          length,
+    sk_buff_t*   skb)
+{
+    int index;
+    gmac_dma_desc_t* tx;
+
+    // Are sufficicent descriptors available for writing by the CPU?
+    if (!available_for_write(&priv->tx_gmac_desc_list_info)) {
+        return -1;
+    }
+
+    // Get the index of the next TX descriptor available for writing by the CPU
+    index = priv->tx_gmac_desc_list_info.w_index;
+
+    // Get a pointer to the next TX descriptor available for writing by the CPU
+    tx = priv->tx_gmac_desc_list_info.base_ptr + index;
+
+    // Initialise the TX descriptor length field for the passed single buffer,
+    // without destroying any fields we wish to be persistent
+
+    // No chained second buffer
+    tx->length &= ~(1UL << TX_DESC_LENGTH_TCH_BIT);
+    // Single descriptor holds entire packet
+    tx->length |= ((1UL << TX_DESC_LENGTH_LS_BIT) | (1UL << TX_DESC_LENGTH_FS_BIT));
+    // Zero the second buffer length field
+    tx->length &= ~(((1UL << TX_DESC_LENGTH_TBS2_NUM_BITS) - 1) << TX_DESC_LENGTH_TBS2_BIT);
+    // Zero the first buffer length field
+    tx->length &= ~(((1UL << TX_DESC_LENGTH_TBS1_NUM_BITS) - 1) << TX_DESC_LENGTH_TBS1_BIT);
+    // Fill in the first buffer length
+    tx->length |= (length << TX_DESC_LENGTH_TBS1_BIT);
+
+    // Initialise the first buffer pointer to the single passed buffer
+    tx->buffer1 = dma_address;
+
+    // Remember the socket buffer associated with the single passed buffer
+    tx->skb = (u32)skb;
+
+    // Update the index of the next descriptor available for writing by the CPU
+    priv->tx_gmac_desc_list_info.w_index = (tx->length & (1UL << TX_DESC_LENGTH_TER_BIT)) ? 0 : index + 1;
+
+    // make sure all memory updates are complete before releasing the GMAC on the data.
+    wmb();
+    
+    // Hand TX descriptor to the GMAC DMA by setting the status bit.
+    tx->status = (1UL << TX_DESC_STATUS_OWN_BIT);
+
+    // Account for the number of descriptors used to hold the new packet
+    --priv->tx_gmac_desc_list_info.empty_count;
+    ++priv->tx_gmac_desc_list_info.full_count;
+
+    return index;
+}
+
+static int get_tx_descriptor(
+    gmac_priv_t* priv,
+    u32*         status,
+    dma_addr_t*  dma_address,
+    u32*         length,
+    sk_buff_t**  skb)
+{
+    int index;
+    gmac_dma_desc_t *tx;
+
+    // Is there at least one descriptor with which the GMAC DMA has finished?
+    if (!tx_available_for_read(&priv->tx_gmac_desc_list_info)) {
+        return -1;
+    }
+
+    // Get the index of the descriptor released the longest time ago by the
+    // GMAC DMA 
+    index = priv->tx_gmac_desc_list_info.r_index;
+
+    // Get a pointer to the descriptor released the longest time ago by the
+    // GMAC DMA 
+    tx = priv->tx_gmac_desc_list_info.base_ptr + index;
+
+    // Extract the status field
+    if (status) {
+        *status = tx->status;
+    }
+
+    // Extract the length field - only cope with the first buffer associated
+    // with the descriptor
+    if (length) {
+        *length = (tx->length >> TX_DESC_LENGTH_TBS1_BIT) &
+                  ((1UL << TX_DESC_LENGTH_TBS1_NUM_BITS) - 1);
+    }
+
+    // Extract the pointer to the buffer containing the packet - only cope with
+    // the first buffer associated with the descriptor
+    if (dma_address) {
+        *dma_address = tx->buffer1;
+    }
+
+    // Extract the pointer to the socket buffer associated with the packet
+    if (skb) {
+        *skb = (sk_buff_t*)(tx->skb);
+    }
+
+    // Update the index of the next descriptor with which the GMAC DMA may have
+    // finished
+    priv->tx_gmac_desc_list_info.r_index = (tx->length & (1UL << TX_DESC_LENGTH_TER_BIT)) ? 0 : index + 1;
+
+    // Account for the number of descriptors freed to hold new packets
+    ++priv->tx_gmac_desc_list_info.empty_count;
+    --priv->tx_gmac_desc_list_info.full_count;
+
+    return index;
+}
+
+int set_rx_descriptor(
+    gmac_priv_t* priv,
+    dma_addr_t   dma_address,
+    u32          length,
+    sk_buff_t*   skb)
+{
+    int index;
+    gmac_dma_desc_t* rx;
+    int num_descriptors_required;
+
+    // Currently only support using a single descriptor to describe each packet
+    // queued with the GMAc DMA
+    num_descriptors_required = 1;
+
+    // Are sufficicent descriptors available for writing by the CPU?
+    if (available_for_write(&priv->rx_gmac_desc_list_info) < num_descriptors_required) {
+        index = -1;
+    } else {
+        // Get the index of the next RX descriptor available for writing by the CPU
+        index = priv->rx_gmac_desc_list_info.w_index;
+
+        // Get a pointer to the next RX descriptor available for writing by the CPU
+        rx = priv->rx_gmac_desc_list_info.base_ptr + index;
+
+        // Initialise the RX descriptor length field for the passed single buffer,
+        // without destroying any fields we wish to be persistent
+
+        // No chained second buffer
+        rx->length &= ~(1UL << RX_DESC_LENGTH_RCH_BIT);
+        // Zero the second buffer length field
+        rx->length &= ~(((1UL << RX_DESC_LENGTH_RBS2_NUM_BITS) - 1) << RX_DESC_LENGTH_RBS2_BIT);
+        // Zero the first buffer length field
+        rx->length &= ~(((1UL << RX_DESC_LENGTH_RBS1_NUM_BITS) - 1) << RX_DESC_LENGTH_RBS1_BIT);
+        // Fill in the first buffer length
+        rx->length |= (length << RX_DESC_LENGTH_RBS1_BIT);
+
+        // Initialise the first buffer pointer to the single passed buffer
+        rx->buffer1 = dma_address;
+
+        // Remember the socket buffer associated with the single passed buffer
+        rx->skb = (u32)skb;
+        
+        wmb();
+        
+        // Initialise RX descriptor status to be owned by the GMAC DMA
+        rx->status = (1UL << RX_DESC_STATUS_OWN_BIT);
+
+        // Update the index of the next descriptor available for writing by the CPU
+        priv->rx_gmac_desc_list_info.w_index = (rx->length & (1UL << RX_DESC_LENGTH_RER_BIT)) ? 0 : index + 1;
+
+        // Account for the number of descriptors used to hold the new packet
+        priv->rx_gmac_desc_list_info.empty_count -= num_descriptors_required;
+        priv->rx_gmac_desc_list_info.full_count  += num_descriptors_required;
+    }
+
+    return index;
+}
+
+int get_rx_descriptor(
+    gmac_priv_t* priv,
+    u32*         status,
+    dma_addr_t*  dma_address,
+    u32*         length,
+    sk_buff_t**  skb)
+{
+    int index;
+    gmac_dma_desc_t *rx;
+    int num_descriptors_required;
+
+    // Is there at least one descriptor with which the GMAC DMA has finished?
+    if (!rx_available_for_read(&priv->rx_gmac_desc_list_info)) {
+        return -1;
+    }
+
+    // Currently can only cope with packets entirely contained within a single
+    // descriptor
+    num_descriptors_required = 1;
+
+    // Get the index of the descriptor released the longest time ago by the
+    // GMAC DMA 
+    index = priv->rx_gmac_desc_list_info.r_index;
+
+    // Get a pointer to the descriptor released the longest time ago by the
+    // GMAC DMA 
+    rx = priv->rx_gmac_desc_list_info.base_ptr + index;
+
+    // Extract the status field
+    if (status) {
+        *status = rx->status;
+    }
+
+    // Extract the length field - only cope with the first buffer associated
+    // with the descriptor
+    if (length) {
+        *length = (rx->length >> RX_DESC_LENGTH_RBS1_BIT) &
+                  ((1UL << RX_DESC_LENGTH_RBS1_NUM_BITS) - 1);
+    }
+
+    // Extract the pointer to the buffer containing the packet - only cope with
+    // the first buffer associated with the descriptor
+    if (dma_address) {
+        *dma_address = rx->buffer1;
+    }
+
+    // Extract the pointer to the socket buffer associated with the packet
+    if (skb) {
+        *skb = (sk_buff_t*)(rx->skb);
+    }
+
+    wmb();
+    // Update the index of the next descriptor with which the GMAC DMA may have
+    // finished
+    priv->rx_gmac_desc_list_info.r_index = (rx->length & (1UL << RX_DESC_LENGTH_RER_BIT)) ? 0 : index + 1;
+
+    // Account for the number of descriptors freed to hold new packets
+    priv->rx_gmac_desc_list_info.empty_count += num_descriptors_required;
+    priv->rx_gmac_desc_list_info.full_count  -= num_descriptors_required;
+
+    return index;
+}
+
+/**
+ * GMAC register access functions
+ */
+
+/**
+ * MAC register access functions
+ */
+
+/**
+ * @param priv A gmac_priv_t* pointing to private device data
+ * @param reg_num An int specifying the index of the MAC register to access
+ */
+static inline u32 mac_reg_read(gmac_priv_t* priv, int reg_num)
+{
+    return *(volatile u32*)(priv->macBase + (reg_num << 2));
+}
+
+/**
+ * @param priv A gmac_priv_t* pointing to private device data
+ * @param reg_num An int specifying the index of the MAC register to access
+ */
+static inline void mac_reg_write(gmac_priv_t* priv, int reg_num, u32 value)
+{
+    *(volatile u32*)(priv->macBase + (reg_num << 2)) = value;
+   
+}
+
+/**
+ * @param priv A gmac_priv_t* pointing to private device data
+ * @param reg_num An int specifying the index of the MAC register to access
+ * @param bits_to_clear A u32 specifying which bits of the specified register to
+ *  clear. A set bit in this parameter will cause the matching bit in the
+ *  register to be cleared
+ */
+static inline void mac_reg_clear_mask(gmac_priv_t* priv, int reg_num, u32 bits_to_clear)
+{
+    mac_reg_write(priv, reg_num, mac_reg_read(priv, reg_num) & ~bits_to_clear);
+}
+
+/**
+ * @param priv A gmac_priv_t* pointing to private device data
+ * @param reg_num An int specifying the index of the MAC register to access
+ * @param bits_to_set A u32 specifying which bits of the specified register to
+ *  set. A set bit in this parameter will cause the matching bit in the register
+ *  to be set
+ */
+static inline void mac_reg_set_mask(gmac_priv_t* priv, int reg_num, u32 bits_to_set)
+{
+    mac_reg_write(priv, reg_num, mac_reg_read(priv, reg_num) | bits_to_set);
+}
+
+
+/**
+ * DMA register access functions
+ */
+
+/**
+ * @param priv A gmac_priv_t* pointing to private device data
+ * @param reg_num An int specifying the index of the DMA register to access
+ */
+static inline u32 dma_reg_read(gmac_priv_t* priv, int reg_num)
+{
+    return *(volatile u32*)(priv->dmaBase + (reg_num << 2));
+}
+
+/**
+ * @param priv A gmac_priv_t* pointing to private device data
+ * @param reg_num An int specifying the index of the DMA register to access
+ */
+static inline void dma_reg_write(gmac_priv_t* priv, int reg_num, u32 value)
+{
+    *(volatile u32*)(priv->dmaBase + (reg_num << 2)) = value;
+    wmb();
+}
+
+/**
+ * @param priv A gmac_priv_t* pointing to private device data
+ * @param reg_num An int specifying the index of the DMA register to access
+ * @param bits_to_clear A u32 specifying which bits of the specified register to
+ *  clear. A set bit in this parameter will cause the matching bit in the
+ *  register to be cleared
+ * @return An u32 containing the new value written to the register
+ */
+static inline u32 dma_reg_clear_mask(gmac_priv_t* priv, int reg_num, u32 bits_to_clear)
+{
+    u32 new_value = dma_reg_read(priv, reg_num) & ~bits_to_clear;
+    dma_reg_write(priv, reg_num, new_value);
+    return new_value;
+}
+
+/**
+ * @param priv A gmac_priv_t* pointing to private device data
+ * @param reg_num An int specifying the index of the DMA register to access
+ * @param bits_to_set A u32 specifying which bits of the specified register to
+ *  set. A set bit in this parameter will cause the matching bit in the register
+ *  to be set
+ * @return An u32 containing the new value written to the register
+ */
+static inline u32 dma_reg_set_mask(gmac_priv_t* priv, int reg_num, u32 bits_to_set)
+{
+    u32 new_value = dma_reg_read(priv, reg_num) | bits_to_set;
+    dma_reg_write(priv, reg_num, new_value);
+    return new_value;
+}
+
+static void eth_down(void)
+{
+    // Stop transmitter, take ownership of all tx descriptors
+    dma_reg_clear_mask(priv, DMA_OP_MODE_REG, DMA_OP_MODE_ST_BIT);
+    if (priv->desc_base_addr) {
+        tx_take_ownership(&priv->tx_gmac_desc_list_info);
+    }
+
+    // Stop receiver, take ownership of all rx descriptors
+    dma_reg_clear_mask(priv, DMA_OP_MODE_REG, DMA_OP_MODE_SR_BIT);
+    if (priv->desc_base_addr) {
+        rx_take_ownership(&priv->rx_gmac_desc_list_info);
+    }
+
+    // Free descriptor resources. The TX descriptor will not have a packet
+    // buffer attached, as this is provided by the stack when transmission is
+    // required and ownership is not retained by the descriptor, as the stack
+    // waits for transmission to complete via polling
+    if (priv->desc_base_addr) {
+        // Free receive descriptors, accounting for buffer offset used to
+        // ensure IP header alignment
+        while (1) {
+            dma_addr_t dma_address;
+            if (get_rx_descriptor(priv, 0, &dma_address, 0, 0) < 0) {
+                break;
+            }
+            free((void*)(dma_address - ETHER_FRAME_ALIGN_WASTAGE));
+        }
+
+        // Free DMA descriptors' storage
+        free(priv->desc_base_addr);
+
+        // Remember that we've freed the descriptors memory
+        priv->desc_base_addr = 0;
+    }
+}
+
+/*
+ * Reads a register from the MII Management serial interface
+ */
+int phy_read(int phyaddr, int phyreg)
+{
+    int data = 0;
+    u32 addr = (phyaddr << MAC_GMII_ADR_PA_BIT) |
+               (phyreg << MAC_GMII_ADR_GR_BIT) |
+               (5 << MAC_GMII_ADR_CR_BIT) |
+               (1UL << MAC_GMII_ADR_GB_BIT);
+
+    mac_reg_write(priv, MAC_GMII_ADR_REG, addr);
+
+    for (;;) {
+        if (!(mac_reg_read(priv, MAC_GMII_ADR_REG) & (1UL << MAC_GMII_ADR_GB_BIT))) {
+            // Successfully read from PHY
+            data = mac_reg_read(priv, MAC_GMII_DATA_REG) & 0xFFFF;
+            break;
+        }
+    }
+
+#ifdef DEBUG_GMAC_INIT
+    printf("phy_read() phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", phyaddr, phyreg, data);
+#endif // DEBUG_GMAC_INIT
+
+    return data;
+}
+
+/*
+ * Writes a register to the MII Management serial interface
+ */
+void phy_write(int phyaddr, int phyreg, int phydata)
+{
+    u32 addr = (phyaddr << MAC_GMII_ADR_PA_BIT) |
+               (phyreg << MAC_GMII_ADR_GR_BIT) |
+               (5 << MAC_GMII_ADR_CR_BIT) |
+               (1UL << MAC_GMII_ADR_GW_BIT) |
+               (1UL << MAC_GMII_ADR_GB_BIT);
+
+    mac_reg_write(priv, MAC_GMII_DATA_REG, phydata);
+    mac_reg_write(priv, MAC_GMII_ADR_REG, addr);
+
+    for (;;) {
+        if (!(mac_reg_read(priv, MAC_GMII_ADR_REG) & (1UL << MAC_GMII_ADR_GB_BIT))) {
+            break;
+        }
+    }
+
+#ifdef DEBUG_GMAC_INIT
+    printf("phy_write() phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", phyaddr, phyreg, phydata);
+#endif // DEBUG_GMAC_INIT
+}
+
+/*
+ * Finds and reports the PHY address
+ */
+int phy_detect(void)
+{
+	int found = 0;
+    int phyaddr;
+
+    // Scan all 32 PHY addresses if necessary
+    priv->phy_type = 0;
+    for (phyaddr = 1; phyaddr < 33; ++phyaddr) {
+        unsigned int id1, id2;
+
+        // Read the PHY identifiers
+        id1 = phy_read(phyaddr & 31, MII_PHYSID1);
+        id2 = phy_read(phyaddr & 31, MII_PHYSID2);
+
+#ifdef DEBUG_GMAC_INIT
+        printf("phy_detect() PHY adr = %u -> phy_id1=0x%x, phy_id2=0x%x\n", phyaddr, id1, id2);
+#endif // DEBUG_GMAC_INIT
+
+        // Make sure it is a valid identifier
+        if (id1 != 0x0000 && id1 != 0xffff && id1 != 0x8000 &&
+            id2 != 0x0000 && id2 != 0xffff && id2 != 0x8000) {
+#ifdef DEBUG_GMAC_INIT
+            printf("phy_detect() Found PHY at address = %u\n", phyaddr);
+#endif // DEBUG_GMAC_INIT
+
+            priv->phy_id   = phyaddr & 31;
+            priv->phy_type = id1 << 16 | id2;
+            priv->phy_addr = phyaddr;
+
+			found = 1;
+            break;
+        }
+    }
+
+	return found;
+}
+
+void start_phy_reset(void)
+{
+    // Ask the PHY to reset
+    phy_write(priv->phy_addr, MII_BMCR, BMCR_RESET);
+}
+
+int is_phy_reset_complete(void)
+{
+    int complete = 0;
+    int bmcr;
+
+    // Read back the status until it indicates reset, or we timeout
+    bmcr = phy_read(priv->phy_addr, MII_BMCR);
+    if (!(bmcr & BMCR_RESET)) {
+        complete = 1;
+    }
+
+    return complete;
+}
+
+void set_phy_type_rgmii(void)
+{
+	// Use sysctrl to switch MAC link lines into either (G)MII or RGMII mode
+    *(volatile u32*)SYS_CTRL_GMAC_CTRL |= (1UL << SYS_CTRL_GMAC_RGMII);
+}
+
+void phy_initialise(void)
+{
+	switch (priv->phy_type) {
+		case PHY_TYPE_VITESSE_VSC8201XVZ:
+			{
+				// Allow s/w to override mode/duplex pin settings
+				u32 acsr = phy_read(priv->phy_id, VSC8201_MII_ACSR);
+
+				printf("PHY is Vitesse VSC8201XVZ\n");
+				acsr |= (1UL << VSC8201_MII_ACSR_MDPPS_BIT);
+				phy_write(priv->phy_id, VSC8201_MII_ACSR, acsr);
+			}
+			break;
+		case PHY_TYPE_REALTEK_RTL8211BGR:
+			printf("PHY is Realtek RTL8211BGR\n");
+			set_phy_type_rgmii();
+			break;
+		case PHY_TYPE_LSI_ET1011C:
+			{
+				u32 phy_reg;
+
+				printf("PHY is LSI ET1011C\n");
+
+				// Configure clocks
+				phy_reg = phy_read(priv->phy_id, ET1011C_MII_CONFIG);
+				phy_reg &= ~(((1UL << ET1011C_MII_CONFIG_IFMODESEL_NUM_BITS) - 1) << ET1011C_MII_CONFIG_IFMODESEL);
+				phy_reg |= (ET1011C_MII_CONFIG_IFMODESEL_GMII_MII << ET1011C_MII_CONFIG_IFMODESEL);
+				phy_reg |= ((1UL << ET1011C_MII_CONFIG_SYSCLKEN) |
+                              (1UL << ET1011C_MII_CONFIG_TXCLKEN) |
+							   (1UL << ET1011C_MII_CONFIG_TBI_RATESEL) |
+							   (1UL << ET1011C_MII_CONFIG_CRS_TX_EN));
+				phy_write(priv->phy_id, ET1011C_MII_CONFIG, phy_reg);
+
+				// Enable Tx/Rx LED
+				phy_reg = phy_read(priv->phy_id, ET1011C_MII_LED2);
+				phy_reg &= ~(((1UL << ET1011C_MII_LED2_LED_NUM_BITS) - 1) << ET1011C_MII_LED2_LED_TXRX);
+				phy_reg |= (ET1011C_MII_LED2_LED_TXRX_ACTIVITY << ET1011C_MII_LED2_LED_TXRX);
+				phy_write(priv->phy_id, ET1011C_MII_LED2, phy_reg);
+			}
+			break;
+	}
+}
+
+int detect_link_speed(void)
+{
+	u32 lpa2 = phy_read(priv->phy_id, MII_STAT1000);
+
+	if (((lpa2 & LPA_1000FULL)) ||
+		((lpa2 & LPA_1000HALF))) {
+		priv->link_is_1000M = 1;
+	} else {
+		priv->link_is_1000M = 0;
+	}
+
+	return 0;
+}
+
+int is_autoneg_complete(void)
+{
+    return phy_read(priv->phy_addr, MII_BMSR) & BMSR_ANEGCOMPLETE;
+}
+
+int is_link_ok(void)
+{
+	return phy_read(priv->phy_id, MII_BMSR) & BMSR_LSTATUS;
+}
+
+int eth_init(bd_t *bd)
+{
+    u32  version;
+    u32  reg_contents;
+    u8  *mac_addr;
+    int  desc;
+
+    // Set hardware device base addresses
+    priv->macBase = (MAC_BASE_PA + MAC_BASE_OFFSET);
+    priv->dmaBase = (MAC_BASE_PA + DMA_BASE_OFFSET);
+
+#ifdef DEBUG_GMAC_INIT
+    printf("eth_init(): About to reset MAC core\n");
+#endif // DEBUG_GMAC_INIT
+    // Ensure the MAC block is properly reset
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_MAC_BIT);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_MAC_BIT);
+
+    // Enable the clock to the MAC block
+    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_MAC_BIT);
+
+    version = mac_reg_read(priv, MAC_VERSION_REG);
+#ifdef DEBUG_GMAC_INIT
+    printf("eth_init(): GMAC Synopsis version = 0x%x, vendor version = 0x%x\n", version & 0xff, (version >> 8) & 0xff);
+#endif // DEBUG_GMAC_INIT
+
+    // Use simple mux for 25/125 Mhz clock switching
+    *(volatile u32*)SYS_CTRL_GMAC_CTRL |= (1UL << SYS_CTRL_GMAC_SIMPLE_MAX);
+
+    // Enable GMII_GTXCLK to follow GMII_REFCLK - required for gigabit PHY
+    *(volatile u32*)SYS_CTRL_GMAC_CTRL |= (1UL << SYS_CTRL_GMAC_CKEN_GTX);
+
+    // Disable all GMAC interrupts
+    dma_reg_write(priv, DMA_INT_ENABLE_REG, 0);
+
+    // Reset the entire GMAC
+    dma_reg_write(priv, DMA_BUS_MODE_REG, 1UL << DMA_BUS_MODE_SWR_BIT);
+
+    // Wait for the reset operation to complete
+	printf("Wait GMAC to reset");
+    while (dma_reg_read(priv, DMA_BUS_MODE_REG) & (1UL << DMA_BUS_MODE_SWR_BIT)) {
+		udelay(250000);
+		printf(".");
+    }
+	printf("\n");
+
+	// Attempt to discover link speed from the PHY
+	if (!phy_detect()) {
+		printf("No PHY found\n");
+	} else {
+		// Ensure the PHY is in a sensible state by resetting it
+		start_phy_reset();
+
+		// Read back the status until it indicates reset, or we timeout
+		printf("Wait for PHY reset");
+		while (!is_phy_reset_complete()) {
+			udelay(250000);
+			printf(".");
+		}
+		printf("\n");
+
+		// Setup the PHY based on its type
+		phy_initialise();
+
+		printf("Wait for link to come up");
+		while (!is_link_ok()) {
+			udelay(250000);
+			printf(".");
+		}
+		printf("Link up\n");
+
+		// Wait for PHY to have completed autonegotiation
+		printf("Wait for auto-negotiation to complete");
+		while (!is_autoneg_complete()) {
+			udelay(250000);
+			printf(".");
+		}
+		printf("\n");
+
+		// Interrogate the PHY for the link speed
+		if (detect_link_speed()) {
+			printf("Failed to detect link speed\n");
+		} else {
+			printf("Link is %s\n", priv->link_is_1000M ? "1000M" : "10M/100M");
+		}
+	}
+
+    // Form the MAC config register contents
+    reg_contents = 0;
+	if (!priv->link_is_1000M) {
+		reg_contents |= (1UL << MAC_CONFIG_PS_BIT); // Gigabit
+	}
+    reg_contents |= (1UL << MAC_CONFIG_DM_BIT); // Full duplex
+    reg_contents |= ((1UL << MAC_CONFIG_TE_BIT) |
+                     (1UL << MAC_CONFIG_RE_BIT));
+    mac_reg_write(priv, MAC_CONFIG_REG, reg_contents);
+
+    // Form the MAC frame filter register contents
+    reg_contents = 0;
+    mac_reg_write(priv, MAC_FRAME_FILTER_REG, reg_contents);
+
+    // Form the hash table registers contents
+    mac_reg_write(priv, MAC_HASH_HIGH_REG, 0);
+    mac_reg_write(priv, MAC_HASH_LOW_REG, 0);
+
+    // Form the MAC flow control register contents
+    reg_contents = 0;
+    reg_contents |= ((1UL << MAC_FLOW_CNTL_RFE_BIT) |
+                     (1UL << MAC_FLOW_CNTL_TFE_BIT));
+    mac_reg_write(priv, MAC_FLOW_CNTL_REG, reg_contents);
+
+    // Form the MAC VLAN tag register contents
+    reg_contents = 0;
+    mac_reg_write(priv, MAC_VLAN_TAG_REG, reg_contents);
+
+    // Form the MAC addr0 high and low registers contents from the character
+    // string representation from the environment
+    mac_addr = getenv("ethaddr");
+#ifdef DEBUG_GMAC_INIT
+    printf("eth_init(): Mac addr = %s\n", mac_addr);
+#endif // DEBUG_GMAC_INIT
+    reg_contents  =  simple_strtoul(mac_addr+0, 0, 16);
+    reg_contents |= (simple_strtoul(mac_addr+3, 0, 16) << 8);
+    reg_contents |= (simple_strtoul(mac_addr+6, 0, 16) << 16);
+    reg_contents |= (simple_strtoul(mac_addr+9, 0, 16) << 24);
+    mac_reg_write(priv, MAC_ADR0_LOW_REG, reg_contents);
+    reg_contents  =  simple_strtoul(mac_addr+12, 0, 16);
+    reg_contents |= (simple_strtoul(mac_addr+15, 0, 16) << 8);
+    mac_reg_write(priv, MAC_ADR0_HIGH_REG, reg_contents);
+
+    // Disable all MMC interrupt sources
+    mac_reg_write(priv, MMC_RX_MASK_REG, ~0UL);
+    mac_reg_write(priv, MMC_TX_MASK_REG, ~0UL);
+
+    // Remember how large the unified descriptor array is to be
+    priv->total_num_descriptors = NUM_RX_DMA_DESCRIPTORS + NUM_TX_DMA_DESCRIPTORS;
+
+    // Need a consistent DMA mapping covering all the memory occupied by DMA
+    // unified descriptor array, as both CPU and DMA engine will be reading and
+    // writing descriptor fields.
+    priv->desc_base_addr = (gmac_dma_desc_t*)malloc(sizeof(gmac_dma_desc_t) * priv->total_num_descriptors);
+    if (!priv->desc_base_addr) {
+       printf("eth_init(): Failed to allocate memory for DMA descriptors\n");
+        goto err_out;
+    }
+
+    // Initialise the structures managing the TX descriptor list
+    init_tx_desc_list(&priv->tx_gmac_desc_list_info,
+                      priv->desc_base_addr,
+                      NUM_TX_DMA_DESCRIPTORS);
+
+    // Initialise the structures managing the RX descriptor list
+    init_rx_desc_list(&priv->rx_gmac_desc_list_info,
+                      priv->desc_base_addr + NUM_TX_DMA_DESCRIPTORS,
+                      priv->total_num_descriptors - NUM_TX_DMA_DESCRIPTORS);
+
+    // Prepare receive descriptors
+    desc = 0;
+    while (available_for_write(&priv->rx_gmac_desc_list_info)) {
+        // Allocate a new buffer for the descriptor which is large enough for
+        // any packet received from the link
+        dma_addr_t dma_address = (dma_addr_t)malloc(ETHER_MTU + ETHER_FRAME_ALIGN_WASTAGE + EXTRA_RX_SKB_SPACE);
+        if (!dma_address) {
+            printf("eth_init(): No memory for socket buffer\n");
+            break;
+        }
+
+        desc = set_rx_descriptor(priv,
+                                 dma_address + ETHER_FRAME_ALIGN_WASTAGE,
+                                 ETHER_MTU + EXTRA_RX_SKB_SPACE,
+                                 0);
+
+        if (desc < 0) {
+            // Release the buffer
+            free((void*)dma_address);
+
+            printf("eth_init(): Error, no RX descriptor available\n");
+            goto err_out;
+        }
+    }
+
+    // Initialise the GMAC DMA bus mode register
+    dma_reg_write(priv, DMA_BUS_MODE_REG, ((0UL << DMA_BUS_MODE_FB_BIT)   |
+                                           (0UL << DMA_BUS_MODE_PR_BIT)   |
+                                           (32UL << DMA_BUS_MODE_PBL_BIT) | // AHB burst size
+                                           (1UL << DMA_BUS_MODE_DSL_BIT)  | 
+                                           (0UL << DMA_BUS_MODE_DA_BIT)));
+
+    // Write the address of the start of the tx descriptor array
+    dma_reg_write(priv, DMA_TX_DESC_ADR_REG, (u32)priv->desc_base_addr);
+
+    // Write the address of the start of the rx descriptor array
+    dma_reg_write(priv, DMA_RX_DESC_ADR_REG,
+        (u32)(priv->desc_base_addr + priv->tx_gmac_desc_list_info.num_descriptors));
+
+    // Clear any pending interrupt requests
+    dma_reg_write(priv, DMA_STATUS_REG, dma_reg_read(priv, DMA_STATUS_REG));
+
+    // Initialise the GMAC DMA operation mode register, starting both the
+    // transmitter and receiver
+    dma_reg_write(priv, DMA_OP_MODE_REG, ((1UL << DMA_OP_MODE_SF_BIT)  |    // Store and forward
+                                          (0UL << DMA_OP_MODE_TTC_BIT) |    // Tx threshold
+                                          (1UL << DMA_OP_MODE_ST_BIT)  |    // Enable transmitter
+                                          (0UL << DMA_OP_MODE_RTC_BIT) |    // Rx threshold
+                                          (1UL << DMA_OP_MODE_SR_BIT)));    // Enable receiver
+
+    // Success
+    return 1;
+
+err_out:
+    eth_down();
+
+    return 0;
+}
+
+void eth_halt(void)
+{
+    eth_down();
+
+    // Disable the clock to the MAC block
+    *(volatile u32*)(SYS_CTRL_CKEN_CLR_CTRL) = (1UL << SYS_CTRL_CKEN_MAC_BIT);
+}
+
+int eth_rx(void)
+{
+    static const int MAX_LOOPS = 2000;   // 2 seconds
+
+    int length = 0;
+    dma_addr_t dma_address;
+    u32 desc_status;
+    int loops = 0;
+
+    // Look for the first available received packet
+    while (loops++ < MAX_LOOPS) {
+        if (get_rx_descriptor(priv, &desc_status, &dma_address, 0, 0) >= 0) {
+            if (is_rx_valid(desc_status)) {
+                // Get the length of the packet within the buffer
+                length = get_rx_length(desc_status);
+
+                // Pass packet up the network stack - will block until processing is
+                // completed
+                NetReceive((uchar*)dma_address, length);
+            } else {
+                printf("eth_rx() Received packet has bad desc_status = 0x%08x\n", desc_status);
+            }
+
+            // Re-initialise the RX descriptor with its buffer - relies on always
+            // setting an RX descriptor directly after getting it
+            if (set_rx_descriptor(priv, dma_address, ETHER_MTU + EXTRA_RX_SKB_SPACE, 0) < 0) {
+                 printf("eth_rx(): Failed to set RX descriptor\n");
+            }
+
+            break;
+        }
+
+        // Wait a bit before trying again to get a descriptor
+        udelay(1000);   // 1mS
+    }
+
+    return length;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+    // Transmit the new packet
+    while (1) {
+        // Get the TX descriptor
+        if (set_tx_descriptor(priv, (dma_addr_t)packet, length, 0) >= 0) {
+            // Tell the GMAC to poll for the updated descriptor
+            dma_reg_write(priv, DMA_TX_POLL_REG, 0);
+            break;
+        }
+
+        // Wait a bit before trying again to get a descriptor
+        udelay(1000);   // 1mS
+    }
+
+    // Wait for the packet buffer to be finished with
+    while (get_tx_descriptor(priv, 0, 0, 0, 0) < 0) {
+        // Wait a bit before examining the descriptor again
+        udelay(1000);   // 1mS
+    }
+
+    return length;
+}
+
diff -Nurd u-boot-1.1.2/board/oxnas/ide-810.c u-boot-1.1.2-oxe810/board/oxnas/ide-810.c
--- u-boot-1.1.2/board/oxnas/ide-810.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/board/oxnas/ide-810.c	2008-06-11 17:55:18.000000000 +0200
@@ -0,0 +1,892 @@
+/*
+ * (C) Copyright 2005
+ * Oxford Semiconductor Ltd
+ *
+ * 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>
+
+#define SATA_DMA_CHANNEL 0
+
+#define DMA_CTRL_STATUS      (0x0)
+#define DMA_BASE_SRC_ADR     (0x4)
+#define DMA_BASE_DST_ADR     (0x8)
+#define DMA_BYTE_CNT         (0xC)
+#define DMA_CURRENT_SRC_ADR  (0x10)
+#define DMA_CURRENT_DST_ADR  (0x14)
+#define DMA_CURRENT_BYTE_CNT (0x18)
+#define DMA_INTR_ID          (0x1C)
+#define DMA_INTR_CLEAR_REG   (DMA_CURRENT_SRC_ADR)
+
+#define DMA_CALC_REG_ADR(channel, register) ((volatile u32*)(DMA_BASE_PA + ((channel) << 5) + (register)))
+
+#define DMA_CTRL_STATUS_FAIR_SHARE_ARB            (1 << 0)
+#define DMA_CTRL_STATUS_IN_PROGRESS               (1 << 1)
+#define DMA_CTRL_STATUS_SRC_DREQ_MASK             (0x0000003C)
+#define DMA_CTRL_STATUS_SRC_DREQ_SHIFT            (2)
+#define DMA_CTRL_STATUS_DEST_DREQ_MASK            (0x000003C0)
+#define DMA_CTRL_STATUS_DEST_DREQ_SHIFT           (6)
+#define DMA_CTRL_STATUS_INTR                      (1 << 10)
+#define DMA_CTRL_STATUS_NXT_FREE                  (1 << 11)
+#define DMA_CTRL_STATUS_RESET                     (1 << 12)
+#define DMA_CTRL_STATUS_DIR_MASK                  (0x00006000)
+#define DMA_CTRL_STATUS_DIR_SHIFT                 (13)
+#define DMA_CTRL_STATUS_SRC_ADR_MODE              (1 << 15)
+#define DMA_CTRL_STATUS_DEST_ADR_MODE             (1 << 16)
+#define DMA_CTRL_STATUS_TRANSFER_MODE_A           (1 << 17)
+#define DMA_CTRL_STATUS_TRANSFER_MODE_B           (1 << 18)
+#define DMA_CTRL_STATUS_SRC_WIDTH_MASK            (0x00380000)
+#define DMA_CTRL_STATUS_SRC_WIDTH_SHIFT           (19)
+#define DMA_CTRL_STATUS_DEST_WIDTH_MASK           (0x01C00000)
+#define DMA_CTRL_STATUS_DEST_WIDTH_SHIFT          (22)
+#define DMA_CTRL_STATUS_PAUSE                     (1 << 25)
+#define DMA_CTRL_STATUS_INTERRUPT_ENABLE          (1 << 26)
+#define DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED      (1 << 27)
+#define DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED (1 << 28)
+#define DMA_CTRL_STATUS_STARVE_LOW_PRIORITY       (1 << 29)
+#define DMA_CTRL_STATUS_INTR_CLEAR_ENABLE         (1 << 30)
+
+#define DMA_BYTE_CNT_MASK        ((1 << 21) - 1)
+#define DMA_BYTE_CNT_WR_EOT_MASK (1 << 30)
+#define DMA_BYTE_CNT_RD_EOT_MASK (1 << 31)
+
+#define MAKE_FIELD(value, num_bits, bit_num) (((value) & ((1 << (num_bits)) - 1)) << (bit_num))
+
+typedef enum oxnas_dma_mode {
+    OXNAS_DMA_MODE_FIXED,
+    OXNAS_DMA_MODE_INC
+} oxnas_dma_mode_t;
+
+typedef enum oxnas_dma_direction {
+    OXNAS_DMA_TO_DEVICE,
+    OXNAS_DMA_FROM_DEVICE
+} oxnas_dma_direction_t;
+
+/* The available buses to which the DMA controller is attached */
+typedef enum oxnas_dma_transfer_bus
+{
+    OXNAS_DMA_SIDE_A,
+    OXNAS_DMA_SIDE_B
+} oxnas_dma_transfer_bus_t;
+
+/* Direction of data flow between the DMA controller's pair of interfaces */
+typedef enum oxnas_dma_transfer_direction
+{
+    OXNAS_DMA_A_TO_A,
+    OXNAS_DMA_B_TO_A,
+    OXNAS_DMA_A_TO_B,
+    OXNAS_DMA_B_TO_B
+} oxnas_dma_transfer_direction_t;
+
+/* The available data widths */
+typedef enum oxnas_dma_transfer_width
+{
+    OXNAS_DMA_TRANSFER_WIDTH_8BITS,
+    OXNAS_DMA_TRANSFER_WIDTH_16BITS,
+    OXNAS_DMA_TRANSFER_WIDTH_32BITS
+} oxnas_dma_transfer_width_t;
+
+/* The mode of the DMA transfer */
+typedef enum oxnas_dma_transfer_mode
+{
+    OXNAS_DMA_TRANSFER_MODE_SINGLE,
+    OXNAS_DMA_TRANSFER_MODE_BURST
+} oxnas_dma_transfer_mode_t;
+
+/* The available transfer targets */
+typedef enum oxnas_dma_dreq
+{
+    OXNAS_DMA_DREQ_SATA   = 0,
+    OXNAS_DMA_DREQ_MEMORY = 15
+} oxnas_dma_dreq_t;
+
+typedef struct oxnas_dma_device_settings {
+    unsigned long address_;
+    unsigned      fifo_size_;   // Chained transfers must take account of FIFO offset at end of previous transfer
+    unsigned char dreq_;
+    unsigned      read_eot_:1;
+    unsigned      read_final_eot_:1;
+    unsigned      write_eot_:1;
+    unsigned      write_final_eot_:1;
+    unsigned      bus_:1;
+    unsigned      width_:2;
+    unsigned      transfer_mode_:1;
+    unsigned      address_mode_:1;
+    unsigned      address_really_fixed_:1;
+} oxnas_dma_device_settings_t;
+
+static const int MAX_NO_ERROR_LOOPS  = 100000;  /* 1 second in units of 10uS */
+static const int MAX_DMA_XFER_LOOPS  = 300000;  /* 30 seconds in units of 100uS */
+static const int MAX_DMA_ABORT_LOOPS = 10000;   /* 0.1 second in units of 10uS */
+static const int MAX_SRC_READ_LOOPS  = 10000;   /* 0.1 second in units of 10uS */
+static const int MAX_SRC_WRITE_LOOPS = 10000;   /* 0.1 second in units of 10uS */
+static const int MAX_NOT_BUSY_LOOPS  = 10000;   /* 1 second in units of 100uS */
+
+/* The internal SATA drive on which we should attempt to find partitions */
+static volatile u32* sata_regs_base[2] = 
+{
+    (volatile u32*)SATA_0_REGS_BASE,
+    (volatile u32*)SATA_1_REGS_BASE,
+    
+};
+static u32 wr_sata_orb1[2] = { 0, 0 };
+static u32 wr_sata_orb2[2] = { 0, 0 };
+static u32 wr_sata_orb3[2] = { 0, 0 };
+static u32 wr_sata_orb4[2] = { 0, 0 };
+
+static oxnas_dma_device_settings_t oxnas_sata_dma_settings = {
+    .address_              = SATA_DATA_BASE_PA,
+    .fifo_size_            = 16,
+    .dreq_                 = OXNAS_DMA_DREQ_SATA,
+    .read_eot_             = 0,
+    .read_final_eot_       = 1,
+    .write_eot_            = 0,
+    .write_final_eot_      = 1,
+    .bus_                  = OXNAS_DMA_SIDE_A,
+    .width_                = OXNAS_DMA_TRANSFER_WIDTH_32BITS,
+    .transfer_mode_        = OXNAS_DMA_TRANSFER_MODE_BURST,
+    .address_mode_         = OXNAS_DMA_MODE_FIXED,
+    .address_really_fixed_ = 0
+};
+
+oxnas_dma_device_settings_t oxnas_ram_dma_settings = {
+    .address_              = 0,
+    .fifo_size_            = 0,
+    .dreq_                 = OXNAS_DMA_DREQ_MEMORY,
+    .read_eot_             = 1,
+    .read_final_eot_       = 1,
+    .write_eot_            = 1,
+    .write_final_eot_      = 1,
+    .bus_                  = OXNAS_DMA_SIDE_B,
+    .width_                = OXNAS_DMA_TRANSFER_WIDTH_32BITS,
+    .transfer_mode_        = OXNAS_DMA_TRANSFER_MODE_BURST,
+    .address_mode_         = OXNAS_DMA_MODE_FIXED,
+    .address_really_fixed_ = 1
+};
+
+static void xfer_wr_shadow_to_orbs(int device)
+{
+    *(sata_regs_base[device] + SATA_ORB1_OFF) = wr_sata_orb1[device];
+    *(sata_regs_base[device] + SATA_ORB2_OFF) = wr_sata_orb2[device];
+    *(sata_regs_base[device] + SATA_ORB3_OFF) = wr_sata_orb3[device];
+    *(sata_regs_base[device] + SATA_ORB4_OFF) = wr_sata_orb4[device];
+}
+
+static inline void device_select(int device)
+{
+    /* master/slave has no meaning to SATA core */
+}
+
+static int disk_present[CFG_IDE_MAXDEVICE];
+
+#include <ata.h>
+
+unsigned char oxnas_sata_inb(int device, int port)
+{
+    unsigned char val = 0;
+
+    /* Only permit accesses to disks found to be present during ide_preinit() */
+    if (!disk_present[device]) {
+        return ATA_STAT_FAULT;
+    }
+
+    device_select(device);
+
+    switch (port) {
+        case ATA_PORT_CTL:
+            val = (*(sata_regs_base[device] + SATA_ORB4_OFF) & (0xFFUL << SATA_CTL_BIT)) >> SATA_CTL_BIT;
+            break;
+        case ATA_PORT_FEATURE:
+            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_FEATURE_BIT)) >> SATA_FEATURE_BIT;
+            break;
+        case ATA_PORT_NSECT:
+            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_NSECT_BIT)) >> SATA_NSECT_BIT;
+            break;
+        case ATA_PORT_LBAL:
+            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAL_BIT)) >> SATA_LBAL_BIT;
+            break;
+        case ATA_PORT_LBAM:
+            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAM_BIT)) >> SATA_LBAM_BIT;
+            break;
+        case ATA_PORT_LBAH:
+            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_LBAH_BIT)) >> SATA_LBAH_BIT;
+            break;
+        case ATA_PORT_DEVICE:
+            val = (*(sata_regs_base[device] + SATA_ORB3_OFF) & (0xFFUL << SATA_HOB_LBAH_BIT)) >> SATA_HOB_LBAH_BIT;
+            val |= (*(sata_regs_base[device] + SATA_ORB1_OFF) & (0xFFUL << SATA_DEVICE_BIT)) >> SATA_DEVICE_BIT;
+            break;
+        case ATA_PORT_COMMAND:
+            val = (*(sata_regs_base[device] + SATA_ORB2_OFF) & (0xFFUL << SATA_COMMAND_BIT)) >> SATA_COMMAND_BIT;
+            val |= ATA_STAT_DRQ ;
+            break;
+        default:
+            printf("ide_inb() Unknown port = %d\n", port);
+            break;
+    }
+
+//    printf("inb: %d:%01x => %02x\n", device, port, val);
+
+    return val;
+}
+
+/**
+ * Possible that ATA status will not become no-error, so must have timeout
+ * @returns An int which is zero on error
+ */
+static inline int wait_no_error(int device)
+{
+    int status = 0;
+
+	/* Check for ATA core error */
+	if (*(sata_regs_base[device] + SATA_INT_STATUS_OFF) & (1 << SATA_INT_STATUS_ERROR_BIT)) {
+		printf("wait_no_error() SATA core flagged error\n");
+	} else {
+		int loops = MAX_NO_ERROR_LOOPS;
+		do {
+			/* Check for ATA device error */
+			if (!(oxnas_sata_inb(device, ATA_PORT_COMMAND) & (1 << ATA_STATUS_ERR_BIT))) {
+				status = 1;
+				break;
+			}
+			udelay(10);
+		} while (--loops);
+
+		if (!loops) {
+			printf("wait_no_error() Timed out of wait for SATA no-error condition\n");
+		}
+	}
+
+    return status;
+}
+
+/**
+ * Expect SATA command to always finish, perhaps with error
+ * @returns An int which is zero on error
+ */
+static inline int wait_sata_command_not_busy(int device)
+{
+    /* Wait for data to be available */
+    int status = 0;
+    int loops = MAX_NOT_BUSY_LOOPS;
+    do {
+        if (!(*(sata_regs_base[device] + SATA_COMMAND_OFF) & (1 << SATA_CMD_BUSY_BIT) )) {
+            status = 1;
+            break;
+        }
+        udelay(100);
+    } while (--loops);
+
+    if (!loops) {
+        printf("wait_sata_command_not_busy() Timed out of wait for SATA command to finish\n");
+    }
+
+    return status;
+}
+
+void oxnas_sata_outb(int device, int port, unsigned char val)
+{
+    typedef enum send_method {
+        SEND_NONE,
+        SEND_SIMPLE,
+        SEND_CMD,
+        SEND_CTL,
+    } send_method_t;
+
+    /* Only permit accesses to disks found to be present during ide_preinit() */
+    if (!disk_present[device]) {
+        return;
+    }
+    
+//    printf("outb: %d:%01x <= %02x\n", device, port, val);
+
+    device_select(device);
+
+    send_method_t send_regs = SEND_NONE;
+    switch (port) {
+        case ATA_PORT_CTL:
+            wr_sata_orb4[device] &= ~(0xFFUL << SATA_CTL_BIT);
+            wr_sata_orb4[device] |= (val << SATA_CTL_BIT);
+            send_regs = SEND_CTL;
+            break;
+        case ATA_PORT_FEATURE:
+            wr_sata_orb2[device] &= ~(0xFFUL << SATA_FEATURE_BIT);
+            wr_sata_orb2[device] |= (val << SATA_FEATURE_BIT);
+            send_regs = SEND_SIMPLE;
+            break;
+        case ATA_PORT_NSECT:
+            wr_sata_orb2[device] &= ~(0xFFUL << SATA_NSECT_BIT);
+            wr_sata_orb2[device] |= (val << SATA_NSECT_BIT);
+            send_regs = SEND_SIMPLE;
+            break;
+        case ATA_PORT_LBAL:
+            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAL_BIT);
+            wr_sata_orb3[device] |= (val << SATA_LBAL_BIT);
+            send_regs = SEND_SIMPLE;
+            break;
+        case ATA_PORT_LBAM:
+            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAM_BIT);
+            wr_sata_orb3[device] |= (val << SATA_LBAM_BIT);
+            send_regs = SEND_SIMPLE;
+            break;
+        case ATA_PORT_LBAH:
+            wr_sata_orb3[device] &= ~(0xFFUL << SATA_LBAH_BIT);
+            wr_sata_orb3[device] |= (val << SATA_LBAH_BIT);
+            send_regs = SEND_SIMPLE;
+            break;
+        case ATA_PORT_DEVICE:
+            wr_sata_orb1[device] &= ~(0xFFUL << SATA_DEVICE_BIT);
+            wr_sata_orb1[device] |= ((val & 0xf0) << SATA_DEVICE_BIT);
+            wr_sata_orb3[device] &= ~(0xFFUL << SATA_HOB_LBAH_BIT);
+            wr_sata_orb3[device] |= ((val & 0x0f) << SATA_HOB_LBAH_BIT);
+            send_regs = SEND_SIMPLE;
+            break;
+        case ATA_PORT_COMMAND:
+            wr_sata_orb2[device] &= ~(0xFFUL << SATA_COMMAND_BIT);
+            wr_sata_orb2[device] |= (val << SATA_COMMAND_BIT);
+            send_regs = SEND_CMD;
+            break;
+        default:
+            printf("ide_outb() Unknown port = %d\n", port);
+    }
+
+    u32 command;
+    switch (send_regs) {
+        case SEND_CMD:
+            wait_sata_command_not_busy(device);
+            command = *(sata_regs_base[device] + SATA_COMMAND_OFF);
+            command &= ~SATA_OPCODE_MASK;
+            command |= SATA_CMD_WRITE_TO_ORB_REGS;
+            xfer_wr_shadow_to_orbs(device);
+            wait_sata_command_not_busy(device);
+            *(sata_regs_base[device] + SATA_COMMAND_OFF) = command;
+            if (!wait_no_error(device)) {
+                printf("oxnas_sata_outb() Wait for ATA no-error timed-out\n");
+            }
+            break;
+        case SEND_CTL:
+            wait_sata_command_not_busy(device);
+            command = *(sata_regs_base[device] + SATA_COMMAND_OFF);
+            command &= ~SATA_OPCODE_MASK;
+            command |= SATA_CMD_WRITE_TO_ORB_REGS_NO_COMMAND;
+            xfer_wr_shadow_to_orbs(device);
+            wait_sata_command_not_busy(device);
+            *(sata_regs_base[device] + SATA_COMMAND_OFF) = command;
+            if (!wait_no_error(device)) {
+                printf("oxnas_sata_outb() Wait for ATA no-error timed-out\n");
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+static u32 encode_start(u32 ctrl_status)
+{
+    return ctrl_status & ~DMA_CTRL_STATUS_PAUSE;
+}
+
+static void dma_start(void)
+{
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) =
+        encode_start(*(DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)));
+}
+
+static unsigned long encode_control_status(
+    oxnas_dma_device_settings_t* src_settings,
+    oxnas_dma_device_settings_t* dst_settings)
+{
+    unsigned long ctrl_status;
+    oxnas_dma_transfer_direction_t direction;
+
+    ctrl_status  = DMA_CTRL_STATUS_PAUSE;                                       // Paused
+    ctrl_status |= DMA_CTRL_STATUS_FAIR_SHARE_ARB;                              // High priority
+    ctrl_status |= (src_settings->dreq_ << DMA_CTRL_STATUS_SRC_DREQ_SHIFT);     // Dreq
+    ctrl_status |= (dst_settings->dreq_ << DMA_CTRL_STATUS_DEST_DREQ_SHIFT);    // Dreq
+    ctrl_status &= ~DMA_CTRL_STATUS_RESET;                                      // !RESET
+
+    // Use new interrupt clearing register
+    ctrl_status |= DMA_CTRL_STATUS_INTR_CLEAR_ENABLE;
+
+    // Setup the transfer direction and burst/single mode for the two DMA busses
+    if (src_settings->bus_ == OXNAS_DMA_SIDE_A) {
+        // Set the burst/single mode for bus A based on src device's settings
+        if (src_settings->transfer_mode_ == OXNAS_DMA_TRANSFER_MODE_BURST) {
+            ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_A;
+        } else {
+            ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_A;
+        }
+
+        if (dst_settings->bus_ == OXNAS_DMA_SIDE_A) {
+            direction = OXNAS_DMA_A_TO_A;
+        } else {
+            direction = OXNAS_DMA_A_TO_B;
+
+            // Set the burst/single mode for bus B based on dst device's settings
+            if (dst_settings->transfer_mode_ == OXNAS_DMA_TRANSFER_MODE_BURST) {
+                ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_B;
+            } else {
+                ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_B;
+            }
+        }
+    } else {
+        // Set the burst/single mode for bus B based on src device's settings
+        if (src_settings->transfer_mode_ == OXNAS_DMA_TRANSFER_MODE_BURST) {
+            ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_B;
+        } else {
+            ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_B;
+        }
+
+        if (dst_settings->bus_ == OXNAS_DMA_SIDE_A) {
+            direction = OXNAS_DMA_B_TO_A;
+            
+            // Set the burst/single mode for bus A based on dst device's settings
+            if (dst_settings->transfer_mode_ == OXNAS_DMA_TRANSFER_MODE_BURST) {
+                ctrl_status |= DMA_CTRL_STATUS_TRANSFER_MODE_A;
+            } else {
+                ctrl_status &= ~DMA_CTRL_STATUS_TRANSFER_MODE_A;
+            }
+        } else {
+            direction = OXNAS_DMA_B_TO_B;
+        }
+    }
+    ctrl_status |= (direction << DMA_CTRL_STATUS_DIR_SHIFT);
+
+    // Setup source address mode fixed or increment
+    if (src_settings->address_mode_ == OXNAS_DMA_MODE_FIXED) {
+        // Fixed address
+        ctrl_status &= ~(DMA_CTRL_STATUS_SRC_ADR_MODE);
+        
+        // Set up whether fixed address is _really_ fixed
+        if (src_settings->address_really_fixed_) {
+            ctrl_status |= DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
+        } else {
+            ctrl_status &= ~DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
+        }        
+    } else {
+        // Incrementing address
+        ctrl_status |= DMA_CTRL_STATUS_SRC_ADR_MODE;
+        ctrl_status &= ~DMA_CTRL_STATUS_SOURCE_ADDRESS_FIXED;
+    }
+
+    // Setup destination address mode fixed or increment
+    if (dst_settings->address_mode_ == OXNAS_DMA_MODE_FIXED) {
+        // Fixed address
+        ctrl_status &= ~(DMA_CTRL_STATUS_DEST_ADR_MODE);
+        
+        // Set up whether fixed address is _really_ fixed
+        if (dst_settings->address_really_fixed_) {
+            ctrl_status |= DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
+        } else {
+            ctrl_status &= ~DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
+        }
+    } else {
+        // Incrementing address
+        ctrl_status |= DMA_CTRL_STATUS_DEST_ADR_MODE;
+        ctrl_status &= ~DMA_CTRL_STATUS_DESTINATION_ADDRESS_FIXED;
+    }
+
+    // Set up the width of the transfers on the DMA buses
+    ctrl_status |= (src_settings->width_ << DMA_CTRL_STATUS_SRC_WIDTH_SHIFT);
+    ctrl_status |= (dst_settings->width_ << DMA_CTRL_STATUS_DEST_WIDTH_SHIFT);
+
+    // Setup the priority arbitration scheme
+    ctrl_status &= ~DMA_CTRL_STATUS_STARVE_LOW_PRIORITY;    // !Starve low priority
+
+    return ctrl_status;
+}
+
+static u32 encode_final_eot(
+    oxnas_dma_device_settings_t* src_settings,
+    oxnas_dma_device_settings_t* dst_settings,
+    unsigned long length)
+{
+    // Write the length, with EOT configuration for a final transfer
+    unsigned long encoded = length;
+    if (dst_settings->write_final_eot_) {
+        encoded |= DMA_BYTE_CNT_WR_EOT_MASK;
+    } else {
+        encoded &= ~DMA_BYTE_CNT_WR_EOT_MASK;
+    }
+    if (src_settings->read_final_eot_) {
+        encoded |= DMA_BYTE_CNT_RD_EOT_MASK;
+    } else {
+        encoded &= ~DMA_BYTE_CNT_RD_EOT_MASK;
+    }
+    return encoded;
+}
+
+static void dma_start_write(ulong* buffer, int num_bytes)
+{
+    // Assemble complete memory settings
+    oxnas_dma_device_settings_t mem_settings = oxnas_ram_dma_settings;
+    mem_settings.address_ = (unsigned long)buffer;
+    mem_settings.address_mode_ = OXNAS_DMA_MODE_INC;
+
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)  = encode_control_status(&mem_settings, &oxnas_sata_dma_settings);
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_SRC_ADR) = mem_settings.address_;
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_DST_ADR) = oxnas_sata_dma_settings.address_;
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BYTE_CNT)     = encode_final_eot(&mem_settings, &oxnas_sata_dma_settings, num_bytes);
+
+    dma_start();
+}
+
+static void dma_start_read(ulong* buffer, int num_bytes)
+{
+    // Assemble complete memory settings
+    oxnas_dma_device_settings_t mem_settings = oxnas_ram_dma_settings;
+    mem_settings.address_ = (unsigned long)buffer;
+    mem_settings.address_mode_ = OXNAS_DMA_MODE_INC;
+
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)  = encode_control_status(&oxnas_sata_dma_settings, &mem_settings);
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_SRC_ADR) = oxnas_sata_dma_settings.address_;
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BASE_DST_ADR) = mem_settings.address_;
+    *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_BYTE_CNT)     = encode_final_eot(&oxnas_sata_dma_settings, &mem_settings, num_bytes);
+
+    dma_start();
+}
+
+static inline int dma_busy(void)
+{
+    return (*DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS)) & DMA_CTRL_STATUS_IN_PROGRESS;
+}
+
+static int wait_dma_not_busy(int device)
+{
+    unsigned int cleanup_required = 0;
+
+	/* Poll for DMA completion */
+	int loops = MAX_DMA_XFER_LOOPS;
+	do {
+		if (!dma_busy()) {
+			break;
+		}
+		udelay(100);
+	} while (--loops);
+
+	if (!loops) {
+		printf("wait_dma_not_busy() Timed out of wait for DMA not busy\n");
+		cleanup_required = 1;
+	}
+
+    if (cleanup_required) {
+        /* Abort DMA to make sure it has finished. */
+        unsigned long ctrl_status = *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS);
+        ctrl_status |= DMA_CTRL_STATUS_RESET;
+        *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) = ctrl_status;
+
+        // Wait for the channel to become idle - should be quick as should
+        // finish after the next AHB single or burst transfer
+        loops = MAX_DMA_ABORT_LOOPS;
+        do {
+            if (!(*DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) & DMA_CTRL_STATUS_IN_PROGRESS)) {
+                break;
+            }
+            udelay(10);
+        } while (--loops);
+
+        if (!loops) {
+            printf("wait_dma_not_busy() Timed out of wait for DMA channel abort\n");
+        } else {
+			/* Successfully cleanup the DMA channel */
+			cleanup_required = 0;
+		}
+
+        // Deassert reset for the channel
+        ctrl_status = *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS);
+        ctrl_status &= ~DMA_CTRL_STATUS_RESET;
+        *DMA_CALC_REG_ADR(SATA_DMA_CHANNEL, DMA_CTRL_STATUS) = ctrl_status;
+    }
+
+	return !cleanup_required;
+}
+
+/**
+ * Possible that ATA status will not become not-busy, so must have timeout
+ */
+static unsigned int wait_not_busy(int device, unsigned long timeout_secs)
+{
+    int busy = 1;
+    unsigned long loops = (timeout_secs * 1000) / 50;
+    do {
+        // Test the ATA status register BUSY flag
+        if (!((*(sata_regs_base[device] + SATA_ORB2_OFF) >> SATA_COMMAND_BIT) & (1UL << ATA_STATUS_BSY_BIT))) {
+            /* Not busy, so stop polling */
+            busy = 0;
+            break;
+        }
+
+        // Wait for 50mS before sampling ATA status register again
+        udelay(50000);
+    } while (--loops);
+
+    return busy;
+}
+
+void oxnas_sata_output_data(int device, ulong *sect_buf, int words)
+{
+    /* Only permit accesses to disks found to be present during ide_preinit() */
+    if (!disk_present[device]) {
+        return;
+    }
+
+    /* Select the required internal SATA drive */
+    device_select(device);
+
+    /* Start the DMA channel sending data from the passed buffer to the SATA core */
+    dma_start_write(sect_buf, words << 2);
+
+	/* Don't know why we need this delay, but without it the wait for DMA not 
+	   busy times soemtimes out, e.g. when saving environment to second disk */
+	udelay(1000);
+
+    /* Wait for DMA to finish */
+    if (!wait_dma_not_busy(device)) {
+		printf("Timed out of wait for DMA channel for SATA device %d to have in-progress clear\n", device);
+	}
+
+	/* Sata core should finish after DMA */
+	if (wait_not_busy(device, 30)) {
+		printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
+	}
+	if (!wait_no_error(device)) {
+		printf("oxnas_sata_output_data() Wait for ATA no-error timed-out\n");
+	}
+}
+
+void oxnas_sata_input_data(int device, ulong *sect_buf, int words)
+{
+    /* Only permit accesses to disks found to be present during ide_preinit() */
+    if (!disk_present[device]) {
+        return;
+    }
+
+    /* Select the required internal SATA drive */
+    device_select(device);
+
+    /* Start the DMA channel receiving data from the SATA core into the passed buffer */
+    dma_start_read(sect_buf, words << 2);
+
+	/* Sata core should finish before DMA */
+	if (wait_not_busy(device, 30)) {
+		printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
+	}
+	if (!wait_no_error(device)) {
+		printf("oxnas_sata_output_data() Wait for ATA no-error timed-out\n");
+	}
+
+    /* Wait for DMA to finish */
+    if (!wait_dma_not_busy(device)) {
+		printf("Timed out of wait for DMA channel for SATA device %d to have in-progress clear\n", device);
+	}
+}
+
+static u32 scr_read(int device, unsigned int sc_reg)
+{
+    /* Setup adr of required register. std regs start eight into async region */    
+    *(sata_regs_base[device] + SATA_LINK_RD_ADDR) = sc_reg*4 + SATA_STD_ASYNC_REGS_OFF;
+
+    /* Wait for data to be available */
+    int loops = MAX_SRC_READ_LOOPS;
+    do {
+        if (*(sata_regs_base[device] + SATA_LINK_CONTROL) & 1UL) {
+            break;
+        }
+        udelay(10);
+    } while (--loops);
+
+    if (!loops) {
+        printf("scr_read() Timed out of wait for read completion\n");
+    }
+
+    /* Read the data from the async register */
+    return *(sata_regs_base[device] + SATA_LINK_DATA);
+}
+
+static void scr_write(int device, unsigned int sc_reg, u32 val)
+{
+    /* Setup the data for the write */
+    *(sata_regs_base[device] + SATA_LINK_DATA) = val;
+
+    /* Setup adr of required register. std regs start eight into async region */    
+    *(sata_regs_base[device] + SATA_LINK_WR_ADDR) = sc_reg*4 + SATA_STD_ASYNC_REGS_OFF;
+
+    /* Wait for data to be written */
+    int loops = MAX_SRC_WRITE_LOOPS;
+    do {
+        if (*(sata_regs_base[device] + SATA_LINK_CONTROL) & 1UL) {
+            break;
+        }
+        udelay(10);
+    } while (--loops);
+
+    if (!loops) {
+        printf("scr_write() Timed out of wait for write completion\n");
+    }
+}
+
+#define PHY_LOOP_COUNT  25  /* Wait for upto 5 seconds for PHY to be found */
+static int phy_reset(int device)
+{
+#ifdef FPGA
+    /* The FPGA thinks it can do 3G when infact only 1.5G is possible, so limit
+    it to Gen-1 SATA (1.5G) */ 
+    scr_write(device, SATA_SCR_CONTROL, 0x311);  /* Issue phy wake & core reset */
+    scr_read(device, SATA_SCR_STATUS);           /* Dummy read; flush */
+    udelay(1000);
+    scr_write(device, SATA_SCR_CONTROL, 0x310);  /* Issue phy wake & clear core reset */
+#else
+    scr_write(device, SATA_SCR_CONTROL, 0x301);  /* Issue phy wake & core reset */
+    scr_read(device, SATA_SCR_STATUS);           /* Dummy read; flush */
+    udelay(1000);
+    scr_write(device, SATA_SCR_CONTROL, 0x300);  /* Issue phy wake & clear core reset */
+#endif
+    /* Wait for upto 5 seconds for PHY to become ready */
+    int phy_status = 0;
+    int loops = 0;
+    do {
+        udelay(200000);
+        if ((scr_read(device, SATA_SCR_STATUS) & 0xf) != 1) {
+            phy_status = 1;
+            break;
+        }
+        printf("No SATA PHY found\n");
+    } while (++loops < PHY_LOOP_COUNT);
+
+    if (phy_status) {
+        udelay(500000); /* wait half a second */
+    }
+    return phy_status;
+}
+
+#define FIS_LOOP_COUNT  25  /* Wait for upto 5 seconds for FIS to be received */
+static int wait_FIS(int device)
+{
+    int status = 0;
+    int loops = 0;
+
+    do {
+        udelay(200000);
+        if 	(oxnas_sata_inb(device, ATA_PORT_NSECT) > 0) {
+            status = 1;
+            break;
+        }
+    } while (++loops < FIS_LOOP_COUNT);
+
+    return status;
+}
+
+int ide_preinit(void)
+{
+    int num_disks_found = 0;
+
+    /* Initialise records of which disks are present to all present */
+    int i;
+    for (i=0; i < CFG_IDE_MAXDEVICE; i++) {
+        disk_present[i] = 1;
+    }
+
+//udelay(1000000);
+    /* Enable clocks to SATA and DMA cores */
+    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_SATA_BIT);
+    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_DMA_BIT);
+    
+    /* Block reset SATA and DMA cores */
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_BIT) |
+                                              (1UL << SYS_CTRL_RSTEN_SATA_LINK_BIT) |
+                                              (1UL << SYS_CTRL_RSTEN_SATA_PHY_BIT) |
+                                              (1UL << SYS_CTRL_RSTEN_DMA_BIT);
+    udelay(50);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_PHY_BIT);
+    udelay(50);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_SATA_LINK_BIT) |
+                                              (1UL << SYS_CTRL_RSTEN_SATA_BIT);
+    udelay(50);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_DMA_BIT);
+    udelay(50);
+//udelay(1000000);
+
+    /* disable and clear core interrupts */
+    *((unsigned long*)SATA_HOST_REGS_BASE + SATA_INT_ENABLE_CLR_OFF) = ~0UL;
+    *((unsigned long*)SATA_HOST_REGS_BASE + SATA_INT_CLR_OFF) = ~0UL;
+
+    int device;
+    for (device = 0; device < CFG_IDE_MAXDEVICE; device++) {
+        int found = 0;
+        int retries = 1;
+
+        /* Disable SATA interrupts */
+        *(sata_regs_base[device] + SATA_INT_ENABLE_CLR_OFF) = ~0UL;
+
+        /* Clear any pending SATA interrupts */
+        *(sata_regs_base[device] + SATA_INT_CLR_OFF) = ~0UL;
+
+        do {
+            /* clear sector count register for FIS detection */
+            oxnas_sata_outb(device, ATA_PORT_NSECT, 0);
+    
+            /* Get the PHY working */
+            if (!phy_reset(device)) {
+                printf("SATA PHY not ready for device %d\n", device);
+                break;
+            }
+
+            if (!wait_FIS(device)) {
+                printf("No FIS received from device %d\n", device);
+            } else {
+                if ((scr_read(device, SATA_SCR_STATUS) & 0xf) == 0x3) {
+                    if (wait_not_busy(device, 30)) {
+                        printf("Timed out of wait for SATA device %d to have BUSY clear\n", device);
+                    } else {
+                        ++num_disks_found;
+                        found = 1;
+                    }
+                } else {
+                    printf("No SATA device %d found, PHY status = 0x%08x\n",
+                            device, scr_read(device, SATA_SCR_STATUS));
+                }
+                break;
+            }
+        } while (retries--) ;
+
+        /* Record whether disk is present, so won't attempt to access it later */
+        disk_present[device] = found;
+    }
+
+    /* post disk detection clean-up */
+    for (device = 0; device < CFG_IDE_MAXDEVICE; device++) {
+        if ( disk_present[device] ) {
+            /* set as ata-5 (28-bit) */
+            *(sata_regs_base[device] + SATA_DRIVE_CONTROL_OFF) = 0UL;
+            
+            /* clear phy/link errors */
+            scr_write(device, SATA_SCR_ERROR, ~0);
+            
+            /* clear host errors */
+            *(sata_regs_base[device] + SATA_CONTROL_OFF) |= SATA_SCTL_CLR_ERR;
+            
+            /* clear interrupt register as this clears the error bit in the IDE 
+            status register */
+            *(sata_regs_base[device] + SATA_INT_CLR_OFF) = ~0UL;
+        }
+    }    
+    
+
+    return !num_disks_found;
+}
+
diff -Nurd u-boot-1.1.2/board/oxnas/Makefile u-boot-1.1.2-oxe810/board/oxnas/Makefile
--- u-boot-1.1.2/board/oxnas/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/board/oxnas/Makefile	2008-06-11 17:55:18.000000000 +0200
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2004
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2004
+# ARM Ltd.
+# Philippe Robin, <philippe.robin@arm.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	= lib$(BOARD).a
+
+OBJS	:= oxnas.o eth.o ide-$(NAS_VERSION).o
+SOBJS	:= platform-$(NAS_VERSION).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 -Nurd u-boot-1.1.2/board/oxnas/oxnas.c u-boot-1.1.2-oxe810/board/oxnas/oxnas.c
--- u-boot-1.1.2/board/oxnas/oxnas.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/board/oxnas/oxnas.c	2008-06-11 17:55:18.000000000 +0200
@@ -0,0 +1,280 @@
+/*
+ * (C) Copyright 2005
+ * Oxford Semiconductor Ltd
+ *
+ * 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>
+
+#if defined(CONFIG_SHOW_BOOT_PROGRESS)
+void show_boot_progress(int progress)
+{
+    printf("Boot reached stage %d\n", progress);
+}
+#endif
+
+static inline void delay(unsigned long loops)
+{
+    __asm__ volatile ("1:\n"
+        "subs %0, %1, #1\n"
+        "bne 1b":"=r" (loops):"0" (loops));
+}
+
+/*
+ * Miscellaneous platform dependent initialisations
+ */
+
+/** Expected Intel 28F320B3T CFI info */
+//    mfr_id:			MANUFACTURER_INTEL, -> 0x0089
+//    dev_id:			I28F320B3T,         -> 0x8896
+//    name:			"Intel 28F320B3T",
+//    DevSize:		SIZE_4MiB,              -> 22
+//    CmdSet:			P_ID_INTEL_STD,     -> 0x0003
+//    NumEraseRegions:	2,
+//    regions: {                            -> #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
+//        ERASEINFO(0x10000, 63),
+//        ERASEINFO(0x02000, 8),
+//    }
+
+#define FLASH_WORD_SIZE unsigned short
+
+int board_init(void)
+{
+    DECLARE_GLOBAL_DATA_PTR;
+
+    gd->bd->bi_arch_number = MACH_TYPE_OXNAS;
+    gd->bd->bi_boot_params = PHYS_SDRAM_1_PA + 0x100;
+    gd->flags = 0;
+
+    icache_enable();
+
+    /* Block reset Static core */
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_STATIC_BIT);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_STATIC_BIT);
+
+    /* Enable clock to Static core */
+    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_STATIC_BIT);
+
+#ifdef CONFIG_OXNAS_ENABLE_PCI
+    /* Block reset PCI core */
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_PCI_BIT);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_PCI_BIT);
+
+    /* Enable clock to PCI core */
+    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_PCI_BIT);
+#endif // CONFIG_OXNAS_ENABLE_PCI
+
+#ifdef CONFIG_OXNAS_MANUAL_STATIC_ARBITRATION
+    /* Assert manual static bus PCI arbitration request */
+    *(volatile u32*)SYS_CTRL_PCI_CTRL1 |= (1UL << SYS_CTRL_PCI_CTRL1_PCI_STATIC_RQ_BIT);
+#endif // CONFIG_OXNAS_MANUAL_STATIC_ARBITRATION
+
+#ifdef CONFIG_OXNAS_FEEDBACK_PCI_CLKS
+    /* Set PCI feedback clk GPIO pin as an output */
+    *(volatile u32*)GPIO_1_SET_OE |= 0x800;
+
+    /* Enable PCI feedback clk onto GPIO pin */
+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 |= 0x00000800;
+#endif // CONFIG_OXNAS_FEEDBACK_PCI_CLKS
+
+#ifndef CFG_NO_FLASH
+    /* Enable static bus onto GPIOs, only CS0 as CS1 conflicts with UART2 */
+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 |= 0x002FF000;
+
+    /* Setup the static bus CS0 to access FLASH */
+    *(volatile u32*)STATIC_CONTROL_BANK0 = STATIC_BUS_FLASH_CONFIG;
+#endif // !CFG_NO_FLASH
+
+    /* Set 33MHz PCI clock */
+    *(volatile u32*)SYS_CTRL_CKCTRL_CTRL_ADDR = 5;
+    /* Enable full speed RPS clock */
+    *(volatile u32*)SYS_CTRL_CKCTRL_CTRL_ADDR &= ~(1UL << SYS_CTRL_CKCTRL_SLOW_BIT);
+
+#if (USE_EXTERNAL_UART == 0)
+#ifdef CONFIG_OXNAS_UART1
+    /* Block reset UART1 */
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART1_BIT);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART1_BIT);
+
+    /* Setup pin mux'ing for first internal UART */
+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x80000000;
+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x80000000;
+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x80000000; // Route UART1 SOUT onto external pins
+
+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 &= ~0x00000001;
+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  &= ~0x00000001;
+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 |=  0x00000001; // Route UART1 SIN onto external pins
+
+    *(volatile u32*)GPIO_1_SET_OE |= 0x80000000;                // Make UART1 SOUT an o/p
+    *(volatile u32*)GPIO_2_CLR_OE |= 0x00000001;                // Make UART1 SIN an i/p
+#endif // CONFIG_OXNAS_UART1
+
+#ifdef CONFIG_OXNAS_UART2
+    // Block reset UART2
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART2_BIT);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART2_BIT);
+
+    /* Setup pin mux'ing for second internal UART */
+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x00500000;
+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x00500000;
+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x00500000; // Route UART2 SOUT and SIN onto external pins
+
+    *(volatile u32*)GPIO_1_SET_OE |= 0x00100000;                // Make UART2 SOUT an o/p
+    *(volatile u32*)GPIO_1_CLR_OE |= 0x00400000;                // Make UART2 SIN an i/p
+#endif // CONFIG_OXNAS_UART2
+
+#ifdef CONFIG_OXNAS_UART3
+    // Block reset UART3
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART3_BIT);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART3_BIT);
+
+    // Route UART3 SIN/SOUT onto external pin
+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x000000C0;
+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x000000C0;
+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x000000C0;
+
+    // Setup GPIO line directions for UART3 SIN/SOUT
+    *(volatile u32*)GPIO_1_SET_OE   |= 0x00000080;
+    *(volatile u32*)GPIO_1_CLR_OE |= 0x00000040;
+#endif // CONFIG_ARCH_OXNAS_UART3
+
+#ifdef CONFIG_OXNAS_UART4
+    // Block reset UART4
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART4_BIT);
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART4_BIT);
+
+    // Enable UART4 to override PCI functions onto GPIOs
+    *(volatile u32*)SYS_CTRL_UART_CTRL |= (1UL << SYS_CTRL_UART4_NOT_PCI_MODE);
+#endif // CONFIG_OXNAS_UART4
+#endif // !USE_EXTERNAL_UART
+
+    return 0;
+}
+
+int board_late_init()
+{
+    return 0;
+}
+
+int misc_init_r(void)
+{
+    return 0;
+}
+
+int dram_init(void)
+{
+#ifdef PROBE_MEM_SIZE
+	/* Determine the amount of SDRAM the DDR controller is configured for */
+	volatile unsigned long * const ddr_config_reg_adr = (volatile unsigned long *)(0x45800000);
+	static const int DDR_SIZE_BIT = 17;
+	static const int DDR_SIZE_NUM_BITS = 4;
+	static const unsigned long DDR_SIZE_MASK = (((1UL << DDR_SIZE_NUM_BITS) - 1) << DDR_SIZE_BIT);
+
+	unsigned long ddr_config_reg = *ddr_config_reg_adr;
+	int ddr_size_pow2 = (ddr_config_reg & DDR_SIZE_MASK) >> DDR_SIZE_BIT;
+
+    DECLARE_GLOBAL_DATA_PTR;
+
+    gd->bd->bi_dram[0].size  = (1 << ddr_size_pow2) * 1024 * 1024;
+
+	if ((gd->bd->bi_dram[0].size >> 20) == 256) {
+		/* Do we really have 256M, or are we working around the DDR controller's
+		 * problem with 128M size? */
+		volatile unsigned long * const PROBE_ADR_1 = (volatile unsigned long * const)PHYS_SDRAM_1_PA;
+		volatile unsigned long * const PROBE_ADR_2 = (volatile unsigned long * const)(PHYS_SDRAM_1_PA + (128*1024*1024));
+		static const unsigned long PROBE_VAL_1 = 0xdeadbeef;
+		static const unsigned long PROBE_VAL_2 = 0x12345678;
+
+		*PROBE_ADR_1 = PROBE_VAL_1;
+		*PROBE_ADR_2 = PROBE_VAL_2;
+		if (*PROBE_ADR_1 != PROBE_VAL_1) {
+			gd->bd->bi_dram[0].size  = 128*1024*1024;
+		}
+	}
+#else // PROBE_MEM_SIZE
+    gd->bd->bi_dram[0].size = MEM_SIZE;
+#endif // PROBE_MEM_SIZE
+
+    gd->bd->bi_dram[0].start = PHYS_SDRAM_1_PA;
+
+	gd->bd->bi_sramstart = CFG_SRAM_BASE;
+	gd->bd->bi_sramsize = CFG_SRAM_SIZE;
+
+    return 0;
+}
+
+int reset_cpu(void)
+{
+    printf("Resetting Oxsemi NAS...");
+
+    // Assert reset to cores as per power on defaults
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL =
+        (1UL << SYS_CTRL_RSTEN_COPRO_BIT)    |
+        (1UL << SYS_CTRL_RSTEN_USBHS_BIT)    |
+        (1UL << SYS_CTRL_RSTEN_USBHSPHY_BIT) |
+        (1UL << SYS_CTRL_RSTEN_MAC_BIT)      |
+        (1UL << SYS_CTRL_RSTEN_PCI_BIT)      |
+        (1UL << SYS_CTRL_RSTEN_DMA_BIT)      |
+        (1UL << SYS_CTRL_RSTEN_DPE_BIT)      |
+        (1UL << SYS_CTRL_RSTEN_SATA_BIT)     |
+        (1UL << SYS_CTRL_RSTEN_SATA_LINK_BIT) |
+        (1UL << SYS_CTRL_RSTEN_SATA_PHY_BIT) |
+        (1UL << SYS_CTRL_RSTEN_STATIC_BIT)   |
+        (1UL << SYS_CTRL_RSTEN_UART1_BIT)    |
+        (1UL << SYS_CTRL_RSTEN_UART2_BIT)    |
+        (1UL << SYS_CTRL_RSTEN_MISC_BIT)     |
+        (1UL << SYS_CTRL_RSTEN_I2S_BIT)      |
+        (1UL << SYS_CTRL_RSTEN_AHB_MON_BIT)  |
+        (1UL << SYS_CTRL_RSTEN_UART3_BIT)    |
+        (1UL << SYS_CTRL_RSTEN_UART4_BIT)    |
+        (1UL << SYS_CTRL_RSTEN_SGDMA_BIT);
+
+    // Release reset to cores as per power on defaults
+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_GPIO_BIT);
+
+    // Disable clocks to cores as per power-on defaults
+    *(volatile u32*)SYS_CTRL_CKEN_CLR_CTRL =
+        (1UL << SYS_CTRL_CKEN_COPRO_BIT) |
+        (1UL << SYS_CTRL_CKEN_DMA_BIT)   |
+        (1UL << SYS_CTRL_CKEN_DPE_BIT)   |
+        (1UL << SYS_CTRL_CKEN_SATA_BIT)  |
+        (1UL << SYS_CTRL_CKEN_I2S_BIT)   |
+        (1UL << SYS_CTRL_CKEN_USBHS_BIT) |
+        (1UL << SYS_CTRL_CKEN_MAC_BIT)   |
+        (1UL << SYS_CTRL_CKEN_STATIC_BIT);
+
+    // Enable clocks to cores as per power-on defaults
+    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_PCI_BIT);
+
+    // Set sys-control pin mux'ing as per power-on defaults
+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 = 0x800UL;
+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 = 0x0UL;
+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  = 0x0UL;
+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  = 0x0UL;
+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 = 0x0UL;
+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 = 0x0UL;
+
+    // No need to save any state, as the ROM loader can determine whether reset
+    // is due to power cycling or programatic action, just hit the (self-
+    // clearing) CPU reset bit of the block reset register
+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL =  (1UL << SYS_CTRL_RSTEN_ARM_BIT);
+
+	return 0;
+}
diff -Nurd u-boot-1.1.2/board/oxnas/platform-800.S u-boot-1.1.2-oxe810/board/oxnas/platform-800.S
--- u-boot-1.1.2/board/oxnas/platform-800.S	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/board/oxnas/platform-800.S	2008-06-11 17:55:18.000000000 +0200
@@ -0,0 +1,254 @@
+/*
+ * Board specific setup info
+ *
+ * (C) Copyright 2005
+ * Oxford Semiconductor Ltd
+ *
+ * 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>
+
+/* use estimate of processor speed to calculate number of cycles delay */
+/* delay count is nominal (PLL200 frequency x delay time) / loop count 
+ * expressing 200us as 200/1000000 and re-arranging gives the expression below
+ */
+ 
+#define DELAY_200US   ((NOMINAL_ARMCLK / (5 * 1000000)) * 200) 
+/* this is 8 cycles of ? so choose 8 resulting in 40 cycles */
+#define DELAY_1S   ((DELAY_200US) * 5000)
+#define DELAY_8       8
+#define DELAY_200     200
+
+.globl platformsetup
+platformsetup:
+/* register allocations
+ * r0 - delay counter and scratch
+ * r1 - address register
+ * r2 - data register
+ * r3 - index to table pointer
+ * r4 - iteration counter.
+ * 
+ * r5 - hold return address.
+ * lr - (R14) link register
+ * pc - (R15) program counter.
+ */
+
+#ifdef INITIALISE_SDRAM
+/*
+ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
+ * Controller function is linked to execute in SDRAM must be in ROM if not
+ * there. Check for wrong place.
+ */
+	adrl r0, platformsetup		/* Relative location of function start.*/
+	ldr  r1, _platformsetup
+	cmp  r0, r1
+	moveq pc, lr
+#else
+	mov pc, lr
+#endif
+
+	/* Establish a working setup for the SDRAM */
+	mov r6, lr
+
+#ifdef OXNAS_OVERCLOCK
+	/* Delay so the broken JTAG can get control */
+	ldr r0, =DELAY_1S
+	bl delay
+
+	/* Configure the PLL to run faster */
+	ldr r1, =SYS_CTRL_PLLSYS_CTRL
+	ldr r2, =SYS_CTRL_PLLSYS_KEY_CTRL
+
+	/* 0xBEADFACE -> PLL_KEY */
+	/* Bypass PLL */
+	ldr r3, [r1]
+	ldr r5, =0x20000
+	orr r3, r3, r5
+	ldr r4, =0xbeadface
+	str r4, [r2]
+	str r3, [r1]
+
+	/* 0xBEADFACE -> PLL_KEY */
+	/* Set m,p and s for PLL at 400MHz */
+	ldr r5, =0xffff0000
+	and r3, r3, r5
+	ldr r5, =OXNAS_OVERCLOCK
+	orr r3, r3, r5
+	str r4, [r2]
+	str r3, [r1]
+
+	/* Wait at least 300uS */
+	ldr r0, =DELAY_200US
+	bl delay
+	ldr r0, =DELAY_200US
+	bl delay
+
+	/* 0xBEADFACE -> PLL_KEY */
+	/* Disable PLL bypass */
+	ldr r5, =0xfffdffff
+	and r3, r3, r5
+	str r4, [r2]
+	str r3, [r1]
+#endif // OXNAS_OVERCLOCK
+
+	/* Assert reset to the DDR core */
+	ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
+	ldr r1, =1
+	ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
+	mov r1, r1, LSL r2
+	str r1, [r0]
+
+	/* Deassert reset to the DDR core */
+	ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
+	str r1, [r0]
+
+	/* Turn on the DDR core clock */
+	ldr r0, =SYS_CTRL_CKEN_SET_CTRL
+	ldr r1, =1
+	ldr r2, =SYS_CTRL_CKEN_DDR_BIT
+	mov r1, r1, LSL r2
+	str r1, [r0]
+
+	/* Start using the initialisation value list */
+	adrl r3, init_table
+
+	/* Copy next 6 entries from DDR init table*/
+	ldr r4, =6
+loop0:
+	ldmia r3!, {r1, r2}
+	str r2, [r1]
+	subs r4, r4, #1
+	bne loop0
+
+	/* Delay for 200uS while DRAM controller stabilises. */
+	ldr r0, =DELAY_200US
+	bl delay
+
+#if !TEST_BRD
+	/* Copy next entry */
+	ldr r4, =1
+loopx:	
+	ldmia r3!, {r1, r2}
+	str r2, [r1]
+	subs r4, r4, #1
+	bne loopx
+
+	/* Delay for 200uS while DRAM controller stabilises. */
+	ldr r0, =DELAY_200US
+	bl delay
+#endif // TEST_BRD
+
+	/* Copy next entry */
+	ldr r4, =1
+loop1:	
+	ldmia r3!, {r1, r2}
+	str r2, [r1]
+	subs r4, r4, #1
+	bne loop1
+
+	/* Delay for 200uS while DRAM controller stabilises. */
+	ldr r0, =DELAY_200US
+	bl delay
+
+	/* Copy next entry */
+	ldr r4, =1
+loop2:	
+	ldmia r3!, {r1, r2}
+	str r2, [r1]
+	subs r4, r4, #1
+	bne loop2
+
+	/* Delay for 200uS while DRAM controller stabilises. */
+	ldr r0, =DELAY_200US
+	bl delay
+
+	/* Copy next entry */
+	ldr r4, =1
+loop3:	
+	ldmia r3!, {r1, r2}
+	str r2, [r1]
+	subs r4, r4, #1
+	bne loop3
+
+	/* Delay for 200uS while DRAM controller stabilises. */
+	ldr r0, =DELAY_200US
+	bl delay
+
+	/* Copy next 5 entries */
+	ldr r4, =5
+loop4:	
+	ldmia r3!, {r1, r2}
+	str r2, [r1]
+	subs r4, r4, #1
+	bne loop4
+
+	/* SDRAM initialised so now exit. */
+	mov lr, r6
+	mov pc, lr
+
+/*
+ *  delay()
+ *
+ *  uses 1 + r0 * 5 cycles
+ */
+delay:
+	nop
+	nop
+	nop
+	subs r0, r0, #1
+	bne delay
+	mov pc, lr
+
+_platformsetup:
+	.word platformsetup
+
+init_table:
+	/* Table of address, data for loading into the DRAM controller */
+    	/* Configure for a single DDR device */
+	.word 0x4500002C, 0x08
+	.word 0x45000038, 0x400
+	.word 0x45800000, 0x80100000
+	.word 0x45800004, 0x8000ffff	// Enable DDR core and all clients
+	.word 0x45800024, 0x1e4
+	.word 0x45800014, 0xe0000001	// DLL to automatic with starting value=1
+/* 200uS delay */
+#if !TEST_BRD
+	.word 0x45800014, 0xa0000003	// DLL to automatic with offset value=3
+/* 200uS delay */
+#endif // TEST_BRD
+#if (MEM_SIZE == 32)
+	.word 0x45800000, 0x801B030C
+#else
+	.word 0x45800000, 0x801D030C
+#endif // MEM_SIZE
+/* 200uS delay */
+	.word 0x4580000c, 0x80280400
+/* 200uS delay */
+	.word 0x4580000c, 0x80210000
+/* 200uS delay */
+	.word 0x4580000c, 0x80200063
+	.word 0x45800028, 0x0000001f	// Enable all arbiter features
+	.word 0x45800018, 0x00000000	// Disable all monitoring
+	.word 0x45800010, 0xffffffff	// Disable all read buffering, due to h/w bug
+	.word 0x4580002C, 0x00000000	// Do NOT disable HPROT, ie want write coherency
+
+.ltorg
+
diff -Nurd u-boot-1.1.2/board/oxnas/platform-810.S u-boot-1.1.2-oxe810/board/oxnas/platform-810.S
--- u-boot-1.1.2/board/oxnas/platform-810.S	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/board/oxnas/platform-810.S	2008-06-11 17:55:18.000000000 +0200
@@ -0,0 +1,477 @@
+/*
+ * Board specific setup info
+ *
+ * (C) Copyright 2005
+ * Oxford Semiconductor Ltd
+ *
+ * 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>
+
+/* use estimate of processor speed to calculate number of cycles delay */
+/* delay count is nominal (PLL200 frequency x delay time) / loop count 
+ * expressing 200us as 200/1000000 and re-arranging gives the expression below
+ */
+ 
+#define DELAY_200US   ((NOMINAL_ARMCLK  / (5 * 1000000)) * 200)  
+#define DELAY_300US   ((NOMINAL_ARMCLK  / (5 * 1000000)) * 300)  
+/* this is 8 cycles of ? so choose 8 resulting in 40 cycles */
+#define DELAY_1S   ((DELAY_200US) * 5000)
+#define DELAY_8       8
+#define DELAY_200     200
+
+
+.globl platformsetup
+platformsetup:
+/* register allocations
+ * r0 - delay counter and scratch
+ * r1 - address register
+ * r2 - data register
+ * r3 - index to table pointer
+ * r4 - iteration counter.
+ * 
+ * r5 - hold return address.
+ * lr - (R14) link register
+ * pc - (R15) program counter.
+ */
+
+#ifdef INITIALISE_SDRAM
+/*
+ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
+ * Controller function is linked to execute in SDRAM must be in ROM if not
+ * there. Check for wrong place.
+ */
+    adrl r0, platformsetup      /* Relative location of function start.*/
+    ldr  r1, _platformsetup
+    cmp  r0, r1
+    moveq pc, lr
+#else
+    mov pc, lr
+#endif
+
+#if (FPGA == 1)
+    /* Establish a working setup for the SDRAM */
+    mov r6, lr
+
+    /* Assert reset to the DDR core */
+    ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
+    ldr r1, =1
+    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
+    mov r1, r1, LSL r2
+    str r1, [r0]
+
+    /* Deassert reset to the DDR core */
+    ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
+    str r1, [r0]
+
+    /* Turn on the DDR core clock */
+    ldr r0, =SYS_CTRL_CKEN_SET_CTRL
+    ldr r1, =1
+    ldr r2, =SYS_CTRL_CKEN_DDR_BIT
+    mov r1, r1, LSL r2
+    str r1, [r0]
+
+    /* Start using the initialisation value list */
+    adrl r3, init_table
+
+    /* Copy first 6 entries */
+    ldr r4, =6
+loop0:
+    ldmia r3!, {r1, r2}
+    str r2, [r1]
+    subs r4, r4, #1
+    bne loop0
+
+    /* Delay for 200uS while DRAM controller stabilises. */
+    ldr r0, =DELAY_200US
+    bl delay
+
+    /* Copy next 4 entries */
+    ldr r4, =4
+loop1:  
+    ldmia r3!, {r1, r2}
+    str r2, [r1]
+    subs r4, r4, #1
+    bne loop1
+
+    /* Wait at least 200 clock cycles. */
+    ldr r0, =DELAY_200
+    bl delay
+
+    /* Copy next 2 entries */
+    ldr r4, =2
+loop2:  
+    ldmia r3!, {r1, r2}
+    str r2, [r1]
+    subs r4, r4, #1
+    bne loop2
+
+    /* Wait at least 8 clock  cycles. */
+    ldr r0, =DELAY_8
+    bl delay
+
+    /* Copy next 9 entries */
+    ldr r4, =9
+loop3:  
+    ldmia r3!, {r1, r2}
+    str r2, [r1]
+    subs r4, r4, #1
+    bne loop3
+
+    /* SDRAM initialised so now exit. */
+    mov lr, r6
+    mov pc, lr
+
+/*
+ *  delay()
+ *
+ *  uses 1 + r0 * 5 cycles
+ */
+delay:
+    nop
+    nop
+    nop
+    subs r0, r0, #1
+    bne delay
+    mov pc, lr
+
+_platformsetup:
+    .word platformsetup
+#else // ASIC, (DDR-2)
+/*
+ * Check that not in SDRAM execution. Suicide if re-initialise DRAM.
+ * Controller function is linked to execute in SDRAM must be in ROM if not
+ * there. Check for wrong place.
+ */
+    /* Establish a working setup for the SDRAM */
+    mov r6, lr
+
+#ifdef OVERCLOCK
+    /* 
+      change clock speed on chip 
+    */
+    
+    /* read SYS_CTRL_PLLSYS_CTRL into r3*/
+    mov r5, #0x45000000
+    ldr r3, [r5, #72]
+    
+    /* load the value at dllkey (0xbeadface) into r7 */
+    adrl r7, dllkey
+    ldr r7, [r7]
+    
+    /* pll_sys |= 0x20000; */
+    orr r3, r3, #131072 /* 0x20000 */
+    
+    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
+    str r7, [r5, #108]
+
+    /* write pll_sys (bypass pll)*/
+    str r3, [r5, #72]
+    
+    /* pll_sys &= 0xff000000; */
+    mov r4, r3, lsr #16
+    mov r4, r4, lsl #16
+    
+    /* pll_sys |= 0x00F00061  */
+    orr r4, r4, #15728640   /* 0xf00000 */
+    orr r4, r4, #97 /* 0x61 */
+#if 0
+    orr r4, r4, #7864320    /* 0x780000 */
+    orr r4, r4, #96 /* 0x60 */
+#endif
+    
+    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
+    str r7, [r5, #108]
+
+    /* write pll_sys (with new pll speeds) */    
+    str r4, [r5, #72]
+
+    /* delay 300us */
+    ldr r0, =DELAY_300US
+    bl delay
+
+    /* clear bypass pll bit */
+    bic r4, r4, #131072 /* 0x20000 */
+
+    /* write 0xbeadface into SYS_CTRL_PLLSYS_KEY_CTRL */
+    str r7, [r5, #108]
+
+    /* write pll_sys (with new pll speeds and pll un-bypassed) */    
+    str r4, [r5, #72]
+#endif /* OVERCLOCK */
+  
+    /* Turn on the DDR core and phy clocks */
+    ldr r0, =SYS_CTRL_CKEN_SET_CTRL
+    ldr r1, =1
+    ldr r2, =SYS_CTRL_CKEN_DDR_BIT
+    mov r1, r1, LSL r2
+    str r1, [r0]
+    ldr r1, =1
+    ldr r2, =SYS_CTRL_CKEN_DDR_PHY_BIT
+    mov r1, r1, LSL r2
+    str r1, [r0]
+
+    /* Assert reset to the DDR core and phy */
+    ldr r0, =SYS_CTRL_RSTEN_SET_CTRL
+    ldr r1, =1
+    ldr r2, =SYS_CTRL_RSTEN_DDR_PHY_BIT
+    mov r1, r1, LSL r2
+    str r1, [r0]
+    ldr r1, =1
+    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
+    mov r1, r1, LSL r2
+    str r1, [r0]
+
+    /* Deassert reset to the DDR core and phy*/
+    ldr r0, =SYS_CTRL_RSTEN_CLR_CTRL
+    ldr r1, =1
+    ldr r2, =SYS_CTRL_RSTEN_DDR_PHY_BIT
+    mov r1, r1, LSL r2
+    str r1, [r0]
+    ldr r1, =1
+    ldr r2, =SYS_CTRL_RSTEN_DDR_BIT
+    mov r1, r1, LSL r2
+    str r1, [r0]
+
+    /* Start using the initialisation value list */
+    adrl r3, init_table
+
+    /* Copy first 14 entries of DDR core setup (section A)*/
+    ldr r4, =14
+loop0:
+    ldmia r3!, {r1, r2}
+    str r2, [r1]
+    subs r4, r4, #1
+    bne loop0
+
+    /* Delay for 200uS while DDR controller stabilises. */
+    ldr r0, =DELAY_200US
+    bl delay
+
+    /* Copy next 13 entries of DDR device commands (section B)*/
+    ldr r4, =13
+loop1:
+    ldmia r3!, {r1, r2}
+    str r2, [r1]
+
+    /* Wait at least 200 clock cycles between ram chip command writes */
+    ldr r0, =DELAY_200
+    bl delay
+
+    subs r4, r4, #1
+    bne loop1
+
+    /* Copy final DDR controller setup to set memory size/banks (section C)*/
+    ldmia r3!, {r1, r2}
+    str r2, [r1]
+
+#if (PROBE_MEM_SIZE == 1)
+    /* Load the probe values into SDRAM */
+    adrl r3, probe_table
+    mov r4, #4
+.globl pl1
+pl1:
+    ldmia r3!, {r1, r2}
+    str r2, [r1]
+    subs r4, r4, #1
+    bne pl1
+
+    /* Get the current contents of the DDR controller core's config register */
+    adrl r1, ddr_config_reg
+    ldr r1, [r1]
+    ldr r1, [r1]
+
+    /* Zero the number of banks field - bit 23*/
+    mov r2, #1
+    bic r1, r1, r2, lsl #23
+
+    /* Zero the size field - bits 17-20 inclusive */
+    mov r2, #15
+    bic r1, r1, r2, lsl #17
+
+    /* First probe location tells us the SDRAM size */
+    adrl r3, probe_table
+    ldr r0, [r3]
+    ldr r0, [r0]
+
+    /* Is size 64MB? */
+    ldr r2, [r3, #28]	/* Get probe value 4 */
+    cmp r0, r2
+    moveq r4, #6
+    orreq r1, r1, r4, lsl #17
+    beq pl2
+
+    /* Is 128M or 256M so set banks to 8 */
+    mov r4, #1
+    orr r1, r1, r4, lsl #23
+
+    /* Is size 128MB? */
+    ldr r2, [r3, #20]	/* Get probe value 3 */
+    cmp r0, r2
+//    moveq r4, #7
+    moveq r4, #8	/* DDR controller does not work at 128M, use 256M instead
+    orreq r1, r1, r4, lsl #17
+    beq pl2
+
+    /* Must be 256MB, or something is very wrong */
+    mov r4, #8
+    orr r1, r1, r4, lsl #17
+
+pl2:
+    /* Write the revised contents to the DDR controller core's config register */
+    adrl r2, ddr_config_reg
+    ldr r2, [r2]
+    str r1, [r2]
+#endif
+
+    /* SDRAM setup complete */
+    mov lr, r6
+    mov pc, lr
+
+/*
+ *  delay()
+ *
+ *  uses 1 + r0 * 5 cycles
+ */
+delay:
+    nop
+    nop
+    nop
+    subs r0, r0, #1
+    bne delay
+    mov pc, lr
+
+_platformsetup:
+    .word platformsetup
+#endif
+
+
+init_table:
+#if (FPGA == 1)
+    /* Table of address, data for loading into the DRAM controller on FPGA */
+    .word 0x45800000, 0x000d0000    // Enable the DDR in SDR mode and width 32 bits
+    .word 0x45800034, 0x04442032    // SDR mode timings - #0
+    .word 0x45800038, 0x570A0907    // SDR mode timings - #1
+    .word 0x4580003C, 0x00000002    // SDR mode timings - #2
+    .word 0x45800004, 0x80000000    // Enable DDR core, but not clients yet
+    .word 0x45800014, 0x80000001    // Enable CK and set DLL mode to manual
+/* 200uS delay */
+    .word 0x4580000c, 0x80200000    // Assert CKE for all further commands
+    .word 0x4580000c, 0x80280400    // Issue precharge to all banks
+    .word 0x4580000c, 0x80200000    // NOP, as only DDR has real command here
+    .word 0x4580000c, 0x80200022    // Set burst length 4, sequential CAS 2
+/* 200uS delay */
+    .word 0x4580000c, 0x80280400    // Issue precharge to all banks
+    .word 0x4580000c, 0x80240000    // Issue auto-refresh command, CKE not asserted
+/* 200uS delay */
+    .word 0x4580000c, 0x80240000    // Issue auto-refresh command, CKE not asserted
+    .word 0x4580000c, 0x80200000    // Assert CKE for all further commands
+    .word 0x4580000c, 0x80200022        // Set burst length 4, sequential CAS 2
+    .word 0x45800000, 0x000d0186    // SDR, size and width and refresh rate, assuming
+                        // 25Mhz clk to SDR, divide down to get 15.625uS
+                    // refresh rate
+    .word 0x45800024, 0x00000124    // Set I/O drive strengths
+    .word 0x45800028, 0x0000001f    // Enable all arbiter features
+    .word 0x45800018, 0x00000000    // Disable all monitoring
+    .word 0x45800010, 0xFFFFFFFF    // Disable all read buffering
+    .word 0x45800004, 0x800000ff    // Enable all client interfaces
+#else   // ASIC DDR-2
+    // SECTION A - DDR controller core configuration
+    .word 0x45800000, 0x802d0591    // enable in ddr-2 mode 16 bit wide
+    .word 0x45800034, 0x04442032    // ddr-2 mode timings 
+    .word 0x45800038, 0x870f0b25    // ddr-2 mode timings
+    .word 0x4580003c, 0x00000a23    // ddr-2 mode timings
+    .word 0x45800054, 0x00072000    // phy-3 settings
+    .word 0x45800050, 0x00022828    // phy-2 settings, start
+    .word 0x45800050, 0x00032828    // phy-2 settings, on
+    .word 0x45800028, 0x0000001f    // Enable all arbiter features
+    .word 0x45800018, 0x00000000    // Disable all monitoring
+    .word 0x45800010, 0xffff0000    // Enable all read buffering
+    .word 0x4580002c, 0x00ff00fd    // no burst accl, no hprot on arm data
+    .word 0x45800040, 0x00000000    // enable burst and read cache
+    .word 0x45800044, 0xffff0000    // enable write behind prot, disable timeout     
+    .word 0x45800004, 0x8000ffff    // Enable all client interfaces
+/* 200uS delay after configuring DDR controller core */
+
+    // SECTION B - Memory device configuration
+    .word 0x4580000c, 0x807c0000    // exit something or other
+    .word 0x4580000c, 0x803c0000    // nop - wake up
+    .word 0x4580000c, 0x80280400    // precharge all
+    .word 0x4580000c, 0x80220000    // emr2
+    .word 0x4580000c, 0x80230000    // emr3
+
+#if (MEM_ODT == 150)
+    .word 0x4580000c, 0x80210042    // enable dll, odt to 150
+#elif (MEM_ODT == 75)
+    .word 0x4580000c, 0x80210006    // enable dll, odt to 75
+#elif (MEM_ODT == 50)
+    .word 0x4580000c, 0x80210046    // enable dll, odt to 50
+#else
+#error Unsupported memory on-die termination, set MEM_ODT to 50, 75, or 150
+#endif
+
+    .word 0x4580000c, 0x80200733    // set WR CL BL and reset dll
+    .word 0x4580000c, 0x80280400    // precharge all
+    .word 0x4580000c, 0x80240000    // auto refresh
+    .word 0x4580000c, 0x80240000    // auto refresh
+    .word 0x4580000c, 0x80200733    // set WR CL BL and reset dll
+
+#if (MEM_ODT == 150)
+    .word 0x4580000c, 0x802103c2    // enable OCD
+    .word 0x4580000c, 0x80210042    // disable OCD
+#elif (MEM_ODT == 75)
+    .word 0x4580000c, 0x80210386    // enable OCD
+    .word 0x4580000c, 0x80210006    // disable OCD
+#elif (MEM_ODT == 50)
+    .word 0x4580000c, 0x802103c6    // enable OCD
+    .word 0x4580000c, 0x80210046    // disable OCD
+#else
+#error Unsupported memory on-die termination, set MEM_ODT to 50, 75, or 150
+#endif
+
+    // SECTION C - Final memory size/bank configuration
+#if (PROBE_MEM_SIZE == 1)
+    .word 0x45800000, 0x80b10591    // 256M, 8 banks, 1425 clocks for 7.8us refresh.
+#elif (MEM_SIZE == 64)
+    .word 0x45800000, 0x802d0591    // 64M,  4 banks, 1425 clocks for 7.8us refresh.
+#elif (MEM_SIZE == 128)
+    .word 0x45800000, 0x80af0591    // 128M, 8 banks, 1425 clocks for 7.8us refresh.
+#elif (MEM_SIZE == 256)
+    .word 0x45800000, 0x80b10591    // 256M, 8 banks, 1425 clocks for 7.8us refresh.
+#else
+#error Unsupported memory size, set MEM_SIZE to 64, 128 or 256
+#endif
+
+#endif  // FPGA or ASIC
+dllkey:
+    .word 0xbeadface
+
+ddr_config_reg:
+    .word 0x45800000
+
+probe_table:
+    .word 0x48000000, 0x12345678
+    .word 0x48000040, 0xdeadbeef
+    .word 0x50000000, 0xfafafafa
+    .word 0x50000040, 0xabcdef01
+
+.ltorg
+
diff -Nurd u-boot-1.1.2/board/oxnas/u-boot.lds u-boot-1.1.2-oxe810/board/oxnas/u-boot.lds
--- u-boot-1.1.2/board/oxnas/u-boot.lds	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/board/oxnas/u-boot.lds	2008-06-11 17:55:18.000000000 +0200
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+	. = ALIGN(4);
+	.text	:
+	{
+	  cpu/arm926ejs/start.o	(.text)
+	  *(.text)
+	}
+	.rodata : { *(.rodata) }
+	. = ALIGN(4);
+	.data : { *(.data) }
+	. = ALIGN(4);
+	.got : { *(.got) }
+
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : { *(.bss) }
+	_end = .;
+}
diff -Nurd u-boot-1.1.2/common/cmd_ext2.c u-boot-1.1.2-oxe810/common/cmd_ext2.c
--- u-boot-1.1.2/common/cmd_ext2.c	2004-12-16 18:34:53.000000000 +0100
+++ u-boot-1.1.2-oxe810/common/cmd_ext2.c	2008-06-11 17:55:30.000000000 +0200
@@ -223,7 +223,7 @@
 	PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part);
 
 	if (part != 0) {
-		if (get_partition_info (&dev_desc[dev], part, &info)) {
+		if (get_partition_info (dev_desc, part, &info)) {
 			printf ("** Bad partition %d **\n", part);
 			return(1);
 		}
diff -Nurd u-boot-1.1.2/common/cmd_ide.c u-boot-1.1.2-oxe810/common/cmd_ide.c
--- u-boot-1.1.2/common/cmd_ide.c	2004-12-31 10:32:50.000000000 +0100
+++ u-boot-1.1.2-oxe810/common/cmd_ide.c	2008-06-11 17:55:30.000000000 +0200
@@ -193,6 +193,13 @@
 static void set_pcmcia_timing (int pmode);
 #endif
 
+#ifdef CONFIG_OXNAS
+extern unsigned char oxnas_sata_inb(int dev, int port);
+extern void oxnas_sata_outb(int dev, int port, unsigned char val);
+extern void oxnas_sata_output_data(int dev, ulong *sect_buf, int words);
+extern void oxnas_sata_input_data(int dev, ulong *sect_buf, int words);
+#endif // CONFIG_OXNAS
+
 /* ------------------------------------------------------------------------- */
 
 int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
@@ -491,175 +498,103 @@
 	return rcode;
 }
 
-/* ------------------------------------------------------------------------- */
 
-void ide_init (void)
+static int ide_probe(int device)
 {
+    int found = 0;
+
+    /* Select device */
+    udelay(100000);	    /* 100 ms */
+    ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+    udelay(100000);     /* 100 ms */
 
-#ifdef CONFIG_IDE_8xx_DIRECT
-	DECLARE_GLOBAL_DATA_PTR;
-	volatile immap_t *immr = (immap_t *)CFG_IMMR;
-	volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
-#endif
 	unsigned char c;
-	int i, bus;
-#ifdef CONFIG_AMIGAONEG3SE
-	unsigned int max_bus_scan;
-	unsigned int ata_reset_time;
-	char *s;
+    int i = 0;
+    do {
+        udelay(10000);  /* 10 ms */
+
+        c = ide_inb(device, ATA_STATUS);
+        if (++i > (ATA_RESET_TIME * 100)) {
+            PRINTF("ide_probe() timeout\n");
+            ide_led((LED_IDE1 | LED_IDE2), 0);  /* LED's off */
+            return found;
+        }
+        if ((i >= 100) && ((i%100) == 0)) {
+            putc ('.');
+        }
+    } while (c & ATA_STAT_BUSY);
+
+    if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
+        PRINTF("ide_probe() status = 0x%02X ", c);
+#ifndef CONFIG_ATAPI    /* ATAPI Devices do not set DRDY */
+    } else  if ((c & ATA_STAT_READY) == 0) {
+        PRINTF("ide_probe() status = 0x%02X ", c);
 #endif
-#ifdef CONFIG_IDE_8xx_PCCARD
-	extern int pcmcia_on (void);
-	extern int ide_devices_found; /* Initialized in check_ide_device() */
-#endif	/* CONFIG_IDE_8xx_PCCARD */
+    } else {
+        found = 1;
+    }
 
-#ifdef CONFIG_IDE_PREINIT
-	extern int ide_preinit (void);
-	WATCHDOG_RESET();
+    return found;
+}
 
-	if (ide_preinit ()) {
-		puts ("ide_preinit failed\n");
+void ide_init(void)
+{
+	static int ide_init_called = 0;
+	int i, bus;
+
+	if (ide_init_called) {
 		return;
 	}
-#endif	/* CONFIG_IDE_PREINIT */
-
-#ifdef CONFIG_IDE_8xx_PCCARD
-	extern int pcmcia_on (void);
-	extern int ide_devices_found; /* Initialized in check_ide_device() */
+	ide_init_called = 1;
 
+#ifdef CONFIG_IDE_PREINIT
+	extern int ide_preinit(void);
 	WATCHDOG_RESET();
 
-	ide_devices_found = 0;
-	/* initialize the PCMCIA IDE adapter card */
-	pcmcia_on();
-	if (!ide_devices_found)
+    printf("Initialising disks\n");
+	if (ide_preinit()) {
+		puts ("ide_preinit failed\n");
 		return;
-	udelay (1000000);	/* 1 s */
-#endif	/* CONFIG_IDE_8xx_PCCARD */
+	}
+#endif	/* CONFIG_IDE_PREINIT */
 
 	WATCHDOG_RESET();
 
-#ifdef CONFIG_IDE_8xx_DIRECT
-	/* Initialize PIO timing tables */
-	for (i=0; i <= IDE_MAX_PIO_MODE; ++i) {
-	    pio_config_clk[i].t_setup  = PCMCIA_MK_CLKS(pio_config_ns[i].t_setup,
-							    gd->bus_clk);
-	    pio_config_clk[i].t_length = PCMCIA_MK_CLKS(pio_config_ns[i].t_length,
-							    gd->bus_clk);
-	    pio_config_clk[i].t_hold   = PCMCIA_MK_CLKS(pio_config_ns[i].t_hold,
-							    gd->bus_clk);
-	    PRINTF ("PIO Mode %d: setup=%2d ns/%d clk"
-		    "  len=%3d ns/%d clk"
-		    "  hold=%2d ns/%d clk\n",
-		    i,
-		    pio_config_ns[i].t_setup,  pio_config_clk[i].t_setup,
-		    pio_config_ns[i].t_length, pio_config_clk[i].t_length,
-		    pio_config_ns[i].t_hold,   pio_config_clk[i].t_hold);
-	}
-#endif /* CONFIG_IDE_8xx_DIRECT */
-
 	/* Reset the IDE just to be sure.
 	 * Light LED's to show
 	 */
-	ide_led ((LED_IDE1 | LED_IDE2), 1);		/* LED's on	*/
-	ide_reset (); /* ATAPI Drives seems to need a proper IDE Reset */
-
-#ifdef CONFIG_IDE_8xx_DIRECT
-	/* PCMCIA / IDE initialization for common mem space */
-	pcmp->pcmc_pgcrb = 0;
-
-	/* start in PIO mode 0 - most relaxed timings */
-	pio_mode = 0;
-	set_pcmcia_timing (pio_mode);
-#endif /* CONFIG_IDE_8xx_DIRECT */
+	ide_led((LED_IDE1 | LED_IDE2), 1);		/* LED's on	*/
+	ide_reset(); /* ATAPI Drives seems to need a proper IDE Reset */
 
 	/*
 	 * Wait for IDE to get ready.
 	 * According to spec, this can take up to 31 seconds!
 	 */
-#ifndef CONFIG_AMIGAONEG3SE
-	for (bus=0; bus<CFG_IDE_MAXBUS; ++bus) {
-		int dev = bus * (CFG_IDE_MAXDEVICE / CFG_IDE_MAXBUS);
-#else
-	s = getenv("ide_maxbus");
-	if (s)
-	    max_bus_scan = simple_strtol(s, NULL, 10);
-	else
-	    max_bus_scan = CFG_IDE_MAXBUS;
-
-	for (bus=0; bus<max_bus_scan; ++bus) {
-		int dev = bus * (CFG_IDE_MAXDEVICE / max_bus_scan);
-#endif
-
-#ifdef CONFIG_IDE_8xx_PCCARD
-		/* Skip non-ide devices from probing */
-		if ((ide_devices_found & (1 << bus)) == 0) {
-			ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
-			continue;
-		}
-#endif
-		printf ("Bus %d: ", bus);
-
-		ide_bus_ok[bus] = 0;
-
-		/* Select device
-		 */
-		udelay (100000);		/* 100 ms */
-		ide_outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
-		udelay (100000);		/* 100 ms */
-#ifdef CONFIG_AMIGAONEG3SE
-		ata_reset_time = ATA_RESET_TIME;
-		s = getenv("ide_reset_timeout");
-		if (s) ata_reset_time = 2*simple_strtol(s, NULL, 10);
-#endif
-		i = 0;
-		do {
-			udelay (10000);		/* 10 ms */
-
-			c = ide_inb (dev, ATA_STATUS);
-			i++;
-#ifdef CONFIG_AMIGAONEG3SE
-			if (i > (ata_reset_time * 100)) {
-#else
-			if (i > (ATA_RESET_TIME * 100)) {
-#endif
-				puts ("** Timeout **\n");
-				ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
-#ifdef CONFIG_AMIGAONEG3SE
-				/* If this is the second bus, the first one was OK */
-				if (bus != 0) {
-				    ide_bus_ok[bus] = 0;
-				    goto skip_bus;
-				}
-#endif
-				return;
-			}
-			if ((i >= 100) && ((i%100)==0)) {
-				putc ('.');
-			}
-		} while (c & ATA_STAT_BUSY);
+    printf("Detecting SATA busses:\n");
+    for (bus=0; bus < CFG_IDE_MAXBUS; ++bus) {
+        printf("Bus %d: ", bus);
 
-		if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) {
-			puts ("not available  ");
-			PRINTF ("Status = 0x%02X ", c);
-#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */
-		} else  if ((c & ATA_STAT_READY) == 0) {
-			puts ("not available  ");
-			PRINTF ("Status = 0x%02X ", c);
-#endif
-		} else {
-			puts ("OK ");
-			ide_bus_ok[bus] = 1;
-		}
-		WATCHDOG_RESET();
-	}
+        /* Try to discover if bus is present by probing first device on bus */
+        int device = bus * (CFG_IDE_MAXDEVICE / CFG_IDE_MAXBUS);
+        ide_bus_ok[bus] = ide_probe(device);
+        if (ide_bus_ok[bus]) {
+            puts("Found first device OK\n");
+        } else {
+            WATCHDOG_RESET();
+        
+            /* Try second device on bus */
+            ide_bus_ok[bus] = ide_probe(++device);
+            if (ide_bus_ok[bus]) {
+                puts("Found second device OK\n");
+            } else {
+                puts("No devices found\n");
+            }
+        }
 
-#ifdef CONFIG_AMIGAONEG3SE
-      skip_bus:
-#endif
-	putc ('\n');
+        WATCHDOG_RESET();
+    }
 
-	ide_led ((LED_IDE1 | LED_IDE2), 0);	/* LED's off	*/
+	ide_led((LED_IDE1 | LED_IDE2), 0);	/* LED's off	*/
 
 	curr_device = -1;
 	for (i=0; i<CFG_IDE_MAXDEVICE; ++i) {
@@ -675,13 +610,12 @@
 		ide_dev_desc[i].block_read=ide_read;
 		if (!ide_bus_ok[IDE_BUS(i)])
 			continue;
-		ide_led (led, 1);		/* LED on	*/
+		ide_led(led, 1);		/* LED on	*/
 		ide_ident(&ide_dev_desc[i]);
-		ide_led (led, 0);		/* LED off	*/
+		ide_led(led, 0);		/* LED off	*/
 		dev_print(&ide_dev_desc[i]);
-/*		ide_print (i); */
 		if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
-			init_part (&ide_dev_desc[i]);			/* initialize partition type */
+			init_part(&ide_dev_desc[i]);    /* initialize partition type */
 			if (curr_device < 0)
 				curr_device = i;
 		}
@@ -689,6 +623,11 @@
 	WATCHDOG_RESET();
 }
 
+int is_device_present(int device_number)
+{
+    return ide_dev_desc[device_number].part_type != PART_TYPE_UNKNOWN;
+}
+
 /* ------------------------------------------------------------------------- */
 
 block_dev_desc_t * ide_get_dev(int dev)
@@ -798,6 +737,11 @@
 	EIEIO;
 	*((uchar *)(ATA_CURR_BASE(dev)+port)) = val;
 }
+#elif defined(CONFIG_OXNAS)
+static void __inline__ ide_outb(int dev, int port, unsigned char val)
+{
+    oxnas_sata_outb(dev, port, val);
+}
 #else	/* ! __PPC__ */
 static void __inline__
 ide_outb(int dev, int port, unsigned char val)
@@ -819,6 +763,11 @@
 		dev, port, (ATA_CURR_BASE(dev)+port), val);
 	return (val);
 }
+#elif defined(CONFIG_OXNAS)
+static unsigned char __inline__ ide_inb(int dev, int port)
+{
+    return oxnas_sata_inb(dev, port);
+}
 #else	/* ! __PPC__ */
 static unsigned char __inline__
 ide_inb(int dev, int port)
@@ -921,6 +870,11 @@
 	}
 #endif	/* CONFIG_HMI10 */
 }
+#elif defined(CONFIG_OXNAS)
+static void output_data(int dev, ulong *sect_buf, int words)
+{
+    oxnas_sata_output_data(dev, sect_buf, words);
+}
 #else	/* ! __PPC__ */
 static void
 output_data(int dev, ulong *sect_buf, int words)
@@ -968,6 +922,11 @@
 	}
 #endif	/* CONFIG_HMI10 */
 }
+#elif defined(CONFIG_OXNAS)
+static void input_data(int dev, ulong *sect_buf, int words)
+{
+    oxnas_sata_input_data(dev, sect_buf, words);
+}
 #else	/* ! __PPC__ */
 static void
 input_data(int dev, ulong *sect_buf, int words)
@@ -1001,10 +960,36 @@
 
 /* -------------------------------------------------------------------------
  */
+#ifdef CONFIG_OXNAS
+static void byte_swap_and_trim(char* buf)
+{
+    char *src = buf;
+
+    // Swap bytes in 16-bit words
+    while ((*src != '\0') && (*(src+1) != '\0')) {
+        char tmp = *(src+1);
+        *(src+1) = *src;
+        *src = tmp;
+        src += 2;
+    }
+
+    // Trim leading spaces
+    src = buf;
+    while (*src == ' ') {
+        ++src;
+    }
+    if (src != buf) {
+        memcpy(buf, src, strlen(src));
+        buf[strlen(buf) - (src-buf)] = '\0';
+    }
+}
+#endif // CONFIG_OXNAS
+
 static void ide_ident (block_dev_desc_t *dev_desc)
 {
 	ulong iobuf[ATA_SECTORWORDS];
 	unsigned char c;
+    unsigned int i;
 	hd_driveid_t *iop = (hd_driveid_t *)iobuf;
 
 #ifdef CONFIG_AMIGAONEG3SE
@@ -1023,6 +1008,10 @@
 	device=dev_desc->dev;
 	printf ("  Device %d: ", device);
 
+    for ( i=0; i < ATA_SECTORWORDS; ++i) {
+        iobuf[i] = 0;
+    }
+    
 #ifdef CONFIG_AMIGAONEG3SE
 	s = getenv("ide_maxbus");
 	if (s) {
@@ -1110,20 +1099,22 @@
 
 	input_swap_data (device, iobuf, ATA_SECTORWORDS);
 
-	ident_cpy (dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision));
-	ident_cpy (dev_desc->vendor, iop->model, sizeof(dev_desc->vendor));
-	ident_cpy (dev_desc->product, iop->serial_no, sizeof(dev_desc->product));
+	ident_cpy(dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision));
+	ident_cpy(dev_desc->vendor, iop->model, sizeof(dev_desc->vendor));
+	ident_cpy(dev_desc->product, iop->serial_no, sizeof(dev_desc->product));
+
 #ifdef __LITTLE_ENDIAN
 	/*
-	 * firmware revision and model number have Big Endian Byte
+	 * firmware revision, model number and product have Big Endian Byte
 	 * order in Word. Convert both to little endian.
 	 *
 	 * See CF+ and CompactFlash Specification Revision 2.0:
 	 * 6.2.1.6: Identfy Drive, Table 39 for more details
 	 */
 
-	strswab (dev_desc->revision);
-	strswab (dev_desc->vendor);
+	byte_swap_and_trim(dev_desc->revision);
+	byte_swap_and_trim(dev_desc->vendor);
+	byte_swap_and_trim(dev_desc->product);
 #endif /* __LITTLE_ENDIAN */
 
 	if ((iop->config & 0x0080)==0x0080)
diff -Nurd u-boot-1.1.2/common/cmd_ledfail.c u-boot-1.1.2-oxe810/common/cmd_ledfail.c
--- u-boot-1.1.2/common/cmd_ledfail.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/common/cmd_ledfail.c	2008-06-11 17:55:30.000000000 +0200
@@ -0,0 +1,58 @@
+
+#include <common.h>
+#include <command.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_LEDFAIL)
+#define FAILURE_LED (1 << (34-32))
+
+#define GPIO_B	0x44100000
+#define WARN_GPIO_OUT_REG			(GPIO_B + 0x10)
+#define WARN_GPIO_OUT_ENABLE_SET	(GPIO_B + 0x1C)
+#define WARN_GPIO_OUT_ENABLE_CLR	(GPIO_B + 0x20)
+
+static void ledfail_light(void)
+{
+	printf("Light LED\n");
+	/* Light the failure LED - assumes active low drive */
+	u_int32_t led_state = *((volatile u_int32_t *)WARN_GPIO_OUT_REG);
+	led_state = led_state & ~FAILURE_LED;
+	*((volatile u_int32_t *)WARN_GPIO_OUT_REG) = led_state;
+
+	/* Enable GPIO for output */
+	*((volatile u_int32_t *)WARN_GPIO_OUT_ENABLE_SET) = FAILURE_LED;
+}
+
+static void ledfail_extinguish(void)
+{
+	printf("Extinguish LED\n");
+	/* Extinguish the failure LED - assumes active low drive */
+	u_int32_t led_state = *((volatile u_int32_t *)WARN_GPIO_OUT_REG);
+	led_state = led_state | FAILURE_LED;
+	*((volatile u_int32_t *)WARN_GPIO_OUT_REG) = led_state;
+
+    /* Clear the failure bit output enable in GPIO's */
+	*((volatile u_int32_t *)WARN_GPIO_OUT_ENABLE_CLR) = FAILURE_LED;
+}
+
+int do_ledfail(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	if (argc != 2) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	ulong arg = simple_strtoul(argv[1], NULL, 10);
+	switch (arg) {
+		case 0:
+			ledfail_extinguish();
+			break;
+		case 1:
+			ledfail_light();
+			break;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(ledfail, 2, 2, do_ledfail, "ledfail - Extinguish (0) or light (1) failure LED\n", NULL);
+#endif	/* CFG_CMD_LEDFAIL */
diff -Nurd u-boot-1.1.2/common/cmd_mem.c u-boot-1.1.2-oxe810/common/cmd_mem.c
--- u-boot-1.1.2/common/cmd_mem.c	2004-12-16 18:42:39.000000000 +0100
+++ u-boot-1.1.2-oxe810/common/cmd_mem.c	2008-06-11 17:55:30.000000000 +0200
@@ -731,13 +731,17 @@
 	if (argc > 1) {
 		start = (ulong *)simple_strtoul(argv[1], NULL, 16);
 	} else {
-		start = (ulong *)CFG_MEMTEST_START;
+		DECLARE_GLOBAL_DATA_PTR;
+
+		start = (ulong *)(gd->bd->bi_dram[0].start);
 	}
 
 	if (argc > 2) {
 		end = (ulong *)simple_strtoul(argv[2], NULL, 16);
 	} else {
-		end = (ulong *)(CFG_MEMTEST_END);
+		DECLARE_GLOBAL_DATA_PTR;
+
+		end = (ulong *)(start + gd->bd->bi_dram[0].size);
 	}
 
 	if (argc > 3) {
diff -Nurd u-boot-1.1.2/common/cmd_nvedit.c u-boot-1.1.2-oxe810/common/cmd_nvedit.c
--- u-boot-1.1.2/common/cmd_nvedit.c	2004-09-30 00:55:14.000000000 +0200
+++ u-boot-1.1.2-oxe810/common/cmd_nvedit.c	2008-06-11 17:55:30.000000000 +0200
@@ -55,8 +55,9 @@
     !defined(CFG_ENV_IS_IN_FLASH)	&& \
     !defined(CFG_ENV_IS_IN_DATAFLASH)	&& \
     !defined(CFG_ENV_IS_IN_NAND)	&& \
+    !defined(CFG_ENV_IS_IN_DISK)	&& \
     !defined(CFG_ENV_IS_NOWHERE)
-# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|NOWHERE}
+# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|DISK|NOWHERE}
 #endif
 
 #define XMK_STR(x)	#x
@@ -483,7 +484,7 @@
  * or NULL if not found
  */
 
-char *getenv (uchar *name)
+char *getenv (const uchar *name)
 {
 	int i, nxt;
 
@@ -530,7 +531,9 @@
 	return (-1);
 }
 
-#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) || \
+#if defined(CFG_ENV_IS_IN_NVRAM) || \
+    defined(CFG_ENV_IS_IN_EEPROM) || \
+    defined(CFG_ENV_IS_IN_DISK) || \
     ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == \
       (CFG_CMD_ENV|CFG_CMD_FLASH))
 int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
@@ -586,7 +589,9 @@
 	"    - delete environment variable 'name'\n"
 );
 
-#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) || \
+#if defined(CFG_ENV_IS_IN_NVRAM) || \
+    defined(CFG_ENV_IS_IN_EEPROM) || \
+    defined(CFG_ENV_IS_IN_DISK) || \
     ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == \
       (CFG_CMD_ENV|CFG_CMD_FLASH))
 U_BOOT_CMD(
diff -Nurd u-boot-1.1.2/common/env_common.c u-boot-1.1.2-oxe810/common/env_common.c
--- u-boot-1.1.2/common/env_common.c	2004-06-09 16:58:14.000000000 +0200
+++ u-boot-1.1.2-oxe810/common/env_common.c	2008-06-11 17:55:30.000000000 +0200
@@ -42,7 +42,7 @@
 	extern void disable_nvram(void);
 #endif
 
-#undef DEBUG_ENV
+//#undef DEBUG_ENV
 #ifdef DEBUG_ENV
 #define DEBUGF(fmt,args...) printf(fmt ,##args)
 #else
diff -Nurd u-boot-1.1.2/common/env_disk.c u-boot-1.1.2-oxe810/common/env_disk.c
--- u-boot-1.1.2/common/env_disk.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/common/env_disk.c	2008-06-11 17:55:30.000000000 +0200
@@ -0,0 +1,152 @@
+/*
+ * (C) Copyright 2006
+ * Oxford Semiconductor Ltd
+ *
+ * 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>
+
+#if defined(CFG_ENV_IS_IN_DISK)
+
+#include <command.h>
+#include <environment.h>
+#include <ide.h>
+
+extern int is_device_present(int device_number);
+
+/* Point to the environment as held in SRAM */
+env_t *env_ptr = NULL;
+
+char *env_name_spec = "Disk";
+
+/* The default environment compiled into U-Boot */
+extern uchar default_environment[];
+
+uchar env_get_char_spec(int index)
+{
+    DECLARE_GLOBAL_DATA_PTR;
+
+    return *((uchar *)(gd->env_addr + index));
+}
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+void env_relocate_spec(void)
+{
+    /* Compute the CRC of the environment in SRAM, copied from disk at boot */
+    env_t *sram_env = (env_t*)CFG_ENV_ADDR;
+    ulong  crc = crc32(0, sram_env->data, CFG_ENV_SIZE - offsetof(env_t, data));
+
+    /* Copy the SRAM environment and CRC to the working environment */
+    memcpy(env_ptr->data, sram_env->data, CFG_ENV_SIZE - offsetof(env_t, data));
+    env_ptr->crc = crc;
+}
+
+int saveenv(void)
+{
+    /* Compute the CRC of the working environment */
+    env_ptr->crc = crc32(0, env_ptr->data, CFG_ENV_SIZE - offsetof(env_t, data));
+
+    /* Copy the working environment to the reserved area on each disk device */
+    int status = 1;
+    int i;
+    for (i=0; i < CFG_IDE_MAXDEVICE; ++i) {
+        if (!is_device_present(i)) {
+            continue;
+        }
+
+		/* Write environment to the main environment area on disk */
+        unsigned long written = ide_write(i, CFG_ENV_DISK_SECTOR, CFG_ENV_SIZE/512, (ulong*)env_ptr);
+        if (written != CFG_ENV_SIZE/512) {
+			printf("Saving environment to disk %d primary image failed\n", i);
+            status = 0;
+        } else {
+			/* Write environment to the redundant environment area on disk */
+			written = ide_write(i, CFG_ENV_DISK_REDUNDANT_SECTOR, CFG_ENV_SIZE/512, (ulong*)env_ptr);
+			if (written != CFG_ENV_SIZE/512) {
+				printf("Saving environment to disk %d secondary image failed\n", i);
+				status = 0;
+			}
+		}
+    }
+
+    return status;
+}
+
+static int check_sram_env_integrity(void)
+{
+    DECLARE_GLOBAL_DATA_PTR;
+
+	env_t *sram_env = (env_t*)CFG_ENV_ADDR;
+	ulong crc = crc32(0, sram_env->data, CFG_ENV_SIZE - offsetof(env_t, data));
+
+	if (crc == sram_env->crc) {
+		gd->env_addr  = (ulong)sram_env->data;
+		gd->env_valid = 1;
+	}
+
+	return gd->env_valid;
+}
+
+int env_init(void)
+{
+    DECLARE_GLOBAL_DATA_PTR;
+
+	/* Have not yet found a valid environment */
+	gd->env_valid = 0;
+
+	/* Need SATA available to load environment from alternate disk locations */
+	ide_init();
+
+	int i;
+    for (i=0; i < CFG_IDE_MAXDEVICE; ++i) {
+        if (!is_device_present(i)) {
+            continue;
+        }
+
+		/* Read environment from the primary environment area on disk */
+        unsigned long read = ide_read(i, CFG_ENV_DISK_SECTOR, CFG_ENV_SIZE/512, (ulong*)CFG_ENV_ADDR);
+        if (read == CFG_ENV_SIZE/512) {
+			/* Check integrity of primary environment data */
+			if (check_sram_env_integrity()) {
+				printf("Environment successfully read from disk %d primary image\n", i);
+				break;
+			}
+        }
+
+		/* Read environment from the secondary environment area on disk */
+		read = ide_read(i, CFG_ENV_DISK_REDUNDANT_SECTOR, CFG_ENV_SIZE/512, (ulong*)CFG_ENV_ADDR);
+		if (read == CFG_ENV_SIZE/512) {
+			/* Check integrity of secondary environment data */
+			if (check_sram_env_integrity()) {
+				printf("Environment successfully read from disk %d secondary image\n", i);
+				break;
+			}
+		}
+	}
+
+	if (!gd->env_valid) {
+		printf("Failed to read valid environment from disk, using built-in default\n");
+        gd->env_addr  = (ulong)default_environment;
+        gd->env_valid = 0;
+	}
+
+    return 0;
+}
+#endif // CFG_ENV_IS_IN_DISK
diff -Nurd u-boot-1.1.2/common/main.c u-boot-1.1.2-oxe810/common/main.c
--- u-boot-1.1.2/common/main.c	2004-04-23 22:32:06.000000000 +0200
+++ u-boot-1.1.2-oxe810/common/main.c	2008-06-11 17:55:30.000000000 +0200
@@ -182,7 +182,7 @@
 			else {
 				for (i = 0; i < presskey_max - 1; i ++)
 					presskey [i] = presskey [i + 1];
-
+do_recovery
 				presskey [i] = getc();
 			}
 		}
@@ -369,6 +369,149 @@
 	install_auto_complete();
 #endif
 
+
+#if defined(CONFIG_OXNAS)
+	/* Set the memory size given to Linux */
+	{
+		DECLARE_GLOBAL_DATA_PTR;
+
+		/* Get a copy of the bootargs string from the runtime environment */
+		char tempBuf[1024];
+		char* cmd_string = strcpy(&tempBuf[0], getenv("bootargs"));
+
+		/* Find the extent of memory token in the bootargs string */
+		char* mem_token = strstr(cmd_string, "mem=");
+		char* mem_token_end = mem_token;
+		while ((*mem_token_end != ' ') &&
+			   (*mem_token_end != '\0')) {
+			++mem_token_end;
+		}
+
+		if ((*mem_token_end == '\0') && (mem_token != mem_token_end)) {
+			/* Memory token is last in bootargs string */
+			if (mem_token != cmd_string) {
+				/* Is not the only token, so erase token and previous space" */
+				*(mem_token-1) = '\0';
+			} else {
+				/* Is the only token, so no previous space to erase */
+				*mem_token = '\0';
+			}
+		} else {
+			/* Memory token is at intermediate location in bootargs string */
+			if (*mem_token_end == ' ') {
+				++mem_token_end;
+			}
+
+			/* Form the bootargs string without the memory token present */
+			strcpy(mem_token, mem_token_end);
+		}
+
+		/* How many MB of SDRAM are present */
+		int megabytes = gd->bd->bi_dram[0].size >> 20;
+
+		/* Append the memory token to the bootargs string */
+		switch (megabytes) {
+			case 64:
+				cmd_string = strcat(cmd_string, " mem=64M");
+				break;
+			case 128:
+				cmd_string = strcat(cmd_string, " mem=128M");
+				break;
+			case 256:
+				cmd_string = strcat(cmd_string, " mem=256M");
+				break;
+			default:
+				printf("Unsupported memory size, defaulting to 64M\n");
+				cmd_string = strcat(cmd_string, " mem=64M");
+		}
+
+		/* Save the revised bootargs string to the runtime environment */
+		setenv("bootargs", cmd_string);
+	}
+
+/* Upgrade, recovery and power button monitor code
+*/
+    int do_recovery = 0; /* default no recovery */
+
+    /* Read the upgrade flag from disk into memory */
+    ide_init();
+    run_command("ide read 48700000 ff 1", 0);
+
+    char upgrade_mode = *(volatile char*)0x48700000;
+    char recovery_mode = *(volatile char*)0x48700001;
+    char controlled_pd_mode = *(volatile char*)0x48700002;
+
+	if (recovery_mode == RECOVERY_MAGIC) {
+		do_recovery = 1; /* perform recovery */
+	} 
+
+	if (controlled_pd_mode == CONTROLLED_POWER_DOWN_MAGIC) {
+		/* System in controlled pwer down mode */
+
+		/* Read the SRAM location for normal boot flag */
+		char sram_data = *(volatile char*)(CFG_SRAM_BASE + CFG_SRAM_SIZE - POWER_ON_FLAG_SRAM_OFFSET);
+		char tempBuf[1024];
+		char* cmd_string = strcpy(&tempBuf[0], getenv("bootargs"));
+
+		if (sram_data == CONTROLLED_POWER_UP_MAGIC) {
+			/* The system has to remain in power down state */
+
+			/* Set appropriate boot args */
+			cmd_string = strcat(cmd_string, " powermode=controlledpup");
+			printf("Controlled Power UP requested\n");
+		} else {
+			/* The system is moving to power up state from power down state */
+			cmd_string = strcat(cmd_string, " powermode=controlledpdown");
+			printf("Controlled Power DOWN requested\n");
+		}
+		setenv("bootargs", cmd_string);
+	}
+
+    /* branch off inot recovery or upadate */
+    if (upgrade_mode == UPGRADE_MAGIC) {
+        /* Script to select first disk */
+        parse_string_outer("set select0 ide dev 0", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+
+        /* Script to select second disk */
+        parse_string_outer("set select1 ide dev 1", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+
+        /* Script for loading 256KB of upgrade rootfs image from hidden sectors */
+        parse_string_outer("set loadf ide read 48700000 1770 200", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+
+        /* Script for loading 2MB of upgrade kernel image from hidden sectors */
+        parse_string_outer("set loadk ide read 48800000 1970 1000", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+
+        /* Script to light failure LED */
+        parse_string_outer("set lightled ledfail 1", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+
+        /* Script to extinguish failure LED */
+        parse_string_outer("set extinguishled ledfail 0", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+
+        /* Script for booting Linux kernel image with mkimage-wrapped initrd */
+        parse_string_outer("set boot bootm 48800000 48700000", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+
+        /* Set Linux bootargs to use rootfs in initial ramdisk */
+        parse_string_outer("set bootargs mem=32M console=ttyS0,115200 root=/dev/ram0", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+
+        /* Validate, load and boot the first validate set of initrd and kernel 
+           Theres alot of combos here due to disk/backup/fk arrangments, it'll
+           no doubt work on the first or second one though. */
+        parse_string_outer("run          select0 loadf          loadk                boot || "
+                           "run lightled select1 loadf          loadk  extinguishled boot || "
+                           "run lightled select0 loadf  select1 loadk  extinguishled boot || "
+                           "run lightled select1 loadf  select0 loadk  extinguishled boot || "
+						    "run lightled ", FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+    } else if (do_recovery) {
+		printf ("\nRecovery mode selected\n");
+
+		char tempBuf[1024];
+		char* cmd_string = strcpy(&tempBuf[0], getenv("bootargs"));
+		cmd_string = strcat(cmd_string, " adminmode=recovery");
+		setenv("bootargs", cmd_string);
+    } 
+
+#endif // CONFIG_OXNAS
+
 #ifdef CONFIG_PREBOOT
 	if ((p = getenv ("preboot")) != NULL) {
 # ifdef CONFIG_AUTOBOOT_KEYED
diff -Nurd u-boot-1.1.2/common/Makefile u-boot-1.1.2-oxe810/common/Makefile
--- u-boot-1.1.2/common/Makefile	2004-12-16 18:35:57.000000000 +0100
+++ u-boot-1.1.2-oxe810/common/Makefile	2008-06-11 17:55:30.000000000 +0200
@@ -40,9 +40,10 @@
 	  cmd_nand.o cmd_net.o cmd_nvedit.o \
 	  cmd_pci.o cmd_pcmcia.o cmd_portio.o \
 	  cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o cmd_usb.o cmd_vfd.o \
+	  cmd_ledfail.o \
 	  command.o console.o devices.o dlmalloc.o docecc.o \
 	  environment.o env_common.o \
-	  env_nand.o env_dataflash.o env_flash.o env_eeprom.o env_nvram.o env_nowhere.o exports.o \
+	  env_nand.o env_dataflash.o env_flash.o env_eeprom.o env_nvram.o env_nowhere.o env_disk.o exports.o \
 	  flash.o fpga.o \
 	  hush.o kgdb.o lcd.o lists.o lynxkdi.o \
 	  memsize.o miiphybb.o miiphyutil.o \
diff -Nurd u-boot-1.1.2/cpu/arm926ejs/config.mk u-boot-1.1.2-oxe810/cpu/arm926ejs/config.mk
--- u-boot-1.1.2/cpu/arm926ejs/config.mk	2003-08-30 00:00:47.000000000 +0200
+++ u-boot-1.1.2-oxe810/cpu/arm926ejs/config.mk	2008-06-11 17:55:03.000000000 +0200
@@ -21,7 +21,6 @@
 # MA 02111-1307 USA
 #
 
-PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8 \
-	-mshort-load-bytes -msoft-float
+PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8
 
-PLATFORM_CPPFLAGS += -mapcs-32 -march=armv4
+PLATFORM_CPPFLAGS += -march=armv5te
diff -Nurd u-boot-1.1.2/cpu/arm926ejs/interrupts.c u-boot-1.1.2-oxe810/cpu/arm926ejs/interrupts.c
--- u-boot-1.1.2/cpu/arm926ejs/interrupts.c	2004-03-23 22:43:08.000000000 +0100
+++ u-boot-1.1.2-oxe810/cpu/arm926ejs/interrupts.c	2008-06-11 17:55:03.000000000 +0200
@@ -41,7 +41,12 @@
 #include <asm/proc-armv/ptrace.h>
 
 extern void reset_cpu(ulong addr);
+
+#ifdef CONFIG_OXNAS
+#define TIMER_LOAD_VAL 0xffffUL
+#else // CONFIG_OXNAS
 #define TIMER_LOAD_VAL 0xffffffff
+#endif // CONFIG_OXNAS
 
 /* macro to read the 32 bit timer */
 #ifdef CONFIG_OMAP
@@ -53,6 +58,9 @@
 #ifdef CONFIG_VERSATILE
 #define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+4))
 #endif
+#ifdef CONFIG_OXNAS
+#define READ_TIMER ((*(volatile ushort *)(CFG_TIMERBASE+4)) & 0xFFFFUL)  /* RPS timer value register has only 16 defined bits */
+#endif
 
 #ifdef CONFIG_USE_IRQ
 /* enable IRQ interrupts */
@@ -212,6 +220,16 @@
 	*(volatile ulong *)(CFG_TIMERBASE + 4) = CFG_TIMER_RELOAD;	/* TimerValue */
 	*(volatile ulong *)(CFG_TIMERBASE + 8) = 0x8C;
 #endif	/* CONFIG_VERSATILE */
+#ifdef CONFIG_OXNAS
+    // Setup timer 1 load value
+    *(volatile ulong*)(CFG_TIMERBASE + 0) = TIMER_LOAD_VAL;
+
+    // Setup timer 1 prescaler, periodic operation and start it
+    *(volatile ulong*)(CFG_TIMERBASE + 8) =
+        (TIMER_PRESCALE_ENUM << TIMER_PRESCALE_BIT) |
+        (TIMER_MODE_PERIODIC << TIMER_MODE_BIT) |
+        (TIMER_ENABLE_ENABLE << TIMER_ENABLE_BIT);
+#endif	/* CONFIG_OXNAS */
 
 	/* init the timestamp and lastdec value */
 	reset_timer_masked();
diff -Nurd u-boot-1.1.2/cpu/arm926ejs/start.S u-boot-1.1.2-oxe810/cpu/arm926ejs/start.S
--- u-boot-1.1.2/cpu/arm926ejs/start.S	2004-06-09 02:11:01.000000000 +0200
+++ u-boot-1.1.2-oxe810/cpu/arm926ejs/start.S	2008-06-11 17:55:03.000000000 +0200
@@ -94,6 +94,11 @@
 _TEXT_BASE:
 	.word	TEXT_BASE
 
+#ifdef CONFIG_OXNAS
+_EXCEPTION_BASE:
+	.word	EXCEPTION_BASE
+#endif
+
 .globl _armboot_start
 _armboot_start:
 	.word _start
@@ -135,6 +140,18 @@
 	orr	r0,r0,#0xd3
 	msr	cpsr,r0
 
+#ifdef CONFIG_OXNAS
+	/*
+	 * Copy exception table to relocated address in internal SRAM
+	 */
+	adr	r0, _start				/* Address of exception table in flash */
+	ldr	r1, _EXCEPTION_BASE		/* Relocated address of exception table */
+	ldmia	r0!, {r3-r10}		/* Copy exception table and jump values from */
+	stmia	r1!, {r3-r10}		/* FLASH to relocated address */
+	ldmia	r0!, {r3-r10}
+	stmia	r1!, {r3-r10}
+#endif
+
 	/*
 	 * we do sys-critical inits only at reboot,
 	 * not when booting from ram!
@@ -143,21 +160,21 @@
 	bl	cpu_init_crit
 #endif
 
-relocate:				/* relocate U-Boot to RAM	    */
-	adr	r0, _start		/* r0 <- current position of code   */
-	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
-	cmp     r0, r1                  /* don't reloc during debug         */
-	beq     stack_setup
+relocate:					/* relocate U-Boot to RAM */
+	adr	r0, _start			/* current position of code */
+	ldr	r1, _TEXT_BASE		/* relocated position of code */
+	cmp	r0, r1
+	beq	stack_setup
 
 	ldr	r2, _armboot_start
 	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot            */
-	add	r2, r0, r2		/* r2 <- source end address         */
+	sub	r2, r3, r2			/* r2 <- size of armboot */
+	add	r2, r0, r2			/* r2 <- source end address */
 
 copy_loop:
-	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
-	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
-	cmp	r0, r2			/* until source end addreee [r2]    */
+	ldmia	r0!, {r3-r10}	/* copy from source address [r0] */
+	stmia	r1!, {r3-r10}	/* copy to   target address [r1] */
+	cmp	r0, r2				/* until source end addreee [r2] */
 	ble	copy_loop
 
 	/* Set up the stack						    */
@@ -212,7 +229,7 @@
 	mrc	p15, 0, r0, c1, c0, 0
 	bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
 	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
-	orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
+	orr	r0, r0, #0x00000002	/* set bit 1 (A) Align */
 	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
 	mcr	p15, 0, r0, c1, c0, 0
 
@@ -391,6 +408,7 @@
 
 #endif
 
+#ifndef CONFIG_OXNAS
 	.align	5
 .globl reset_cpu
 reset_cpu:
@@ -405,3 +423,4 @@
 
 rstctl1:
 	.word	0xfffece10
+#endif // !CONFIG_OXNAS
diff -Nurd u-boot-1.1.2/drivers/cfi_flash.c u-boot-1.1.2-oxe810/drivers/cfi_flash.c
--- u-boot-1.1.2/drivers/cfi_flash.c	2004-12-18 23:35:45.000000000 +0100
+++ u-boot-1.1.2-oxe810/drivers/cfi_flash.c	2008-06-11 17:55:31.000000000 +0200
@@ -1056,7 +1056,11 @@
 			}
 			tmp = flash_read_long (info, 0,
 					       FLASH_OFFSET_ERASE_REGIONS +
+#ifdef FORCE_TOP_BOOT_FLASH
+					       (num_erase_regions - 1 - i) * 4);
+#else
 					       i * 4);
+#endif
 			erase_region_size =
 				(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
 			tmp >>= 16;
@@ -1104,6 +1108,7 @@
 	cfiptr_t ctladdr;
 	cfiptr_t cptr;
 	int flag;
+	ulong start;
 
 	ctladdr.cp = flash_make_addr (info, 0, 0);
 	cptr.cp = (uchar *) dest;
@@ -1151,6 +1156,15 @@
 		break;
 	case FLASH_CFI_16BIT:
 		cptr.wp[0] = cword.w;
+		/* Wait for write to complete */
+		start = get_timer (0);
+		while (cptr.wp[0] != cword.w) {
+			printf(".");
+			if (get_timer (start) > info->erase_blk_tout * CFG_HZ) {
+				printf ("Flash write timeout!");;
+			}
+		}
+		printf("\n");
 		break;
 	case FLASH_CFI_32BIT:
 		cptr.lp[0] = cword.l;
diff -Nurd u-boot-1.1.2/drivers/ns16550.c u-boot-1.1.2-oxe810/drivers/ns16550.c
--- u-boot-1.1.2/drivers/ns16550.c	2004-06-07 01:13:57.000000000 +0200
+++ u-boot-1.1.2-oxe810/drivers/ns16550.c	2008-06-11 17:55:31.000000000 +0200
@@ -14,8 +14,25 @@
 #define MCRVAL (MCR_DTR | MCR_RTS)			/* RTS/DTR */
 #define FCRVAL (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR)	/* Clear & enable FIFOs */
 
+#ifdef USE_UART_FRACTIONAL_DIVIDER
+static int oxnas_fractional_divider(NS16550_t com_port, int baud_divisor)
+{
+	// Baud rate is passed around x16
+	int real_divisor = baud_divisor >> 4;
+	// Top three bits of 8-bit dlf register hold the number of eigths
+	// for the fractional part of the divide ratio
+	com_port->dlf = (unsigned char)(((baud_divisor - (real_divisor << 4)) << 4) & 0xFF);
+	// Return the x1 divider for the normal divider register
+	return real_divisor;
+}
+#endif // USE_UART_FRACTIONAL_DIVIDER
+
 void NS16550_init (NS16550_t com_port, int baud_divisor)
 {
+#ifdef USE_UART_FRACTIONAL_DIVIDER
+	baud_divisor = oxnas_fractional_divider(com_port, baud_divisor);
+#endif // USE_UART_FRACTIONAL_DIVIDER
+
 	com_port->ier = 0x00;
 #ifdef CONFIG_OMAP1510
 	com_port->mdr1 = 0x7;	/* mode select reset TL16C750*/
@@ -33,6 +50,10 @@
 
 void NS16550_reinit (NS16550_t com_port, int baud_divisor)
 {
+#ifdef USE_UART_FRACTIONAL_DIVIDER
+	baud_divisor = oxnas_fractional_divider(com_port, baud_divisor);
+#endif // USE_UART_FRACTIONAL_DIVIDER
+
 	com_port->ier = 0x00;
 	com_port->lcr = LCR_BKSE;
 	com_port->dll = baud_divisor & 0xff;
diff -Nurd u-boot-1.1.2/drivers/serial.c u-boot-1.1.2-oxe810/drivers/serial.c
--- u-boot-1.1.2/drivers/serial.c	2003-08-30 00:00:47.000000000 +0200
+++ u-boot-1.1.2-oxe810/drivers/serial.c	2008-06-11 17:55:31.000000000 +0200
@@ -59,7 +59,13 @@
 		return (26);		/* return 26 for base divisor */
 	}
 #endif
-	return (CFG_NS16550_CLK / 16 / gd->baudrate);
+
+#ifdef USE_UART_FRACTIONAL_DIVIDER
+	return (((CFG_NS16550_CLK << 4) / gd->baudrate) + 8) >> 4;	
+#endif // USE_UART_FRACTIONAL_DIVIDER
+
+    // Round to nearest integer
+    return (((CFG_NS16550_CLK / gd->baudrate) + 8 ) / 16);
 }
 
 int serial_init (void)
diff -Nurd u-boot-1.1.2/examples/Makefile u-boot-1.1.2-oxe810/examples/Makefile
--- u-boot-1.1.2/examples/Makefile	2004-10-10 23:27:33.000000000 +0200
+++ u-boot-1.1.2-oxe810/examples/Makefile	2008-06-11 17:55:30.000000000 +0200
@@ -30,7 +30,8 @@
 endif
 
 ifeq ($(ARCH),arm)
-LOAD_ADDR = 0xc100000
+#LOAD_ADDR = 0xc100000
+LOAD_ADDR = 0x4C004000
 endif
 
 ifeq ($(ARCH),mips)
@@ -58,6 +59,11 @@
 SREC	= hello_world.srec
 BIN	= hello_world.bin hello_world
 
+ifeq ($(ARCH),arm)
+SREC   += mem_test.srec
+BIN    += mem_test.bin mem_test
+endif
+
 ifeq ($(ARCH),i386)
 SREC   += 82559_eeprom.srec
 BIN    += 82559_eeprom.bin 82559_eeprom
@@ -115,10 +121,10 @@
 	$(LD) -g $(EX_LDFLAGS) -Ttext $(LOAD_ADDR) \
 		-o $@ -e $(<:.o=) $< $(LIB) \
 		-L$(gcclibdir) -lgcc
-%.srec:	%
+%.srec:	%.o
 	$(OBJCOPY) -O srec $< $@ 2>/dev/null
 
-%.bin:	%
+%.bin:	%.o
 	$(OBJCOPY) -O binary $< $@ 2>/dev/null
 
 #########################################################################
diff -Nurd u-boot-1.1.2/examples/mem_test.c u-boot-1.1.2-oxe810/examples/mem_test.c
--- u-boot-1.1.2/examples/mem_test.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/examples/mem_test.c	2008-06-11 17:55:30.000000000 +0200
@@ -0,0 +1,1322 @@
+/*
+ * (C) Copyright 2006
+ * Oxford Semiconductor Ltd, www.oxsemi.com
+ * 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
+ */
+
+/********************* OPTIONS ********************************************************/
+
+#define ARM
+/*
+#define QUIET
+#define SHORT
+*/
+
+/********************* TEST DEFINITIONS ********************************************************/
+
+
+#define NUM_PATTYPES 5
+#define PATTYPE_A5     0
+#define PATTYPE_5A     1
+#define PATTYPE_NO_FF  2
+#define PATTYPE_INCR   3
+#define PATTYPE_DECR   4
+
+/* Number of words in a block (to ensure that neither data not ~data is 0xFFxx) */
+
+#ifdef SHORT
+    #define BLOCKWORDS (254*4)
+    #define BLOCKSIZE  (256*4)
+#else
+    #define BLOCKWORDS (254*256*4)
+    #define BLOCKSIZE  (256*256*4)
+#endif
+
+#ifdef ARM
+    #include <common.h>
+    #include <exports.h>
+
+    #define SDRAM_BASE  0x48000000
+    #define SDRAM_TOP   0x49000000
+    #define SDRAM_BLOCK 0x10000
+//    #define SDRAM_WRITE(ADDR, DATA) printf("Write 0x%08x to 0x%08x\n", (DATA), (ADDR));
+//    #define SDRAM_READ(ADDR, VAR) printf("Read from 0x%08x\n", (ADDR));
+//    #define SDRAM_WRITE(ADDR, DATA) printf("Write 0x%08x to 0x%08x\n", (DATA), (ADDR)); (*((volatile unsigned int *)(ADDR)) = (DATA))
+//    #define SDRAM_READ(ADDR, VAR)  printf("Read from 0x%08x\n", (ADDR)); (*(VAR) = *((volatile unsigned int *)(ADDR)))
+    #define SDRAM_WRITE(ADDR, DATA) (*((volatile unsigned int *)(ADDR)) = (DATA))
+    #define SDRAM_READ(ADDR, VAR)  (*(VAR) = *((volatile unsigned int *)(ADDR)))
+#else
+    #include <stdio.h>
+    #include <stdlib.h>
+    /* Not so much space - just 2 blocks from addr 0... */
+    #define SDRAM_BASE  0
+    #define SDRAM_TOP   (2 * BLOCKSIZE)
+    #define SDRAM_BLOCK 0x10000
+    #ifdef QUIET
+        #define SDRAM_WRITE(ADDR, DATA)      array[ADDR] = (DATA)
+        #define SDRAM_READ(ADDR, VAR)        *((volatile unsigned int *)(VAR)) = array[ADDR]
+    #else
+        #define SDRAM_WRITE(ADDR, DATA)      printf("WRITE(%08x)=%08x\n", ADDR, DATA); array[ADDR] = (DATA)
+        #define SDRAM_READ(ADDR, VAR)        printf("READ (%08x)=%08x\n", ADDR, array[ADDR]); *((volatile unsigned int *)(VAR)) = array[ADDR]
+    #endif
+    unsigned volatile int array[SDRAM_TOP];
+#endif
+
+
+#define SYSCTRL_PRIMSEL_LO      0x4500000C
+#define SYSCTRL_SECSEL_LO       0x45000014
+#define SYSCTRL_TERSEL_LO       0x4500008C
+#define SYSCTRL_PRIMSEL_HI      0x45000010
+#define SYSCTRL_SECSEL_HI       0x45000018
+#define SYSCTRL_TERSEL_HI       0x45000090
+
+/* GPIO */
+#define GPIOB_IO_VAL       0x44100000
+#define GPIOB_OE_VAL       0x44100004
+#define GPIOB_SET_OE       0x4410001C
+#define GPIOB_CLEAR_OE     0x44100020
+#define GPIOB_OUTPUT_VAL   0x44100010
+#define GPIOB_SET_OUTPUT   0x44100014
+#define GPIOB_CLEAR_OUTPUT 0x44100018
+#define GPIOB_BIT_34       0x00000004
+
+void configure_caches(void);
+void report_err(unsigned int address, unsigned int bad_data, unsigned int correct_data, unsigned int iteration);
+
+/********************* TYPES.H ********************************************************/
+
+typedef unsigned int    UINT,  *PUINT;
+/*
+#ifndef __MY_BASIC_TYPES_H
+#define __MY_BASIC_TYPES_H
+
+typedef signed char     CHAR,  *PCHAR;
+typedef unsigned char   BYTE,   UCHAR,  *PBYTE, *PUCHAR;
+typedef signed short    SHORT, *PSHORT;
+typedef unsigned short  WORD,   USHORT, *PWORD, *PUSHORT;
+typedef signed long     LONG,  *PLONG;
+typedef unsigned long   DWORD, *PDWORD;
+typedef int             BOOL,  *PBOOL;
+typedef unsigned int    UINT,  *PUINT;
+typedef void            VOID,  *PVOID;
+
+typedef float           SINGLE,*PSINGLE;
+typedef double          DOUBLE,*PDOUBLE;
+
+
+#define FALSE 0
+#define TRUE  1
+
+#endif
+*/
+
+/********************* CHIP.H ********************************************************/
+
+// Address Map
+#define BOOT_ROM_BASE       0x00000000
+#define USBHS_BASE          0x00200000
+#define GMAC_BASE           0x00400000
+#define PCI_BASE            0x00600000
+#define PCI_DATA_BASE       0x00800000
+#define STATIC0_BASE        0x01000000
+#define STATIC1_BASE        0x01400000
+#define STATIC2_BASE        0x01800000
+#define STATIC_BASE         0x01C00000
+#define SATA_DATA_BASE      0x02000000
+#define DPE_DATA_BASE       0x03000000
+#define GPIOA_BASE          0x04000000
+#define GPIOB_BASE          0x04100000
+#define UARTA_BASE          0x04200000
+#define UARTB_BASE          0x04300000
+#define I2C_MASTER_BASE     0x04400000
+#define AUDIO_BASE          0x04500000
+#define FAN_BASE            0x04600000
+#define PWM_BASE            0x04700000
+#define IR_RX_BASE          0x04800000
+#define UARTC_BASE          0x04900000
+#define UARTD_BASE          0x04A00000
+#define SYS_CTRL_BASE       0x05000000
+#define RPSA_BASE           0x05300000
+#define  ARM_RPS_BASE  RPSA_BASE 
+#define RPSC_BASE           0x05400000
+#define AHB_MON_BASE        0x05500000
+#define DMA_BASE            0x05600000
+#define DPE_BASE            0x05700000
+#define IBIW_BASE           0x05780000
+#define DDR_BASE            0x05800000
+#define SATA0_BASE          0x05900000
+#define SATA1_BASE          0x05980000
+#define DMA_CHKSUM_BASE     0x05A00000
+#define COPRO_BASE          0x05B00000
+#define SGDMA_BASE          0x05C00000
+#define DDR_DATA_BASE       0x08000000
+#define SRAM_BASE           0x0C000000
+#define SRAM0_BASE          0x0C000000
+#define SRAM1_BASE          0x0C002000
+#define SRAM2_BASE          0x0C004000
+#define SRAM3_BASE          0x0C006000
+
+// Virtual peripheral for TB sync
+#define TB_SYNC_BASE        0x05F00100
+
+
+/********************* DMA.H ********************************************************/
+
+
+// DMA Control register settings
+
+#define DMA_FAIR_SHARE                  (1<<0)
+#define DMA_IN_PROGRESS                 (1<<1)
+
+#define DMA_SDREQ_SATA                  (0<<2)
+#define DMA_SDREQ_DPE_OUT               (2<<2)
+#define DMA_SDREQ_UARTA_RX              (4<<2)
+#define DMA_SDREQ_AUDIO_RX              (6<<2)
+#define DMA_SDREQ_MEM                   (0xF<<2)
+
+#define DMA_DDREQ_SATA                  (0<<6)
+#define DMA_DDREQ_DPE_IN                (1<<6)
+#define DMA_DDREQ_UARTA_TX              (3<<6)
+#define DMA_DDREQ_AUDIO_TX              (5<<6)
+#define DMA_DDREQ_MEM                   (0xF<<6)
+
+#define DMA_INTERRUPT                   (1 << 10)
+#define DMA_NEXT_FREE                   (1 << 11)
+#define DMA_CH_RESET                    (1 << 12)
+
+#define DMA_DIR_ATOA                    (0 << 13)
+#define DMA_DIR_BTOA                    (1 << 13)
+#define DMA_DIR_ATOB                    (2 << 13)
+#define DMA_DIR_BTOB                    (3 << 13)
+
+#define DMA_BURST_A                     (1 << 17)
+#define DMA_BURST_B                     (1 << 18)
+
+#define DMA_SWIDTH_8                    (0 << 19)
+#define DMA_SWIDTH_16                   (1 << 19)
+#define DMA_SWIDTH_32                   (2 << 19)
+
+#define DMA_DWIDTH_8                    (0 << 22)
+#define DMA_DWIDTH_16                   (1 << 22)
+#define DMA_DWIDTH_32                   (2 << 22)
+
+#define DMA_PAUSE                       (1 << 25)
+#define DMA_INT_ENABLE                  (1 << 26)
+#define DMA_STARVE_LO_PRIORITY          (1 << 29)
+#define DMA_NEW_INT_CLEAR               (1 << 30)
+
+#define DMA_FIXED_SADDR                 ((0 << 15) | (1 << 27))
+#define DMA_INCR_SADDR                  ((1 << 15) | (0 << 27))
+#define DMA_SEMI_FIXED_SADDR            ((0 << 15) | (0 << 27))
+
+#define DMA_FIXED_DADDR                 ((0 << 16) | (1 << 28))
+#define DMA_INCR_DADDR                  ((1 << 16) | (0 << 28))
+#define DMA_SEMI_FIXED_DADDR            ((0 << 16) | (0 << 28))
+
+#define DMA_BASE_CTRL                   (DMA_BURST_A | DMA_BURST_B | DMA_INT_ENABLE | DMA_NEW_INT_CLEAR)
+
+// Common base setups
+
+#define DMA_CTRL_A32TOA32               ( DMA_BASE_CTRL | DMA_DIR_ATOA | DMA_SWIDTH_32 | DMA_DWIDTH_32 )
+#define DMA_CTRL_B32TOA32               ( DMA_BASE_CTRL | DMA_DIR_BTOA | DMA_SWIDTH_32 | DMA_DWIDTH_32 )
+#define DMA_CTRL_A32TOB32               ( DMA_BASE_CTRL | DMA_DIR_ATOB | DMA_SWIDTH_32 | DMA_DWIDTH_32 )
+#define DMA_CTRL_B32TOB32               ( DMA_BASE_CTRL | DMA_DIR_BTOB | DMA_SWIDTH_32 | DMA_DWIDTH_32 )
+
+#define DMA_CTRL_A8TOB32                ( DMA_BASE_CTRL | DMA_DIR_ATOB | DMA_SWIDTH_8  | DMA_DWIDTH_32 )
+#define DMA_CTRL_B32TOA8                ( DMA_BASE_CTRL | DMA_DIR_BTOA | DMA_SWIDTH_32 | DMA_DWIDTH_8  )
+#define DMA_CTRL_A32TOB8                ( DMA_BASE_CTRL | DMA_DIR_ATOB | DMA_SWIDTH_32 | DMA_DWIDTH_8  )
+
+// Most likely transactions
+
+#define DMA_CTRL_MEM_TO_MEM_AA          ( DMA_CTRL_A32TOA32 | DMA_SDREQ_MEM      | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_MEM_AB          ( DMA_CTRL_A32TOB32 | DMA_SDREQ_MEM      | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_MEM_BB          ( DMA_CTRL_B32TOB32 | DMA_SDREQ_MEM      | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_MEM_BA          ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM      | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_MEM             ( DMA_CTRL_MEM_TO_MEM_AB ) 
+
+//DMA A-A
+#define DMA_CTRL_SATA_TO_MEM_AA         ( DMA_CTRL_A32TOA32 | DMA_SDREQ_SATA     | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_SATA_AA         ( DMA_CTRL_A32TOA32 | DMA_SDREQ_MEM      | DMA_DDREQ_SATA     | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+
+#define DMA_CTRL_SATA_TO_MEM            ( DMA_CTRL_A32TOB32 | DMA_SDREQ_SATA     | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_SATA            ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM      | DMA_DDREQ_SATA     | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_SATA_TO_DPE            ( DMA_CTRL_A32TOA32 | DMA_SDREQ_SATA     | DMA_DDREQ_DPE_IN   | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_DPE_TO_SATA            ( DMA_CTRL_A32TOA32 | DMA_SDREQ_DPE_OUT  | DMA_DDREQ_SATA     | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_DPE             ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM      | DMA_DDREQ_DPE_IN   | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_DPE_TO_MEM             ( DMA_CTRL_A32TOB32 | DMA_SDREQ_DPE_OUT  | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_PCI_TO_MEM             ( DMA_CTRL_A32TOB32 | DMA_SDREQ_MEM      | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+
+#define DMA_CTRL_MEM_TO_PCI             ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM      | DMA_DDREQ_MEM      | DMA_INCR_SADDR       | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_AUDIO           ( DMA_CTRL_B32TOA32 | DMA_SDREQ_MEM      | DMA_DDREQ_AUDIO_TX | DMA_INCR_SADDR       | DMA_FIXED_DADDR )
+#define DMA_CTRL_AUDIO_TO_MEM           ( DMA_CTRL_A32TOB32 | DMA_SDREQ_AUDIO_RX | DMA_DDREQ_MEM      | DMA_FIXED_SADDR      | DMA_INCR_DADDR )
+#define DMA_CTRL_MEM_TO_UART            ( DMA_CTRL_B32TOA8  | DMA_SDREQ_MEM      | DMA_DDREQ_UARTA_TX | DMA_INCR_SADDR       | DMA_FIXED_DADDR )
+#define DMA_CTRL_UART_TO_MEM            ( DMA_CTRL_A8TOB32  | DMA_SDREQ_UARTA_RX | DMA_DDREQ_MEM      | DMA_FIXED_SADDR      | DMA_INCR_DADDR )
+
+// Byte count register flags
+
+#define DMA_HBURST_EN                   (1<<28)
+#define DMA_WR_BUFFERABLE               (1<<29)
+#define DMA_WR_EOT                      (1<<30)
+#define DMA_RD_EOT                      (1<<31)
+
+
+// Pause the DMA channel specified
+void PauseDMA( UINT channel );
+
+// UnPause the DMA channel specified
+void UnPauseDMA( UINT channel );
+
+// Configure a DMA
+void SetupDMA( UINT channel,
+               UINT src_addr,
+               UINT dest_addr,
+               UINT byte_count,
+               UINT control,
+               UINT flags );
+
+// Wait while the given DMA channel is busy
+void WaitWhileDMABusy( UINT channel );
+
+// Perform a memory to memory copy
+void DMAMemCopy ( UINT channel,
+                  UINT src_addr,
+                  UINT dest_addr,
+                  UINT byte_count );
+
+
+/****************************** MAIN ***********************************************/
+#ifdef ARM
+int mem_test(int argc, char* argv[])
+#else
+int main(int argc, char* argv[])
+#endif
+{
+    unsigned int i;
+    unsigned int iteration;
+    unsigned int block_base;
+    unsigned int datapattern;
+    unsigned int correct_data;
+    unsigned volatile int read_data;
+    unsigned int pattype, starting_pattype;
+    unsigned int end_addr;
+    unsigned int row, col, bank;
+
+#ifdef ARM
+    /* Print the ABI version */
+    app_startup(argv);
+    printf ("Example expects ABI version %d\n", XF_VERSION);
+    printf ("Actual U-Boot ABI version %d\n", (int)get_version());
+
+    printf("GPIO34 is output, low\n");
+    * (volatile unsigned int *) GPIOB_CLEAR_OUTPUT = GPIOB_BIT_34;
+    * (volatile unsigned int *) GPIOB_SET_OE       = GPIOB_BIT_34;
+#endif
+
+//    configure_caches();
+//printf("Caches enabled\n");
+
+    /* ******************************************************************* */
+    printf("DMA TEST.\n" );
+    /* ******************************************************************* */
+
+
+    #define DMA0_CTRL_STAT    0x45A00000
+    #define DMA0_SRC_BASE     0x45A00004
+    #define DMA0_DEST_BASE    0x45A00008
+    #define DMA0_BYTE_COUNT   0x45A0000C
+    #define DMA0_CURRENT_BYTE 0x45A00018
+
+    printf("Test to top of 1st SDRAM" );
+    #define BLOCK_BYTES 0x20000
+    #define SDRAM_STOP SDRAM_TOP
+
+    for (iteration=0; 1; iteration++) {
+
+        if ((iteration % 5)==0)
+            printf("Iteration %d\n", iteration );
+
+//        printf("Write pattern into first block.\n" );
+        end_addr = SDRAM_BASE + BLOCK_BYTES;
+        for (i=SDRAM_BASE; i < end_addr; i=i+4) {
+            SDRAM_WRITE( i, i);
+        }
+
+//        printf("Clear last block and a few blocks more - easy to see on LA.\n" );
+        end_addr = SDRAM_BASE + (BLOCK_BYTES << 3);
+        for (i=SDRAM_STOP - BLOCK_BYTES; i < end_addr; i=i+4) {
+            SDRAM_WRITE( i, 0);
+        }
+
+        end_addr = SDRAM_STOP - BLOCK_BYTES;
+        for (i=SDRAM_BASE; i < end_addr; i=i+BLOCK_BYTES) {
+
+//            printf("DMA transfer from %08x to %08x.\n", i, i + BLOCK_BYTES );
+#ifdef ARM
+            DMAMemCopy ( 0, i, i + BLOCK_BYTES, BLOCK_BYTES );
+#endif
+//            printf("...pending.\n" );
+#ifdef ARM
+            WaitWhileDMABusy( 0 );
+#endif
+//            printf("...complete.\n" );
+        }
+
+//        printf("Verify pattern in last block.\n" );
+        end_addr = SDRAM_STOP;
+        correct_data = SDRAM_BASE;
+        for (i=SDRAM_STOP - BLOCK_BYTES; i < end_addr; i=i+4) {
+            SDRAM_READ( i, &read_data);
+            if (read_data != correct_data)
+            {
+            /* Expand out the report_err function to avoid the stack operations. */
+            #ifdef ARM
+                /* ASSERT GPIO */
+                * (volatile unsigned int *) GPIOB_SET_OUTPUT = GPIOB_BIT_34;
+            #endif
+
+                /* REPORT ERROR */
+                printf("Wrong on [%08x]= %08x should be %08x on iteration %d\n", i, read_data, correct_data, iteration );
+
+                /* WRITE TO ANOTHER LOCATION */
+                SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
+
+                /* READ AGAIN */
+                SDRAM_READ(i, &read_data);
+                if (read_data != correct_data)
+                    printf("Again 1  [%08x]= %08x should be %08x\n", i, read_data, correct_data );
+
+                /* WRITE TO ANOTHER LOCATION */
+                SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
+
+                /* READ AGAIN */
+                SDRAM_READ(i, &read_data);
+                if (read_data != correct_data)
+                    printf("Again 2  [%08x]= %08x should be %08x\n", i, read_data, correct_data );
+
+                /* WRITE TO ANOTHER LOCATION */
+                SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
+
+                /* READ AGAIN */
+                SDRAM_READ(i, &read_data);
+                if (read_data != correct_data)
+                    printf("Again 3  [%08x]= %08x should be %08x\n", i, read_data, correct_data );
+
+                row = (((i >> 26) & 0x1) << 13) | (((i >> 23) & 0x3) << 11) | ((i >> 10) & 0x7FF); /* [26], [24:23], [20:10]*/
+                col = (((i >> 27) & 0x1) << 10) | (((i >> 25) & 0x1) << 9) | (((i >> 22) & 0x1) << 8); /* [27], [25], [22]... */
+                col |= (((i >> 6) & 0xF) << 4) | (((i >> 21) & 0x1) << 3) | (((i >> 1) & 0x3) << 1); /* ...[9:8], [21], [3:2], '0' */
+                col |= 0x800; /* bit 11 set for auto-precharge */
+                bank = (i >> 4) & 0x3; /* [5:4] */
+                printf("Bank   %08x\n", bank );
+                printf("Row    %08x\n", row );
+                printf("Column %08x\n", col );
+            #ifdef ARM
+                /* DEASSERT GPIO */
+                * (volatile unsigned int *) GPIOB_CLEAR_OUTPUT = GPIOB_BIT_34;
+            #endif
+            }
+
+
+            correct_data += 4;
+        }
+    }
+
+
+    /* ******************************************************************* */
+    printf("MEM_TEST2\n");
+    /* ******************************************************************* */
+
+
+    pattype=0;
+    iteration=0;
+
+    for (;;) { 
+        /* FOR EACH 64Kword==256KB BLOCK IN 16Mword=64MB (2 OFF 16M16) MEMORY... */
+
+#ifdef SHORT
+        if ((iteration % 5)==0)
+            printf("Iteration %d\n", iteration );
+#else
+        if ((iteration % 1000)==0)
+            printf("Iteration %d\n", iteration );
+#endif
+
+        /* WRITE DATA BLOCKS */
+        starting_pattype = pattype; /* Record for later */
+
+        for (block_base=SDRAM_BASE; block_base < SDRAM_TOP; block_base=block_base + BLOCKSIZE) {
+	    switch (pattype) {
+	    case PATTYPE_A5 :
+                /* Write alternating 1s and 0s... */
+                end_addr = block_base + BLOCKWORDS;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_WRITE( i, 0xaa55aa55);
+                }
+                break;
+	    case PATTYPE_5A :
+                /* Write alternating 1s and 0s (inverse of above)... */
+                end_addr = block_base + BLOCKWORDS;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_WRITE( i, 0x55aa55aa);
+                }
+                break;
+	    case PATTYPE_NO_FF : 
+                /* Write data=address with bit[n+16]=~bit[n]... */
+                datapattern = 0x0100FEFF;
+                /* In range 0x0100...0xFEFF so that
+                    a. temp[15:8] is never 0xFF
+                    b. Inverse of temp[15:8] is never 0xFF
+                */
+                end_addr = block_base + BLOCKWORDS;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_WRITE( i, datapattern);
+                    datapattern = datapattern + 0xFFFF;
+                }
+                break;
+	    case PATTYPE_INCR : 
+                /* Write data=address... */
+                end_addr = block_base + BLOCKSIZE;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_WRITE( i, i);
+                }
+                break;
+	    case PATTYPE_DECR : 
+                /* Write data=~address... */
+                end_addr = block_base + BLOCKSIZE;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_WRITE( i, ~i);
+                }
+                break;
+            }
+        }
+
+        /* VERIFY DATA BLOCKS */
+        pattype = starting_pattype; /* Reset to same as for writes */
+
+        for (block_base=SDRAM_BASE; block_base < SDRAM_TOP; block_base=block_base + BLOCKSIZE) {
+	    switch (pattype) {
+	    case PATTYPE_A5 :
+                correct_data = 0xaa55aa55;
+                end_addr = block_base + BLOCKWORDS;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_READ( i, &read_data);
+                    if (read_data != correct_data)
+                        report_err(i, read_data, correct_data, iteration);
+                }
+                break;
+	    case PATTYPE_5A :
+                correct_data = 0x55aa55aa;
+                end_addr = block_base + BLOCKWORDS;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_READ( i, &read_data);
+                    if (read_data != correct_data)
+                        report_err(i, read_data, correct_data, iteration);
+                }
+                break;
+	    case PATTYPE_NO_FF :
+                correct_data = 0x0100FEFF;
+                end_addr = block_base + BLOCKWORDS;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_READ( i, &read_data);
+                    if (read_data != correct_data)
+                        report_err(i, read_data, correct_data, iteration);
+                    correct_data = correct_data + 0xFFFF;
+                }
+                break;
+	    case PATTYPE_INCR :
+                end_addr = block_base + BLOCKSIZE;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_READ( i, &read_data);
+                    if (read_data != i)
+                        report_err(i, read_data, i, iteration);
+                }
+                break;
+	    case PATTYPE_DECR :
+                end_addr = block_base + BLOCKSIZE;
+                for (i=block_base; i < end_addr; i=i+4) {
+                    SDRAM_READ( i, &read_data);
+                    if (read_data != ~i)
+                        report_err(i, read_data, ~i, iteration);
+                }
+                break;
+            }
+        }
+
+	pattype = pattype + 1;
+	if (pattype >= NUM_PATTYPES) { pattype = 0; }
+        ++iteration;
+    }
+
+    return 0;
+}
+
+/********************* REPORT ERROR FUNC ********************************************************/
+
+void report_err(unsigned int address, unsigned int bad_data, unsigned int correct_data, unsigned int iteration)
+{
+    volatile unsigned int readvalue;
+
+#ifdef ARM
+    /* ASSERT GPIO */
+    * (volatile unsigned int *) GPIOB_SET_OUTPUT = GPIOB_BIT_34;
+#endif
+
+    /* REPORT ERROR */
+    printf("Wrong on [%08x]= %08x should be %08x on iteration %d\n", address, bad_data, correct_data, iteration );
+
+    /* WRITE TO ANOTHER LOCATION */
+    SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
+
+    /* READ AGAIN */
+    SDRAM_READ(address, &readvalue);
+    if (readvalue != correct_data)
+        printf("Again 1  [%08x]= %08x should be %08x\n", address, readvalue, correct_data );
+
+    /* WRITE TO ANOTHER LOCATION */
+    SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
+
+    /* READ AGAIN */
+    SDRAM_READ(address, &readvalue);
+    if (readvalue != correct_data)
+        printf("Again 2  [%08x]= %08x should be %08x\n", address, readvalue, correct_data );
+
+    /* WRITE TO ANOTHER LOCATION */
+    SDRAM_WRITE(SDRAM_BASE, 0xFFFFFFFF);
+
+    /* READ AGAIN */
+    SDRAM_READ(address, &readvalue);
+    if (readvalue != correct_data)
+        printf("Again 3  [%08x]= %08x should be %08x\n", address, readvalue, correct_data );
+
+#ifdef ARM
+    /* DEASSERT GPIO */
+    * (volatile unsigned int *) GPIOB_CLEAR_OUTPUT = GPIOB_BIT_34;
+#endif
+
+} /* end of report_err */
+
+
+
+
+/********************* DMA.C FUNCTIONS ********************************************************/
+
+void ResetDMA( UINT channel ) {
+    
+    // Clear and abort the dma channel
+    
+    volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
+    dma[0] =  (1 << 12);
+    dma[0] &=  ~(1 << 12);
+}
+
+
+
+
+void PauseDMA( UINT channel ) {
+    
+    // Pause the DMA channel specified
+    
+    volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
+    UINT  rd;
+    
+    rd = dma[0];
+    
+    rd |= DMA_PAUSE;
+    
+    dma[0] = rd;
+}
+
+
+
+
+void UnPauseDMA( UINT channel ) {
+    
+    // UnPause the DMA channel specified
+    
+    volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
+    UINT  rd;
+    
+    rd = dma[0];
+    
+    rd &= ~DMA_PAUSE;
+    
+    dma[0] = rd;
+}
+
+
+
+
+void SetupDMA( UINT channel,
+               UINT src_addr,
+               UINT dest_addr,
+               UINT byte_count,
+               UINT control,
+               UINT flags ) {
+
+    // Configure a DMA
+    
+    volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
+    
+    dma[0] = control;
+    dma[1] = src_addr;
+    dma[2] = dest_addr;
+    dma[3] = byte_count | (flags & 0xF0000000);
+}
+
+// EXAMPLE:
+//
+// DMA 2kB from SRAM to SATA core with a write EOT set, and HBURST enabled, using DMA channel 2
+// Then wait for the DMA to complete
+//
+//   SetupDMA ( 2 , 0x4C001100, BASE_SATA, 2048, DMA_CTRL_MEM_TO_SATA, WR_EOT | DMA_HBURST_EN );
+//   WaitWhileDMABusy( 2 );
+
+int DMABusy(UINT channel)
+{
+    volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
+    return (dma[0] & DMA_IN_PROGRESS ? 1 : 0);
+}
+
+
+void WaitWhileDMABusy( UINT channel ) // Wait while the given DMA channel is busy
+{
+    volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
+    while (dma[0] & DMA_IN_PROGRESS) ; // Do Nothing
+}
+
+void DMAClearIRQ(UINT channel) 
+{
+    volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
+    dma[4] = 1; // write any value to offset 0x10 (16 / 4 => 4) 
+
+}
+
+void DMAMemCopy ( UINT channel,
+                  UINT src_addr,
+                  UINT dest_addr,
+                  UINT byte_count ) {
+    
+    // Perform a memory to memory copy
+    
+    volatile PUINT dma = (PUINT) (DMA_BASE + (channel << 5));
+    
+    // Choose fastest configuration possible for required transfer
+    
+    if (src_addr < SRAM_BASE) {
+        if (dest_addr < SRAM_BASE) {
+            dma[0] = DMA_CTRL_MEM_TO_MEM_AA; // Src and Dest must use A
+        } else {
+            dma[0] = DMA_CTRL_MEM_TO_MEM_AB; // Src must use A
+        }
+    } else {
+        if (dest_addr < SRAM_BASE) {
+            dma[0] = DMA_CTRL_MEM_TO_MEM_BA; // Dest must use A
+        } else {
+            dma[0] = DMA_CTRL_MEM_TO_MEM_AB; // No restriction
+        }
+    }
+    
+    dma[1] = src_addr;
+    dma[2] = dest_addr;
+    dma[3] = byte_count | DMA_WR_BUFFERABLE | DMA_HBURST_EN;
+    
+    WaitWhileDMABusy( channel );
+}
+ 
+
+
+
+
+
+
+#define CP15R1_M_ENABLE 0x0001 // MMU Enable
+#define CP15R1_A_ENABLE 0x0002 // Address alignment fault enable
+#define CP15R1_C_ENABLE 0x0004 // (data) cache enable
+#define CP15R1_W_ENABLE 0x0008 // write buffer enable
+#define CP15R1_PROG32   0x0010 // PROG32
+#define CP15R1_DATA32   0x0020 // DATA32
+#define CP15R1_L_ENABLE 0x0040 // Late abort on earlier CPUs
+#define CP15R1_BIGEND   0x0080 // Big-endian (=1), little-endian (=0)
+#define CP15R1_SYSTEM   0x0100 // System bit, modifies MMU protections
+#define CP15R1_ROM      0x0200 // ROM bit, modifies MMU protections
+#define CP15R1_F        0x0400 // Should Be Zero
+#define CP15R1_Z_ENABLE 0x0800 // Branch prediction enable on 810
+#define CP15R1_I_ENABLE 0x1000 // Instruction cache enable
+#define CP15R1_RESERVED 0x00000078
+#define CP15R2_RESERVED 0xFFFFC000
+
+#define NUM_DOMAINS 16
+
+#define DAV_NO_ACCESS 0
+#define DAV_CLIENT    1
+#define DAV_RESERVED  2
+#define DAV_MANAGER   3
+#define NUM_DOMAIN_ACCESS_VALUES 4
+
+#define AP_LEVEL_0 0
+#define AP_LEVEL_1 0
+#define AP_LEVEL_2 0
+#define AP_LEVEL_3 0
+#define NUM_ACCESS_PERMISSIONS 4
+
+#define FAULT_ID 0
+
+#define FLD_COURSE_ID  1
+#define FLD_SECTION_ID 2
+#define FLD_FINE_ID    3
+
+#define FD_USER_DATA_BIT 2
+
+#define FD_USER_DATA_NUM_BITS 30
+
+#define SD_BUFFERABLE_BIT 2
+#define SD_CACHEABLE_BIT  3
+#define SD_IMP_BIT        4
+#define SD_DOMAIN_BIT     5
+#define SD_AP_BIT         10
+#define SD_ADDRESS_BIT    20
+
+#define SD_DOMAIN_NUM_BITS  4
+#define SD_AP_NUM_BITS      2
+
+void CoPro15Regs_SetCP15Reg1(const unsigned long mask) {
+    asm volatile(
+        "MOV  r0, %0;"
+        "MRC  p15, 0, r1, c1, c0, 0;"
+        "ORR  r1,r1,r0;"
+        "MCR  p15, 0, r1, c1, c0, 0;"
+        :
+        : "r" (mask | CP15R1_RESERVED)
+        : "r0","r1");
+}
+
+void CoPro15Regs_ClearCP15Reg1(const unsigned long mask) {
+    asm volatile(
+        "MOV  r0, %0;"
+        "MRC  p15, 0, r1, c1, c0, 0;"
+        "BIC  r1,r1,r0;"
+        "MCR  p15, 0, r1, c1, c0, 0;"
+        :
+        : "r" (mask)
+        : "r0","r1");
+}
+
+unsigned long CoPro15Regs_GetCP15Reg1(const unsigned long mask) {
+    unsigned long value;
+    asm volatile(
+        "MRC  p15, 0, r1, c1, c0, 0;"
+        "MOV  r0, %1;"
+        "BIC  %0,r1,r0; "
+        : "=r" (value)
+        : "r" (mask)
+        : "r0","r1");
+    return value;
+}
+
+unsigned long CoPro15Regs_GetCP15Reg2(void) {
+    unsigned long value;
+    asm volatile(
+        "MRC  p15, 0, r0, c2, c0, 0;"
+        "MOV  %0, r0;"
+        : "=r" (value)
+        :
+        : "r0");
+    return value & CP15R2_RESERVED;
+}
+
+unsigned long CoPro15Regs_GetCP15Reg3(void) {
+    unsigned long value;
+    asm volatile(
+        "MRC  p15, 0, r0, c3, c0, 0;"
+        "MOV  %0, r0;"
+        : "=r" (value)
+        :
+        : "r0");
+    return value;
+}
+
+void CoPro15Regs_SetCP15Reg3(unsigned long value) {
+    asm volatile(
+        "MOV  r0, %0;"
+        "MCR  p15, 0, r0, c3, c0, 0;"
+        :
+        : "r" (value)
+        : "r0");
+}
+
+void CoPro15Regs_SetCP15Reg2(unsigned long value) {
+    asm volatile(
+        "MOV  r0, %0;"
+        "MCR  p15, 0, r0, c2, c0, 0;"
+        :
+        : "r" (value & CP15R2_RESERVED)
+        : "r0");
+}
+
+void Cache_CleanDataCache(void)
+{
+    // Clean the data cache - usually precedes a data cache invalidation.
+    // Forces the data cache content to be written to main memory - only
+    // required if using write-back data cache
+    asm volatile(
+        "MOV  r3,pc;"
+        "LDR  r1, =0;"
+        "  MOV  r4,pc;"
+        "  LDR  r0, =0;"
+        "    ORR  r2, r1, r0;"
+        "    MCR  p15, 0, r2, c7, c10, 2 ;"     // I (BHC) think that this should be c10, 2 not c14, 1 -- See ARM ARM
+        "    ADD  r0, r0, #0x10;"
+        "    CMP  r0,#0x40;"
+        "  BXNE  r4;"
+        "  ADD  r1, r1, #0x04000000;"
+        "  CMP  r1, #0x0;"
+        "BXNE  r3;"
+        :
+        :
+        : "r0","r1","r2","r3","r4");
+}
+
+void Cache_DrainWriteBuffer(void)
+{
+    // Forces the write buffer to update to main memory
+    asm volatile(
+        "LDR  r1, =0;"
+        "MCR  p15, 0, r1, c7, c10, 4 ;"
+        :
+        :
+        : "r1");
+}
+
+void Cache_FlushPrefetchBuffer(void)
+{
+    // Forces the CPU to flush the instruction prefetch buffer
+    asm volatile(
+        "LDR  r1, =0;"
+        "MCR  p15, 0, r1, c7, c5, 4 ;"
+        :
+        :
+        : "r1");
+}
+
+void Cache_InvalidateDataCache(void)
+{
+    asm volatile(
+        "LDR  r1, =0;"
+        "MCR  p15, 0, r1, c7, c6, 0;"
+        :
+        :
+        : "r1");
+}
+
+void Cache_InvalidateInstructionCache(void)
+{
+    asm volatile(
+        "LDR  r1, =0;"
+        "MCR  p15, 0, r1, c7, c5, 0;"
+        :
+        :
+        : "r1");
+}
+
+void Cache_InstOn(void)
+{
+    // Invalidate the instruction cache, in case there's anything
+    // left from when it was last enabled
+    Cache_InvalidateInstructionCache();
+
+    // Enable the instruction cache
+    CoPro15Regs_SetCP15Reg1(CP15R1_I_ENABLE);
+}
+
+void Cache_InstOff(void)
+{
+    // Disable the instruction cache
+    CoPro15Regs_ClearCP15Reg1(CP15R1_I_ENABLE);
+}
+
+void Cache_DataOn(void)
+{
+    // Invalidate the data cache, in case there's anything left from when
+    // it was last enabled
+    Cache_InvalidateDataCache();
+
+    // Enable the data cache
+    CoPro15Regs_SetCP15Reg1(CP15R1_C_ENABLE);
+}
+
+void Cache_DataOff(void)
+{
+    // Ensure all data in data cache or write buffer is written to memory
+    Cache_CleanDataCache();
+    Cache_DrainWriteBuffer();
+
+    // Disable the data cache
+    CoPro15Regs_ClearCP15Reg1(CP15R1_C_ENABLE);
+}
+
+void Cache_WriteBufferOn(void)
+{
+    // Enable the write buffer
+    CoPro15Regs_SetCP15Reg1(CP15R1_W_ENABLE);
+}
+
+void Cache_WriteBufferOff(void)
+{
+    // Ensure all data in the write buffer is written to memory
+    Cache_DrainWriteBuffer();
+
+    // Disable the write buffer
+    CoPro15Regs_ClearCP15Reg1(CP15R1_W_ENABLE);
+}
+
+int MMU_SetDomainAccessValue(
+    int domainNumber,
+    int value) {
+    int status = 0;
+    if ((value < NUM_DOMAIN_ACCESS_VALUES) && (domainNumber < NUM_DOMAINS))
+    {
+        // Insert the 2-bit domain field into the slot for the specified domain
+        unsigned long registerContents = CoPro15Regs_GetCP15Reg3();
+        registerContents &= ~(3UL << (2*domainNumber));
+        registerContents |= ((unsigned long)value << (2*domainNumber));
+        CoPro15Regs_SetCP15Reg3(registerContents);
+        status = 1;
+    }
+    return status;
+}
+
+void MMU_SetAlignmentChecked(int alignmentChecked) {
+    alignmentChecked ? CoPro15Regs_SetCP15Reg1(CP15R1_A_ENABLE) : CoPro15Regs_ClearCP15Reg1(CP15R1_A_ENABLE);
+}
+
+void MMU_SetEnabled(int enabled) {
+    enabled ? CoPro15Regs_SetCP15Reg1(CP15R1_M_ENABLE) : CoPro15Regs_ClearCP15Reg1(CP15R1_M_ENABLE);
+}
+void MMU_InvalidateDataTLB(void)
+{
+    asm volatile(
+        "MCR  p15, 0, r0, c8, c6, 0;"
+        :
+        :
+        : "r0");
+}
+
+void MMU_InvalidateInstructionTLB(void)
+{
+    asm volatile(
+        "MCR  p15, 0, r0, c8, c5, 0;"
+        :
+        :
+        : "r0");
+}
+
+void MMU_SetROMPermission(int rOM_Permitted) {
+    rOM_Permitted ? CoPro15Regs_SetCP15Reg1(CP15R1_ROM) : CoPro15Regs_ClearCP15Reg1(CP15R1_ROM);
+}
+
+void MMU_SetSystemPermission(int systemPermitted) {
+    systemPermitted ? CoPro15Regs_SetCP15Reg1(CP15R1_SYSTEM) : CoPro15Regs_ClearCP15Reg1(CP15R1_SYSTEM);
+}
+
+void MMU_SetTranslationTableBaseAddress(unsigned long *baseAddress) {
+    CoPro15Regs_SetCP15Reg2((unsigned long)baseAddress);
+}
+
+unsigned long SetBit(
+    unsigned long source,
+    int           state,
+    int           offset)
+{
+    source = state ? (source | (1UL << offset)) :
+                     (source & ~(1UL << offset));
+    return source;
+}
+
+unsigned long SetField(
+    unsigned long source,
+    unsigned long newFieldContents,
+    int           offset,
+    int           length)
+{
+    unsigned long mask = (1UL << length) - 1;
+    source &= ~(mask << offset);
+    source |= ((newFieldContents & mask) << offset);
+    return source;
+}
+
+unsigned long FD_SetUserData(
+    unsigned long userData,
+    unsigned long descriptor)
+{
+    return SetField(descriptor, userData, FD_USER_DATA_BIT, FD_USER_DATA_NUM_BITS);
+}
+
+unsigned long FLPT_CreateFaultDescriptor(unsigned long userData)
+{
+    unsigned long descriptor = FAULT_ID;
+    descriptor = FD_SetUserData(userData, descriptor);
+    return descriptor;
+}
+
+void FLPT_InsertFaultDescriptor(
+    unsigned long *tableBaseAdr,
+    int            index,
+    unsigned long  descriptor)
+{
+    *(tableBaseAdr + index) = descriptor;
+}
+
+unsigned long SD_SetAccessPermission(
+    int           ap,
+    unsigned long descriptor)
+{
+    return SetField(descriptor, ap, SD_AP_BIT, SD_AP_NUM_BITS);
+}
+
+unsigned long SD_SetBaseAddress(
+    unsigned long baseAddress,
+    unsigned long descriptor)
+{
+    unsigned long mask = ~0UL << SD_ADDRESS_BIT;
+    baseAddress &= mask;
+    descriptor &= ~mask;
+    descriptor |= baseAddress;
+    return descriptor;
+}
+
+unsigned long SD_SetBufferable(
+    int           bufferable,
+    unsigned long descriptor)
+{
+    return SetBit(descriptor, bufferable, SD_BUFFERABLE_BIT);
+}
+
+unsigned long SD_SetCacheable(
+    int           cacheable,
+    unsigned long descriptor)
+{
+    return SetBit(descriptor, cacheable, SD_CACHEABLE_BIT);
+}
+
+unsigned long SD_SetDomain(
+    int           domain,
+    unsigned long descriptor)
+{
+    return SetField(descriptor, domain, SD_DOMAIN_BIT, SD_DOMAIN_NUM_BITS);
+}
+
+unsigned long SD_SetImplementationDefined(
+    unsigned long implementationDefined,
+    unsigned long descriptor)
+{
+    return SetBit(descriptor, implementationDefined, SD_IMP_BIT);
+}
+
+unsigned long FLPT_CreateSectionDescriptor(
+    unsigned long baseAddress,
+    unsigned char domain,
+    int           implementationDefined,
+    int           ap,
+    int           bufferable,
+    int           cacheable)
+{
+    unsigned long descriptor = FLD_SECTION_ID;
+    descriptor = SD_SetAccessPermission(ap, descriptor);
+    descriptor = SD_SetBaseAddress(baseAddress, descriptor);
+    descriptor = SD_SetBufferable(bufferable, descriptor);
+    descriptor = SD_SetCacheable(cacheable, descriptor);
+    descriptor = SD_SetDomain(domain, descriptor);
+    descriptor = SD_SetImplementationDefined(implementationDefined, descriptor);
+    return descriptor;
+}
+
+void FLPT_InsertSectionDescriptor(
+    unsigned long *tableBaseAdr,
+    int            index,
+    unsigned long  descriptor)
+{
+    *(tableBaseAdr + index) = descriptor;
+}
+
+void FLPT_Zeroise(
+    unsigned long *base_adr,
+    int            numberOfdescriptors) {
+    unsigned long faultDescriptor = FLPT_CreateFaultDescriptor(0);
+    int i;
+    for (i=0; i < numberOfdescriptors; i++) {
+        FLPT_InsertFaultDescriptor(base_adr, i, faultDescriptor);
+    }
+}
+
+void configure_caches(void)
+{
+    // Disable caches
+//    Cache_DataOff();
+printf("1");
+    Cache_InstOff();
+//    Cache_WriteBufferOff();
+
+    // Disable MMU
+printf("2");
+    MMU_SetEnabled(0);
+printf("3");
+    MMU_InvalidateDataTLB();
+printf("4");
+    MMU_InvalidateInstructionTLB();
+
+    // Setup the MMU
+printf("5");
+    MMU_SetAlignmentChecked(1);
+printf("6");
+    MMU_SetROMPermission(0);
+printf("7");
+    MMU_SetSystemPermission(1);
+
+    // Allow client access to all protection domains
+    int i;
+    for (i=0; i < NUM_DOMAINS; i++) {
+        MMU_SetDomainAccessValue(i, DAV_CLIENT);
+    }
+printf("8");
+
+    // Allocate first level page table, which we'll populate only with section
+    // descriptors, which cover 1MB each. Table must be aligned to a 16KB
+    // boundary.
+    // We'll put it 4KB into the SRAM and it will occupy:
+    //   64 entries for SDRAM
+    //   1  entry for SRAM
+    //   16 entries for APB bridge A
+    //   16 entries for APB bridge B
+    // The largest memory address we need to map is that of the SRAM at
+    // 0x4c000000 -> (4c000000/2^20)*4 = offset 1300h from table start ->
+    // require at least 1300h/4 +1 entries in table = 1217
+    unsigned long *firstLevelPageTableBaseAdr = (unsigned long*)SRAM_BASE;
+    FLPT_Zeroise(firstLevelPageTableBaseAdr, 4096);
+printf("9");
+
+    // Map entire adr space uncached, unbuffered, read/write, virtual == physical
+    unsigned megabytesPresent = 4096;
+    unsigned index = 0;
+    for (i=0; i < megabytesPresent; i++) {
+        FLPT_InsertSectionDescriptor(
+            firstLevelPageTableBaseAdr,
+            index,
+            FLPT_CreateSectionDescriptor(
+                index * 1024 * 1024,    // Base address
+                0,                      // Domain number
+                0,                      // Implementation defined
+                AP_LEVEL_1,             // Access permissions
+                0,                      // Bufferable
+                0));                    // Cacheable
+
+        ++index;
+    }
+printf("10");
+
+    // Map SDRAM as cached and buffered, read/write, virtual == physical
+    megabytesPresent = 64;
+    index = PHYS_SDRAM_1_PA / (1024 * 1024);
+    for (i=0; i < megabytesPresent; i++) {
+        FLPT_InsertSectionDescriptor(
+            firstLevelPageTableBaseAdr,
+            index,
+            FLPT_CreateSectionDescriptor(
+                index * 1024 * 1024,    // Base address
+                0,                      // Domain number
+                0,                      // Implementation defined
+                AP_LEVEL_1,             // Access permissions
+                1,                      // Bufferable
+                1));                    // Cacheable
+
+        ++index;
+    }
+printf("11");
+
+    // Map SRAM as cached and buffered, read/write, virtual == physical
+    megabytesPresent = 1;   // Actually only 32KB
+    index = SRAM_BASE / (1024 * 1024);
+    for (i=0; i < megabytesPresent; i++) {
+        FLPT_InsertSectionDescriptor(
+            firstLevelPageTableBaseAdr,
+            index,
+            FLPT_CreateSectionDescriptor(
+                index * 1024 * 1024,    // Base address
+                0,                      // Domain number
+                0,                      // Implementation defined
+                AP_LEVEL_1,             // Access permissions
+                1,                      // Bufferable
+                1));                    // Cacheable
+
+        ++index;
+    }
+printf("12");
+
+    // Map APB bridge A address space as uncached, unbuffered, read/write,
+    // virtual == physical
+    megabytesPresent = 16;
+    index = APB_BRIDGE_A_BASE_PA / (1024 * 1024);
+    for (i=0; i < megabytesPresent; i++) {
+        FLPT_InsertSectionDescriptor(
+            firstLevelPageTableBaseAdr,
+            index,
+            FLPT_CreateSectionDescriptor(
+                index * 1024 * 1024,    // Base address
+                0,                      // Domain number
+                0,                      // Implementation defined
+                AP_LEVEL_1,             // Access permissions
+                0,                      // Bufferable
+                0));                    // Cacheable
+
+        ++index;
+    }
+printf("13");
+
+    // Map APB bridge B address space as uncached, unbuffered, read/write,
+    // virtual == physical
+    megabytesPresent = 16;
+    index = APB_BRIDGE_B_BASE_PA / (1024 * 1024);
+    for (i=0; i < megabytesPresent; i++) {
+        FLPT_InsertSectionDescriptor(
+            firstLevelPageTableBaseAdr,
+            index,
+            FLPT_CreateSectionDescriptor(
+                index * 1024 * 1024,    // Base address
+                0,                      // Domain number
+                0,                      // Implementation defined
+                AP_LEVEL_1,             // Access permissions
+                0,                      // Bufferable
+                0));                    // Cacheable
+
+        ++index;
+    }
+printf("14");
+
+    // Load base address of first level page table
+    MMU_SetTranslationTableBaseAddress(firstLevelPageTableBaseAdr);
+printf("15");
+
+    // Enable MMU
+    MMU_SetEnabled(1);
+printf("16");
+
+    // Enable caches
+    Cache_DataOn();
+printf("17");
+    Cache_InstOn();
+printf("18");
+    Cache_WriteBufferOn();
+printf("19");
+}
+
diff -Nurd u-boot-1.1.2/include/asm-arm/barrier.h u-boot-1.1.2-oxe810/include/asm-arm/barrier.h
--- u-boot-1.1.2/include/asm-arm/barrier.h	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/include/asm-arm/barrier.h	2008-06-11 17:55:08.000000000 +0200
@@ -0,0 +1,25 @@
+#if !defined(__BARRIER_H__)
+#define __BARRIER_H__
+
+static inline void rmb(void)
+{
+    asm volatile ("" : : : "memory");
+}
+
+/*
+ * wmb() Would normally need to ensure shared memory regions are marked as
+ *       non-cacheable and non-bufferable, then the work to be done by wmb() is
+ *       to ensure the compiler and any possible CPU out of order writes are
+ *       flushed to memory, however we have no data cache and as far as I'm
+ *       aware we can't use the MMU to set page properties, so in our case wmb()
+ *       must cause the compiler to flush.
+ */
+
+static inline void wmb(void)
+{
+    // Cause the compiler to flush any registers containing pending write data
+    // to memory
+    asm volatile ("" : : : "memory");
+
+}
+#endif        //  #if !defined(__BARRIER_H__)
diff -Nurd u-boot-1.1.2/include/asm-arm/global_data.h u-boot-1.1.2-oxe810/include/asm-arm/global_data.h
--- u-boot-1.1.2/include/asm-arm/global_data.h	2003-10-10 12:05:43.000000000 +0200
+++ u-boot-1.1.2-oxe810/include/asm-arm/global_data.h	2008-06-11 17:55:08.000000000 +0200
@@ -61,6 +61,7 @@
 #define	GD_FLG_DEVINIT	0x00002		/* Devices have been initialized	*/
 #define	GD_FLG_SILENT	0x00004		/* Silent mode				*/
 
-#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")
+#define DECLARE_GLOBAL_DATA_PTR     register gd_t* volatile gd asm ("r8");
 
 #endif /* __ASM_GBL_DATA_H */
+
diff -Nurd u-boot-1.1.2/include/asm-arm/mach-types.h u-boot-1.1.2-oxe810/include/asm-arm/mach-types.h
--- u-boot-1.1.2/include/asm-arm/mach-types.h	2004-10-10 20:41:14.000000000 +0200
+++ u-boot-1.1.2-oxe810/include/asm-arm/mach-types.h	2008-06-11 17:55:08.000000000 +0200
@@ -624,6 +624,7 @@
 #define MACH_TYPE_RMS100               611
 #define MACH_TYPE_KB9200               612
 #define MACH_TYPE_SX1                  613
+#define MACH_TYPE_OXNAS                1152
 
 #ifdef CONFIG_ARCH_EBSA110
 # ifdef machine_arch_type
@@ -7945,6 +7946,18 @@
 # define machine_is_sx1()	(0)
 #endif
 
+#ifdef CONFIG_MACH_OXNAS
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type	__machine_arch_type
+# else
+#  define machine_arch_type	MACH_TYPE_OXNAS
+# endif
+# define machine_is_oxnas()	(machine_arch_type == MACH_TYPE_OXNAS)
+#else
+# define machine_is_oxnas()	(0)
+#endif
+
 /*
  * These have not yet been registered
  */
diff -Nurd u-boot-1.1.2/include/asm-arm/u-boot.h u-boot-1.1.2-oxe810/include/asm-arm/u-boot.h
--- u-boot-1.1.2/include/asm-arm/u-boot.h	2002-11-03 01:33:10.000000000 +0100
+++ u-boot-1.1.2-oxe810/include/asm-arm/u-boot.h	2008-06-11 17:55:08.000000000 +0200
@@ -41,6 +41,8 @@
 	ulong start;
 	ulong size;
     } 			bi_dram[CONFIG_NR_DRAM_BANKS];
+	unsigned long	bi_sramstart;	/* start of SRAM memory */
+	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
 } bd_t;
 
 #define bi_env_data bi_env->data
diff -Nurd u-boot-1.1.2/include/ata.h u-boot-1.1.2-oxe810/include/ata.h
--- u-boot-1.1.2/include/ata.h	2004-03-14 23:25:50.000000000 +0100
+++ u-boot-1.1.2-oxe810/include/ata.h	2008-06-11 17:55:11.000000000 +0200
@@ -80,7 +80,12 @@
 /*
  * Device / Head Register Bits
  */
+#ifdef CONFIG_OXNAS
+#define ATA_DEVICE(x) (0)
+#else
 #define ATA_DEVICE(x)	((x & 1)<<4)
+#endif // CONFIG_OXNAS
+
 #define ATA_LBA		0xE0
 
 /*
diff -Nurd u-boot-1.1.2/include/cmd_confdefs.h u-boot-1.1.2-oxe810/include/cmd_confdefs.h
--- u-boot-1.1.2/include/cmd_confdefs.h	2004-12-16 18:59:53.000000000 +0100
+++ u-boot-1.1.2-oxe810/include/cmd_confdefs.h	2008-06-11 17:55:11.000000000 +0200
@@ -92,6 +92,7 @@
 #define CFG_CMD_XIMG	0x0400000000000000ULL	/* Load part of Multi Image	*/
 #define CFG_CMD_UNIVERSE 0x0800000000000000ULL	/* Tundra Universe Support      */
 #define CFG_CMD_EXT2    0x1000000000000000ULL	/* EXT2 Support                 */
+#define CFG_CMD_LEDFAIL 0x2000000000000000ULL	/* OXNAS Failure LED support */
 
 #define CFG_CMD_ALL	0xFFFFFFFFFFFFFFFFULL	/* ALL commands			*/
 
diff -Nurd u-boot-1.1.2/include/common.h u-boot-1.1.2-oxe810/include/common.h
--- u-boot-1.1.2/include/common.h	2004-12-13 10:49:01.000000000 +0100
+++ u-boot-1.1.2-oxe810/include/common.h	2008-06-11 17:55:11.000000000 +0200
@@ -204,7 +204,7 @@
 /* common/cmd_nvedit.c */
 int	env_init     (void);
 void	env_relocate (void);
-char	*getenv	     (uchar *);
+char	*getenv	     (const uchar *);
 int	getenv_r     (uchar *name, uchar *buf, unsigned len);
 int	saveenv	     (void);
 #ifdef CONFIG_PPC		/* ARM version to be fixed! */
diff -Nurd u-boot-1.1.2/include/configs/oxnas.h u-boot-1.1.2-oxe810/include/configs/oxnas.h
--- u-boot-1.1.2/include/configs/oxnas.h	1970-01-01 01:00:00.000000000 +0100
+++ u-boot-1.1.2-oxe810/include/configs/oxnas.h	2008-06-12 13:57:57.000000000 +0200
@@ -0,0 +1,593 @@
+/*
+ * (C) Copyright 2005
+ * Oxford Semiconductor Ltd
+ *
+ * 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 __CONFIG_H
+#define __CONFIG_H
+
+#define readb(p)  (*(volatile u8 *)(p))
+#define readl(p)  (*(volatile u32 *)(p))
+#define writeb(v, p) (*(volatile u8 *)(p)= (v))
+#define writel(v, p) (*(volatile u32*)(p)=(v))
+
+#define CFG_FLASH_EMPTY_INFO
+
+/**
+ * Architecture
+ */
+#define CONFIG_ARM926EJS    1
+#define CONFIG_OXNAS        1
+#define CONFIG_OXNAS_ENABLE_PCI         /* Enables PCI clock and takes out of reset - needed if require access to static bus */
+#define CONFIG_OXNAS_FEEDBACK_PCI_CLKS  /* Feedback PCI clock out 3 to drive PCI core clock - needed if require access to static bus */
+#define CONFIG_OXNAS_MANUAL_STATIC_ARBITRATION
+#if (USE_SATA == 1)
+#define CONFIG_OXNAS_USE_SATA           /* Define to include support for SATA disks */
+#if (USE_SATA_ENV == 1)
+#define ENV_ON_SATA                     /* Define to have the U-Boot env. stored on SATA disk */
+#endif // USE_SATA_ENV
+#endif // USE_SATA
+#if (USE_FLASH == 0)
+#define CFG_NO_FLASH                    /* Define to NOT include flash support on static bus*/
+#endif //USE_FLASH
+
+/* Won't be using any interrupts */
+#undef CONFIG_USE_IRQ
+
+/* Everything, incl board info, in Hz */
+#undef CFG_CLKS_IN_HZ
+
+#define CFG_HUSH_PARSER		1
+#define CFG_PROMPT_HUSH_PS2	"> "
+
+/* Miscellaneous configurable options */
+#define CFG_LONGHELP				/* undef to save memory		*/
+#ifdef CFG_HUSH_PARSER
+#define CFG_PROMPT		"$ "		/* Monitor Command Prompt */
+#else
+#define CFG_PROMPT		"# "		/* Monitor Command Prompt */
+#endif
+#define CFG_CBSIZE      256             /* Console I/O Buffer Size  */
+
+/* Print Buffer Size */
+#define CFG_PBSIZE      ((CFG_CBSIZE)+sizeof(CFG_PROMPT)+16)
+#define CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE    (CFG_CBSIZE)    /* Boot Argument Buffer Size    */
+
+#define CONFIG_CMDLINE_TAG          1   /* enable passing of ATAGs  */
+#define CONFIG_SETUP_MEMORY_TAGS    1
+#define CONFIG_MISC_INIT_R          1   /* call misc_init_r during start up */
+#define CONFIG_INITRD_TAG           1   /* allow initrd tag to be generated */
+
+/* May want to do some setup prior to relocation */
+#define CONFIG_INIT_CRITICAL
+
+/* ARM specific late initialisation */
+#define BOARD_LATE_INIT
+
+/**
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE        (128*1024)  /* regular stack */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ    (4*1024)    /* IRQ stack */
+#define CONFIG_STACKSIZE_FIQ    (4*1024)    /* FIQ stack */
+#endif
+
+/**
+ * RAM
+ */
+#define CONFIG_NR_DRAM_BANKS    1           /* We have 1 bank of SDRAM */
+#define PHYS_SDRAM_1_PA         0x48000000  /* SDRAM Bank #1 */
+#if (NAS_VERSION == 810)
+#define PHYS_SDRAM_1_MAX_SIZE	 (256 * 1024 * 1024)
+#endif // NAS_VERSION
+#define CFG_SRAM_BASE           ((PHYS_SDRAM_1_PA) + (PHYS_SDRAM_1_MAX_SIZE))
+#if (NAS_VERSION == 810)
+#define CFG_SRAM_SIZE			 (128 * 1024)
+#endif // NAS_VERSION
+
+#define INITIALISE_SDRAM
+
+/* Default location from which bootm etc will load */
+#define CFG_LOAD_ADDR   (PHYS_SDRAM_1_PA)
+
+/**
+ * Core addresses
+ */
+#define MAC_BASE_PA             0x40400000
+#define STATIC_CS0_BASE_PA      0x41000000
+#define STATIC_CS1_BASE_PA      0x41400000
+#define STATIC_CS2_BASE_PA      0x41800000
+#define STATIC_CONTROL_BASE_PA  0x41C00000
+#define SATA_DATA_BASE_PA       0x42000000
+
+#define APB_BRIDGE_A_BASE_PA    0x44000000
+#define APB_BRIDGE_B_BASE_PA    0x45000000
+
+#define GPIO_1_PA               ((APB_BRIDGE_A_BASE_PA) + 0x0)
+#define GPIO_2_PA               ((APB_BRIDGE_A_BASE_PA) + 0x100000)
+
+#define SYS_CONTROL_BASE_PA     ((APB_BRIDGE_B_BASE_PA) + 0x0)
+#define DMA_BASE_PA             ((APB_BRIDGE_B_BASE_PA) + 0x600000)
+#define RPS_BASE                ((APB_BRIDGE_B_BASE_PA) + 0x300000)
+
+/* Static bus registers */
+#define STATIC_CONTROL_VERSION  ((STATIC_CONTROL_BASE_PA) + 0x0)
+#define STATIC_CONTROL_BANK0    ((STATIC_CONTROL_BASE_PA) + 0x4)
+#define STATIC_CONTROL_BANK1    ((STATIC_CONTROL_BASE_PA) + 0x8)
+#define STATIC_CONTROL_BANK2    ((STATIC_CONTROL_BASE_PA) + 0xC)
+
+/* Clock to the ARM/DDR */
+#if (FPGA == 0)
+#define NOMINAL_ARMCLK  ((PLL400) / 2)
+#define NOMINAL_SYSCLK  ((PLL400) / 4)
+#else // !FPGA
+#define NOMINAL_ARMCLK  (FPGA_ARM_CLK)
+#define NOMINAL_SYSCLK  ((PLL400) / 4)
+#endif // !FPGA
+
+/**
+ * Timer
+ */
+#define CFG_TIMERBASE            ((RPS_BASE) + 0x200)
+#define TIMER_PRESCALE_BIT       2
+#define TIMER_PRESCALE_1_ENUM    0
+#define TIMER_PRESCALE_16_ENUM   1
+#define TIMER_PRESCALE_256_ENUM  2
+#define TIMER_MODE_BIT           6
+#define TIMER_MODE_FREE_RUNNING  0
+#define TIMER_MODE_PERIODIC      1
+#define TIMER_ENABLE_BIT         7
+#define TIMER_ENABLE_DISABLE     0
+#define TIMER_ENABLE_ENABLE      1
+
+#define TIMER_PRESCALE_ENUM      (TIMER_PRESCALE_256_ENUM)
+#define CFG_HZ                   ((RPSCLK) / 256)
+
+/**
+ * GPIO
+ */
+#define GPIO_1_OE       ((GPIO_1_PA) + 0x4)
+#define GPIO_1_SET_OE   ((GPIO_1_PA) + 0x1C)
+#define GPIO_1_CLR_OE   ((GPIO_1_PA) + 0x20)
+
+#define GPIO_2_OE       ((GPIO_2_PA) + 0x4)
+#define GPIO_2_SET_OE   ((GPIO_2_PA) + 0x1C)
+#define GPIO_2_CLR_OE   ((GPIO_2_PA) + 0x20)
+
+/**
+ * Serial Configuration
+ */
+#define EXT_UART_BASE       0x28000000
+
+#define UART_1_BASE (APB_BRIDGE_A_BASE_PA + 0x200000)
+#define UART_2_BASE (APB_BRIDGE_A_BASE_PA + 0x300000)
+#define UART_3_BASE (APB_BRIDGE_A_BASE_PA + 0x900000) 
+#define UART_4_BASE (APB_BRIDGE_A_BASE_PA + 0xA00000) 
+
+#define CFG_NS16550          1
+#define CFG_NS16550_SERIAL   1
+#define CFG_NS16550_REG_SIZE 1
+
+#if (USE_EXTERNAL_UART != 0)
+#define CFG_NS16550_CLK      16000000
+#define CFG_NS16550_COM1     (EXT_UART_BASE)
+#else // USE_EXTERNAL_UART
+#define CFG_NS16550_CLK      (NOMINAL_SYSCLK)
+#define USE_UART_FRACTIONAL_DIVIDER
+#if (INTERNAL_UART == 1)
+#define CONFIG_OXNAS_UART1
+#define CFG_NS16550_COM1     (UART_1_BASE)
+#elif (INTERNAL_UART == 2)
+#define CONFIG_OXNAS_UART2
+#define CFG_NS16550_COM1     (UART_2_BASE)
+#elif (INTERNAL_UART == 3)
+#define CONFIG_OXNAS_UART3
+#define CFG_NS16550_COM1     (UART_3_BASE)
+#else
+#define CONFIG_OXNAS_UART4
+#define CFG_NS16550_COM1     (UART_4_BASE)
+#endif // CONFIG_OXNAS_UART
+#endif // USE_EXTERNAL_UART
+
+#define CONFIG_CONS_INDEX    1
+#define CONFIG_BAUDRATE      115200
+#define CFG_BAUDRATE_TABLE   { 9600, 19200, 38400, 57600, 115200 }
+
+/**
+ * Monitor commands
+ */
+#define BASE_COMMANDS (CFG_CMD_IMI    | \
+                       CFG_CMD_IMLS   | \
+                       CFG_CMD_BDI    | \
+                       CFG_CMD_NET    | \
+                       CFG_CMD_PING   | \
+                       CFG_CMD_ENV    | \
+                       CFG_CMD_RUN    | \
+                       CFG_CMD_MEMORY)
+
+#ifdef CFG_NO_FLASH
+#define FLASH_COMMANDS (BASE_COMMANDS)
+#else
+#define FLASH_COMMANDS (BASE_COMMANDS | CFG_CMD_FLASH)
+#endif // CFG_NO_FLASH
+
+#ifdef CONFIG_OXNAS_USE_SATA
+#define SATA_COMMANDS (FLASH_COMMANDS | CFG_CMD_IDE | CFG_CMD_EXT2 | CFG_CMD_LEDFAIL)
+#else
+#define SATA_COMMANDS (FLASH_COMMANDS)
+#endif // CONFIG_OXNAS_USE_SATA
+
+#define CONFIG_COMMANDS SATA_COMMANDS
+
+/* This must be included AFTER the definition of CONFIG_COMMANDS */
+#include <cmd_confdefs.h>
+
+/**
+ * Booting
+ */
+#if (LINUX_ROOT_RAIDED == 1)
+#define LINUX_ROOT_DEVICE "root=/dev/md1"
+#else
+#define LINUX_ROOT_DEVICE "root=/dev/sda1"
+#endif
+#define CONFIG_BOOTARGS LINUX_ROOT_DEVICE " console=ttyS0,115200 elevator=cfq gmac.mac_adr=0x00,0x30,0xe0,0x00,0x00,0x01"
+
+#ifdef CONFIG_OXNAS_USE_SATA
+#define CONFIG_BOOTDELAY	2
+#define CONFIG_BOOTCOMMAND	"run select0 load boot || run select0 load2 boot || run lightled select1 load extinguishled boot || run lightled select1 load2 extinguishled boot || lightled"
+#define CONFIG_EXTRA_ENV_SETTINGS \
+    "select0=ide dev 0\0" \
+    "select1=ide dev 1\0" \
+    "load=ide read 0x48500000 12c 1644\0" \
+    "load2=ide read 0x48500000 2a6e 1644\0" \
+	"lightled=ledfail 1\0" \
+	"extinguishled=ledfail 0\0" \
+    "boot=bootm 48500000\0"
+#else // CONFIG_OXNAS_USE_SATA
+#define CONFIG_BOOTDELAY	15
+#define CONFIG_BOOTCOMMAND	"bootm 0x41020000"
+#endif // CONFIG_OXNAS_USE_SATA
+
+//#define CONFIG_SHOW_BOOT_PROGRESS   1
+
+/**
+ * Networking
+ */
+#define CONFIG_ETHADDR      00:30:e0:00:00:01
+#define CONFIG_NETMASK      255.255.0.0
+#define CONFIG_IPADDR       172.31.0.128
+#define CONFIG_SERVERIP     172.31.0.100
+#define CONFIG_BOOTFILE     "uImage"
+#define CFG_AUTOLOAD        "n"
+#define CONFIG_NET_RETRY_COUNT 30
+
+/**
+ * Flash support
+ */
+#ifndef CFG_NO_FLASH
+
+#define FORCE_TOP_BOOT_FLASH	1
+
+#define CFG_FLASH_CFI			1
+#define CFG_FLASH_CFI_DRIVER	1
+
+#define NUM_FLASH_MAIN_BLOCKS   63          /* For Intel 28F320B3T */
+#define NUM_FLASH_PARAM_BLOCKS  8           /* For Intel 28F320B3T */
+#define FLASH_MAIN_BLOCK_SIZE   (64*1024)   /* For Intel 28F320B3T family */
+#define FLASH_PARAM_BLOCK_SIZE  (8*1024)    /* For Intel 28F320B3T family */
+
+/* Assuming counts main blocks and parameter blocks, as the Intel/AMD detection */
+/* I'm intending to copy would seem to indicate */
+#define CFG_MAX_FLASH_SECT      (NUM_FLASH_MAIN_BLOCKS + NUM_FLASH_PARAM_BLOCKS)
+
+#define CFG_MAX_FLASH_BANKS     1           /* Assume counts flash devices */
+#define FLASH_BASE_OFF          0
+#define CFG_FLASH_BASE          ((STATIC_CS0_BASE_PA) + (FLASH_BASE_OFF))
+#define PHYS_FLASH_1            (CFG_FLASH_BASE)
+
+#define CFG_FLASH_ERASE_TOUT    (20*CFG_HZ)	/* Timeout for Flash Erase */
+#define CFG_FLASH_WRITE_TOUT    (20*CFG_HZ)	/* Timeout for Flash Write */
+#define CFG_FLASH_WRITE_ATTEMPTS 5
+
+#define STATIC_BUS_FLASH_CONFIG 0x4f1f3f3f  /* Slow ASIC settings */
+
+#endif // !CFG_NO_FLASH
+
+/**
+ * Environment organization
+ */
+#ifdef ENV_ON_SATA
+
+/* Environment on SATA disk */
+#define SIZE_TO_SECTORS(x) ((x) / 512)
+#define CFG_ENV_IS_IN_DISK
+#define CFG_ENV_SIZE			(8*1024)
+#define ENVIRONMENT_OFFSET		((CFG_SRAM_SIZE) - (CFG_ENV_SIZE) - 1024)
+#define CFG_ENV_ADDR			((CFG_SRAM_BASE) + (ENVIRONMENT_OFFSET))
+#define ROM_LOADER_LOAD_START_SECTOR 1
+#define CFG_ENV_DISK_SECTOR 	((ROM_LOADER_LOAD_START_SECTOR) + SIZE_TO_SECTORS(ENVIRONMENT_OFFSET))
+#define ROM_LOADER_LOAD_REDUNDANT_START_SECTOR 10608
+#define CFG_ENV_DISK_REDUNDANT_SECTOR ((ROM_LOADER_LOAD_REDUNDANT_START_SECTOR) + SIZE_TO_SECTORS(ENVIRONMENT_OFFSET))
+
+#else
+/** Flash based environment
+ *
+ *  It appears that all flash env start/size info. has to be pre-defined. How
+ *  this is supposed to work when the flash detection code could cope with all
+ *  sorts of different flash is hard to see.
+ *  It appears from the README that with bottom/top boot flashes with smaller
+ *  parameter blocks available, the environment code will only use a single
+ *  one of these smaller sectors for the environment, i.e. CFG_ENV_SECT_SIZE
+ *  is the size of the environment. I hope this isn't really true. The defines
+ *  below may well not work if this is the truth
+ */
+#define CFG_ENV_IS_IN_FLASH
+/* Environment in flash device parameter blocks */
+#define CFG_ENV_SECT_SIZE   (8*1024)
+/* First parameter block for environment */
+#define CFG_ENV_SIZE        CFG_ENV_SECT_SIZE
+/* Second parameter block for backup environment */
+#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE)
+/* Main environment occupies first parameter block */
+#define CFG_ENV_ADDR        ((CFG_FLASH_BASE)+((NUM_FLASH_MAIN_BLOCKS)*(FLASH_MAIN_BLOCK_SIZE)))
+/* Backup environment occupies second parameter block */
+#define CFG_ENV_ADDR_REDUND ((CFG_ENV_ADDR)+(CFG_ENV_SIZE))
+
+#endif // ENV_ON_SATA
+
+#define CONFIG_ENV_OVERWRITE
+
+/* Magic number that indicates rebooting into upgrade mode */
+#define UPGRADE_MAGIC 0x31	/* ASCII '1' */
+
+/* Magic number that indicates user recovery on reboot */
+/* Also defined in oxnas_user_recovery.agent */
+#define RECOVERY_MAGIC 0x31    /* ASCII '1' */
+
+/* Magic number that indicates controlled power down on reboot */
+/* Also defined in controlled_power_down.sh in init.d */
+#define CONTROLLED_POWER_DOWN_MAGIC 0x31  /* ASCII '1' */
+
+/* This flag is set in SRAM location by Co Proc */
+#define CONTROLLED_POWER_UP_MAGIC  0x31 /* ASCII '1' */
+/* 9k + a quad from top */
+/* Be carefule on changing the location of this flag
+ * u-boot has other things to write in SRAM too
+ */
+#define POWER_ON_FLAG_SRAM_OFFSET 	9220
+
+/* Size of malloc() pool */
+#define CFG_MALLOC_LEN      (CFG_ENV_SIZE + 128*1024)
+#define CFG_GBL_DATA_SIZE   128 /* size in bytes reserved for initial data */
+
+/**
+ * ASM startup control
+ */
+/* Start of address within SRAM of loader's exception table. */
+/* ROM-based exception table will redirect to here */
+#define EXCEPTION_BASE  (CFG_SRAM_BASE)
+
+/**
+ * Disk related stuff
+ */
+#define CONFIG_LBA48
+#define CONFIG_DOS_PARTITION
+#define CFG_IDE_MAXDEVICE   2
+#define CFG_IDE_MAXBUS      1
+#define CONFIG_IDE_PREINIT
+#undef CONFIG_IDE_RESET
+#undef CONFIG_IDE_LED
+#define CFG_ATA_DATA_OFFSET 0
+#define CFG_ATA_REG_OFFSET  0
+#define CFG_ATA_ALT_OFFSET  0
+
+/**
+ * System block reset and clock control
+ */
+#define SYS_CTRL_USB11_CTRL           (SYS_CONTROL_BASE_PA + 0x00)
+#define SYS_CTRL_PCI_CTRL0            (SYS_CONTROL_BASE_PA + 0x04)
+#define SYS_CTRL_PCI_CTRL1            (SYS_CONTROL_BASE_PA + 0x08)
+#define SYS_CTRL_GPIO_PRIMSEL_CTRL_0  (SYS_CONTROL_BASE_PA + 0x0C)
+#define SYS_CTRL_GPIO_PRIMSEL_CTRL_1  (SYS_CONTROL_BASE_PA + 0x10)
+#define SYS_CTRL_GPIO_SECSEL_CTRL_0   (SYS_CONTROL_BASE_PA + 0x14)
+#define SYS_CTRL_GPIO_SECSEL_CTRL_1   (SYS_CONTROL_BASE_PA + 0x18)
+#define SYS_CTRL_GPIO_TERTSEL_CTRL_0  (SYS_CONTROL_BASE_PA + 0x8C)
+#define SYS_CTRL_GPIO_TERTSEL_CTRL_1  (SYS_CONTROL_BASE_PA + 0x90)
+#define SYS_CTRL_USB11_STAT           (SYS_CONTROL_BASE_PA + 0x1c)
+#define SYS_CTRL_PCI_STAT             (SYS_CONTROL_BASE_PA + 0x20)
+#define SYS_CTRL_CKEN_SET_CTRL        (SYS_CONTROL_BASE_PA + 0x2C)
+#define SYS_CTRL_CKEN_CLR_CTRL        (SYS_CONTROL_BASE_PA + 0x30)
+#define SYS_CTRL_RSTEN_SET_CTRL       (SYS_CONTROL_BASE_PA + 0x34)
+#define SYS_CTRL_RSTEN_CLR_CTRL       (SYS_CONTROL_BASE_PA + 0x38)
+#define SYS_CTRL_PLLSYS_CTRL          (SYS_CONTROL_BASE_PA + 0x48)
+#define SYS_CTRL_PLLSYS_KEY_CTRL      (SYS_CONTROL_BASE_PA + 0x6C)
+#define SYS_CTRL_GMAC_CTRL            (SYS_CONTROL_BASE_PA + 0x78)
+#define SYS_CTRL_UART_CTRL            (SYS_CONTROL_BASE_PA + 0x94)
+
+#define SYS_CTRL_CKEN_COPRO_BIT  0
+#define SYS_CTRL_CKEN_DMA_BIT    1
+#define SYS_CTRL_CKEN_DPE_BIT    2
+#define SYS_CTRL_CKEN_DDR_BIT    3
+#define SYS_CTRL_CKEN_SATA_BIT   4
+#define SYS_CTRL_CKEN_I2S_BIT    5
+#define SYS_CTRL_CKEN_USBHS_BIT  6
+#define SYS_CTRL_CKEN_MAC_BIT    7
+#define SYS_CTRL_CKEN_PCI_BIT    8
+#define SYS_CTRL_CKEN_STATIC_BIT 9
+#define SYS_CTRL_CKEN_DDR_PHY_BIT 10
+
+#define SYS_CTRL_RSTEN_ARM_BIT          0
+#define SYS_CTRL_RSTEN_COPRO_BIT        1
+#define SYS_CTRL_RSTEN_USBHS_BIT        4
+#define SYS_CTRL_RSTEN_USBHSPHY_BIT     5
+#define SYS_CTRL_RSTEN_MAC_BIT          6
+#define SYS_CTRL_RSTEN_PCI_BIT          7
+#define SYS_CTRL_RSTEN_DMA_BIT          8
+#define SYS_CTRL_RSTEN_DPE_BIT          9
+#define SYS_CTRL_RSTEN_DDR_BIT          10
+#define SYS_CTRL_RSTEN_SATA_BIT         11
+#define SYS_CTRL_RSTEN_SATA_LINK_BIT    12
+#define SYS_CTRL_RSTEN_SATA_PHY_BIT     13
+#define SYS_CTRL_RSTEN_STATIC_BIT       15
+#define SYS_CTRL_RSTEN_GPIO_BIT         16
+#define SYS_CTRL_RSTEN_UART1_BIT        17
+#define SYS_CTRL_RSTEN_UART2_BIT        18
+#define SYS_CTRL_RSTEN_MISC_BIT         19
+#define SYS_CTRL_RSTEN_I2S_BIT          20
+#define SYS_CTRL_RSTEN_AHB_MON_BIT      21
+#define SYS_CTRL_RSTEN_UART3_BIT        22
+#define SYS_CTRL_RSTEN_UART4_BIT        23
+#define SYS_CTRL_RSTEN_SGDMA_BIT        24
+#define SYS_CTRL_RSTEN_DDR_PHY_BIT      25
+#define SYS_CTRL_RSTEN_BUS_BIT          31
+
+#define SYS_CTRL_GMAC_RGMII         2
+#define SYS_CTRL_GMAC_SIMPLE_MAX    1
+#define SYS_CTRL_GMAC_CKEN_GTX      0
+
+#define SYS_CTRL_CKCTRL_CTRL_ADDR     (SYS_CONTROL_BASE_PA + 0x64)
+
+#define SYS_CTRL_CKCTRL_PCI_DIV_BIT 0
+#define SYS_CTRL_CKCTRL_SLOW_BIT    8
+
+#define SYS_CTRL_UART2_DEQ_EN       0
+#define SYS_CTRL_UART3_DEQ_EN       1
+#define SYS_CTRL_UART3_IQ_EN        2
+#define SYS_CTRL_UART4_IQ_EN        3
+#define SYS_CTRL_UART4_NOT_PCI_MODE 4
+
+#define SYS_CTRL_PCI_CTRL1_PCI_STATIC_RQ_BIT 11
+
+/**
+ * SATA related definitions
+ */
+#define ATA_PORT_CTL        0
+#define ATA_PORT_FEATURE    1
+#define ATA_PORT_NSECT      2
+#define ATA_PORT_LBAL       3
+#define ATA_PORT_LBAM       4
+#define ATA_PORT_LBAH       5
+#define ATA_PORT_DEVICE     6
+#define ATA_PORT_COMMAND    7
+
+#define SATA_0_REGS_BASE    (APB_BRIDGE_B_BASE_PA + 0x900000)
+#define SATA_1_REGS_BASE    (APB_BRIDGE_B_BASE_PA + 0x910000)
+#define SATA_HOST_REGS_BASE (APB_BRIDGE_B_BASE_PA + 0x9e0000)
+
+/* The offsets to the SATA registers */
+#define SATA_ORB1_OFF           0
+#define SATA_ORB2_OFF           1
+#define SATA_ORB3_OFF           2
+#define SATA_ORB4_OFF           3
+#define SATA_ORB5_OFF           4
+
+#define SATA_FIS_ACCESS         11
+#define SATA_INT_STATUS_OFF     12  /* Read only */
+#define SATA_INT_CLR_OFF        12  /* Write only */
+#define SATA_INT_ENABLE_OFF     13  /* Read only */
+#define SATA_INT_ENABLE_SET_OFF 13  /* Write only */
+#define SATA_INT_ENABLE_CLR_OFF 14  /* Write only */
+#define SATA_VERSION_OFF        15
+#define SATA_CONTROL_OFF        23
+#define SATA_COMMAND_OFF        24
+#define SATA_PORT_CONTROL_OFF   25
+#define SATA_DRIVE_CONTROL_OFF  26
+
+/* The offsets to the link registers that are access in an asynchronous manner */
+#define SATA_LINK_DATA     28
+#define SATA_LINK_RD_ADDR  29
+#define SATA_LINK_WR_ADDR  30
+#define SATA_LINK_CONTROL  31
+
+/* SATA interrupt status register fields */
+#define SATA_INT_STATUS_EOC_RAW_BIT     ( 0 + 16) 
+#define SATA_INT_STATUS_ERROR_BIT       ( 2 + 16)
+#define SATA_INT_STATUS_EOADT_RAW_BIT   ( 1 + 16)
+
+/* SATA core command register commands */
+#define SATA_CMD_WRITE_TO_ORB_REGS              2
+#define SATA_CMD_WRITE_TO_ORB_REGS_NO_COMMAND   4
+
+#define SATA_CMD_BUSY_BIT 7
+
+#define SATA_SCTL_CLR_ERR 0x00000316UL
+
+#define SATA_OPCODE_MASK 0x3
+
+#define SATA_LBAL_BIT    0
+#define SATA_LBAM_BIT    8
+#define SATA_LBAH_BIT    16
+#define SATA_HOB_LBAH_BIT 24
+#define SATA_DEVICE_BIT  24
+#define SATA_NSECT_BIT   0
+#define SATA_FEATURE_BIT 16
+#define SATA_COMMAND_BIT 24
+#define SATA_CTL_BIT     24
+
+/* ATA status (7) register field definitions */
+#define ATA_STATUS_BSY_BIT     7
+#define ATA_STATUS_DRDY_BIT    6
+#define ATA_STATUS_DF_BIT      5
+#define ATA_STATUS_DRQ_BIT     3
+#define ATA_STATUS_ERR_BIT     0
+
+/* ATA device (6) register field definitions */
+#define ATA_DEVICE_FIXED_MASK 0xA0
+#define ATA_DEVICE_DRV_BIT 4
+#define ATA_DEVICE_DRV_NUM_BITS 1
+#define ATA_DEVICE_LBA_BIT 6
+
+/* ATA control (0) register field definitions */
+#define ATA_CTL_SRST_BIT   2
+
+/* ATA Command register initiated commands */
+#define ATA_CMD_INIT    0x91
+#define ATA_CMD_IDENT   0xEC
+
+#define SATA_STD_ASYNC_REGS_OFF 0x20
+#define SATA_SCR_STATUS      0
+#define SATA_SCR_ERROR       1
+#define SATA_SCR_CONTROL     2
+#define SATA_SCR_ACTIVE      3
+#define SATA_SCR_NOTIFICAION 4
+
+#define SATA_BURST_BUF_FORCE_EOT_BIT        0
+#define SATA_BURST_BUF_DATA_INJ_ENABLE_BIT  1
+#define SATA_BURST_BUF_DIR_BIT              2
+#define SATA_BURST_BUF_DATA_INJ_END_BIT     3
+#define SATA_BURST_BUF_FIFO_DIS_BIT         4
+#define SATA_BURST_BUF_DIS_DREQ_BIT         5
+#define SATA_BURST_BUF_DREQ_BIT             6
+
+/* Button on GPIO 32 */
+#define RECOVERY_BUTTON         (0x00000001 << 0)
+#define RECOVERY_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_1
+#define RECOVERY_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_1
+#define RECOVERY_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_1
+#define RECOVERY_CLR_OE_REG     GPIO_2_CLR_OE
+#define RECOVERY_DEBOUNCE_REG   GPIO_2_INPUT_DEBOUNCE_ENABLE
+#define RECOVERY_DATA           GPIO_2_PA
+
+#endif // CONFIG_H
diff -Nurd u-boot-1.1.2/include/_exports.h u-boot-1.1.2-oxe810/include/_exports.h
--- u-boot-1.1.2/include/_exports.h	2003-09-12 17:35:33.000000000 +0200
+++ u-boot-1.1.2-oxe810/include/_exports.h	2008-06-11 17:55:11.000000000 +0200
@@ -12,6 +12,7 @@
 EXPORT_FUNC(get_timer)
 EXPORT_FUNC(vprintf)
 EXPORT_FUNC(do_reset)
+EXPORT_FUNC(raise)
 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
 EXPORT_FUNC(i2c_write)
 EXPORT_FUNC(i2c_read)
diff -Nurd u-boot-1.1.2/include/flash.h u-boot-1.1.2-oxe810/include/flash.h
--- u-boot-1.1.2/include/flash.h	2004-12-16 19:01:48.000000000 +0100
+++ u-boot-1.1.2-oxe810/include/flash.h	2008-06-11 17:55:11.000000000 +0200
@@ -207,6 +207,7 @@
 #define ATM_ID_BV1614	0x000000C0	/* 49BV1614  ID */
 #define ATM_ID_BV1614A	0x000000C8	/* 49BV1614A ID */
 #define ATM_ID_BV6416	0x000000D6	/* 49BV6416  ID */
+#define ATM_ID_BV322    0x000000c9      /* 49BV322A  ID */
 
 #define FUJI_ID_29F800BA  0x22582258	/* MBM29F800BA ID  (8M) */
 #define FUJI_ID_29F800TA  0x22D622D6	/* MBM29F800TA ID  (8M) */
@@ -405,6 +406,7 @@
 #define FLASH_MAN_INTEL 0x00300000
 #define FLASH_MAN_MT	0x00400000
 #define FLASH_MAN_SHARP 0x00500000
+#define FLASH_MAN_ATM   0x00070000      /* Atmel */
 
 
 #define FLASH_TYPEMASK	0x0000FFFF	/* extract FLASH type	information	*/
diff -Nurd u-boot-1.1.2/include/ns16550.h u-boot-1.1.2-oxe810/include/ns16550.h
--- u-boot-1.1.2/include/ns16550.h	2004-06-07 01:13:57.000000000 +0200
+++ u-boot-1.1.2-oxe810/include/ns16550.h	2008-06-11 17:55:11.000000000 +0200
@@ -19,6 +19,10 @@
 	unsigned char lsr;		/* 5 */
 	unsigned char msr;		/* 6 */
 	unsigned char scr;		/* 7 */
+#if defined(CONFIG_OXNAS)
+	unsigned char ext;		/* 8 */
+	unsigned char dlf;		/* 9 */
+#endif
 #if defined(CONFIG_OMAP730)
 	unsigned char mdr1;		/* 8 */
 	unsigned char reg9;		/* 9 */
diff -Nurd u-boot-1.1.2/lib_arm/board.c u-boot-1.1.2-oxe810/lib_arm/board.c
--- u-boot-1.1.2/lib_arm/board.c	2004-08-02 00:48:22.000000000 +0200
+++ u-boot-1.1.2-oxe810/lib_arm/board.c	2008-06-11 17:55:06.000000000 +0200
@@ -39,6 +39,9 @@
 #include "../drivers/lan91c96.h"
 #endif
 
+DECLARE_GLOBAL_DATA_PTR
+
+
 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
 void nand_init (void);
 #endif
@@ -106,7 +109,6 @@
 
 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));
@@ -142,16 +144,18 @@
  */
 static int display_dram_config (void)
 {
-	DECLARE_GLOBAL_DATA_PTR;
 	int i;
 
 	puts ("RAM Configuration:\n");
 
 	for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
-		printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
+		printf ("\tBank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
 		print_size (gd->bd->bi_dram[i].size, "\n");
 	}
 
+	puts("SRAM Configuration:\n");
+	printf("\t%dKB at 0x%08x\n", gd->bd->bi_sramsize >> 10, gd->bd->bi_sramstart);
+
 	return (0);
 }
 
@@ -191,6 +195,12 @@
 	cpu_init,		/* basic cpu dependent setup */
 	board_init,		/* basic board dependent setup */
 	interrupt_init,		/* set up exceptions */
+#ifdef CONFIG_OXNAS
+	/* Need early console to see SATA env. load messages */
+	init_baudrate,		/* initialze baudrate settings */
+	serial_init,		/* serial communications setup */
+	console_init_f,		/* stage 1 init of console */
+#endif // CONFIG_OXNAS
 	env_init,		/* initialize environment */
 	init_baudrate,		/* initialze baudrate settings */
 	serial_init,		/* serial communications setup */
@@ -206,7 +216,6 @@
 
 void start_armboot (void)
 {
-	DECLARE_GLOBAL_DATA_PTR;
 
 	ulong size;
 	init_fnc_t **init_fnc_ptr;
@@ -232,9 +241,11 @@
 		}
 	}
 
+#ifndef CFG_NO_FLASH
 	/* configure available FLASH banks */
 	size = flash_init ();
 	display_flash_config (size);
+#endif // CFG_NO_FLASH
 
 #ifdef CONFIG_VFD
 #	ifndef PAGE_SIZE
@@ -354,6 +365,12 @@
 {
 	puts ("### ERROR ### Please RESET the board ###\n");
 	for (;;);
+}
+
+void raise (int n)
+{
+	puts ("### ERROR ### Please RESET the board ###\n");
+	for (;;);
 }
 
 #ifdef CONFIG_MODEM_SUPPORT
diff -Nurd u-boot-1.1.2/MAKEALL u-boot-1.1.2-oxe810/MAKEALL
--- u-boot-1.1.2/MAKEALL	2004-12-31 10:32:48.000000000 +0100
+++ u-boot-1.1.2-oxe810/MAKEALL	2008-06-11 17:55:31.000000000 +0200
@@ -154,7 +154,7 @@
 	lpd7a400	mx1ads		mx1fs2		omap1510inn	\
 	omap1610h2	omap1610inn	omap730p2	scb9328		\
 	smdk2400	smdk2410	trab		VCMA9		\
-	versatile							\
+	versatile	oxnas	\
 "
 
 #########################################################################
diff -Nurd u-boot-1.1.2/Makefile u-boot-1.1.2-oxe810/Makefile
--- u-boot-1.1.2/Makefile	2004-12-19 10:58:11.000000000 +0100
+++ u-boot-1.1.2-oxe810/Makefile	2008-06-11 17:55:31.000000000 +0200
@@ -1296,6 +1296,9 @@
 SX1_config :		unconfig
 	@./mkconfig $(@:_config=) arm arm925t sx1
 
+oxnas_config :	unconfig
+	@./mkconfig $(@:_config=) arm arm926ejs oxnas
+
 # TRAB default configuration:	8 MB Flash, 32 MB RAM
 trab_config \
 trab_bigram_config \
@@ -1561,11 +1564,12 @@
 clean:
 	find . -type f \
 		\( -name 'core' -o -name '*.bak' -o -name '*~' \
-		-o -name '*.o'  -o -name '*.a'  \) -print \
+		-o -name '*.o'  -o -name '*.a' -o -name '.depend' \) -print \
 		| xargs rm -f
 	rm -f examples/hello_world examples/timer \
 	      examples/eepro100_eeprom examples/sched \
-	      examples/mem_to_mem_idma2intr examples/82559_eeprom
+	      examples/mem_to_mem_idma2intr examples/82559_eeprom \
+              examples/mem_test
 	rm -f tools/img2srec tools/mkimage tools/envcrc tools/gen_eth_addr
 	rm -f tools/mpc86x_clk tools/ncb
 	rm -f tools/easylogo/easylogo tools/bmp_logo
diff -Nurd u-boot-1.1.2/net/net.c u-boot-1.1.2-oxe810/net/net.c
--- u-boot-1.1.2/net/net.c	2004-10-12 00:51:14.000000000 +0200
+++ u-boot-1.1.2-oxe810/net/net.c	2008-06-11 17:55:11.000000000 +0200
@@ -225,7 +225,7 @@
 		return;
 
 	t = get_timer(0);
-
+	
 	/* check for arp timeout */
 	if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) {
 		NetArpWaitTry++;
@@ -235,6 +235,7 @@
 			NetArpWaitTry = 0;
 			NetStartAgain();
 		} else {
+			puts ("\nARP Resend request\n");
 			NetArpWaitTimerStart = t;
 			ArpRequest();
 		}
@@ -738,7 +739,7 @@
 #if defined(CONFIG_NET_MULTI)
 	printf ("Using %s device\n", eth_get_name());
 #endif	/* CONFIG_NET_MULTI */
-	NetSetTimeout (10 * CFG_HZ, PingTimeout);
+	NetSetTimeout (30 * CFG_HZ, PingTimeout);
 	NetSetHandler (PingHandler);
 
 	PingSend();
@@ -1384,7 +1385,7 @@
 				 */
 				/* XXX point to ip packet */
 				(*packetHandler)((uchar *)ip, 0, 0, 0);
-				break;
+				return;/**break; BHC Changed to remove second invocation of ping handler below */
 #endif
 			default:
 				return;
@@ -1492,10 +1493,11 @@
 NetCksum(uchar * ptr, int len)
 {
 	ulong	xsum;
+	ushort *s = ptr;
 
 	xsum = 0;
 	while (len-- > 0)
-		xsum += *((ushort *)ptr)++;
+		xsum += *s++;
 	xsum = (xsum & 0xffff) + (xsum >> 16);
 	xsum = (xsum & 0xffff) + (xsum >> 16);
 	return (xsum & 0xffff);
diff -Nurd u-boot-1.1.2/net/tftp.c u-boot-1.1.2-oxe810/net/tftp.c
--- u-boot-1.1.2/net/tftp.c	2004-04-15 23:48:55.000000000 +0200
+++ u-boot-1.1.2-oxe810/net/tftp.c	2008-06-11 17:55:11.000000000 +0200
@@ -106,6 +106,7 @@
 	volatile uchar *	pkt;
 	volatile uchar *	xp;
 	int			len = 0;
+	volatile ushort *	s;
 
 	/*
 	 *	We will always be sending some sort of packet, so
@@ -117,7 +118,9 @@
 
 	case STATE_RRQ:
 		xp = pkt;
-		*((ushort *)pkt)++ = htons(TFTP_RRQ);
+		s = (ushort *)pkt;
+		*s++ = htons(TFTP_RRQ);
+		pkt = (uchar *)s;
 		strcpy ((char *)pkt, tftp_filename);
 		pkt += strlen(tftp_filename) + 1;
 		strcpy ((char *)pkt, "octet");
@@ -135,15 +138,19 @@
 	case STATE_DATA:
 	case STATE_OACK:
 		xp = pkt;
-		*((ushort *)pkt)++ = htons(TFTP_ACK);
-		*((ushort *)pkt)++ = htons(TftpBlock);
+		s = (ushort *)pkt;
+		*s++ = htons(TFTP_ACK);
+		*s++ = htons(TftpBlock);
+		pkt = (uchar *)s;
 		len = pkt - xp;
 		break;
 
 	case STATE_TOO_LARGE:
 		xp = pkt;
-		*((ushort *)pkt)++ = htons(TFTP_ERROR);
-		*((ushort *)pkt)++ = htons(3);
+		s = (ushort *)pkt;
+		*s++ = htons(TFTP_ERROR);
+		*s++ = htons(3);
+		pkt = (uchar *)s;
 		strcpy ((char *)pkt, "File too large");
 		pkt += 14 /*strlen("File too large")*/ + 1;
 		len = pkt - xp;
@@ -151,8 +158,10 @@
 
 	case STATE_BAD_MAGIC:
 		xp = pkt;
-		*((ushort *)pkt)++ = htons(TFTP_ERROR);
-		*((ushort *)pkt)++ = htons(2);
+		s = (ushort *)pkt;
+		*s++ = htons(TFTP_ERROR);
+		*s++ = htons(2);
+		pkt = (uchar *)s;
 		strcpy ((char *)pkt, "File has bad magic");
 		pkt += 18 /*strlen("File has bad magic")*/ + 1;
 		len = pkt - xp;
@@ -167,6 +176,7 @@
 TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
 {
 	ushort proto;
+	ushort *s;
 
 	if (dest != TftpOurPort) {
 		return;
@@ -180,7 +190,9 @@
 	}
 	len -= 2;
 	/* warning: don't use increment (++) in ntohs() macros!! */
-	proto = *((ushort *)pkt)++;
+	s = (ushort *)pkt;
+	proto = *s++;
+	pkt = (uchar *)s;
 	switch (ntohs(proto)) {
 
 	case TFTP_RRQ: