Browse Source

* Patch by Peter Ryser, 20 Feb 2004:
Add support for the Xilinx ML300 platform

* Patch by Stephan Linz, 17 Feb 2004:
Fix watchdog support for NIOS

* Patch by Josh Fryman, 16 Feb 2004:
Fix byte-swapping for cfi_flash.c for different bus widths

* Patch by Jon Diekema, 14 Jeb 2004:
Remove duplicate "FPGA Support" notes from the README file

wdenk 21 năm trước cách đây
mục cha
commit
028ab6b598
57 tập tin đã thay đổi với 12176 bổ sung170 xóa
  1. 12 0
      CHANGELOG
  2. 4 4
      MAKEALL
  3. 3 0
      Makefile
  4. 0 54
      README
  5. 0 1
      board/emk/top860/top860.c
  6. 5 5
      board/omap1610inn/omap1610innovator.c
  7. 2 2
      board/omap1610inn/platform.S
  8. 165 0
      board/xilinx/common/xbasic_types.c
  9. 283 0
      board/xilinx/common/xbasic_types.h
  10. 252 0
      board/xilinx/common/xbuf_descriptor.h
  11. 738 0
      board/xilinx/common/xdma_channel.c
  12. 291 0
      board/xilinx/common/xdma_channel.h
  13. 110 0
      board/xilinx/common/xdma_channel_i.h
  14. 1317 0
      board/xilinx/common/xdma_channel_sg.c
  15. 81 0
      board/xilinx/common/xio.h
  16. 763 0
      board/xilinx/common/xipif_v1_23_b.h
  17. 448 0
      board/xilinx/common/xpacket_fifo_v1_00_b.c
  18. 306 0
      board/xilinx/common/xpacket_fifo_v1_00_b.h
  19. 347 0
      board/xilinx/common/xstatus.h
  20. 350 0
      board/xilinx/common/xversion.c
  21. 97 0
      board/xilinx/common/xversion.h
  22. 57 0
      board/xilinx/ml300/Makefile
  23. 29 0
      board/xilinx/ml300/config.mk
  24. 48 0
      board/xilinx/ml300/init.S
  25. 109 0
      board/xilinx/ml300/ml300.c
  26. 155 0
      board/xilinx/ml300/serial.c
  27. 41 0
      board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes
  28. 48 0
      board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld
  29. 298 0
      board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl
  30. 146 0
      board/xilinx/ml300/u-boot.lds
  31. 135 0
      board/xilinx/ml300/u-boot.lds.debug
  32. 216 0
      board/xilinx/ml300/xparameters.h
  33. 153 0
      board/xilinx/xilinx_enet/emac_adapter.c
  34. 844 0
      board/xilinx/xilinx_enet/xemac.c
  35. 673 0
      board/xilinx/xilinx_enet/xemac.h
  36. 60 0
      board/xilinx/xilinx_enet/xemac_g.c
  37. 207 0
      board/xilinx/xilinx_enet/xemac_i.h
  38. 402 0
      board/xilinx/xilinx_enet/xemac_intr.c
  39. 1344 0
      board/xilinx/xilinx_enet/xemac_intr_dma.c
  40. 462 0
      board/xilinx/xilinx_enet/xemac_l.h
  41. 318 0
      board/xilinx/xilinx_enet/xemac_options.c
  42. 482 0
      board/xilinx/xilinx_enet/xemac_polled.c
  43. 4 4
      common/cmd_bdinfo.c
  44. 1 1
      cpu/arm925t/interrupts.c
  45. 1 1
      cpu/arm926ejs/interrupts.c
  46. 2 0
      cpu/nios/interrupts.c
  47. 3 2
      cpu/nios/serial.c
  48. 4 0
      cpu/ppc4xx/speed.c
  49. 128 0
      doc/README.ml300
  50. 63 94
      drivers/cfi_flash.c
  51. 154 0
      include/configs/ml300.h
  52. 1 1
      include/configs/omap1610h2.h
  53. 4 0
      include/watchdog.h
  54. 5 0
      lib_nios/board.c
  55. 2 0
      lib_nios/time.c
  56. 2 0
      lib_ppc/board.c
  57. 1 1
      nios_config.mk

+ 12 - 0
CHANGELOG

@@ -2,6 +2,18 @@
 Changes for U-Boot 1.0.2:
 ======================================================================
 
+* Patch by Peter Ryser, 20 Feb 2004:
+  Add support for the Xilinx ML300 platform
+
+* Patch by Stephan Linz, 17 Feb 2004:
+  Fix watchdog support for NIOS
+
+* Patch by Josh Fryman, 16 Feb 2004:
+  Fix byte-swapping for cfi_flash.c for different bus widths
+
+* Patch by Jon Diekema, 14 Jeb 2004:
+  Remove duplicate "FPGA Support" notes from the README file
+
 * Patches by Reinhard Meyer, 14 Feb 2004:
   - update board/emk tree; use common flash driver
   - Corrected tested bits in machine check exception in cpu/mpc5xxx/traps.c

+ 4 - 4
MAKEALL

@@ -61,10 +61,10 @@ LIST_4xx="	\
 	CPCI440		CPCIISER4	CRAYL1		csb272		\
 	DASA_SIM	DP405		DU405		EBONY		\
 	ERIC		EXBITGEN	HUB405		MIP405		\
-	MIP405T		ML2		OCRTC		ORSG		\
-	PCI405		PIP405		PLU405		PMC405		\
-	PPChameleonEVB	VOH405		W7OLMC		W7OLMG		\
-	WALNUT405	XPEDITE1K					\
+	MIP405T		ML2		ml300		OCRTC		\
+	ORSG		PCI405		PIP405		PLU405		\
+	PMC405		PPChameleonEVB	VOH405		W7OLMC		\
+	W7OLMG		WALNUT405	XPEDITE1K			\
 "
 
 #########################################################################

+ 3 - 0
Makefile

@@ -593,6 +593,9 @@ MIP405T_config:unconfig
 ML2_config:unconfig
 	@./mkconfig $(@:_config=) ppc ppc4xx ml2
 
+ml300_config:unconfig
+	@./mkconfig $(@:_config=) ppc ppc4xx ml300 xilinx
+
 OCRTC_config		\
 ORSG_config:	unconfig
 	@./mkconfig $(@:_config=) ppc ppc4xx ocrtc esd

+ 0 - 54
README

@@ -1153,60 +1153,6 @@ The following options need to be configured:
 		SPI configuration items (port pins to use, etc). For
 		an example, see include/configs/sacsng.h.
 
-- FPGA Support: CONFIG_FPGA_COUNT
-
-		Specify the number of FPGA devices to support.
-
-		CONFIG_FPGA
-
-		Used to specify the types of FPGA devices. For
-		example,
-		#define CONFIG_FPGA  CFG_XILINX_VIRTEX2
-
-		CFG_FPGA_PROG_FEEDBACK
-
-		Enable printing of hash marks during FPGA
-		configuration.
-
-		CFG_FPGA_CHECK_BUSY
-
-		Enable checks on FPGA configuration interface busy
-		status by the configuration function. This option
-		will require a board or device specific function to
-		be written.
-
-		CONFIG_FPGA_DELAY
-
-		If defined, a function that provides delays in the
-		FPGA configuration driver.
-
-		CFG_FPGA_CHECK_CTRLC
-
-		Allow Control-C to interrupt FPGA configuration
-
-		CFG_FPGA_CHECK_ERROR
-
-		Check for configuration errors during FPGA bitfile
-		loading. For example, abort during Virtex II
-		configuration if the INIT_B line goes low (which
-		indicated a CRC error).
-
-		CFG_FPGA_WAIT_INIT
-
-		Maximum time to wait for the INIT_B line to deassert
-		after PROB_B has been deasserted during a Virtex II
-		FPGA configuration sequence. The default time is 500 mS.
-
-		CFG_FPGA_WAIT_BUSY
-
-		Maximum time to wait for BUSY to deassert during
-		Virtex II FPGA configuration. The default is 5 mS.
-
-		CFG_FPGA_WAIT_CONFIG
-
-		Time to wait after FPGA configuration. The default is
-		200 mS.
-
 - FPGA Support: CONFIG_FPGA_COUNT
 
 		Specify the number of FPGA devices to support.

+ 0 - 1
board/emk/top860/top860.c

@@ -145,4 +145,3 @@ int misc_init_r (void)
 
 	return (0);
 }
-

+ 5 - 5
board/omap1610inn/omap1610innovator.c

@@ -11,7 +11,7 @@
  * Kshitij Gupta <Kshitij@ti.com>
  *
  * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004
- * 
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -112,9 +112,9 @@ void ether__init (void)
 #ifdef CONFIG_H2_OMAP1610
 	#define LAN_RESET_REGISTER 0x0400001c
 
-	/* The debug board on which the lan chip resides may not be powered 
-	 * ON at the same time as the OMAP chip. So wait in a loop until the 
-	 * lan reset register (on the debug board) is available (powered on) 
+	/* The debug board on which the lan chip resides may not be powered
+	 * ON at the same time as the OMAP chip. So wait in a loop until the
+	 * lan reset register (on the debug board) is available (powered on)
 	 * and reset the lan chip.
 	 */
 
@@ -123,7 +123,7 @@ void ether__init (void)
 		*((volatile unsigned short *) LAN_RESET_REGISTER) = 0x0001;
 		udelay (3);
 	} while (*((volatile unsigned short *) LAN_RESET_REGISTER) != 0x0001);
-	
+
 	do {
 		*((volatile unsigned short *) LAN_RESET_REGISTER) = 0x0000;
 		udelay (3);

+ 2 - 2
board/omap1610inn/platform.S

@@ -6,7 +6,7 @@
  * Kshitij Gupta <Kshitij@ti.com>
  *
  * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004
- * 
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -251,7 +251,7 @@ common_tc:
 	ldr	r0,	REG_TC_EMIFS_CS3_CONFIG
 	str	r1,	[r0] /* Chip Select 3 */
 
-#ifdef CONFIG_H2_OMAP1610	
+#ifdef CONFIG_H2_OMAP1610
 	/* inserting additional 2 clock cycle hold time for LAN */
 	ldr     r0,     REG_TC_EMIFS_CS1_ADVANCED
 	ldr    	r1,     VAL_TC_EMIFS_CS1_ADVANCED

+ 165 - 0
board/xilinx/common/xbasic_types.c

@@ -0,0 +1,165 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+     *
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xbasic_types.c
+*
+* This file contains basic functions for Xilinx software IP.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a rpm  11/07/03 Added XNullHandler function as a stub interrupt handler
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Variable Definitions *****************************/
+
+/**
+ * This variable allows testing to be done easier with asserts. An assert
+ * sets this variable such that a driver can evaluate this variable
+ * to determine if an assert occurred.
+ */
+unsigned int XAssertStatus;
+
+/**
+ * This variable allows the assert functionality to be changed for testing
+ * such that it does not wait infinitely. Use the debugger to disable the
+ * waiting during testing of asserts.
+ */
+u32 XWaitInAssert = TRUE;
+
+/* The callback function to be invoked when an assert is taken */
+static XAssertCallback XAssertCallbackRoutine = (XAssertCallback) NULL;
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+*
+* Implements assert. Currently, it calls a user-defined callback function
+* if one has been set.  Then, it potentially enters an infinite loop depending
+* on the value of the XWaitInAssert variable.
+*
+* @param    File is the name of the filename of the source
+* @param    Line is the linenumber within File
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XAssert(char *File, int Line)
+{
+	/* if the callback has been set then invoke it */
+	if (XAssertCallbackRoutine != NULL) {
+		(*XAssertCallbackRoutine) (File, Line);
+	}
+
+	/* if specified, wait indefinitely such that the assert will show up
+	 * in testing
+	 */
+	while (XWaitInAssert) {
+	}
+}
+
+/*****************************************************************************/
+/**
+*
+* Sets up a callback function to be invoked when an assert occurs. If there
+* was already a callback installed, then it is replaced.
+*
+* @param    Routine is the callback to be invoked when an assert is taken
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* This function has no effect if NDEBUG is set
+*
+******************************************************************************/
+void
+XAssertSetCallback(XAssertCallback Routine)
+{
+	XAssertCallbackRoutine = Routine;
+}
+
+/*****************************************************************************/
+/**
+*
+* Null handler function. This follows the XInterruptHandler signature for
+* interrupt handlers. It can be used to assign a null handler (a stub) to an
+* interrupt controller vector table.
+*
+* @param    NullParameter is an arbitrary void pointer and not used.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XNullHandler(void *NullParameter)
+{
+}

+ 283 - 0
board/xilinx/common/xbasic_types.h

@@ -0,0 +1,283 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xbasic_types.h
+*
+* This file contains basic types for Xilinx software IP.  These types do not
+* follow the standard naming convention with respect to using the component
+* name in front of each name because they are considered to be primitives.
+*
+* @note
+*
+* This file contains items which are architecture dependent.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver	Who    Date   Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a rmm  12/14/01 First release
+*	rmm  05/09/03 Added "xassert always" macros to rid ourselves of diab
+*		      compiler warnings
+* 1.00a rpm  11/07/03 Added XNullHandler function as a stub interrupt handler
+* </pre>
+*
+******************************************************************************/
+
+#ifndef XBASIC_TYPES_H		/* prevent circular inclusions */
+#define XBASIC_TYPES_H		/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+/************************** Constant Definitions *****************************/
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+/** Null */
+
+#define XCOMPONENT_IS_READY	0x11111111	/* component has been initialized */
+#define XCOMPONENT_IS_STARTED	0x22222222	/* component has been started */
+
+/* the following constants and declarations are for unit test purposes and are
+ * designed to be used in test applications.
+ */
+#define XTEST_PASSED	0
+#define XTEST_FAILED	1
+
+#define XASSERT_NONE	 0
+#define XASSERT_OCCURRED 1
+
+extern unsigned int XAssertStatus;
+extern void XAssert(char *, int);
+
+/**************************** Type Definitions *******************************/
+
+/** @name Primitive types
+ * These primitive types are created for transportability.
+ * They are dependent upon the target architecture.
+ * @{
+ */
+#include <linux/types.h>
+
+typedef struct {
+	u32 Upper;
+	u32 Lower;
+} Xuint64;
+
+/*@}*/
+
+/**
+ * This data type defines an interrupt handler for a device.
+ * The argument points to the instance of the component
+ */
+typedef void (*XInterruptHandler) (void *InstancePtr);
+
+/**
+ * This data type defines a callback to be invoked when an
+ * assert occurs. The callback is invoked only when asserts are enabled
+ */
+typedef void (*XAssertCallback) (char *FilenamePtr, int LineNumber);
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/*****************************************************************************/
+/**
+* Return the most significant half of the 64 bit data type.
+*
+* @param x is the 64 bit word.
+*
+* @return
+*
+* The upper 32 bits of the 64 bit word.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+#define XUINT64_MSW(x) ((x).Upper)
+
+/*****************************************************************************/
+/**
+* Return the least significant half of the 64 bit data type.
+*
+* @param x is the 64 bit word.
+*
+* @return
+*
+* The lower 32 bits of the 64 bit word.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+#define XUINT64_LSW(x) ((x).Lower)
+
+#ifndef NDEBUG
+
+/*****************************************************************************/
+/**
+* This assert macro is to be used for functions that do not return anything
+* (void). This in conjunction with the XWaitInAssert boolean can be used to
+* accomodate tests so that asserts which fail allow execution to continue.
+*
+* @param expression is the expression to evaluate. If it evaluates to false,
+*	 the assert occurs.
+*
+* @return
+*
+* Returns void unless the XWaitInAssert variable is true, in which case
+* no return is made and an infinite loop is entered.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+#define XASSERT_VOID(expression)			\
+{							\
+	if (expression) {				\
+		XAssertStatus = XASSERT_NONE;		\
+	} else {					\
+		XAssert(__FILE__, __LINE__);		\
+		XAssertStatus = XASSERT_OCCURRED;	\
+		return;					\
+	}						\
+}
+
+/*****************************************************************************/
+/**
+* This assert macro is to be used for functions that do return a value. This in
+* conjunction with the XWaitInAssert boolean can be used to accomodate tests so
+* that asserts which fail allow execution to continue.
+*
+* @param expression is the expression to evaluate. If it evaluates to false,
+*	 the assert occurs.
+*
+* @return
+*
+* Returns 0 unless the XWaitInAssert variable is true, in which case
+* no return is made and an infinite loop is entered.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+#define XASSERT_NONVOID(expression)		   \
+{						   \
+	if (expression) {			   \
+		XAssertStatus = XASSERT_NONE;	   \
+	} else {				   \
+		XAssert(__FILE__, __LINE__);	   \
+		XAssertStatus = XASSERT_OCCURRED;  \
+		return 0;			   \
+	}					   \
+}
+
+/*****************************************************************************/
+/**
+* Always assert. This assert macro is to be used for functions that do not
+* return anything (void). Use for instances where an assert should always
+* occur.
+*
+* @return
+*
+* Returns void unless the XWaitInAssert variable is true, in which case
+* no return is made and an infinite loop is entered.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+#define XASSERT_VOID_ALWAYS()			   \
+{						   \
+	XAssert(__FILE__, __LINE__);		   \
+	XAssertStatus = XASSERT_OCCURRED;	   \
+	return;					   \
+}
+
+/*****************************************************************************/
+/**
+* Always assert. This assert macro is to be used for functions that do return
+* a value. Use for instances where an assert should always occur.
+*
+* @return
+*
+* Returns void unless the XWaitInAssert variable is true, in which case
+* no return is made and an infinite loop is entered.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+#define XASSERT_NONVOID_ALWAYS()		   \
+{						   \
+	XAssert(__FILE__, __LINE__);		   \
+	XAssertStatus = XASSERT_OCCURRED;	   \
+	return 0;				   \
+}
+
+#else
+
+#define XASSERT_VOID(expression)
+#define XASSERT_VOID_ALWAYS()
+#define XASSERT_NONVOID(expression)
+#define XASSERT_NONVOID_ALWAYS()
+#endif
+
+/************************** Function Prototypes ******************************/
+
+void XAssertSetCallback(XAssertCallback Routine);
+void XNullHandler(void *NullParameter);
+
+#endif	/* end of protection macro */

+ 252 - 0
board/xilinx/common/xbuf_descriptor.h

@@ -0,0 +1,252 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* FILENAME:
+*
+* xbuf_descriptor.h
+*
+* DESCRIPTION:
+*
+* This file contains the interface for the XBufDescriptor component.
+* The XBufDescriptor component is a passive component that only maps over
+* a buffer descriptor data structure shared by the scatter gather DMA hardware
+* and software. The component's primary purpose is to provide encapsulation of
+* the buffer descriptor processing.  See the source file xbuf_descriptor.c for
+* details.
+*
+* NOTES:
+*
+* Most of the functions of this component are implemented as macros in order
+* to optimize the processing.  The names are not all uppercase such that they
+* can be switched between macros and functions easily.
+*
+******************************************************************************/
+
+#ifndef XBUF_DESCRIPTOR_H	/* prevent circular inclusions */
+#define XBUF_DESCRIPTOR_H	/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xdma_channel_i.h"
+
+/************************** Constant Definitions *****************************/
+
+/* The following constants allow access to all fields of a buffer descriptor
+ * and are necessary at this level of visibility to allow macros to access
+ * and modify the fields of a buffer descriptor.  It is not expected that the
+ * user of a buffer descriptor would need to use these constants.
+ */
+
+#define XBD_DEVICE_STATUS_OFFSET    0
+#define XBD_CONTROL_OFFSET	    1
+#define XBD_SOURCE_OFFSET	    2
+#define XBD_DESTINATION_OFFSET	    3
+#define XBD_LENGTH_OFFSET	    4
+#define XBD_STATUS_OFFSET	    5
+#define XBD_NEXT_PTR_OFFSET	    6
+#define XBD_ID_OFFSET		    7
+#define XBD_FLAGS_OFFSET	    8
+#define XBD_RQSTED_LENGTH_OFFSET    9
+
+#define XBD_SIZE_IN_WORDS	    10
+
+/*
+ * The following constants define the bits of the flags field of a buffer
+ * descriptor
+ */
+
+#define XBD_FLAGS_LOCKED_MASK	    1UL
+
+/**************************** Type Definitions *******************************/
+
+typedef u32 XBufDescriptor[XBD_SIZE_IN_WORDS];
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/* each of the following macros are named the same as functions rather than all
+ * upper case in order to allow either the macros or the functions to be
+ * used, see the source file xbuf_descriptor.c for documentation
+ */
+
+#define XBufDescriptor_Initialize(InstancePtr)			\
+{								\
+    (*((u32 *)InstancePtr + XBD_CONTROL_OFFSET) = 0);	    \
+    (*((u32 *)InstancePtr + XBD_SOURCE_OFFSET) = 0);	    \
+    (*((u32 *)InstancePtr + XBD_DESTINATION_OFFSET) = 0);   \
+    (*((u32 *)InstancePtr + XBD_LENGTH_OFFSET) = 0);	    \
+    (*((u32 *)InstancePtr + XBD_STATUS_OFFSET) = 0);	    \
+    (*((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET) = 0); \
+    (*((u32 *)InstancePtr + XBD_NEXT_PTR_OFFSET) = 0);	    \
+    (*((u32 *)InstancePtr + XBD_ID_OFFSET) = 0);	    \
+    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) = 0);	    \
+    (*((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET) = 0); \
+}
+
+#define XBufDescriptor_GetControl(InstancePtr)	 \
+    (u32)(*((u32 *)InstancePtr + XBD_CONTROL_OFFSET))
+
+#define XBufDescriptor_SetControl(InstancePtr, Control)	 \
+    (*((u32 *)InstancePtr + XBD_CONTROL_OFFSET) = (u32)Control)
+
+#define XBufDescriptor_IsLastControl(InstancePtr) \
+    (u32)(*((u32 *)InstancePtr + XBD_CONTROL_OFFSET) & \
+	       XDC_CONTROL_LAST_BD_MASK)
+
+#define XBufDescriptor_SetLast(InstancePtr) \
+    (*((u32 *)InstancePtr + XBD_CONTROL_OFFSET) |= XDC_CONTROL_LAST_BD_MASK)
+
+#define XBufDescriptor_GetSrcAddress(InstancePtr) \
+    ((u32 *)(*((u32 *)InstancePtr + XBD_SOURCE_OFFSET)))
+
+#define XBufDescriptor_SetSrcAddress(InstancePtr, Source) \
+    (*((u32 *)InstancePtr + XBD_SOURCE_OFFSET) = (u32)Source)
+
+#define XBufDescriptor_GetDestAddress(InstancePtr) \
+    ((u32 *)(*((u32 *)InstancePtr + XBD_DESTINATION_OFFSET)))
+
+#define XBufDescriptor_SetDestAddress(InstancePtr, Destination) \
+    (*((u32 *)InstancePtr + XBD_DESTINATION_OFFSET) = (u32)Destination)
+
+#define XBufDescriptor_GetLength(InstancePtr)				\
+    (u32)(*((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET) -	\
+	      *((u32 *)InstancePtr + XBD_LENGTH_OFFSET))
+
+#define XBufDescriptor_SetLength(InstancePtr, Length)			    \
+{									    \
+    (*((u32 *)InstancePtr + XBD_LENGTH_OFFSET) = (u32)(Length));    \
+    (*((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET) = (u32)(Length));\
+}
+
+#define XBufDescriptor_GetStatus(InstancePtr)	 \
+    (u32)(*((u32 *)InstancePtr + XBD_STATUS_OFFSET))
+
+#define XBufDescriptor_SetStatus(InstancePtr, Status)	 \
+    (*((u32 *)InstancePtr + XBD_STATUS_OFFSET) = (u32)Status)
+
+#define XBufDescriptor_IsLastStatus(InstancePtr) \
+    (u32)(*((u32 *)InstancePtr + XBD_STATUS_OFFSET) & \
+	       XDC_STATUS_LAST_BD_MASK)
+
+#define XBufDescriptor_GetDeviceStatus(InstancePtr) \
+    ((u32)(*((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET)))
+
+#define XBufDescriptor_SetDeviceStatus(InstancePtr, Status) \
+    (*((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET) = (u32)Status)
+
+#define XBufDescriptor_GetNextPtr(InstancePtr) \
+    (XBufDescriptor *)(*((u32 *)InstancePtr + XBD_NEXT_PTR_OFFSET))
+
+#define XBufDescriptor_SetNextPtr(InstancePtr, NextPtr) \
+    (*((u32 *)InstancePtr + XBD_NEXT_PTR_OFFSET) = (u32)NextPtr)
+
+#define XBufDescriptor_GetId(InstancePtr) \
+    (u32)(*((u32 *)InstancePtr + XBD_ID_OFFSET))
+
+#define XBufDescriptor_SetId(InstancePtr, Id) \
+    (*((u32 *)InstancePtr + XBD_ID_OFFSET) = (u32)Id)
+
+#define XBufDescriptor_GetFlags(InstancePtr) \
+    (u32)(*((u32 *)InstancePtr + XBD_FLAGS_OFFSET))
+
+#define XBufDescriptor_SetFlags(InstancePtr, Flags) \
+    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) = (u32)Flags)
+
+#define XBufDescriptor_Lock(InstancePtr) \
+    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) |= XBD_FLAGS_LOCKED_MASK)
+
+#define XBufDescriptor_Unlock(InstancePtr) \
+    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) &= ~XBD_FLAGS_LOCKED_MASK)
+
+#define XBufDescriptor_IsLocked(InstancePtr) \
+    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) & XBD_FLAGS_LOCKED_MASK)
+
+/************************** Function Prototypes ******************************/
+
+/* The following prototypes are provided to allow each of the functions to
+ * be implemented as a function rather than a macro, and to provide the
+ * syntax to allow users to understand how to call the macros, they are
+ * commented out to prevent linker errors
+ *
+
+u32 XBufDescriptor_Initialize(XBufDescriptor* InstancePtr);
+
+u32 XBufDescriptor_GetControl(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetControl(XBufDescriptor* InstancePtr, u32 Control);
+
+u32 XBufDescriptor_IsLastControl(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetLast(XBufDescriptor* InstancePtr);
+
+u32 XBufDescriptor_GetLength(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetLength(XBufDescriptor* InstancePtr, u32 Length);
+
+u32 XBufDescriptor_GetStatus(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetStatus(XBufDescriptor* InstancePtr, u32 Status);
+u32 XBufDescriptor_IsLastStatus(XBufDescriptor* InstancePtr);
+
+u32 XBufDescriptor_GetDeviceStatus(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetDeviceStatus(XBufDescriptor* InstancePtr,
+				    u32 Status);
+
+u32 XBufDescriptor_GetSrcAddress(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetSrcAddress(XBufDescriptor* InstancePtr,
+				  u32 SourceAddress);
+
+u32 XBufDescriptor_GetDestAddress(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetDestAddress(XBufDescriptor* InstancePtr,
+				   u32 DestinationAddress);
+
+XBufDescriptor* XBufDescriptor_GetNextPtr(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetNextPtr(XBufDescriptor* InstancePtr,
+			       XBufDescriptor* NextPtr);
+
+u32 XBufDescriptor_GetId(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetId(XBufDescriptor* InstancePtr, u32 Id);
+
+u32 XBufDescriptor_GetFlags(XBufDescriptor* InstancePtr);
+void XBufDescriptor_SetFlags(XBufDescriptor* InstancePtr, u32 Flags);
+
+void XBufDescriptor_Lock(XBufDescriptor* InstancePtr);
+void XBufDescriptor_Unlock(XBufDescriptor* InstancePtr);
+u32 XBufDescriptor_IsLocked(XBufDescriptor* InstancePtr);
+
+void XBufDescriptor_Copy(XBufDescriptor* InstancePtr,
+			 XBufDescriptor* DestinationPtr);
+
+*/
+
+#endif				/* end of protection macro */

+ 738 - 0
board/xilinx/common/xdma_channel.c

@@ -0,0 +1,738 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* FILENAME:
+*
+* xdma_channel.c
+*
+* DESCRIPTION:
+*
+* This file contains the DMA channel component. This component supports
+* a distributed DMA design in which each device can have it's own dedicated
+* DMA channel, as opposed to a centralized DMA design. This component
+* performs processing for DMA on all devices.
+*
+* See xdma_channel.h for more information about this component.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xdma_channel.h"
+#include "xbasic_types.h"
+#include "xio.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_Initialize
+*
+* DESCRIPTION:
+*
+* This function initializes a DMA channel.  This function must be called
+* prior to using a DMA channel.  Initialization of a channel includes setting
+* up the registers base address, and resetting the channel such that it's in a
+* known state.  Interrupts for the channel are disabled when the channel is
+* reset.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* BaseAddress contains the base address of the registers for the DMA channel.
+*
+* RETURN VALUE:
+*
+* XST_SUCCESS indicating initialization was successful.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XDmaChannel_Initialize(XDmaChannel * InstancePtr, u32 BaseAddress)
+{
+	/* assert to verify input arguments, don't assert base address */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+
+	/* setup the base address of the registers for the DMA channel such
+	 * that register accesses can be done
+	 */
+	InstancePtr->RegBaseAddress = BaseAddress;
+
+	/* initialize the scatter gather list such that it indicates it has not
+	 * been created yet and the DMA channel is ready to use (initialized)
+	 */
+	InstancePtr->GetPtr = NULL;
+	InstancePtr->PutPtr = NULL;
+	InstancePtr->CommitPtr = NULL;
+	InstancePtr->LastPtr = NULL;
+
+	InstancePtr->TotalDescriptorCount = 0;
+	InstancePtr->ActiveDescriptorCount = 0;
+	InstancePtr->IsReady = XCOMPONENT_IS_READY;
+
+	/* initialize the version of the component
+	 */
+	XVersion_FromString(&InstancePtr->Version, "1.00a");
+
+	/* reset the DMA channel such that it's in a known state and ready
+	 * and indicate the initialization occured with no errors, note that
+	 * the is ready variable must be set before this call or reset will assert
+	 */
+	XDmaChannel_Reset(InstancePtr);
+
+	return XST_SUCCESS;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_IsReady
+*
+* DESCRIPTION:
+*
+* This function determines if a DMA channel component has been successfully
+* initialized such that it's ready to use.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* RETURN VALUE:
+*
+* TRUE if the DMA channel component is ready, FALSE otherwise.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u32
+XDmaChannel_IsReady(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments used by the base component */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+
+	return InstancePtr->IsReady == XCOMPONENT_IS_READY;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetVersion
+*
+* DESCRIPTION:
+*
+* This function gets the software version for the specified DMA channel
+* component.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* RETURN VALUE:
+*
+* A pointer to the software version of the specified DMA channel.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+XVersion *
+XDmaChannel_GetVersion(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* return a pointer to the version of the DMA channel */
+
+	return &InstancePtr->Version;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_SelfTest
+*
+* DESCRIPTION:
+*
+* This function performs a self test on the specified DMA channel.  This self
+* test is destructive as the DMA channel is reset and a register default is
+* verified.
+*
+* ARGUMENTS:
+*
+* InstancePtr is a pointer to the DMA channel to be operated on.
+*
+* RETURN VALUE:
+*
+* XST_SUCCESS is returned if the self test is successful, or one of the
+* following errors.
+*
+*	XST_DMA_RESET_REGISTER_ERROR 		Indicates the control register value
+*										after a reset was not correct
+*
+* NOTES:
+*
+* This test does not performs a DMA transfer to test the channel because the
+* DMA hardware will not currently allow a non-local memory transfer to non-local
+* memory (memory copy), but only allows a non-local memory to or from the device
+* memory (typically a FIFO).
+*
+******************************************************************************/
+
+#define XDC_CONTROL_REG_RESET_MASK  0x98000000UL	/* control reg reset value */
+
+XStatus
+XDmaChannel_SelfTest(XDmaChannel * InstancePtr)
+{
+	u32 ControlReg;
+
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* reset the DMA channel such that it's in a known state before the test
+	 * it resets to no interrupts enabled, the desired state for the test
+	 */
+	XDmaChannel_Reset(InstancePtr);
+
+	/* this should be the first test to help prevent a lock up with the polling
+	 * loop that occurs later in the test, check the reset value of the DMA
+	 * control register to make sure it's correct, return with an error if not
+	 */
+	ControlReg = XDmaChannel_GetControl(InstancePtr);
+	if (ControlReg != XDC_CONTROL_REG_RESET_MASK) {
+		return XST_DMA_RESET_REGISTER_ERROR;
+	}
+
+	return XST_SUCCESS;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_Reset
+*
+* DESCRIPTION:
+*
+* This function resets the DMA channel. This is a destructive operation such
+* that it should not be done while a channel is being used.  If the DMA channel
+* is transferring data into other blocks, such as a FIFO, it may be necessary
+* to reset other blocks.  This function does not modify the contents of a
+* scatter gather list for a DMA channel such that the user is responsible for
+* getting buffer descriptors from the list if necessary.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+void
+XDmaChannel_Reset(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* reset the DMA channel such that it's in a known state, the reset
+	 * register is self clearing such that it only has to be set
+	 */
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_RST_REG_OFFSET,
+		  XDC_RESET_MASK);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetControl
+*
+* DESCRIPTION:
+*
+* This function gets the control register contents of the DMA channel.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* RETURN VALUE:
+*
+* The control register contents of the DMA channel. One or more of the
+* following values may be contained the register.  Each of the values are
+* unique bit masks.
+*
+*	XDC_DMACR_SOURCE_INCR_MASK	Increment the source address
+*	XDC_DMACR_DEST_INCR_MASK	Increment the destination address
+*	XDC_DMACR_SOURCE_LOCAL_MASK Local source address
+*	XDC_DMACR_DEST_LOCAL_MASK	Local destination address
+*	XDC_DMACR_SG_ENABLE_MASK	Scatter gather enable
+*	XDC_DMACR_GEN_BD_INTR_MASK	Individual buffer descriptor interrupt
+*	XDC_DMACR_LAST_BD_MASK		Last buffer descriptor in a packet
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u32
+XDmaChannel_GetControl(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* return the contents of the DMA control register */
+
+	return XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_SetControl
+*
+* DESCRIPTION:
+*
+* This function sets the control register of the specified DMA channel.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* Control contains the value to be written to the control register of the DMA
+* channel. One or more of the following values may be contained the register.
+* Each of the values are unique bit masks such that they may be ORed together
+* to enable multiple bits or inverted and ANDed to disable multiple bits.
+*
+*	XDC_DMACR_SOURCE_INCR_MASK	Increment the source address
+*	XDC_DMACR_DEST_INCR_MASK	Increment the destination address
+*	XDC_DMACR_SOURCE_LOCAL_MASK Local source address
+*	XDC_DMACR_DEST_LOCAL_MASK	Local destination address
+*	XDC_DMACR_SG_ENABLE_MASK	Scatter gather enable
+*	XDC_DMACR_GEN_BD_INTR_MASK	Individual buffer descriptor interrupt
+*	XDC_DMACR_LAST_BD_MASK		Last buffer descriptor in a packet
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+void
+XDmaChannel_SetControl(XDmaChannel * InstancePtr, u32 Control)
+{
+	/* assert to verify input arguments except the control which can't be
+	 * asserted since all values are valid
+	 */
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* set the DMA control register to the specified value */
+
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET, Control);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetStatus
+*
+* DESCRIPTION:
+*
+* This function gets the status register contents of the DMA channel.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* RETURN VALUE:
+*
+* The status register contents of the DMA channel. One or more of the
+* following values may be contained the register. Each of the values are
+* unique bit masks.
+*
+*	XDC_DMASR_BUSY_MASK			The DMA channel is busy
+*	XDC_DMASR_BUS_ERROR_MASK	A bus error occurred
+*	XDC_DMASR_BUS_TIMEOUT_MASK	A bus timeout occurred
+*	XDC_DMASR_LAST_BD_MASK		The last buffer descriptor of a packet
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u32
+XDmaChannel_GetStatus(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* return the contents of the DMA status register */
+
+	return XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAS_REG_OFFSET);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_SetIntrStatus
+*
+* DESCRIPTION:
+*
+* This function sets the interrupt status register of the specified DMA channel.
+* Setting any bit of the interrupt status register will clear the bit to
+* indicate the interrupt processing has been completed. The definitions of each
+* bit in the register match the definition of the bits in the interrupt enable
+* register.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* Status contains the value to be written to the status register of the DMA
+* channel.  One or more of the following values may be contained the register.
+* Each of the values are unique bit masks such that they may be ORed together
+* to enable multiple bits or inverted and ANDed to disable multiple bits.
+*
+*	XDC_IXR_DMA_DONE_MASK		The dma operation is done
+*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error
+*	XDC_IXR_PKT_DONE_MASK	    A packet is complete
+*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached
+*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached
+*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed
+*	XDC_IXR_BD_MASK				A buffer descriptor is done
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+void
+XDmaChannel_SetIntrStatus(XDmaChannel * InstancePtr, u32 Status)
+{
+	/* assert to verify input arguments except the status which can't be
+	 * asserted since all values are valid
+	 */
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* set the interrupt status register with the specified value such that
+	 * all bits which are set in the register are cleared effectively clearing
+	 * any active interrupts
+	 */
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET, Status);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetIntrStatus
+*
+* DESCRIPTION:
+*
+* This function gets the interrupt status register of the specified DMA channel.
+* The interrupt status register indicates which interrupts are active
+* for the DMA channel.  If an interrupt is active, the status register must be
+* set (written) with the bit set for each interrupt which has been processed
+* in order to clear the interrupts.  The definitions of each bit in the register
+* match the definition of the bits in the interrupt enable register.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* RETURN VALUE:
+*
+* The interrupt status register contents of the specified DMA channel.
+* One or more of the following values may be contained the register.
+* Each of the values are unique bit masks.
+*
+*	XDC_IXR_DMA_DONE_MASK		The dma operation is done
+*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error
+*	XDC_IXR_PKT_DONE_MASK	    A packet is complete
+*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached
+*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached
+*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed
+*	XDC_IXR_SG_END_MASK			Current descriptor was the end of the list
+*	XDC_IXR_BD_MASK				A buffer descriptor is done
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u32
+XDmaChannel_GetIntrStatus(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* return the contents of the interrupt status register */
+
+	return XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_SetIntrEnable
+*
+* DESCRIPTION:
+*
+* This function sets the interrupt enable register of the specified DMA
+* channel.  The interrupt enable register contains bits which enable
+* individual interrupts for the DMA channel.  The definitions of each bit
+* in the register match the definition of the bits in the interrupt status
+* register.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* Enable contains the interrupt enable register contents to be written
+* in the DMA channel. One or more of the following values may be contained
+* the register. Each of the values are unique bit masks such that they may be
+* ORed together to enable multiple bits or inverted and ANDed to disable
+* multiple bits.
+*
+*	XDC_IXR_DMA_DONE_MASK		The dma operation is done
+*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error
+*	XDC_IXR_PKT_DONE_MASK	    A packet is complete
+*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached
+*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached
+*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed
+*	XDC_IXR_SG_END_MASK			Current descriptor was the end of the list
+*	XDC_IXR_BD_MASK				A buffer descriptor is done
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+void
+XDmaChannel_SetIntrEnable(XDmaChannel * InstancePtr, u32 Enable)
+{
+	/* assert to verify input arguments except the enable which can't be
+	 * asserted since all values are valid
+	 */
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* set the interrupt enable register to the specified value */
+
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IE_REG_OFFSET, Enable);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetIntrEnable
+*
+* DESCRIPTION:
+*
+* This function gets the interrupt enable of the DMA channel.  The
+* interrupt enable contains flags which enable individual interrupts for the
+* DMA channel. The definitions of each bit in the register match the definition
+* of the bits in the interrupt status register.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* RETURN VALUE:
+*
+* The interrupt enable of the DMA channel.  One or more of the following values
+* may be contained the register. Each of the values are unique bit masks.
+*
+*	XDC_IXR_DMA_DONE_MASK		The dma operation is done
+*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error
+*	XDC_IXR_PKT_DONE_MASK	    A packet is complete
+*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached
+*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached
+*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed
+*	XDC_IXR_BD_MASK				A buffer descriptor is done
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u32
+XDmaChannel_GetIntrEnable(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* return the contents of the interrupt enable register */
+
+	return XIo_In32(InstancePtr->RegBaseAddress + XDC_IE_REG_OFFSET);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_Transfer
+*
+* DESCRIPTION:
+*
+* This function starts the DMA channel transferring data from a memory source
+* to a memory destination. This function only starts the operation and returns
+* before the operation may be complete.  If the interrupt is enabled, an
+* interrupt will be generated when the operation is complete, otherwise it is
+* necessary to poll the channel status to determine when it's complete.  It is
+* the responsibility of the caller to determine when the operation is complete
+* by handling the generated interrupt or polling the status.  It is also the
+* responsibility of the caller to ensure that the DMA channel is not busy with
+* another transfer before calling this function.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.
+*
+* SourcePtr contains a pointer to the source memory where the data is to
+* be tranferred from and must be 32 bit aligned.
+*
+* DestinationPtr contains a pointer to the destination memory where the data
+* is to be transferred and must be 32 bit aligned.
+*
+* ByteCount contains the number of bytes to transfer during the DMA operation.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* The DMA h/w will not currently allow a non-local memory transfer to non-local
+* memory (memory copy), but only allows a non-local memory to or from the device
+* memory (typically a FIFO).
+*
+* It is the responsibility of the caller to ensure that the cache is
+* flushed and invalidated both before and after the DMA operation completes
+* if the memory pointed to is cached. The caller must also ensure that the
+* pointers contain a physical address rather than a virtual address
+* if address translation is being used.
+*
+******************************************************************************/
+void
+XDmaChannel_Transfer(XDmaChannel * InstancePtr,
+		     u32 * SourcePtr, u32 * DestinationPtr, u32 ByteCount)
+{
+	/* assert to verify input arguments and the alignment of any arguments
+	 * which have expected alignments
+	 */
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(SourcePtr != NULL);
+	XASSERT_VOID(((u32) SourcePtr & 3) == 0);
+	XASSERT_VOID(DestinationPtr != NULL);
+	XASSERT_VOID(((u32) DestinationPtr & 3) == 0);
+	XASSERT_VOID(ByteCount != 0);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* setup the source and destination address registers for the transfer */
+
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SA_REG_OFFSET,
+		  (u32) SourcePtr);
+
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DA_REG_OFFSET,
+		  (u32) DestinationPtr);
+
+	/* start the DMA transfer to copy from the source buffer to the
+	 * destination buffer by writing the length to the length register
+	 */
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_LEN_REG_OFFSET, ByteCount);
+}

+ 291 - 0
board/xilinx/common/xdma_channel.h

@@ -0,0 +1,291 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* FILENAME:
+*
+* xdma_channel.h
+*
+* DESCRIPTION:
+*
+* This file contains the DMA channel component implementation. This component
+* supports a distributed DMA design in which each device can have it's own
+* dedicated DMA channel, as opposed to a centralized DMA design.
+* A device which uses DMA typically contains two DMA channels, one for
+* sending data and the other for receiving data.
+*
+* This component is designed to be used as a basic building block for
+* designing a device driver. It provides registers accesses such that all
+* DMA processing can be maintained easier, but the device driver designer
+* must still understand all the details of the DMA channel.
+*
+* The DMA channel allows a CPU to minimize the CPU interaction required to move
+* data between a memory and a device.  The CPU requests the DMA channel to
+* perform a DMA operation and typically continues performing other processing
+* until the DMA operation completes.  DMA could be considered a primitive form
+* of multiprocessing such that caching and address translation can be an issue.
+*
+* Scatter Gather Operations
+*
+* The DMA channel may support scatter gather operations. A scatter gather
+* operation automates the DMA channel such that multiple buffers can be
+* sent or received with minimal software interaction with the hardware.  Buffer
+* descriptors, contained in the XBufDescriptor component, are used by the
+* scatter gather operations of the DMA channel to describe the buffers to be
+* processed.
+*
+* Scatter Gather List Operations
+*
+* A scatter gather list may be supported by each DMA channel.  The scatter
+* gather list allows buffer descriptors to be put into the list by a device
+* driver which requires scatter gather.  The hardware processes the buffer
+* descriptors which are contained in the list and modifies the buffer
+* descriptors to reflect the status of the DMA operations.  The device driver
+* is notified by interrupt that specific DMA events occur including scatter
+* gather events.  The device driver removes the completed buffer descriptors
+* from the scatter gather list to evaluate the status of each DMA operation.
+*
+* The scatter gather list is created and buffer descriptors are inserted into
+* the list.  Buffer descriptors are never removed from the list after it's
+* creation such that a put operation copies from a temporary buffer descriptor
+* to a buffer descriptor in the list.  Get operations don't copy from the list
+* to a temporary, but return a pointer to the buffer descriptor in the list.
+* A buffer descriptor in the list may be locked to prevent it from being
+* overwritten by a put operation.  This allows the device driver to get a
+* descriptor from a scatter gather list and prevent it from being overwritten
+* until the buffer associated with the buffer descriptor has been processed.
+*
+* Typical Scatter Gather Processing
+*
+* The following steps illustrate the typical processing to use the
+* scatter gather features of a DMA channel.
+*
+* 1. Create a scatter gather list for the DMA channel which puts empty buffer
+*    descriptors into the list.
+* 2. Create buffer descriptors which describe the buffers to be filled with
+* 	 receive data or the buffers which contain data to be sent.
+* 3. Put buffer descriptors into the DMA channel scatter list such that scatter
+*    gather operations are requested.
+* 4. Commit the buffer descriptors in the list such that they are ready to be
+*    used by the DMA channel hardware.
+* 5. Start the scatter gather operations of the DMA channel.
+* 6. Process any interrupts which occur as a result of the scatter gather
+*    operations or poll the DMA channel to determine the status.
+*
+* Interrupts
+*
+* Each DMA channel has the ability to generate an interrupt.  This component
+* does not perform processing for the interrupt as this processing is typically
+* tightly coupled with the device which is using the DMA channel.  It is the
+* responsibility of the caller of DMA functions to manage the interrupt
+* including connecting to the interrupt and enabling/disabling the interrupt.
+*
+* Critical Sections
+*
+* It is the responsibility of the device driver designer to use critical
+* sections as necessary when calling functions of the DMA channel.  This
+* component does not use critical sections and it does access registers using
+* read-modify-write operations.  Calls to DMA functions from a main thread
+* and from an interrupt context could produce unpredictable behavior such that
+* the caller must provide the appropriate critical sections.
+*
+* Address Translation
+*
+* All addresses of data structures which are passed to DMA functions must
+* be physical (real) addresses as opposed to logical (virtual) addresses.
+*
+* Caching
+*
+* The memory which is passed to the function which creates the scatter gather
+* list must not be cached such that buffer descriptors are non-cached.  This
+* is necessary because the buffer descriptors are kept in a ring buffer and
+* not directly accessible to the caller of DMA functions.
+*
+* The caller of DMA functions is responsible for ensuring that any data
+* buffers which are passed to the DMA channel are cache-line aligned if
+* necessary.
+*
+* The caller of DMA functions is responsible for ensuring that any data
+* buffers which are passed to the DMA channel have been flushed from the cache.
+*
+* The caller of DMA functions is responsible for ensuring that the cache is
+* invalidated prior to using any data buffers which are the result of a DMA
+* operation.
+*
+* Memory Alignment
+*
+* The addresses of data buffers which are passed to DMA functions must be
+* 32 bit word aligned since the DMA hardware performs 32 bit word transfers.
+*
+* Mutual Exclusion
+*
+* The functions of the DMA channel are not thread safe such that the caller
+* of all DMA functions is responsible for ensuring mutual exclusion for a
+* DMA channel.  Mutual exclusion across multiple DMA channels is not
+* necessary.
+*
+* NOTES:
+*
+* Many of the provided functions which are register accessors don't provide
+* a lot of error detection. The caller is expected to understand the impact
+* of a function call based upon the current state of the DMA channel.  This
+* is done to minimize the overhead in this component.
+*
+******************************************************************************/
+
+#ifndef XDMA_CHANNEL_H		/* prevent circular inclusions */
+#define XDMA_CHANNEL_H		/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xdma_channel_i.h"	/* constants shared with buffer descriptor */
+#include "xbasic_types.h"
+#include "xstatus.h"
+#include "xversion.h"
+#include "xbuf_descriptor.h"
+
+/************************** Constant Definitions *****************************/
+
+/* the following constants provide access to the bit fields of the DMA control
+ * register (DMACR)
+ */
+#define XDC_DMACR_SOURCE_INCR_MASK	0x80000000UL	/* increment source address */
+#define XDC_DMACR_DEST_INCR_MASK	0x40000000UL	/* increment dest address */
+#define XDC_DMACR_SOURCE_LOCAL_MASK 0x20000000UL	/* local source address */
+#define XDC_DMACR_DEST_LOCAL_MASK	0x10000000UL	/* local dest address */
+#define XDC_DMACR_SG_DISABLE_MASK	0x08000000UL	/* scatter gather disable */
+#define XDC_DMACR_GEN_BD_INTR_MASK	0x04000000UL	/* descriptor interrupt */
+#define XDC_DMACR_LAST_BD_MASK		XDC_CONTROL_LAST_BD_MASK	/* last buffer */
+															 /*     descriptor  */
+
+/* the following constants provide access to the bit fields of the DMA status
+ * register (DMASR)
+ */
+#define XDC_DMASR_BUSY_MASK			0x80000000UL	/* channel is busy */
+#define XDC_DMASR_BUS_ERROR_MASK	0x40000000UL	/* bus error occurred */
+#define XDC_DMASR_BUS_TIMEOUT_MASK	0x20000000UL	/* bus timeout occurred */
+#define XDC_DMASR_LAST_BD_MASK		XDC_STATUS_LAST_BD_MASK	/* last buffer */
+														    /* descriptor  */
+#define XDC_DMASR_SG_BUSY_MASK		0x08000000UL	/* scatter gather is busy */
+
+/* the following constants provide access to the bit fields of the interrupt
+ * status register (ISR) and the interrupt enable register (IER), bit masks
+ * match for both registers such that they are named IXR
+ */
+#define XDC_IXR_DMA_DONE_MASK		0x1UL	/* dma operation done */
+#define XDC_IXR_DMA_ERROR_MASK	    0x2UL	/* dma operation error */
+#define XDC_IXR_PKT_DONE_MASK	    0x4UL	/* packet done */
+#define XDC_IXR_PKT_THRESHOLD_MASK 	0x8UL	/* packet count threshold */
+#define XDC_IXR_PKT_WAIT_BOUND_MASK 0x10UL	/* packet wait bound reached */
+#define XDC_IXR_SG_DISABLE_ACK_MASK 0x20UL	/* scatter gather disable
+						   acknowledge occurred */
+#define XDC_IXR_SG_END_MASK			0x40UL	/* last buffer descriptor
+							   disabled scatter gather */
+#define XDC_IXR_BD_MASK				0x80UL	/* buffer descriptor done */
+
+/**************************** Type Definitions *******************************/
+
+/*
+ * the following structure contains data which is on a per instance basis
+ * for the XDmaChannel component
+ */
+typedef struct XDmaChannelTag {
+	XVersion Version;	/* version of the driver */
+	u32 RegBaseAddress;	/* base address of registers */
+	u32 IsReady;		/* device is initialized and ready */
+
+	XBufDescriptor *PutPtr;	/* keep track of where to put into list */
+	XBufDescriptor *GetPtr;	/* keep track of where to get from list */
+	XBufDescriptor *CommitPtr;	/* keep track of where to commit in list */
+	XBufDescriptor *LastPtr;	/* keep track of the last put in the list */
+	u32 TotalDescriptorCount;	/* total # of descriptors in the list */
+	u32 ActiveDescriptorCount;	/* # of descriptors pointing to buffers
+					   * in the buffer descriptor list */
+} XDmaChannel;
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+XStatus XDmaChannel_Initialize(XDmaChannel * InstancePtr, u32 BaseAddress);
+u32 XDmaChannel_IsReady(XDmaChannel * InstancePtr);
+XVersion *XDmaChannel_GetVersion(XDmaChannel * InstancePtr);
+XStatus XDmaChannel_SelfTest(XDmaChannel * InstancePtr);
+void XDmaChannel_Reset(XDmaChannel * InstancePtr);
+
+/* Control functions */
+
+u32 XDmaChannel_GetControl(XDmaChannel * InstancePtr);
+void XDmaChannel_SetControl(XDmaChannel * InstancePtr, u32 Control);
+
+/* Status functions */
+
+u32 XDmaChannel_GetStatus(XDmaChannel * InstancePtr);
+void XDmaChannel_SetIntrStatus(XDmaChannel * InstancePtr, u32 Status);
+u32 XDmaChannel_GetIntrStatus(XDmaChannel * InstancePtr);
+void XDmaChannel_SetIntrEnable(XDmaChannel * InstancePtr, u32 Enable);
+u32 XDmaChannel_GetIntrEnable(XDmaChannel * InstancePtr);
+
+/* DMA without scatter gather functions */
+
+void XDmaChannel_Transfer(XDmaChannel * InstancePtr,
+			  u32 * SourcePtr, u32 * DestinationPtr, u32 ByteCount);
+
+/* Scatter gather functions */
+
+XStatus XDmaChannel_SgStart(XDmaChannel * InstancePtr);
+XStatus XDmaChannel_SgStop(XDmaChannel * InstancePtr,
+			   XBufDescriptor ** BufDescriptorPtr);
+XStatus XDmaChannel_CreateSgList(XDmaChannel * InstancePtr,
+				 u32 * MemoryPtr, u32 ByteCount);
+u32 XDmaChannel_IsSgListEmpty(XDmaChannel * InstancePtr);
+
+XStatus XDmaChannel_PutDescriptor(XDmaChannel * InstancePtr,
+				  XBufDescriptor * BufDescriptorPtr);
+XStatus XDmaChannel_CommitPuts(XDmaChannel * InstancePtr);
+XStatus XDmaChannel_GetDescriptor(XDmaChannel * InstancePtr,
+				  XBufDescriptor ** BufDescriptorPtr);
+
+/* Packet functions for interrupt collescing */
+
+u32 XDmaChannel_GetPktCount(XDmaChannel * InstancePtr);
+void XDmaChannel_DecrementPktCount(XDmaChannel * InstancePtr);
+XStatus XDmaChannel_SetPktThreshold(XDmaChannel * InstancePtr, u8 Threshold);
+u8 XDmaChannel_GetPktThreshold(XDmaChannel * InstancePtr);
+void XDmaChannel_SetPktWaitBound(XDmaChannel * InstancePtr, u32 WaitBound);
+u32 XDmaChannel_GetPktWaitBound(XDmaChannel * InstancePtr);
+
+#endif				/* end of protection macro */

+ 110 - 0
board/xilinx/common/xdma_channel_i.h

@@ -0,0 +1,110 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* FILENAME:
+*
+* xdma_channel_i.h
+*
+* DESCRIPTION:
+*
+* This file contains data which is shared internal data for the DMA channel
+* component. It is also shared with the buffer descriptor component which is
+* very tightly coupled with the DMA channel component.
+*
+* NOTES:
+*
+* The last buffer descriptor constants must be located here to prevent a
+* circular dependency between the DMA channel component and the buffer
+* descriptor component.
+*
+******************************************************************************/
+
+#ifndef XDMA_CHANNEL_I_H	/* prevent circular inclusions */
+#define XDMA_CHANNEL_I_H	/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xstatus.h"
+#include "xversion.h"
+
+/************************** Constant Definitions *****************************/
+
+#define XDC_DMA_CHANNEL_V1_00_A		"1.00a"
+
+/* the following constant provides access to the bit fields of the DMA control
+ * register (DMACR) which must be shared between the DMA channel component
+ * and the buffer descriptor component
+ */
+#define XDC_CONTROL_LAST_BD_MASK	0x02000000UL	/* last buffer descriptor */
+
+/* the following constant provides access to the bit fields of the DMA status
+ * register (DMASR) which must be shared between the DMA channel component
+ * and the buffer descriptor component
+ */
+#define XDC_STATUS_LAST_BD_MASK		0x10000000UL	/* last buffer descriptor */
+
+/* the following constants provide access to each of the registers of a DMA
+ * channel
+ */
+#define XDC_RST_REG_OFFSET	0	/* reset register */
+#define XDC_MI_REG_OFFSET	0	/* module information register */
+#define XDC_DMAC_REG_OFFSET	4	/* DMA control register */
+#define XDC_SA_REG_OFFSET	8	/* source address register */
+#define XDC_DA_REG_OFFSET	12	/* destination address register */
+#define XDC_LEN_REG_OFFSET	16	/* length register */
+#define XDC_DMAS_REG_OFFSET	20	/* DMA status register */
+#define XDC_BDA_REG_OFFSET	24	/* buffer descriptor address register */
+#define XDC_SWCR_REG_OFFSET 28	/* software control register */
+#define XDC_UPC_REG_OFFSET	32	/* unserviced packet count register */
+#define	XDC_PCT_REG_OFFSET	36	/* packet count threshold register */
+#define XDC_PWB_REG_OFFSET	40	/* packet wait bound register */
+#define XDC_IS_REG_OFFSET	44	/* interrupt status register */
+#define XDC_IE_REG_OFFSET	48	/* interrupt enable register */
+
+/* the following constant is written to the reset register to reset the
+ * DMA channel
+ */
+#define XDC_RESET_MASK				0x0000000AUL
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+#endif				/* end of protection macro */

+ 1317 - 0
board/xilinx/common/xdma_channel_sg.c

@@ -0,0 +1,1317 @@
+/* $Id: xdma_channel_sg.c,v 1.6 2003/02/03 19:50:33 moleres Exp $ */
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* FILENAME:
+*
+* xdma_channel_sg.c
+*
+* DESCRIPTION:
+*
+* This file contains the implementation of the XDmaChannel component which is
+* related to scatter gather operations.
+*
+* Scatter Gather Operations
+*
+* The DMA channel may support scatter gather operations. A scatter gather
+* operation automates the DMA channel such that multiple buffers can be
+* sent or received with minimal software interaction with the hardware.	 Buffer
+* descriptors, contained in the XBufDescriptor component, are used by the
+* scatter gather operations of the DMA channel to describe the buffers to be
+* processed.
+*
+* Scatter Gather List Operations
+*
+* A scatter gather list may be supported by each DMA channel.  The scatter
+* gather list allows buffer descriptors to be put into the list by a device
+* driver which requires scatter gather.	 The hardware processes the buffer
+* descriptors which are contained in the list and modifies the buffer
+* descriptors to reflect the status of the DMA operations.  The device driver
+* is notified by interrupt that specific DMA events occur including scatter
+* gather events.  The device driver removes the completed buffer descriptors
+* from the scatter gather list to evaluate the status of each DMA operation.
+*
+* The scatter gather list is created and buffer descriptors are inserted into
+* the list.  Buffer descriptors are never removed from the list after it's
+* creation such that a put operation copies from a temporary buffer descriptor
+* to a buffer descriptor in the list.  Get operations don't copy from the list
+* to a temporary, but return a pointer to the buffer descriptor in the list.
+* A buffer descriptor in the list may be locked to prevent it from being
+* overwritten by a put operation.  This allows the device driver to get a
+* descriptor from a scatter gather list and prevent it from being overwritten
+* until the buffer associated with the buffer descriptor has been processed.
+*
+* The get and put functions only operate on the list and are asynchronous from
+* the hardware which may be using the list of descriptors.  This is important
+* because there are no checks in the get and put functions to ensure that the
+* hardware has processed the descriptors.  This must be handled by the driver
+* using the DMA scatter gather channel through the use of the other functions.
+* When a scatter gather operation is started, the start function does ensure
+* that the descriptor to start has not already been processed by the hardware
+* and is not the first of a series of descriptors that have not been committed
+* yet.
+*
+* Descriptors are put into the list but not marked as ready to use by the
+* hardware until a commit operation is done.  This allows multiple descriptors
+* which may contain a single packet of information for a protocol to be
+* guaranteed not to cause any underflow conditions during transmission. The
+* hardware design only allows descriptors to cause it to stop after a descriptor
+* has been processed rather than before it is processed.  A series of
+* descriptors are put into the list followed by a commit operation, or each
+* descriptor may be commited.  A commit operation is performed by changing a
+* single descriptor, the first of the series of puts, to indicate that the
+* hardware may now use all descriptors after it.  The last descriptor in the
+* list is always set to cause the hardware to stop after it is processed.
+*
+* Typical Scatter Gather Processing
+*
+* The following steps illustrate the typical processing to use the
+* scatter gather features of a DMA channel.
+*
+* 1. Create a scatter gather list for the DMA channel which puts empty buffer
+*    descriptors into the list.
+* 2. Create buffer descriptors which describe the buffers to be filled with
+*    receive data or the buffers which contain data to be sent.
+* 3. Put buffer descriptors into the DMA channel scatter list such that scatter
+*    gather operations are requested.
+* 4. Commit the buffer descriptors in the list such that they are ready to be
+*    used by the DMA channel hardware.
+* 5. Start the scatter gather operations of the DMA channel.
+* 6. Process any interrupts which occur as a result of the scatter gather
+*    operations or poll the DMA channel to determine the status.  This may
+*    be accomplished by getting the packet count for the channel and then
+*    getting the appropriate number of descriptors from the list for that
+*    number of packets.
+*
+* Minimizing Interrupts
+*
+* The Scatter Gather operating mode is designed to reduce the amount of CPU
+* throughput necessary to manage the hardware for devices. A key to the CPU
+* throughput is the number and rate of interrupts that the CPU must service.
+* Devices with higher data rates can cause larger numbers of interrupts and
+* higher frequency interrupts. Ideally the number of interrupts can be reduced
+* by only generating an interrupt when a specific amount of data has been
+* received from the interface. This design suffers from a lack of interrupts
+* when the amount of data received is less than the specified amount of data
+* to generate an interrupt. In order to help minimize the number of interrupts
+* which the CPU must service, an algorithm referred to as "interrupt coalescing"
+* is utilized.
+*
+* Interrupt Coalescing
+*
+* The principle of interrupt coalescing is to wait before generating an
+* interrupt until a certain number of packets have been received or sent. An
+* interrupt is also generated if a smaller number of packets have been received
+* followed by a certain period of time with no packet reception. This is a
+* trade-off of latency for bandwidth and is accomplished using several
+* mechanisms of the hardware including a counter for packets received or
+* transmitted and a packet timer. These two hardware mechanisms work in
+* combination to allow a reduction in the number of interrupts processed by the
+* CPU for packet reception.
+*
+* Unserviced Packet Count
+*
+* The purpose of the packet counter is to count the number of packets received
+* or transmitted and provide an interrupt when a specific number of packets
+* have been processed by the hardware. An interrupt is generated whenever the
+* counter is greater than or equal to the Packet Count Threshold. This counter
+* contains an accurate count of the number of packets that the hardware has
+* processed, either received or transmitted, and the software has not serviced.
+*
+* The packet counter allows the number of interrupts to be reduced by waiting
+* to generate an interrupt until enough packets are received. For packet
+* reception, packet counts of less than the number to generate an interrupt
+* would not be serviced without the addition of a packet timer. This counter is
+* continuously updated by the hardware, not latched to the value at the time
+* the interrupt occurred.
+*
+* The packet counter can be used within the interrupt service routine for the
+* device to reduce the number of interrupts. The interrupt service routine
+* loops while performing processing for each packet which has been received or
+* transmitted and decrements the counter by a specified value. At the same time,
+* the hardware is possibly continuing to receive or transmit more packets such
+* that the software may choose, based upon the value in the packet counter, to
+* remain in the interrupt service routine rather than exiting and immediately
+* returning. This feature should be used with caution as reducing the number of
+* interrupts is beneficial, but unbounded interrupt processing is not desirable.
+*
+* Since the hardware may be incrementing the packet counter simultaneously
+* with the software decrementing the counter, there is a need for atomic
+* operations. The hardware ensures that the operation is atomic such that
+* simultaneous accesses are properly handled.
+*
+* Packet Wait Bound
+*
+* The purpose of the packet wait bound is to augment the unserviced packet
+* count. Whenever there is no pending interrupt for the channel and the
+* unserviced packet count is non-zero, a timer starts counting timeout at the
+* value contained the the packet wait bound register.  If the timeout is
+* reached, an interrupt is generated such that the software may service the
+* data which was buffered.
+*
+* NOTES:
+*
+* Special Test Conditions:
+*
+* The scatter gather list processing must be thoroughly tested if changes are
+* made.	 Testing should include putting and committing single descriptors and
+* putting multiple descriptors followed by a single commit.  There are some
+* conditions in the code which handle the exception conditions.
+*
+* The Put Pointer points to the next location in the descriptor list to copy
+* in a new descriptor. The Get Pointer points to the next location in the
+* list to get a descriptor from.  The Get Pointer only allows software to
+* have a traverse the list after the hardware has finished processing some
+* number of descriptors.  The Commit Pointer points to the descriptor in the
+* list which is to be committed.  It is also used to determine that no
+* descriptor is waiting to be commited (NULL).	The Last Pointer points to
+* the last descriptor that was put into the list.  It typically points
+* to the previous descriptor to the one pointed to by the Put Pointer.
+* Comparisons are done between these pointers to determine when the following
+* special conditions exist.
+
+* Single Put And Commit
+*
+* The buffer descriptor is ready to be used by the hardware so it is important
+* for the descriptor to not appear to be waiting to be committed.  The commit
+* pointer is reset when a commit is done indicating there are no descriptors
+* waiting to be committed.  In all cases but this one, the descriptor is
+* changed to cause the hardware to go to the next descriptor after processing
+* this one.  But in this case, this is the last descriptor in the list such
+* that it must not be changed.
+*
+* 3 Or More Puts And Commit
+*
+* A series of 3 or more puts followed by a single commit is different in that
+* only the 1st descriptor put into the list is changed when the commit is done.
+* This requires each put starting on the 3rd to change the previous descriptor
+* so that it allows the hardware to continue to the next descriptor in the list.
+*
+* The 1st Put Following A Commit
+*
+* The commit caused the commit pointer to be NULL indicating that there are no
+* descriptors waiting to be committed.	It is necessary for the next put to set
+* the commit pointer so that a commit must follow the put for the hardware to
+* use the descriptor.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver	Who  Date     Changes
+* ----- ---- -------- ------------------------------------------------------
+* 1.00a rpm  02/03/03 Removed the XST_DMA_SG_COUNT_EXCEEDED return code
+*		      from SetPktThreshold.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xdma_channel.h"
+#include "xbasic_types.h"
+#include "xio.h"
+#include "xbuf_descriptor.h"
+#include "xstatus.h"
+
+/************************** Constant Definitions *****************************/
+
+#define XDC_SWCR_SG_ENABLE_MASK 0x80000000UL	/* scatter gather enable */
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/* the following macro copies selected fields of a buffer descriptor to another
+ * buffer descriptor, this was provided by the buffer descriptor component but
+ * was moved here since it is only used internally to this component and since
+ * it does not copy all fields
+ */
+#define CopyBufferDescriptor(InstancePtr, DestinationPtr)	   \
+{								   \
+    *((u32 *)DestinationPtr + XBD_CONTROL_OFFSET) =	       \
+	*((u32 *)InstancePtr + XBD_CONTROL_OFFSET);	       \
+    *((u32 *)DestinationPtr + XBD_SOURCE_OFFSET) =	       \
+	*((u32 *)InstancePtr + XBD_SOURCE_OFFSET);	       \
+    *((u32 *)DestinationPtr + XBD_DESTINATION_OFFSET) =	       \
+	*((u32 *)InstancePtr + XBD_DESTINATION_OFFSET);	       \
+    *((u32 *)DestinationPtr + XBD_LENGTH_OFFSET) =	       \
+	*((u32 *)InstancePtr + XBD_LENGTH_OFFSET);	       \
+    *((u32 *)DestinationPtr + XBD_STATUS_OFFSET) =	       \
+	*((u32 *)InstancePtr + XBD_STATUS_OFFSET);	       \
+    *((u32 *)DestinationPtr + XBD_DEVICE_STATUS_OFFSET) =      \
+	*((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET);      \
+    *((u32 *)DestinationPtr + XBD_ID_OFFSET) =		       \
+	*((u32 *)InstancePtr + XBD_ID_OFFSET);		       \
+    *((u32 *)DestinationPtr + XBD_FLAGS_OFFSET) =	       \
+	*((u32 *)InstancePtr + XBD_FLAGS_OFFSET);	       \
+    *((u32 *)DestinationPtr + XBD_RQSTED_LENGTH_OFFSET) =      \
+	*((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET);      \
+}
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_SgStart
+*
+* DESCRIPTION:
+*
+* This function starts a scatter gather operation for a scatter gather
+* DMA channel.	The first buffer descriptor in the buffer descriptor list
+* will be started with the scatter gather operation.  A scatter gather list
+* should have previously been created for the DMA channel and buffer
+* descriptors put into the scatter gather list such that there are scatter
+* operations ready to be performed.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* RETURN VALUE:
+*
+* A status containing XST_SUCCESS if scatter gather was started successfully
+* for the DMA channel.
+*
+* A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
+* been created.
+*
+* A value of XST_DMA_SG_LIST_EMPTY indicates scatter gather was not started
+* because the scatter gather list of the DMA channel does not contain any
+* buffer descriptors that are ready to be processed by the hardware.
+*
+* A value of XST_DMA_SG_IS_STARTED indicates scatter gather was not started
+* because the scatter gather was not stopped, but was already started.
+*
+* A value of XST_DMA_SG_BD_NOT_COMMITTED indicates the buffer descriptor of
+* scatter gather list which was to be started is not committed to the list.
+* This status is more likely if this function is being called from an ISR
+* and non-ISR processing is putting descriptors into the list.
+*
+* A value of XST_DMA_SG_NO_DATA indicates that the buffer descriptor of the
+* scatter gather list which was to be started had already been used by the
+* hardware for a DMA transfer that has been completed.
+*
+* NOTES:
+*
+* It is the responsibility of the caller to get all the buffer descriptors
+* after performing a stop operation and before performing a start operation.
+* If buffer descriptors are not retrieved between stop and start operations,
+* buffer descriptors may be processed by the hardware more than once.
+*
+******************************************************************************/
+XStatus
+XDmaChannel_SgStart(XDmaChannel * InstancePtr)
+{
+	u32 Register;
+	XBufDescriptor *LastDescriptorPtr;
+
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* if a scatter gather list has not been created yet, return a status */
+
+	if (InstancePtr->TotalDescriptorCount == 0) {
+		return XST_DMA_SG_NO_LIST;
+	}
+
+	/* if the scatter gather list exists but is empty then return a status */
+
+	if (XDmaChannel_IsSgListEmpty(InstancePtr)) {
+		return XST_DMA_SG_LIST_EMPTY;
+	}
+
+	/* if scatter gather is busy for the DMA channel, return a status because
+	 * restarting it could lose data
+	 */
+
+	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAS_REG_OFFSET);
+	if (Register & XDC_DMASR_SG_BUSY_MASK) {
+		return XST_DMA_SG_IS_STARTED;
+	}
+
+	/* get the address of the last buffer descriptor which the DMA hardware
+	 * finished processing
+	 */
+	LastDescriptorPtr =
+	    (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress +
+					XDC_BDA_REG_OFFSET);
+
+	/* setup the first buffer descriptor that will be sent when the scatter
+	 * gather channel is enabled, this is only necessary one time since
+	 * the BDA register of the channel maintains the last buffer descriptor
+	 * processed
+	 */
+	if (LastDescriptorPtr == NULL) {
+		XIo_Out32(InstancePtr->RegBaseAddress + XDC_BDA_REG_OFFSET,
+			  (u32) InstancePtr->GetPtr);
+	} else {
+		XBufDescriptor *NextDescriptorPtr;
+
+		/* get the next descriptor to be started, if the status indicates it
+		 * hasn't already been used by the h/w, then it's OK to start it,
+		 * s/w sets the status of each descriptor to busy and then h/w clears
+		 * the busy when it is complete
+		 */
+		NextDescriptorPtr =
+		    XBufDescriptor_GetNextPtr(LastDescriptorPtr);
+
+		if ((XBufDescriptor_GetStatus(NextDescriptorPtr) &
+		     XDC_DMASR_BUSY_MASK) == 0) {
+			return XST_DMA_SG_NO_DATA;
+		}
+		/* don't start the DMA SG channel if the descriptor to be processed
+		 * by h/w is to be committed by the s/w, this function can be called
+		 * such that it interrupts a thread that was putting into the list
+		 */
+		if (NextDescriptorPtr == InstancePtr->CommitPtr) {
+			return XST_DMA_SG_BD_NOT_COMMITTED;
+		}
+	}
+
+	/* start the scatter gather operation by clearing the stop bit in the
+	 * control register and setting the enable bit in the s/w control register,
+	 * both of these are necessary to cause it to start, right now the order of
+	 * these statements is important, the software control register should be
+	 * set 1st.  The other order can cause the CPU to have a loss of sync
+	 * because it cannot read/write the register while the DMA operation is
+	 * running
+	 */
+
+	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET);
+
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET,
+		  Register | XDC_SWCR_SG_ENABLE_MASK);
+
+	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET);
+
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET,
+		  Register & ~XDC_DMACR_SG_DISABLE_MASK);
+
+	/* indicate the DMA channel scatter gather operation was started
+	 * successfully
+	 */
+	return XST_SUCCESS;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_SgStop
+*
+* DESCRIPTION:
+*
+* This function stops a scatter gather operation for a scatter gather
+* DMA channel. This function starts the process of stopping a scatter
+* gather operation that is in progress and waits for the stop to be completed.
+* Since it waits for the operation to stopped before returning, this function
+* could take an amount of time relative to the size of the DMA scatter gather
+* operation which is in progress.  The scatter gather list of the DMA channel
+* is not modified by this function such that starting the scatter gather
+* channel after stopping it will cause it to resume.  This operation is
+* considered to be a graceful stop in that the scatter gather operation
+* completes the current buffer descriptor before stopping.
+*
+* If the interrupt is enabled, an interrupt will be generated when the
+* operation is stopped and the caller is responsible for handling the
+* interrupt.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* BufDescriptorPtr is also a return value which contains a pointer to the
+* buffer descriptor which the scatter gather operation completed when it
+* was stopped.
+*
+* RETURN VALUE:
+*
+* A status containing XST_SUCCESS if scatter gather was stopped successfully
+* for the DMA channel.
+*
+* A value of XST_DMA_SG_IS_STOPPED indicates scatter gather was not stoppped
+* because the scatter gather is not started, but was already stopped.
+*
+* BufDescriptorPtr contains a pointer to the buffer descriptor which was
+* completed when the operation was stopped.
+*
+* NOTES:
+*
+* This function implements a loop which polls the hardware for an infinite
+* amount of time. If the hardware is not operating correctly, this function
+* may never return.
+*
+******************************************************************************/
+XStatus
+XDmaChannel_SgStop(XDmaChannel * InstancePtr,
+		   XBufDescriptor ** BufDescriptorPtr)
+{
+	u32 Register;
+
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BufDescriptorPtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* get the contents of the software control register, if scatter gather is not
+	 * enabled (started), then return a status because the disable acknowledge
+	 * would not be generated
+	 */
+	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET);
+
+	if ((Register & XDC_SWCR_SG_ENABLE_MASK) == 0) {
+		return XST_DMA_SG_IS_STOPPED;
+	}
+
+	/* Ensure the interrupt status for the scatter gather is cleared such
+	 * that this function will wait til the disable has occurred, writing
+	 * a 1 to only that bit in the register will clear only it
+	 */
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET,
+		  XDC_IXR_SG_DISABLE_ACK_MASK);
+
+	/* disable scatter gather by writing to the software control register
+	 * without modifying any other bits of the register
+	 */
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET,
+		  Register & ~XDC_SWCR_SG_ENABLE_MASK);
+
+	/* scatter gather does not disable immediately, but after the current
+	 * buffer descriptor is complete, so wait for the DMA channel to indicate
+	 * the disable is complete
+	 */
+	do {
+		Register =
+		    XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET);
+	} while ((Register & XDC_IXR_SG_DISABLE_ACK_MASK) == 0);
+
+	/* Ensure the interrupt status for the scatter gather disable is cleared,
+	 * writing a 1 to only that bit in the register will clear only it
+	 */
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET,
+		  XDC_IXR_SG_DISABLE_ACK_MASK);
+
+	/* set the specified buffer descriptor pointer to point to the buffer
+	 * descriptor that the scatter gather DMA channel was processing
+	 */
+	*BufDescriptorPtr =
+	    (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress +
+					XDC_BDA_REG_OFFSET);
+
+	return XST_SUCCESS;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_CreateSgList
+*
+* DESCRIPTION:
+*
+* This function creates a scatter gather list in the DMA channel.  A scatter
+* gather list consists of a list of buffer descriptors that are available to
+* be used for scatter gather operations.  Buffer descriptors are put into the
+* list to request a scatter gather operation to be performed.
+*
+* A number of buffer descriptors are created from the specified memory and put
+* into a buffer descriptor list as empty buffer descriptors. This function must
+* be called before non-empty buffer descriptors may be put into the DMA channel
+* to request scatter gather operations.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* MemoryPtr contains a pointer to the memory which is to be used for buffer
+* descriptors and must not be cached.
+*
+* ByteCount contains the number of bytes for the specified memory to be used
+* for buffer descriptors.
+*
+* RETURN VALUE:
+*
+* A status contains XST_SUCCESS if the scatter gather list was successfully
+* created.
+*
+* A value of XST_DMA_SG_LIST_EXISTS indicates that the scatter gather list
+* was not created because the list has already been created.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XDmaChannel_CreateSgList(XDmaChannel * InstancePtr,
+			 u32 * MemoryPtr, u32 ByteCount)
+{
+	XBufDescriptor *BufferDescriptorPtr = (XBufDescriptor *) MemoryPtr;
+	XBufDescriptor *PreviousDescriptorPtr = NULL;
+	XBufDescriptor *StartOfListPtr = BufferDescriptorPtr;
+	u32 UsedByteCount;
+
+	/* assert to verify valid input arguments, alignment for those
+	 * arguments that have alignment restrictions, and at least enough
+	 * memory for one buffer descriptor
+	 */
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(MemoryPtr != NULL);
+	XASSERT_NONVOID(((u32) MemoryPtr & 3) == 0);
+	XASSERT_NONVOID(ByteCount != 0);
+	XASSERT_NONVOID(ByteCount >= sizeof (XBufDescriptor));
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* if the scatter gather list has already been created, then return
+	 * with a status
+	 */
+	if (InstancePtr->TotalDescriptorCount != 0) {
+		return XST_DMA_SG_LIST_EXISTS;
+	}
+
+	/* loop thru the specified memory block and create as many buffer
+	 * descriptors as possible putting each into the list which is
+	 * implemented as a ring buffer, make sure not to use any memory which
+	 * is not large enough for a complete buffer descriptor
+	 */
+	UsedByteCount = 0;
+	while ((UsedByteCount + sizeof (XBufDescriptor)) <= ByteCount) {
+		/* setup a pointer to the next buffer descriptor in the memory and
+		 * update # of used bytes to know when all of memory is used
+		 */
+		BufferDescriptorPtr = (XBufDescriptor *) ((u32) MemoryPtr +
+							  UsedByteCount);
+
+		/* initialize the new buffer descriptor such that it doesn't contain
+		 * garbage which could be used by the DMA hardware
+		 */
+		XBufDescriptor_Initialize(BufferDescriptorPtr);
+
+		/* if this is not the first buffer descriptor to be created,
+		 * then link it to the last created buffer descriptor
+		 */
+		if (PreviousDescriptorPtr != NULL) {
+			XBufDescriptor_SetNextPtr(PreviousDescriptorPtr,
+						  BufferDescriptorPtr);
+		}
+
+		/* always keep a pointer to the last created buffer descriptor such
+		 * that they can be linked together in the ring buffer
+		 */
+		PreviousDescriptorPtr = BufferDescriptorPtr;
+
+		/* keep a count of the number of descriptors in the list to allow
+		 * error processing to be performed
+		 */
+		InstancePtr->TotalDescriptorCount++;
+
+		UsedByteCount += sizeof (XBufDescriptor);
+	}
+
+	/* connect the last buffer descriptor created and inserted in the list
+	 * to the first such that a ring buffer is created
+	 */
+	XBufDescriptor_SetNextPtr(BufferDescriptorPtr, StartOfListPtr);
+
+	/* initialize the ring buffer to indicate that there are no
+	 * buffer descriptors in the list which point to valid data buffers
+	 */
+	InstancePtr->PutPtr = BufferDescriptorPtr;
+	InstancePtr->GetPtr = BufferDescriptorPtr;
+	InstancePtr->CommitPtr = NULL;
+	InstancePtr->LastPtr = BufferDescriptorPtr;
+	InstancePtr->ActiveDescriptorCount = 0;
+
+	/* indicate the scatter gather list was successfully created */
+
+	return XST_SUCCESS;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_IsSgListEmpty
+*
+* DESCRIPTION:
+*
+* This function determines if the scatter gather list of a DMA channel is
+* empty with regard to buffer descriptors which are pointing to buffers to be
+* used for scatter gather operations.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* RETURN VALUE:
+*
+* A value of TRUE if the scatter gather list is empty, otherwise a value of
+* FALSE.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u32
+XDmaChannel_IsSgListEmpty(XDmaChannel * InstancePtr)
+{
+	/* assert to verify valid input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* if the number of descriptors which are being used in the list is zero
+	 * then the list is empty
+	 */
+	return (InstancePtr->ActiveDescriptorCount == 0);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_PutDescriptor
+*
+* DESCRIPTION:
+*
+* This function puts a buffer descriptor into the DMA channel scatter
+* gather list. A DMA channel maintains a list of buffer descriptors which are
+* to be processed.  This function puts the specified buffer descriptor
+* at the next location in the list.  Note that since the list is already intact,
+* the information in the parameter is copied into the list (rather than modify
+* list pointers on the fly).
+*
+* After buffer descriptors are put into the list, they must also be committed
+* by calling another function.	This allows multiple buffer descriptors which
+* span a single packet to be put into the list while preventing the hardware
+* from starting the first buffer descriptor of the packet.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* BufferDescriptorPtr is a pointer to the buffer descriptor to be put into
+* the next available location of the scatter gather list.
+*
+* RETURN VALUE:
+*
+* A status which indicates XST_SUCCESS if the buffer descriptor was
+* successfully put into the scatter gather list.
+*
+* A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
+* been created.
+*
+* A value of XST_DMA_SG_LIST_FULL indicates the buffer descriptor was not
+* put into the list because the list was full.
+*
+* A value of XST_DMA_SG_BD_LOCKED indicates the buffer descriptor was not
+* put into the list because the buffer descriptor in the list which is to
+* be overwritten was locked.  A locked buffer descriptor indicates the higher
+* layered software is still using the buffer descriptor.
+*
+* NOTES:
+*
+* It is necessary to create a scatter gather list for a DMA channel before
+* putting buffer descriptors into it.
+*
+******************************************************************************/
+XStatus
+XDmaChannel_PutDescriptor(XDmaChannel * InstancePtr,
+			  XBufDescriptor * BufferDescriptorPtr)
+{
+	u32 Control;
+
+	/* assert to verify valid input arguments and alignment for those
+	 * arguments that have alignment restrictions
+	 */
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BufferDescriptorPtr != NULL);
+	XASSERT_NONVOID(((u32) BufferDescriptorPtr & 3) == 0);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* if a scatter gather list has not been created yet, return a status */
+
+	if (InstancePtr->TotalDescriptorCount == 0) {
+		return XST_DMA_SG_NO_LIST;
+	}
+
+	/* if the list is full because all descriptors are pointing to valid
+	 * buffers, then indicate an error, this code assumes no list or an
+	 * empty list is detected above
+	 */
+	if (InstancePtr->ActiveDescriptorCount ==
+	    InstancePtr->TotalDescriptorCount) {
+		return XST_DMA_SG_LIST_FULL;
+	}
+
+	/* if the buffer descriptor in the list which is to be overwritten is
+	 * locked, then don't overwrite it and return a status
+	 */
+	if (XBufDescriptor_IsLocked(InstancePtr->PutPtr)) {
+		return XST_DMA_SG_BD_LOCKED;
+	}
+
+	/* set the scatter gather stop bit in the control word of the descriptor
+	 * to cause the h/w to stop after it processes this descriptor since it
+	 * will be the last in the list
+	 */
+	Control = XBufDescriptor_GetControl(BufferDescriptorPtr);
+	XBufDescriptor_SetControl(BufferDescriptorPtr,
+				  Control | XDC_DMACR_SG_DISABLE_MASK);
+
+	/* set both statuses in the descriptor so we tell if they are updated with
+	 * the status of the transfer, the hardware should change the busy in the
+	 * DMA status to be false when it completes
+	 */
+	XBufDescriptor_SetStatus(BufferDescriptorPtr, XDC_DMASR_BUSY_MASK);
+	XBufDescriptor_SetDeviceStatus(BufferDescriptorPtr, 0);
+
+	/* copy the descriptor into the next position in the list so it's ready to
+	 * be used by the h/w, this assumes the descriptor in the list prior to this
+	 * one still has the stop bit in the control word set such that the h/w
+	 * use this one yet
+	 */
+	CopyBufferDescriptor(BufferDescriptorPtr, InstancePtr->PutPtr);
+
+	/* only the last in the list and the one to be committed have scatter gather
+	 * disabled in the control word, a commit requires only one descriptor
+	 * to be changed, when # of descriptors to commit > 2 all others except the
+	 * 1st and last have scatter gather enabled
+	 */
+	if ((InstancePtr->CommitPtr != InstancePtr->LastPtr) &&
+	    (InstancePtr->CommitPtr != NULL)) {
+		Control = XBufDescriptor_GetControl(InstancePtr->LastPtr);
+		XBufDescriptor_SetControl(InstancePtr->LastPtr,
+					  Control & ~XDC_DMACR_SG_DISABLE_MASK);
+	}
+
+	/* update the list data based upon putting a descriptor into the list,
+	 * these operations must be last
+	 */
+	InstancePtr->ActiveDescriptorCount++;
+
+	/* only update the commit pointer if it is not already active, this allows
+	 * it to be deactivated after every commit such that a single descriptor
+	 * which is committed does not appear to be waiting to be committed
+	 */
+	if (InstancePtr->CommitPtr == NULL) {
+		InstancePtr->CommitPtr = InstancePtr->LastPtr;
+	}
+
+	/* these updates MUST BE LAST after the commit pointer update in order for
+	 * the commit pointer to track the correct descriptor to be committed
+	 */
+	InstancePtr->LastPtr = InstancePtr->PutPtr;
+	InstancePtr->PutPtr = XBufDescriptor_GetNextPtr(InstancePtr->PutPtr);
+
+	return XST_SUCCESS;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_CommitPuts
+*
+* DESCRIPTION:
+*
+* This function commits the buffer descriptors which have been put into the
+* scatter list for the DMA channel since the last commit operation was
+* performed.  This enables the calling functions to put several buffer
+* descriptors into the list (e.g.,a packet's worth) before allowing the scatter
+* gather operations to start.  This prevents the DMA channel hardware from
+* starting to use the buffer descriptors in the list before they are ready
+* to be used (multiple buffer descriptors for a single packet).
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* RETURN VALUE:
+*
+* A status indicating XST_SUCCESS if the buffer descriptors of the list were
+* successfully committed.
+*
+* A value of XST_DMA_SG_NOTHING_TO_COMMIT indicates that the buffer descriptors
+* were not committed because there was nothing to commit in the list.  All the
+* buffer descriptors which are in the list are commited.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XDmaChannel_CommitPuts(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* if the buffer descriptor to be committed is already committed or
+	 * the list is empty (none have been put in), then indicate an error
+	 */
+	if ((InstancePtr->CommitPtr == NULL) ||
+	    XDmaChannel_IsSgListEmpty(InstancePtr)) {
+		return XST_DMA_SG_NOTHING_TO_COMMIT;
+	}
+
+	/* last descriptor in the list must have scatter gather disabled so the end
+	 * of the list is hit by h/w, if descriptor to commit is not last in list,
+	 * commit descriptors by enabling scatter gather in the descriptor
+	 */
+	if (InstancePtr->CommitPtr != InstancePtr->LastPtr) {
+		u32 Control;
+
+		Control = XBufDescriptor_GetControl(InstancePtr->CommitPtr);
+		XBufDescriptor_SetControl(InstancePtr->CommitPtr, Control &
+					  ~XDC_DMACR_SG_DISABLE_MASK);
+	}
+	/* Update the commit pointer to indicate that there is nothing to be
+	 * committed, this state is used by start processing to know that the
+	 * buffer descriptor to start is not waiting to be committed
+	 */
+	InstancePtr->CommitPtr = NULL;
+
+	return XST_SUCCESS;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetDescriptor
+*
+* DESCRIPTION:
+*
+* This function gets a buffer descriptor from the scatter gather list of the
+* DMA channel. The buffer descriptor is retrieved from the scatter gather list
+* and the scatter gather list is updated to not include the retrieved buffer
+* descriptor.  This is typically done after a scatter gather operation
+* completes indicating that a data buffer has been successfully sent or data
+* has been received into the data buffer. The purpose of this function is to
+* allow the device using the scatter gather operation to get the results of the
+* operation.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* BufDescriptorPtr is a pointer to a pointer to the buffer descriptor which
+* was retrieved from the list.	The buffer descriptor is not really removed
+* from the list, but it is changed to a state such that the hardware will not
+* use it again until it is put into the scatter gather list of the DMA channel.
+*
+* RETURN VALUE:
+*
+* A status indicating XST_SUCCESS if a buffer descriptor was retrieved from
+* the scatter gather list of the DMA channel.
+*
+* A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
+* been created.
+*
+* A value of XST_DMA_SG_LIST_EMPTY indicates no buffer descriptor was
+* retrieved from the list because there are no buffer descriptors to be
+* processed in the list.
+*
+* BufDescriptorPtr is updated to point to the buffer descriptor which was
+* retrieved from the list if the status indicates success.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XDmaChannel_GetDescriptor(XDmaChannel * InstancePtr,
+			  XBufDescriptor ** BufDescriptorPtr)
+{
+	u32 Control;
+
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BufDescriptorPtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* if a scatter gather list has not been created yet, return a status */
+
+	if (InstancePtr->TotalDescriptorCount == 0) {
+		return XST_DMA_SG_NO_LIST;
+	}
+
+	/* if the buffer descriptor list is empty, then indicate an error */
+
+	if (XDmaChannel_IsSgListEmpty(InstancePtr)) {
+		return XST_DMA_SG_LIST_EMPTY;
+	}
+
+	/* retrieve the next buffer descriptor which is ready to be processed from
+	 * the buffer descriptor list for the DMA channel, set the control word
+	 * such that hardware will stop after the descriptor has been processed
+	 */
+	Control = XBufDescriptor_GetControl(InstancePtr->GetPtr);
+	XBufDescriptor_SetControl(InstancePtr->GetPtr,
+				  Control | XDC_DMACR_SG_DISABLE_MASK);
+
+	/* set the input argument, which is also an output, to point to the
+	 * buffer descriptor which is to be retrieved from the list
+	 */
+	*BufDescriptorPtr = InstancePtr->GetPtr;
+
+	/* update the pointer of the DMA channel to reflect the buffer descriptor
+	 * was retrieved from the list by setting it to the next buffer descriptor
+	 * in the list and indicate one less descriptor in the list now
+	 */
+	InstancePtr->GetPtr = XBufDescriptor_GetNextPtr(InstancePtr->GetPtr);
+	InstancePtr->ActiveDescriptorCount--;
+
+	return XST_SUCCESS;
+}
+
+/*********************** Interrupt Collescing Functions **********************/
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetPktCount
+*
+* DESCRIPTION:
+*
+* This function returns the value of the unserviced packet count register of
+* the DMA channel.  This count represents the number of packets that have been
+* sent or received by the hardware, but not processed by software.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* RETURN VALUE:
+*
+* The unserviced packet counter register contents for the DMA channel.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u32
+XDmaChannel_GetPktCount(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* get the unserviced packet count from the register and return it */
+
+	return XIo_In32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_DecrementPktCount
+*
+* DESCRIPTION:
+*
+* This function decrements the value of the unserviced packet count register.
+* This informs the hardware that the software has processed a packet.  The
+* unserviced packet count register may only be decremented by one in the
+* hardware.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+void
+XDmaChannel_DecrementPktCount(XDmaChannel * InstancePtr)
+{
+	u32 Register;
+
+	/* assert to verify input arguments */
+
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* if the unserviced packet count register can be decremented (rather
+	 * than rolling over) decrement it by writing a 1 to the register,
+	 * this is the only valid write to the register as it serves as an
+	 * acknowledge that a packet was handled by the software
+	 */
+	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET);
+	if (Register > 0) {
+		XIo_Out32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET,
+			  1UL);
+	}
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_SetPktThreshold
+*
+* DESCRIPTION:
+*
+* This function sets the value of the packet count threshold register of the
+* DMA channel.	It reflects the number of packets that must be sent or
+* received before generating an interrupt.  This value helps implement
+* a concept called "interrupt coalescing", which is used to reduce the number
+* of interrupts from devices with high data rates.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* Threshold is the value that is written to the threshold register of the
+* DMA channel.
+*
+* RETURN VALUE:
+*
+* A status containing XST_SUCCESS if the packet count threshold was
+* successfully set.
+*
+* NOTES:
+*
+* The packet threshold could be set to larger than the number of descriptors
+* allocated to the DMA channel. In this case, the wait bound will take over
+* and always indicate data arrival. There was a check in this function that
+* returned an error if the treshold was larger than the number of descriptors,
+* but that was removed because users would then have to set the threshold
+* only after they set descriptor space, which is an order dependency that
+* caused confustion.
+*
+******************************************************************************/
+XStatus
+XDmaChannel_SetPktThreshold(XDmaChannel * InstancePtr, u8 Threshold)
+{
+	/* assert to verify input arguments, don't assert the threshold since
+	 * it's range is unknown
+	 */
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* set the packet count threshold in the register such that an interrupt
+	 * may be generated, if enabled, when the packet count threshold is
+	 * reached or exceeded
+	 */
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_PCT_REG_OFFSET,
+		  (u32) Threshold);
+
+	/* indicate the packet count threshold was successfully set */
+
+	return XST_SUCCESS;
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetPktThreshold
+*
+* DESCRIPTION:
+*
+* This function gets the value of the packet count threshold register of the
+* DMA channel.	This value reflects the number of packets that must be sent or
+* received before generating an interrupt.  This value helps implement a concept
+* called "interrupt coalescing", which is used to reduce the number of
+* interrupts from devices with high data rates.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* RETURN VALUE:
+*
+* The packet threshold register contents for the DMA channel and is a value in
+* the range 0 - 1023.  A value of 0 indicates the packet wait bound timer is
+* disabled.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u8
+XDmaChannel_GetPktThreshold(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* get the packet count threshold from the register and return it,
+	 * since only 8 bits are used, cast it to return only those bits */
+
+	return (u8) XIo_In32(InstancePtr->RegBaseAddress + XDC_PCT_REG_OFFSET);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_SetPktWaitBound
+*
+* DESCRIPTION:
+*
+* This function sets the value of the packet wait bound register of the
+* DMA channel.	This value reflects the timer value used to trigger an
+* interrupt when not enough packets have been received to reach the packet
+* count threshold.
+*
+* The timer is in millisecond units with +/- 33% accuracy.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* WaitBound is the value, in milliseconds, to be stored in the wait bound
+* register of the DMA channel and is a value in the range 0  - 1023.  A value
+* of 0 disables the packet wait bound timer.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+void
+XDmaChannel_SetPktWaitBound(XDmaChannel * InstancePtr, u32 WaitBound)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(WaitBound < 1024);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* set the packet wait bound in the register such that interrupt may be
+	 * generated, if enabled, when packets have not been handled for a specific
+	 * amount of time
+	 */
+	XIo_Out32(InstancePtr->RegBaseAddress + XDC_PWB_REG_OFFSET, WaitBound);
+}
+
+/******************************************************************************
+*
+* FUNCTION:
+*
+* XDmaChannel_GetPktWaitBound
+*
+* DESCRIPTION:
+*
+* This function gets the value of the packet wait bound register of the
+* DMA channel.	This value contains the timer value used to trigger an
+* interrupt when not enough packets have been received to reach the packet
+* count threshold.
+*
+* The timer is in millisecond units with +/- 33% accuracy.
+*
+* ARGUMENTS:
+*
+* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA
+* channel should be configured to use scatter gather in order for this function
+* to be called.
+*
+* RETURN VALUE:
+*
+* The packet wait bound register contents for the DMA channel.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+u32
+XDmaChannel_GetPktWaitBound(XDmaChannel * InstancePtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* get the packet wait bound from the register and return it */
+
+	return XIo_In32(InstancePtr->RegBaseAddress + XDC_PWB_REG_OFFSET);
+}

+ 81 - 0
board/xilinx/common/xio.h

@@ -0,0 +1,81 @@
+/*
+ * xio.h
+ *
+ * Defines XIo functions for Xilinx OCP in terms of Linux primitives
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ *
+ *  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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef XIO_H
+#define XIO_H
+
+#include "xbasic_types.h"
+#include <asm/io.h>
+
+typedef u32 XIo_Address;
+
+extern inline u8
+XIo_In8(XIo_Address InAddress)
+{
+	return (u8) in_8((volatile unsigned char *) InAddress);
+}
+extern inline u16
+XIo_In16(XIo_Address InAddress)
+{
+	return (u16) in_be16((volatile unsigned short *) InAddress);
+}
+extern inline u32
+XIo_In32(XIo_Address InAddress)
+{
+	return (u32) in_be32((volatile unsigned *) InAddress);
+}
+extern inline void
+XIo_Out8(XIo_Address OutAddress, u8 Value)
+{
+	out_8((volatile unsigned char *) OutAddress, Value);
+}
+extern inline void
+XIo_Out16(XIo_Address OutAddress, u16 Value)
+{
+	out_be16((volatile unsigned short *) OutAddress, Value);
+}
+extern inline void
+XIo_Out32(XIo_Address OutAddress, u32 Value)
+{
+	out_be32((volatile unsigned *) OutAddress, Value);
+}
+
+#define XIo_ToLittleEndian16(s,d) (*(u16*)(d) = cpu_to_le16((u16)(s)))
+#define XIo_ToLittleEndian32(s,d) (*(u32*)(d) = cpu_to_le32((u32)(s)))
+#define XIo_ToBigEndian16(s,d) (*(u16*)(d) = cpu_to_be16((u16)(s)))
+#define XIo_ToBigEndian32(s,d) (*(u32*)(d) = cpu_to_be32((u32)(s)))
+
+#define XIo_FromLittleEndian16(s,d) (*(u16*)(d) = le16_to_cpu((u16)(s)))
+#define XIo_FromLittleEndian32(s,d) (*(u32*)(d) = le32_to_cpu((u32)(s)))
+#define XIo_FromBigEndian16(s,d) (*(u16*)(d) = be16_to_cpu((u16)(s)))
+#define XIo_FromBigEndian32(s,d) (*(u32*)(d) = be32_to_cpu((u32)(s)))
+
+#endif				/* XIO_H */

+ 763 - 0
board/xilinx/common/xipif_v1_23_b.h

@@ -0,0 +1,763 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/******************************************************************************
+*
+* FILENAME:
+*
+* xipif.h
+*
+* DESCRIPTION:
+*
+* The XIpIf component encapsulates the IPIF, which is the standard interface
+* that IP must adhere to when connecting to a bus.  The purpose of this
+* component is to encapsulate the IPIF processing such that maintainability
+* is increased.	 This component does not provide a lot of abstraction from
+* from the details of the IPIF as it is considered a building block for
+* device drivers.  A device driver designer must be familiar with the
+* details of the IPIF hardware to use this component.
+*
+* The IPIF hardware provides a building block for all hardware devices such
+* that each device does not need to reimplement these building blocks. The
+* IPIF contains other building blocks, such as FIFOs and DMA channels, which
+* are also common to many devices.  These blocks are implemented as separate
+* hardware blocks and instantiated within the IPIF.  The primary hardware of
+* the IPIF which is implemented by this software component is the interrupt
+* architecture.	 Since there are many blocks of a device which may generate
+* interrupts, all the interrupt processing is contained in the common part
+* of the device, the IPIF.  This interrupt processing is for the device level
+* only and does not include any processing for the interrupt controller.
+*
+* A device is a mechanism such as an Ethernet MAC.  The device is made
+* up of several parts which include an IPIF and the IP.	 The IPIF contains most
+* of the device infrastructure which is common to all devices, such as
+* interrupt processing, DMA channels, and FIFOs.  The infrastructure may also
+* be referred to as IPIF internal blocks since they are part of the IPIF and
+* are separate blocks that can be selected based upon the needs of the device.
+* The IP of the device is the logic that is unique to the device and interfaces
+* to the IPIF of the device.
+*
+* In general, there are two levels of registers within the IPIF.  The first
+* level, referred to as the device level, contains registers which are for the
+* entire device.  The second level, referred to as the IP level, contains
+* registers which are specific to the IP of the device.	 The two levels of
+* registers are designed to be hierarchical such that the device level is
+* is a more general register set above the more specific registers of the IP.
+* The IP level of registers provides functionality which is typically common
+* across all devices and allows IP designers to focus on the unique aspects
+* of the IP.
+*
+* Critical Sections
+*
+* It is the responsibility of the device driver designer to use critical
+* sections as necessary when calling functions of the IPIF.  This component
+* does not use critical sections and it does access registers using
+* read-modify-write operations.	 Calls to IPIF functions from a main thread
+* and from an interrupt context could produce unpredictable behavior such that
+* the caller must provide the appropriate critical sections.
+*
+* Mutual Exclusion
+*
+* The functions of the IPIF are not thread safe such that the caller of all
+* functions is responsible for ensuring mutual exclusion for an IPIF.  Mutual
+* exclusion across multiple IPIF components is not necessary.
+*
+* NOTES:
+*
+* None.
+*
+* MODIFICATION HISTORY:
+*
+* Ver	Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.23b jhl  02/27/01 Repartioned to minimize size
+*
+******************************************************************************/
+
+#ifndef XIPIF_H			/* prevent circular inclusions */
+#define XIPIF_H			/* by using protection macros */
+
+/***************************** Include Files *********************************/
+#include "xbasic_types.h"
+#include "xstatus.h"
+#include "xversion.h"
+
+/************************** Constant Definitions *****************************/
+
+/* the following constants define the register offsets for the registers of the
+ * IPIF, there are some holes in the memory map for reserved addresses to allow
+ * other registers to be added and still match the memory map of the interrupt
+ * controller registers
+ */
+#define XIIF_V123B_DISR_OFFSET	   0UL	/* device interrupt status register */
+#define XIIF_V123B_DIPR_OFFSET	   4UL	/* device interrupt pending register */
+#define XIIF_V123B_DIER_OFFSET	   8UL	/* device interrupt enable register */
+#define XIIF_V123B_DIIR_OFFSET	   24UL /* device interrupt ID register */
+#define XIIF_V123B_DGIER_OFFSET	   28UL /* device global interrupt enable reg */
+#define XIIF_V123B_IISR_OFFSET	   32UL /* IP interrupt status register */
+#define XIIF_V123B_IIER_OFFSET	   40UL /* IP interrupt enable register */
+#define XIIF_V123B_RESETR_OFFSET   64UL /* reset register */
+
+#define XIIF_V123B_RESET_MASK		  0xAUL
+
+/* the following constant is used for the device global interrupt enable
+ * register, to enable all interrupts for the device, this is the only bit
+ * in the register
+ */
+#define XIIF_V123B_GINTR_ENABLE_MASK	  0x80000000UL
+
+/* the following constants contain the masks to identify each internal IPIF
+ * condition in the device registers of the IPIF, interrupts are assigned
+ * in the register from LSB to the MSB
+ */
+#define XIIF_V123B_ERROR_MASK		  1UL	/* LSB of the register */
+
+/* The following constants contain interrupt IDs which identify each internal
+ * IPIF condition, this value must correlate with the mask constant for the
+ * error
+ */
+#define XIIF_V123B_ERROR_INTERRUPT_ID	  0	/* interrupt bit #, (LSB = 0) */
+#define XIIF_V123B_NO_INTERRUPT_ID	  128	/* no interrupts are pending */
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_RESET
+*
+* DESCRIPTION:
+*
+* Reset the IPIF component and hardware.  This is a destructive operation that
+* could cause the loss of data since resetting the IPIF of a device also
+* resets the device using the IPIF and any blocks, such as FIFOs or DMA
+* channels, within the IPIF.  All registers of the IPIF will contain their
+* reset value when this function returns.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+
+/* the following constant is used in the reset register to cause the IPIF to
+ * reset
+ */
+#define XIIF_V123B_RESET(RegBaseAddress) \
+    XIo_Out32(RegBaseAddress + XIIF_V123B_RESETR_OFFSET, XIIF_V123B_RESET_MASK)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_WRITE_DISR
+*
+* DESCRIPTION:
+*
+* This function sets the device interrupt status register to the value.
+* This register indicates the status of interrupt sources for a device
+* which contains the IPIF.  The status is independent of whether interrupts
+* are enabled and could be used for polling a device at a higher level rather
+* than a more detailed level.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* device which contains the IPIF.  With the exception of some internal IPIF
+* conditions, the contents of this register are not latched but indicate
+* the live status of the interrupt sources within the device.  Writing any of
+* the non-latched bits of the register will have no effect on the register.
+*
+* For the latched bits of this register only, setting a bit which is zero
+* within this register causes an interrupt to generated.  The device global
+* interrupt enable register and the device interrupt enable register must be set
+* appropriately to allow an interrupt to be passed out of the device. The
+* interrupt is cleared by writing to this register with the bits to be
+* cleared set to a one and all others to zero.	This register implements a
+* toggle on write functionality meaning any bits which are set in the value
+* written cause the bits in the register to change to the opposite state.
+*
+* This function writes the specified value to the register such that
+* some bits may be set and others cleared.  It is the caller's responsibility
+* to get the value of the register prior to setting the value to prevent a
+* destructive behavior.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* Status contains the value to be written to the interrupt status register of
+* the device.  The only bits which can be written are the latched bits which
+* contain the internal IPIF conditions.	 The following values may be used to
+* set the status register or clear an interrupt condition.
+*
+*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_WRITE_DISR(RegBaseAddress, Status) \
+    XIo_Out32((RegBaseAddress) + XIIF_V123B_DISR_OFFSET, (Status))
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_READ_DISR
+*
+* DESCRIPTION:
+*
+* This function gets the device interrupt status register contents.
+* This register indicates the status of interrupt sources for a device
+* which contains the IPIF.  The status is independent of whether interrupts
+* are enabled and could be used for polling a device at a higher level.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* device which contains the IPIF.  With the exception of some internal IPIF
+* conditions, the contents of this register are not latched but indicate
+* the live status of the interrupt sources within the device.
+*
+* For only the latched bits of this register, the interrupt may be cleared by
+* writing to these bits in the status register.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* A status which contains the value read from the interrupt status register of
+* the device. The bit definitions are specific to the device with
+* the exception of the latched internal IPIF condition bits. The following
+* values may be used to detect internal IPIF conditions in the status.
+*
+*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_READ_DISR(RegBaseAddress) \
+    XIo_In32((RegBaseAddress) + XIIF_V123B_DISR_OFFSET)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_WRITE_DIER
+*
+* DESCRIPTION:
+*
+* This function sets the device interrupt enable register contents.
+* This register controls which interrupt sources of the device are allowed to
+* generate an interrupt.  The device global interrupt enable register must also
+* be set appropriately for an interrupt to be passed out of the device.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* device which contains the IPIF.  Setting a bit in this register enables that
+* interrupt source to generate an interrupt.  Clearing a bit in this register
+* disables interrupt generation for that interrupt source.
+*
+* This function writes only the specified value to the register such that
+* some interrupts source may be enabled and others disabled.  It is the
+* caller's responsibility to get the value of the interrupt enable register
+* prior to setting the value to prevent an destructive behavior.
+*
+* An interrupt source may not be enabled to generate an interrupt, but can
+* still be polled in the interrupt status register.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* Enable contains the value to be written to the interrupt enable register
+* of the device.  The bit definitions are specific to the device with
+* the exception of the internal IPIF conditions. The following
+* values may be used to enable the internal IPIF conditions interrupts.
+*
+*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* Signature: u32 XIIF_V123B_WRITE_DIER(u32 RegBaseAddress,
+*					  u32 Enable)
+*
+******************************************************************************/
+#define XIIF_V123B_WRITE_DIER(RegBaseAddress, Enable) \
+    XIo_Out32((RegBaseAddress) + XIIF_V123B_DIER_OFFSET, (Enable))
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_READ_DIER
+*
+* DESCRIPTION:
+*
+* This function gets the device interrupt enable register contents.
+* This register controls which interrupt sources of the device
+* are allowed to generate an interrupt.	 The device global interrupt enable
+* register and the device interrupt enable register must also be set
+* appropriately for an interrupt to be passed out of the device.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* device which contains the IPIF.  Setting a bit in this register enables that
+* interrupt source to generate an interrupt if the global enable is set
+* appropriately.  Clearing a bit in this register disables interrupt generation
+* for that interrupt source regardless of the global interrupt enable.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* The value read from the interrupt enable register of the device.  The bit
+* definitions are specific to the device with the exception of the internal
+* IPIF conditions. The following values may be used to determine from the
+* value if the internal IPIF conditions interrupts are enabled.
+*
+*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_READ_DIER(RegBaseAddress) \
+    XIo_In32((RegBaseAddress) + XIIF_V123B_DIER_OFFSET)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_READ_DIPR
+*
+* DESCRIPTION:
+*
+* This function gets the device interrupt pending register contents.
+* This register indicates the pending interrupt sources, those that are waiting
+* to be serviced by the software, for a device which contains the IPIF.
+* An interrupt must be enabled in the interrupt enable register of the IPIF to
+* be pending.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* the device which contains the IPIF.  With the exception of some internal IPIF
+* conditions, the contents of this register are not latched since the condition
+* is latched in the IP interrupt status register, by an internal block of the
+* IPIF such as a FIFO or DMA channel, or by the IP of the device.  This register
+* is read only and is not latched, but it is necessary to acknowledge (clear)
+* the interrupt condition by performing the appropriate processing for the IP
+* or block within the IPIF.
+*
+* This register can be thought of as the contents of the interrupt status
+* register ANDed with the contents of the interrupt enable register.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* The value read from the interrupt pending register of the device.  The bit
+* definitions are specific to the device with the exception of the latched
+* internal IPIF condition bits. The following values may be used to detect
+* internal IPIF conditions in the value.
+*
+*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_READ_DIPR(RegBaseAddress) \
+    XIo_In32((RegBaseAddress) + XIIF_V123B_DIPR_OFFSET)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_READ_DIIR
+*
+* DESCRIPTION:
+*
+* This function gets the device interrupt ID for the highest priority interrupt
+* which is pending from the interrupt ID register. This function provides
+* priority resolution such that faster interrupt processing is possible.
+* Without priority resolution, it is necessary for the software to read the
+* interrupt pending register and then check each interrupt source to determine
+* if an interrupt is pending.  Priority resolution becomes more important as the
+* number of interrupt sources becomes larger.
+*
+* Interrupt priorities are based upon the bit position of the interrupt in the
+* interrupt pending register with bit 0 being the highest priority. The
+* interrupt ID is the priority of the interrupt, 0 - 31, with 0 being the
+* highest priority. The interrupt ID register is live rather than latched such
+* that multiple calls to this function may not yield the same results.	A
+* special value, outside of the interrupt priority range of 0 - 31, is
+* contained in the register which indicates that no interrupt is pending.  This
+* may be useful for allowing software to continue processing interrupts in a
+* loop until there are no longer any interrupts pending.
+*
+* The interrupt ID is designed to allow a function pointer table to be used
+* in the software such that the interrupt ID is used as an index into that
+* table.  The function pointer table could contain an instance pointer, such
+* as to DMA channel, and a function pointer to the function which handles
+* that interrupt.  This design requires the interrupt processing of the device
+* driver to be partitioned into smaller more granular pieces based upon
+* hardware used by the device, such as DMA channels and FIFOs.
+*
+* It is not mandatory that this function be used by the device driver software.
+* It may choose to read the pending register and resolve the pending interrupt
+* priorities on it's own.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* An interrupt ID, 0 - 31, which identifies the highest priority interrupt
+* which is pending.  A value of XIIF_NO_INTERRUPT_ID indicates that there is
+* no interrupt pending. The following values may be used to identify the
+* interrupt ID for the internal IPIF interrupts.
+*
+*   XIIF_V123B_ERROR_INTERRUPT_ID     Indicates a device error in the IPIF
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_READ_DIIR(RegBaseAddress) \
+    XIo_In32((RegBaseAddress) + XIIF_V123B_DIIR_OFFSET)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_GLOBAL_INTR_DISABLE
+*
+* DESCRIPTION:
+*
+* This function disables all interrupts for the device by writing to the global
+* interrupt enable register.  This register provides the ability to disable
+* interrupts without any modifications to the interrupt enable register such
+* that it is minimal effort to restore the interrupts to the previous enabled
+* state.  The corresponding function, XIpIf_GlobalIntrEnable, is provided to
+* restore the interrupts to the previous enabled state.	 This function is
+* designed to be used in critical sections of device drivers such that it is
+* not necessary to disable other device interrupts.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_GINTR_DISABLE(RegBaseAddress) \
+    XIo_Out32((RegBaseAddress) + XIIF_V123B_DGIER_OFFSET, 0)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_GINTR_ENABLE
+*
+* DESCRIPTION:
+*
+* This function writes to the global interrupt enable register to enable
+* interrupts from the device.  This register provides the ability to enable
+* interrupts without any modifications to the interrupt enable register such
+* that it is minimal effort to restore the interrupts to the previous enabled
+* state.  This function does not enable individual interrupts as the interrupt
+* enable register must be set appropriately.  This function is designed to be
+* used in critical sections of device drivers such that it is not necessary to
+* disable other device interrupts.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_GINTR_ENABLE(RegBaseAddress)		  \
+    XIo_Out32((RegBaseAddress) + XIIF_V123B_DGIER_OFFSET, \
+	       XIIF_V123B_GINTR_ENABLE_MASK)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_IS_GINTR_ENABLED
+*
+* DESCRIPTION:
+*
+* This function determines if interrupts are enabled at the global level by
+* reading the gloabl interrupt register. This register provides the ability to
+* disable interrupts without any modifications to the interrupt enable register
+* such that it is minimal effort to restore the interrupts to the previous
+* enabled state.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* TRUE if interrupts are enabled for the IPIF, FALSE otherwise.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_IS_GINTR_ENABLED(RegBaseAddress)		\
+    (XIo_In32((RegBaseAddress) + XIIF_V123B_DGIER_OFFSET) ==	\
+	      XIIF_V123B_GINTR_ENABLE_MASK)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_WRITE_IISR
+*
+* DESCRIPTION:
+*
+* This function sets the IP interrupt status register to the specified value.
+* This register indicates the status of interrupt sources for the IP of the
+* device.  The IP is defined as the part of the device that connects to the
+* IPIF.	 The status is independent of whether interrupts are enabled such that
+* the status register may also be polled when interrupts are not enabled.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* IP.  All bits of this register are latched. Setting a bit which is zero
+* within this register causes an interrupt to be generated.  The device global
+* interrupt enable register and the device interrupt enable register must be set
+* appropriately to allow an interrupt to be passed out of the device. The
+* interrupt is cleared by writing to this register with the bits to be
+* cleared set to a one and all others to zero.	This register implements a
+* toggle on write functionality meaning any bits which are set in the value
+* written cause the bits in the register to change to the opposite state.
+*
+* This function writes only the specified value to the register such that
+* some status bits may be set and others cleared.  It is the caller's
+* responsibility to get the value of the register prior to setting the value
+* to prevent an destructive behavior.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* Status contains the value to be written to the IP interrupt status
+* register.  The bit definitions are specific to the device IP.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_WRITE_IISR(RegBaseAddress, Status) \
+    XIo_Out32((RegBaseAddress) + XIIF_V123B_IISR_OFFSET, (Status))
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_READ_IISR
+*
+* DESCRIPTION:
+*
+* This function gets the contents of the IP interrupt status register.
+* This register indicates the status of interrupt sources for the IP of the
+* device.  The IP is defined as the part of the device that connects to the
+* IPIF. The status is independent of whether interrupts are enabled such
+* that the status register may also be polled when interrupts are not enabled.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* device.  All bits of this register are latched.  Writing a 1 to a bit within
+* this register causes an interrupt to be generated if enabled in the interrupt
+* enable register and the global interrupt enable is set.  Since the status is
+* latched, each status bit must be acknowledged in order for the bit in the
+* status register to be updated.  Each bit can be acknowledged by writing a
+* 0 to the bit in the status register.
+
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* A status which contains the value read from the IP interrupt status register.
+* The bit definitions are specific to the device IP.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_READ_IISR(RegBaseAddress) \
+    XIo_In32((RegBaseAddress) + XIIF_V123B_IISR_OFFSET)
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_WRITE_IIER
+*
+* DESCRIPTION:
+*
+* This function sets the IP interrupt enable register contents.	 This register
+* controls which interrupt sources of the IP are allowed to generate an
+* interrupt.  The global interrupt enable register and the device interrupt
+* enable register must also be set appropriately for an interrupt to be
+* passed out of the device containing the IPIF and the IP.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* IP.  Setting a bit in this register enables the interrupt source to generate
+* an interrupt.	 Clearing a bit in this register disables interrupt generation
+* for that interrupt source.
+*
+* This function writes only the specified value to the register such that
+* some interrupt sources may be enabled and others disabled.  It is the
+* caller's responsibility to get the value of the interrupt enable register
+* prior to setting the value to prevent an destructive behavior.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* Enable contains the value to be written to the IP interrupt enable register.
+* The bit definitions are specific to the device IP.
+*
+* RETURN VALUE:
+*
+* None.
+*
+* NOTES:
+*
+* None.
+*
+******************************************************************************/
+#define XIIF_V123B_WRITE_IIER(RegBaseAddress, Enable) \
+    XIo_Out32((RegBaseAddress) + XIIF_V123B_IIER_OFFSET, (Enable))
+
+/******************************************************************************
+*
+* MACRO:
+*
+* XIIF_V123B_READ_IIER
+*
+* DESCRIPTION:
+*
+*
+* This function gets the IP interrupt enable register contents.	 This register
+* controls which interrupt sources of the IP are allowed to generate an
+* interrupt.  The global interrupt enable register and the device interrupt
+* enable register must also be set appropriately for an interrupt to be
+* passed out of the device containing the IPIF and the IP.
+*
+* Each bit of the register correlates to a specific interrupt source within the
+* IP.  Setting a bit in this register enables the interrupt source to generate
+* an interrupt.	 Clearing a bit in this register disables interrupt generation
+* for that interrupt source.
+*
+* ARGUMENTS:
+*
+* RegBaseAddress contains the base address of the IPIF registers.
+*
+* RETURN VALUE:
+*
+* The contents read from the IP interrupt enable register.  The bit definitions
+* are specific to the device IP.
+*
+* NOTES:
+*
+* Signature: u32 XIIF_V123B_READ_IIER(u32 RegBaseAddress)
+*
+******************************************************************************/
+#define XIIF_V123B_READ_IIER(RegBaseAddress) \
+    XIo_In32((RegBaseAddress) + XIIF_V123B_IIER_OFFSET)
+
+/************************** Function Prototypes ******************************/
+
+/*
+ * Initialization Functions
+ */
+XStatus XIpIfV123b_SelfTest(u32 RegBaseAddress, u8 IpRegistersWidth);
+
+#endif				/* end of protection macro */

+ 448 - 0
board/xilinx/common/xpacket_fifo_v1_00_b.c

@@ -0,0 +1,448 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/*
+*
+* @file xpacket_fifo_v1_00_b.c
+*
+* Contains functions for the XPacketFifoV100b component. See xpacket_fifo_v1_00_b.h
+* for more information about the component.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b rpm 03/26/02  First release
+* </pre>
+*
+*****************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xio.h"
+#include "xstatus.h"
+#include "xpacket_fifo_v1_00_b.h"
+
+/************************** Constant Definitions *****************************/
+
+/* width of a FIFO word */
+
+#define XPF_FIFO_WIDTH_BYTE_COUNT       4UL
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************* Variable Definitions ******************************/
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/*
+*
+* This function initializes a packet FIFO.  Initialization resets the
+* FIFO such that it's empty and ready to use.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+* @param RegBaseAddress contains the base address of the registers for
+*        the packet FIFO.
+* @param DataBaseAddress contains the base address of the data for
+*        the packet FIFO.
+*
+* @return
+*
+* Always returns XST_SUCCESS.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XPacketFifoV100b_Initialize(XPacketFifoV100b * InstancePtr,
+			    u32 RegBaseAddress, u32 DataBaseAddress)
+{
+	/* assert to verify input argument are valid */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+
+	/* initialize the component variables to the specified state */
+
+	InstancePtr->RegBaseAddress = RegBaseAddress;
+	InstancePtr->DataBaseAddress = DataBaseAddress;
+	InstancePtr->IsReady = XCOMPONENT_IS_READY;
+
+	/* reset the FIFO such that it's empty and ready to use and indicate the
+	 * initialization was successful, note that the is ready variable must be
+	 * set prior to calling the reset function to prevent an assert
+	 */
+	XPF_V100B_RESET(InstancePtr);
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/*
+*
+* This function performs a self-test on the specified packet FIFO.  The self
+* test resets the FIFO and reads a register to determine if it is the correct
+* reset value.  This test is destructive in that any data in the FIFO will
+* be lost.
+*
+* @param InstancePtr is a pointer to the packet FIFO to be operated on.
+*
+* @param FifoType specifies the type of FIFO, read or write, for the self test.
+*        The FIFO type is specified by the values XPF_READ_FIFO_TYPE or
+*        XPF_WRITE_FIFO_TYPE.
+*
+* @return
+*
+* XST_SUCCESS is returned if the selftest is successful, or
+* XST_PFIFO_BAD_REG_VALUE indicating that the value readback from the
+* occupancy/vacancy count register after a reset does not match the
+* specified reset value.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XPacketFifoV100b_SelfTest(XPacketFifoV100b * InstancePtr, u32 FifoType)
+{
+	u32 Register;
+
+	/* assert to verify valid input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID((FifoType == XPF_READ_FIFO_TYPE) ||
+			(FifoType == XPF_WRITE_FIFO_TYPE));
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* reset the fifo and then check to make sure the occupancy/vacancy
+	 * register contents are correct for a reset condition
+	 */
+	XPF_V100B_RESET(InstancePtr);
+
+	Register = XIo_In32(InstancePtr->RegBaseAddress +
+			    XPF_COUNT_STATUS_REG_OFFSET);
+
+	/* check the value of the register to ensure that it's correct for the
+	 * specified FIFO type since both FIFO types reset to empty, but a bit
+	 * in the register changes definition based upon FIFO type
+	 */
+
+	if (FifoType == XPF_READ_FIFO_TYPE) {
+		/* check the regiser value for a read FIFO which should be empty */
+
+		if (Register != XPF_EMPTY_FULL_MASK) {
+			return XST_PFIFO_BAD_REG_VALUE;
+		}
+	} else {
+		/* check the register value for a write FIFO which should not be full
+		 * on reset
+		 */
+		if ((Register & XPF_EMPTY_FULL_MASK) != 0) {
+			return XST_PFIFO_BAD_REG_VALUE;
+		}
+	}
+
+	/* the test was successful */
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/*
+*
+* Read data from a FIFO and puts it into a specified buffer. The packet FIFO is
+* currently 32 bits wide such that an input buffer which is a series of bytes
+* is filled from the FIFO a word at a time. If the requested byte count is not
+* a multiple of 32 bit words, it is necessary for this function to format the
+* remaining 32 bit word from the FIFO into a series of bytes in the buffer.
+* There may be up to 3 extra bytes which must be extracted from the last word
+* of the FIFO and put into the buffer.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+* @param BufferPtr points to the memory buffer to write the data into. This
+*        buffer must be 32 bit aligned or an alignment exception could be
+*        generated. Since this buffer is a byte buffer, the data is assumed to
+*        be endian independent.
+* @param ByteCount contains the number of bytes to read from the FIFO. This
+*        number of bytes must be present in the FIFO or an error will be
+*        returned.
+*
+* @return
+*
+* XST_SUCCESS indicates the operation was successful.  If the number of
+* bytes specified by the byte count is not present in the FIFO
+* XST_PFIFO_LACK_OF_DATA is returned.
+*
+* If the function was successful, the specified buffer is modified to contain
+* the bytes which were removed from the FIFO.
+*
+* @note
+*
+* Note that the exact number of bytes which are present in the FIFO is
+* not known by this function.  It can only check for a number of 32 bit
+* words such that if the byte count specified is incorrect, but is still
+* possible based on the number of words in the FIFO, up to 3 garbage bytes
+* may be present at the end of the buffer.
+* <br><br>
+* This function assumes that if the device consuming data from the FIFO is
+* a byte device, the order of the bytes to be consumed is from the most
+* significant byte to the least significant byte of a 32 bit word removed
+* from the FIFO.
+*
+******************************************************************************/
+XStatus
+XPacketFifoV100b_Read(XPacketFifoV100b * InstancePtr,
+		      u8 * BufferPtr, u32 ByteCount)
+{
+	u32 FifoCount;
+	u32 WordCount;
+	u32 ExtraByteCount;
+	u32 *WordBuffer = (u32 *) BufferPtr;
+
+	/* assert to verify valid input arguments including 32 bit alignment of
+	 * the buffer pointer
+	 */
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BufferPtr != NULL);
+	XASSERT_NONVOID(((u32) BufferPtr &
+			 (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0);
+	XASSERT_NONVOID(ByteCount != 0);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* get the count of how many 32 bit words are in the FIFO, if there aren't
+	 * enought words to satisfy the request, return an error
+	 */
+
+	FifoCount = XIo_In32(InstancePtr->RegBaseAddress +
+			     XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK;
+
+	if ((FifoCount * XPF_FIFO_WIDTH_BYTE_COUNT) < ByteCount) {
+		return XST_PFIFO_LACK_OF_DATA;
+	}
+
+	/* calculate the number of words to read from the FIFO before the word
+	 * containing the extra bytes, and calculate the number of extra bytes
+	 * the extra bytes are defined as those at the end of the buffer when
+	 * the buffer does not end on a 32 bit boundary
+	 */
+	WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT;
+	ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT;
+
+	/* Read the 32 bit words from the FIFO for all the buffer except the
+	 * last word which contains the extra bytes, the following code assumes
+	 * that the buffer is 32 bit aligned, otherwise an alignment exception could
+	 * be generated
+	 */
+	for (FifoCount = 0; FifoCount < WordCount; FifoCount++) {
+		WordBuffer[FifoCount] = XIo_In32(InstancePtr->DataBaseAddress);
+	}
+
+	/* if there are extra bytes to handle, read the last word from the FIFO
+	 * and insert the extra bytes into the buffer
+	 */
+	if (ExtraByteCount > 0) {
+		u32 LastWord;
+		u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount);
+
+		/* get the last word from the FIFO for the extra bytes */
+
+		LastWord = XIo_In32(InstancePtr->DataBaseAddress);
+
+		/* one extra byte in the last word, put the byte into the next location
+		 * of the buffer, bytes in a word of the FIFO are ordered from most
+		 * significant byte to least
+		 */
+		if (ExtraByteCount == 1) {
+			ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
+		}
+
+		/* two extra bytes in the last word, put each byte into the next two
+		 * locations of the buffer
+		 */
+		else if (ExtraByteCount == 2) {
+			ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
+			ExtraBytesBuffer[1] = (u8) (LastWord >> 16);
+		}
+		/* three extra bytes in the last word, put each byte into the next three
+		 * locations of the buffer
+		 */
+		else if (ExtraByteCount == 3) {
+			ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
+			ExtraBytesBuffer[1] = (u8) (LastWord >> 16);
+			ExtraBytesBuffer[2] = (u8) (LastWord >> 8);
+		}
+	}
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/*
+*
+* Write data into a packet FIFO. The packet FIFO is currently 32 bits wide
+* such that an input buffer which is a series of bytes must be written into the
+* FIFO a word at a time. If the buffer is not a multiple of 32 bit words, it is
+* necessary for this function to format the remaining bytes into a single 32
+* bit word to be inserted into the FIFO. This is necessary to avoid any
+* accesses past the end of the buffer.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+* @param BufferPtr points to the memory buffer that data is to be read from
+*        and written into the FIFO. Since this buffer is a byte buffer, the data
+*        is assumed to be endian independent. This buffer must be 32 bit aligned
+*        or an alignment exception could be generated.
+* @param ByteCount contains the number of bytes to read from the buffer and to
+*        write to the FIFO.
+*
+* @return
+*
+* XST_SUCCESS is returned if the operation succeeded.  If there is not enough
+* room in the FIFO to hold the specified bytes, XST_PFIFO_NO_ROOM is
+* returned.
+*
+* @note
+*
+* This function assumes that if the device inserting data into the FIFO is
+* a byte device, the order of the bytes in each 32 bit word is from the most
+* significant byte to the least significant byte.
+*
+******************************************************************************/
+XStatus
+XPacketFifoV100b_Write(XPacketFifoV100b * InstancePtr,
+		       u8 * BufferPtr, u32 ByteCount)
+{
+	u32 FifoCount;
+	u32 WordCount;
+	u32 ExtraByteCount;
+	u32 *WordBuffer = (u32 *) BufferPtr;
+
+	/* assert to verify valid input arguments including 32 bit alignment of
+	 * the buffer pointer
+	 */
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BufferPtr != NULL);
+	XASSERT_NONVOID(((u32) BufferPtr &
+			 (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0);
+	XASSERT_NONVOID(ByteCount != 0);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/* get the count of how many words may be inserted into the FIFO */
+
+	FifoCount = XIo_In32(InstancePtr->RegBaseAddress +
+			     XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK;
+
+	/* Calculate the number of 32 bit words required to insert the specified
+	 * number of bytes in the FIFO and determine the number of extra bytes
+	 * if the buffer length is not a multiple of 32 bit words
+	 */
+
+	WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT;
+	ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT;
+
+	/* take into account the extra bytes in the total word count */
+
+	if (ExtraByteCount > 0) {
+		WordCount++;
+	}
+
+	/* if there's not enough room in the FIFO to hold the specified
+	 * number of bytes, then indicate an error,
+	 */
+	if (FifoCount < WordCount) {
+		return XST_PFIFO_NO_ROOM;
+	}
+
+	/* readjust the word count to not take into account the extra bytes */
+
+	if (ExtraByteCount > 0) {
+		WordCount--;
+	}
+
+	/* Write all the bytes of the buffer which can be written as 32 bit
+	 * words into the FIFO, waiting to handle the extra bytes seperately
+	 */
+	for (FifoCount = 0; FifoCount < WordCount; FifoCount++) {
+		XIo_Out32(InstancePtr->DataBaseAddress, WordBuffer[FifoCount]);
+	}
+
+	/* if there are extra bytes to handle, extract them from the buffer
+	 * and create a 32 bit word and write it to the FIFO
+	 */
+	if (ExtraByteCount > 0) {
+		u32 LastWord = 0;
+		u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount);
+
+		/* one extra byte in the buffer, put the byte into the last word
+		 * to be inserted into the FIFO, perform this processing inline rather
+		 * than in a loop to help performance
+		 */
+		if (ExtraByteCount == 1) {
+			LastWord = ExtraBytesBuffer[0] << 24;
+		}
+
+		/* two extra bytes in the buffer, put each byte into the last word
+		 * to be inserted into the FIFO
+		 */
+		else if (ExtraByteCount == 2) {
+			LastWord = ExtraBytesBuffer[0] << 24 |
+			    ExtraBytesBuffer[1] << 16;
+		}
+
+		/* three extra bytes in the buffer, put each byte into the last word
+		 * to be inserted into the FIFO
+		 */
+		else if (ExtraByteCount == 3) {
+			LastWord = ExtraBytesBuffer[0] << 24 |
+			    ExtraBytesBuffer[1] << 16 |
+			    ExtraBytesBuffer[2] << 8;
+		}
+
+		/* write the last 32 bit word to the FIFO and return with no errors */
+
+		XIo_Out32(InstancePtr->DataBaseAddress, LastWord);
+	}
+
+	return XST_SUCCESS;
+}

+ 306 - 0
board/xilinx/common/xpacket_fifo_v1_00_b.h

@@ -0,0 +1,306 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/*
+*
+* @file xpacket_fifo_v1_00_b.h
+*
+* This component is a common component because it's primary purpose is to
+* prevent code duplication in drivers. A driver which must handle a packet
+* FIFO uses this component rather than directly manipulating a packet FIFO.
+*
+* A FIFO is a device which has dual port memory such that one user may be
+* inserting data into the FIFO while another is consuming data from the FIFO.
+* A packet FIFO is designed for use with packet protocols such as Ethernet and
+* ATM.  It is typically only used with devices when DMA and/or Scatter Gather
+* is used.  It differs from a nonpacket FIFO in that it does not provide any
+* interrupts for thresholds of the FIFO such that it is less useful without
+* DMA.
+*
+* @note
+*
+* This component has the capability to generate an interrupt when an error
+* condition occurs.  It is the user's responsibility to provide the interrupt
+* processing to handle the interrupt. This component provides the ability to
+* determine if that interrupt is active, a deadlock condition, and the ability
+* to reset the FIFO to clear the condition. In this condition, the device which
+* is using the FIFO should also be reset to prevent other problems. This error
+* condition could occur as a normal part of operation if the size of the FIFO
+* is not setup correctly.  See the hardware IP specification for more details.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b rpm 03/26/02  First release
+* </pre>
+*
+*****************************************************************************/
+#ifndef XPACKET_FIFO_H		/* prevent circular inclusions */
+#define XPACKET_FIFO_H		/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xstatus.h"
+
+/************************** Constant Definitions *****************************/
+
+/*
+ * These constants specify the FIFO type and are mutually exclusive
+ */
+#define XPF_READ_FIFO_TYPE      0	/* a read FIFO */
+#define XPF_WRITE_FIFO_TYPE     1	/* a write FIFO */
+
+/*
+ * These constants define the offsets to each of the registers from the
+ * register base address, each of the constants are a number of bytes
+ */
+#define XPF_RESET_REG_OFFSET            0UL
+#define XPF_MODULE_INFO_REG_OFFSET      0UL
+#define XPF_COUNT_STATUS_REG_OFFSET     4UL
+
+/*
+ * This constant is used with the Reset Register
+ */
+#define XPF_RESET_FIFO_MASK             0x0000000A
+
+/*
+ * These constants are used with the Occupancy/Vacancy Count Register. This
+ * register also contains FIFO status
+ */
+#define XPF_COUNT_MASK                  0x0000FFFF
+#define XPF_DEADLOCK_MASK               0x20000000
+#define XPF_ALMOST_EMPTY_FULL_MASK      0x40000000
+#define XPF_EMPTY_FULL_MASK             0x80000000
+
+/**************************** Type Definitions *******************************/
+
+/*
+ * The XPacketFifo driver instance data. The driver is required to allocate a
+ * variable of this type for every packet FIFO in the device.
+ */
+typedef struct {
+	u32 RegBaseAddress;	/* Base address of registers */
+	u32 IsReady;		/* Device is initialized and ready */
+	u32 DataBaseAddress;	/* Base address of data for FIFOs */
+} XPacketFifoV100b;
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/*****************************************************************************/
+/*
+*
+* Reset the specified packet FIFO.  Resetting a FIFO will cause any data
+* contained in the FIFO to be lost.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* Signature: void XPF_V100B_RESET(XPacketFifoV100b *InstancePtr)
+*
+******************************************************************************/
+#define XPF_V100B_RESET(InstancePtr) \
+    XIo_Out32((InstancePtr)->RegBaseAddress + XPF_RESET_REG_OFFSET, XPF_RESET_FIFO_MASK);
+
+/*****************************************************************************/
+/*
+*
+* Get the occupancy count for a read packet FIFO and the vacancy count for a
+* write packet FIFO. These counts indicate the number of 32-bit words
+* contained (occupancy) in the FIFO or the number of 32-bit words available
+* to write (vacancy) in the FIFO.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+*
+* @return
+*
+* The occupancy or vacancy count for the specified packet FIFO.
+*
+* @note
+*
+* Signature: u32 XPF_V100B_GET_COUNT(XPacketFifoV100b *InstancePtr)
+*
+******************************************************************************/
+#define XPF_V100B_GET_COUNT(InstancePtr) \
+    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \
+    XPF_COUNT_MASK)
+
+/*****************************************************************************/
+/*
+*
+* Determine if the specified packet FIFO is almost empty. Almost empty is
+* defined for a read FIFO when there is only one data word in the FIFO.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+*
+* @return
+*
+* TRUE if the packet FIFO is almost empty, FALSE otherwise.
+*
+* @note
+*
+* Signature: u32 XPF_V100B_IS_ALMOST_EMPTY(XPacketFifoV100b *InstancePtr)
+*
+******************************************************************************/
+#define XPF_V100B_IS_ALMOST_EMPTY(InstancePtr) \
+    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \
+    XPF_ALMOST_EMPTY_FULL_MASK)
+
+/*****************************************************************************/
+/*
+*
+* Determine if the specified packet FIFO is almost full. Almost full is
+* defined for a write FIFO when there is only one available data word in the
+* FIFO.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+*
+* @return
+*
+* TRUE if the packet FIFO is almost full, FALSE otherwise.
+*
+* @note
+*
+* Signature: u32 XPF_V100B_IS_ALMOST_FULL(XPacketFifoV100b *InstancePtr)
+*
+******************************************************************************/
+#define XPF_V100B_IS_ALMOST_FULL(InstancePtr) \
+    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \
+    XPF_ALMOST_EMPTY_FULL_MASK)
+
+/*****************************************************************************/
+/*
+*
+* Determine if the specified packet FIFO is empty. This applies only to a
+* read FIFO.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+*
+* @return
+*
+* TRUE if the packet FIFO is empty, FALSE otherwise.
+*
+* @note
+*
+* Signature: u32 XPF_V100B_IS_EMPTY(XPacketFifoV100b *InstancePtr)
+*
+******************************************************************************/
+#define XPF_V100B_IS_EMPTY(InstancePtr) \
+    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \
+    XPF_EMPTY_FULL_MASK)
+
+/*****************************************************************************/
+/*
+*
+* Determine if the specified packet FIFO is full. This applies only to a
+* write FIFO.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+*
+* @return
+*
+* TRUE if the packet FIFO is full, FALSE otherwise.
+*
+* @note
+*
+* Signature: u32 XPF_V100B_IS_FULL(XPacketFifoV100b *InstancePtr)
+*
+******************************************************************************/
+#define XPF_V100B_IS_FULL(InstancePtr) \
+    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \
+    XPF_EMPTY_FULL_MASK)
+
+/*****************************************************************************/
+/*
+*
+* Determine if the specified packet FIFO is deadlocked.  This condition occurs
+* when the FIFO is full and empty at the same time and is caused by a packet
+* being written to the FIFO which exceeds the total data capacity of the FIFO.
+* It occurs because of the mark/restore features of the packet FIFO which allow
+* retransmission of a packet. The software should reset the FIFO and any devices
+* using the FIFO when this condition occurs.
+*
+* @param InstancePtr contains a pointer to the FIFO to operate on.
+*
+* @return
+*
+* TRUE if the packet FIFO is deadlocked, FALSE otherwise.
+*
+* @note
+*
+* This component has the capability to generate an interrupt when an error
+* condition occurs.  It is the user's responsibility to provide the interrupt
+* processing to handle the interrupt. This function provides the ability to
+* determine if a deadlock condition, and the ability to reset the FIFO to
+* clear the condition.
+*
+* In this condition, the device which is using the FIFO should also be reset
+* to prevent other problems. This error condition could occur as a normal part
+* of operation if the size of the FIFO is not setup correctly.
+*
+* Signature: u32 XPF_V100B_IS_DEADLOCKED(XPacketFifoV100b *InstancePtr)
+*
+******************************************************************************/
+#define XPF_V100B_IS_DEADLOCKED(InstancePtr) \
+    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \
+    XPF_DEADLOCK_MASK)
+
+/************************** Function Prototypes ******************************/
+
+/* Standard functions */
+
+XStatus XPacketFifoV100b_Initialize(XPacketFifoV100b * InstancePtr,
+				    u32 RegBaseAddress, u32 DataBaseAddress);
+XStatus XPacketFifoV100b_SelfTest(XPacketFifoV100b * InstancePtr, u32 FifoType);
+
+/* Data functions */
+
+XStatus XPacketFifoV100b_Read(XPacketFifoV100b * InstancePtr,
+			      u8 * ReadBufferPtr, u32 ByteCount);
+XStatus XPacketFifoV100b_Write(XPacketFifoV100b * InstancePtr,
+			       u8 * WriteBufferPtr, u32 ByteCount);
+
+#endif				/* end of protection macro */

+ 347 - 0
board/xilinx/common/xstatus.h

@@ -0,0 +1,347 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xstatus.h
+*
+* This file contains Xilinx software status codes.  Status codes have their
+* own data type called XStatus.  These codes are used throughout the Xilinx
+* device drivers.
+*
+******************************************************************************/
+
+#ifndef XSTATUS_H		/* prevent circular inclusions */
+#define XSTATUS_H		/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+
+/************************** Constant Definitions *****************************/
+
+/*********************** Common statuses 0 - 500 *****************************/
+
+#define XST_SUCCESS                     0L
+#define XST_FAILURE                     1L
+#define XST_DEVICE_NOT_FOUND            2L
+#define XST_DEVICE_BLOCK_NOT_FOUND      3L
+#define XST_INVALID_VERSION             4L
+#define XST_DEVICE_IS_STARTED           5L
+#define XST_DEVICE_IS_STOPPED           6L
+#define XST_FIFO_ERROR                  7L	/* an error occurred during an
+						   operation with a FIFO such as
+						   an underrun or overrun, this
+						   error requires the device to
+						   be reset */
+#define XST_RESET_ERROR                 8L	/* an error occurred which requires
+						   the device to be reset */
+#define XST_DMA_ERROR                   9L	/* a DMA error occurred, this error
+						   typically requires the device
+						   using the DMA to be reset */
+#define XST_NOT_POLLED                  10L	/* the device is not configured for
+						   polled mode operation */
+#define XST_FIFO_NO_ROOM                11L	/* a FIFO did not have room to put
+						   the specified data into */
+#define XST_BUFFER_TOO_SMALL            12L	/* the buffer is not large enough
+						   to hold the expected data */
+#define XST_NO_DATA                     13L	/* there was no data available */
+#define XST_REGISTER_ERROR              14L	/* a register did not contain the
+						   expected value */
+#define XST_INVALID_PARAM               15L	/* an invalid parameter was passed
+						   into the function */
+#define XST_NOT_SGDMA                   16L	/* the device is not configured for
+						   scatter-gather DMA operation */
+#define XST_LOOPBACK_ERROR              17L	/* a loopback test failed */
+#define XST_NO_CALLBACK                 18L	/* a callback has not yet been
+						 * registered */
+#define XST_NO_FEATURE                  19L	/* device is not configured with
+						 * the requested feature */
+#define XST_NOT_INTERRUPT               20L	/* device is not configured for
+						 * interrupt mode operation */
+#define XST_DEVICE_BUSY                 21L	/* device is busy */
+#define XST_ERROR_COUNT_MAX             22L	/* the error counters of a device
+						 * have maxed out */
+#define XST_IS_STARTED                  23L	/* used when part of device is
+						 * already started i.e.
+						 * sub channel */
+#define XST_IS_STOPPED                  24L	/* used when part of device is
+						 * already stopped i.e.
+						 * sub channel */
+
+/***************** Utility Component statuses 401 - 500  *********************/
+
+#define XST_MEMTEST_FAILED              401L	/* memory test failed */
+
+/***************** Common Components statuses 501 - 1000 *********************/
+
+/********************* Packet Fifo statuses 501 - 510 ************************/
+
+#define XST_PFIFO_LACK_OF_DATA          501L	/* not enough data in FIFO   */
+#define XST_PFIFO_NO_ROOM               502L	/* not enough room in FIFO   */
+#define XST_PFIFO_BAD_REG_VALUE         503L	/* self test, a register value
+						   was invalid after reset */
+
+/************************** DMA statuses 511 - 530 ***************************/
+
+#define XST_DMA_TRANSFER_ERROR          511L	/* self test, DMA transfer
+						   failed */
+#define XST_DMA_RESET_REGISTER_ERROR    512L	/* self test, a register value
+						   was invalid after reset */
+#define XST_DMA_SG_LIST_EMPTY           513L	/* scatter gather list contains
+						   no buffer descriptors ready
+						   to be processed */
+#define XST_DMA_SG_IS_STARTED           514L	/* scatter gather not stopped */
+#define XST_DMA_SG_IS_STOPPED           515L	/* scatter gather not running */
+#define XST_DMA_SG_LIST_FULL            517L	/* all the buffer desciptors of
+						   the scatter gather list are
+						   being used */
+#define XST_DMA_SG_BD_LOCKED            518L	/* the scatter gather buffer
+						   descriptor which is to be
+						   copied over in the scatter
+						   list is locked */
+#define XST_DMA_SG_NOTHING_TO_COMMIT    519L	/* no buffer descriptors have been
+						   put into the scatter gather
+						   list to be commited */
+#define XST_DMA_SG_COUNT_EXCEEDED       521L	/* the packet count threshold
+						   specified was larger than the
+						   total # of buffer descriptors
+						   in the scatter gather list */
+#define XST_DMA_SG_LIST_EXISTS          522L	/* the scatter gather list has
+						   already been created */
+#define XST_DMA_SG_NO_LIST              523L	/* no scatter gather list has
+						   been created */
+#define XST_DMA_SG_BD_NOT_COMMITTED     524L	/* the buffer descriptor which was
+						   being started was not committed
+						   to the list */
+#define XST_DMA_SG_NO_DATA              525L	/* the buffer descriptor to start
+						   has already been used by the
+						   hardware so it can't be reused
+						 */
+
+/************************** IPIF statuses 531 - 550 ***************************/
+
+#define XST_IPIF_REG_WIDTH_ERROR        531L	/* an invalid register width
+						   was passed into the function */
+#define XST_IPIF_RESET_REGISTER_ERROR   532L	/* the value of a register at
+						   reset was not valid */
+#define XST_IPIF_DEVICE_STATUS_ERROR    533L	/* a write to the device interrupt
+						   status register did not read
+						   back correctly */
+#define XST_IPIF_DEVICE_ACK_ERROR       534L	/* the device interrupt status
+						   register did not reset when
+						   acked */
+#define XST_IPIF_DEVICE_ENABLE_ERROR    535L	/* the device interrupt enable
+						   register was not updated when
+						   other registers changed */
+#define XST_IPIF_IP_STATUS_ERROR        536L	/* a write to the IP interrupt
+						   status register did not read
+						   back correctly */
+#define XST_IPIF_IP_ACK_ERROR           537L	/* the IP interrupt status register
+						   did not reset when acked */
+#define XST_IPIF_IP_ENABLE_ERROR        538L	/* IP interrupt enable register was
+						   not updated correctly when other
+						   registers changed */
+#define XST_IPIF_DEVICE_PENDING_ERROR   539L	/* The device interrupt pending
+						   register did not indicate the
+						   expected value */
+#define XST_IPIF_DEVICE_ID_ERROR        540L	/* The device interrupt ID register
+						   did not indicate the expected
+						   value */
+
+/****************** Device specific statuses 1001 - 4095 *********************/
+
+/********************* Ethernet statuses 1001 - 1050 *************************/
+
+#define XST_EMAC_MEMORY_SIZE_ERROR  1001L	/* Memory space is not big enough
+						 * to hold the minimum number of
+						 * buffers or descriptors */
+#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L	/* Memory allocation failed */
+#define XST_EMAC_MII_READ_ERROR     1003L	/* MII read error */
+#define XST_EMAC_MII_BUSY           1004L	/* An MII operation is in progress */
+#define XST_EMAC_OUT_OF_BUFFERS     1005L	/* Adapter is out of buffers */
+#define XST_EMAC_PARSE_ERROR        1006L	/* Invalid adapter init string */
+#define XST_EMAC_COLLISION_ERROR    1007L	/* Excess deferral or late
+						 * collision on polled send */
+
+/*********************** UART statuses 1051 - 1075 ***************************/
+#define XST_UART
+
+#define XST_UART_INIT_ERROR         1051L
+#define XST_UART_START_ERROR        1052L
+#define XST_UART_CONFIG_ERROR       1053L
+#define XST_UART_TEST_FAIL          1054L
+#define XST_UART_BAUD_ERROR         1055L
+#define XST_UART_BAUD_RANGE         1056L
+
+/************************ IIC statuses 1076 - 1100 ***************************/
+
+#define XST_IIC_SELFTEST_FAILED         1076	/* self test failed            */
+#define XST_IIC_BUS_BUSY                1077	/* bus found busy              */
+#define XST_IIC_GENERAL_CALL_ADDRESS    1078	/* mastersend attempted with   */
+					     /* general call address        */
+#define XST_IIC_STAND_REG_RESET_ERROR   1079	/* A non parameterizable reg   */
+					     /* value after reset not valid */
+#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080	/* Tx fifo included in design  */
+					     /* value after reset not valid */
+#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081	/* Rx fifo included in design  */
+					     /* value after reset not valid */
+#define XST_IIC_TBA_REG_RESET_ERROR     1082	/* 10 bit addr incl in design  */
+					     /* value after reset not valid */
+#define XST_IIC_CR_READBACK_ERROR       1083	/* Read of the control register */
+					     /* didn't return value written */
+#define XST_IIC_DTR_READBACK_ERROR      1084	/* Read of the data Tx reg     */
+					     /* didn't return value written */
+#define XST_IIC_DRR_READBACK_ERROR      1085	/* Read of the data Receive reg */
+					     /* didn't return value written */
+#define XST_IIC_ADR_READBACK_ERROR      1086	/* Read of the data Tx reg     */
+					     /* didn't return value written */
+#define XST_IIC_TBA_READBACK_ERROR      1087	/* Read of the 10 bit addr reg */
+					     /* didn't return written value */
+#define XST_IIC_NOT_SLAVE               1088	/* The device isn't a slave    */
+
+/*********************** ATMC statuses 1101 - 1125 ***************************/
+
+#define XST_ATMC_ERROR_COUNT_MAX    1101L	/* the error counters in the ATM
+						   controller hit the max value
+						   which requires the statistics
+						   to be cleared */
+
+/*********************** Flash statuses 1126 - 1150 **************************/
+
+#define XST_FLASH_BUSY                1126L	/* Flash is erasing or programming */
+#define XST_FLASH_READY               1127L	/* Flash is ready for commands */
+#define XST_FLASH_ERROR               1128L	/* Flash had detected an internal
+						   error. Use XFlash_DeviceControl
+						   to retrieve device specific codes */
+#define XST_FLASH_ERASE_SUSPENDED     1129L	/* Flash is in suspended erase state */
+#define XST_FLASH_WRITE_SUSPENDED     1130L	/* Flash is in suspended write state */
+#define XST_FLASH_PART_NOT_SUPPORTED  1131L	/* Flash type not supported by
+						   driver */
+#define XST_FLASH_NOT_SUPPORTED       1132L	/* Operation not supported */
+#define XST_FLASH_TOO_MANY_REGIONS    1133L	/* Too many erase regions */
+#define XST_FLASH_TIMEOUT_ERROR       1134L	/* Programming or erase operation
+						   aborted due to a timeout */
+#define XST_FLASH_ADDRESS_ERROR       1135L	/* Accessed flash outside its
+						   addressible range */
+#define XST_FLASH_ALIGNMENT_ERROR     1136L	/* Write alignment error */
+#define XST_FLASH_BLOCKING_CALL_ERROR 1137L	/* Couldn't return immediately from
+						   write/erase function with
+						   XFL_NON_BLOCKING_WRITE/ERASE
+						   option cleared */
+#define XST_FLASH_CFI_QUERY_ERROR     1138L	/* Failed to query the device */
+
+/*********************** SPI statuses 1151 - 1175 ****************************/
+
+#define XST_SPI_MODE_FAULT          1151	/* master was selected as slave */
+#define XST_SPI_TRANSFER_DONE       1152	/* data transfer is complete */
+#define XST_SPI_TRANSMIT_UNDERRUN   1153	/* slave underruns transmit register */
+#define XST_SPI_RECEIVE_OVERRUN     1154	/* device overruns receive register */
+#define XST_SPI_NO_SLAVE            1155	/* no slave has been selected yet */
+#define XST_SPI_TOO_MANY_SLAVES     1156	/* more than one slave is being
+						 * selected */
+#define XST_SPI_NOT_MASTER          1157	/* operation is valid only as master */
+#define XST_SPI_SLAVE_ONLY          1158	/* device is configured as slave-only */
+#define XST_SPI_SLAVE_MODE_FAULT    1159	/* slave was selected while disabled */
+
+/********************** OPB Arbiter statuses 1176 - 1200 *********************/
+
+#define XST_OPBARB_INVALID_PRIORITY  1176	/* the priority registers have either
+						 * one master assigned to two or more
+						 * priorities, or one master not
+						 * assigned to any priority
+						 */
+#define XST_OPBARB_NOT_SUSPENDED     1177	/* an attempt was made to modify the
+						 * priority levels without first
+						 * suspending the use of priority
+						 * levels
+						 */
+#define XST_OPBARB_PARK_NOT_ENABLED  1178	/* bus parking by id was enabled but
+						 * bus parking was not enabled
+						 */
+#define XST_OPBARB_NOT_FIXED_PRIORITY 1179	/* the arbiter must be in fixed
+						 * priority mode to allow the
+						 * priorities to be changed
+						 */
+
+/************************ Intc statuses 1201 - 1225 **************************/
+
+#define XST_INTC_FAIL_SELFTEST      1201	/* self test failed */
+#define XST_INTC_CONNECT_ERROR      1202	/* interrupt already in use */
+
+/********************** TmrCtr statuses 1226 - 1250 **************************/
+
+#define XST_TMRCTR_TIMER_FAILED     1226	/* self test failed */
+
+/********************** WdtTb statuses 1251 - 1275 ***************************/
+
+#define XST_WDTTB_TIMER_FAILED      1251L
+
+/********************** PlbArb statuses 1276 - 1300 **************************/
+
+#define XST_PLBARB_FAIL_SELFTEST    1276L
+
+/********************** Plb2Opb statuses 1301 - 1325 *************************/
+
+#define XST_PLB2OPB_FAIL_SELFTEST   1301L
+
+/********************** Opb2Plb statuses 1326 - 1350 *************************/
+
+#define XST_OPB2PLB_FAIL_SELFTEST   1326L
+
+/********************** SysAce statuses 1351 - 1360 **************************/
+
+#define XST_SYSACE_NO_LOCK          1351L	/* No MPU lock has been granted */
+
+/********************** PCI Bridge statuses 1361 - 1375 **********************/
+
+#define XST_PCI_INVALID_ADDRESS     1361L
+
+/**************************** Type Definitions *******************************/
+
+/**
+ * The status typedef.
+ */
+typedef u32 XStatus;
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+#endif				/* end of protection macro */

+ 350 - 0
board/xilinx/common/xversion.c

@@ -0,0 +1,350 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************
+*
+* This file contains the implementation of the XVersion component. This
+* component represents a version ID.  It is encapsulated within a component
+* so that it's type and implementation can change without affecting users of
+* it.
+*
+* The version is formatted as X.YYZ where X = 0 - 9, Y = 00 - 99, Z = a - z
+* X is the major revision, YY is the minor revision, and Z is the
+* compatability revision.
+*
+* Packed versions are also utilized for the configuration ROM such that
+* memory is minimized. A packed version consumes only 16 bits and is
+* formatted as follows.
+*
+* <pre>
+* Revision                  Range       Bit Positions
+*
+* Major Revision            0 - 9       Bits 15 - 12
+* Minor Revision            0 - 99      Bits 11 - 5
+* Compatability Revision    a - z       Bits 4 - 0
+</pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xversion.h"
+
+/************************** Constant Definitions *****************************/
+
+/* the following constants define the masks and shift values to allow the
+ * revisions to be packed and unpacked, a packed version is packed into a 16
+ * bit value in the following format, XXXXYYYYYYYZZZZZ, where XXXX is the
+ * major revision, YYYYYYY is the minor revision, and ZZZZZ is the compatability
+ * revision
+ */
+#define XVE_MAJOR_SHIFT_VALUE       12
+#define XVE_MINOR_ONLY_MASK         0x0FE0
+#define XVE_MINOR_SHIFT_VALUE       5
+#define XVE_COMP_ONLY_MASK          0x001F
+
+/* the following constants define the specific characters of a version string
+ * for each character of the revision, a version string is in the following
+ * format, "X.YYZ" where X is the major revision (0 - 9), YY is the minor
+ * revision (00 - 99), and Z is the compatability revision (a - z)
+ */
+#define XVE_MAJOR_CHAR      0	/* major revision 0 - 9 */
+#define XVE_MINOR_TENS_CHAR 2	/* minor revision tens 0 - 9 */
+#define XVE_MINOR_ONES_CHAR 3	/* minor revision ones 0 - 9 */
+#define XVE_COMP_CHAR       4	/* compatability revision a - z */
+#define XVE_END_STRING_CHAR 5
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+static u32 IsVersionStringValid(s8 * StringPtr);
+
+/*****************************************************************************
+*
+* Unpacks a packed version into the specified version. Versions are packed
+* into the configuration ROM to reduce the amount storage. A packed version
+* is a binary format as oppossed to a non-packed version which is implemented
+* as a string.
+*
+* @param    InstancePtr points to the version to unpack the packed version into.
+* @param    PackedVersion contains the packed version to unpack.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XVersion_UnPack(XVersion * InstancePtr, u16 PackedVersion)
+{
+	/* not implemented yet since CROM related */
+}
+
+/*****************************************************************************
+*
+* Packs a version into the specified packed version. Versions are packed into
+* the configuration ROM to reduce the amount storage.
+*
+* @param    InstancePtr points to the version to pack.
+* @param    PackedVersionPtr points to the packed version which will receive
+*           the new packed version.
+*
+* @return
+*
+* A status, XST_SUCCESS, indicating the packing was accomplished
+* successfully, or an error, XST_INVALID_VERSION, indicating the specified
+* input version was not valid such that the pack did not occur
+* <br><br>
+* The packed version pointed to by PackedVersionPtr is modified with the new
+* packed version if the status indicates success.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XVersion_Pack(XVersion * InstancePtr, u16 * PackedVersionPtr)
+{
+	/* not implemented yet since CROM related */
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************
+*
+* Determines if two versions are equal.
+*
+* @param    InstancePtr points to the first version to be compared.
+* @param    VersionPtr points to a second version to be compared.
+*
+* @return
+*
+* TRUE if the versions are equal, FALSE otherwise.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+u32
+XVersion_IsEqual(XVersion * InstancePtr, XVersion * VersionPtr)
+{
+	u8 *Version1 = (u8 *) InstancePtr;
+	u8 *Version2 = (u8 *) VersionPtr;
+	int Index;
+
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(VersionPtr != NULL);
+
+	/* check each byte of the versions to see if they are the same,
+	 * return at any point a byte differs between them
+	 */
+	for (Index = 0; Index < sizeof (XVersion); Index++) {
+		if (Version1[Index] != Version2[Index]) {
+			return FALSE;
+		}
+	}
+
+	/* No byte was found to be different between the versions, so indicate
+	 * the versions are equal
+	 */
+	return TRUE;
+}
+
+/*****************************************************************************
+*
+* Converts a version to a null terminated string.
+*
+* @param    InstancePtr points to the version to convert.
+* @param    StringPtr points to the string which will be the result of the
+*           conversion. This does not need to point to a null terminated
+*           string as an input, but must point to storage which is an adequate
+*           amount to hold the result string.
+*
+* @return
+*
+* The null terminated string is inserted at the location pointed to by
+* StringPtr if the status indicates success.
+*
+* @note
+*
+* It is necessary for the caller to have already allocated the storage to
+* contain the string.  The amount of memory necessary for the string is
+* specified in the version header file.
+*
+******************************************************************************/
+void
+XVersion_ToString(XVersion * InstancePtr, s8 * StringPtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(StringPtr != NULL);
+
+	/* since version is implemented as a string, just copy the specified
+	 * input into the specified output
+	 */
+	XVersion_Copy(InstancePtr, (XVersion *) StringPtr);
+}
+
+/*****************************************************************************
+*
+* Initializes a version from a null terminated string. Since the string may not
+* be a format which is compatible with the version, an error could occur.
+*
+* @param    InstancePtr points to the version which is to be initialized.
+* @param    StringPtr points to a null terminated string which will be
+*           converted to a version.  The format of the string must match the
+*           version string format which is X.YYX where X = 0 - 9, YY = 00 - 99,
+*           Z = a - z.
+*
+* @return
+*
+* A status, XST_SUCCESS, indicating the conversion was accomplished
+* successfully, or XST_INVALID_VERSION indicating the version string format
+* was not valid.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XVersion_FromString(XVersion * InstancePtr, s8 * StringPtr)
+{
+	/* assert to verify input arguments */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(StringPtr != NULL);
+
+	/* if the version string specified is not valid, return an error */
+
+	if (!IsVersionStringValid(StringPtr)) {
+		return XST_INVALID_VERSION;
+	}
+
+	/* copy the specified string into the specified version and indicate the
+	 * conversion was successful
+	 */
+	XVersion_Copy((XVersion *) StringPtr, InstancePtr);
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************
+*
+* Copies the contents of a version to another version.
+*
+* @param    InstancePtr points to the version which is the source of data for
+*           the copy operation.
+* @param    VersionPtr points to another version which is the destination of
+*           the copy operation.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XVersion_Copy(XVersion * InstancePtr, XVersion * VersionPtr)
+{
+	u8 *Source = (u8 *) InstancePtr;
+	u8 *Destination = (u8 *) VersionPtr;
+	int Index;
+
+	/* assert to verify input arguments */
+
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(VersionPtr != NULL);
+
+	/* copy each byte of the source version to the destination version */
+
+	for (Index = 0; Index < sizeof (XVersion); Index++) {
+		Destination[Index] = Source[Index];
+	}
+}
+
+/*****************************************************************************
+*
+* Determines if the specified version is valid.
+*
+* @param    StringPtr points to the string to be validated.
+*
+* @return
+*
+* TRUE if the version string is a valid format, FALSE otherwise.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static u32
+IsVersionStringValid(s8 * StringPtr)
+{
+	/* if the input string is not a valid format, "X.YYZ" where X = 0 - 9,
+	 * YY = 00 - 99, and Z = a - z, then indicate it's not valid
+	 */
+	if ((StringPtr[XVE_MAJOR_CHAR] < '0') ||
+	    (StringPtr[XVE_MAJOR_CHAR] > '9') ||
+	    (StringPtr[XVE_MINOR_TENS_CHAR] < '0') ||
+	    (StringPtr[XVE_MINOR_TENS_CHAR] > '9') ||
+	    (StringPtr[XVE_MINOR_ONES_CHAR] < '0') ||
+	    (StringPtr[XVE_MINOR_ONES_CHAR] > '9') ||
+	    (StringPtr[XVE_COMP_CHAR] < 'a') ||
+	    (StringPtr[XVE_COMP_CHAR] > 'z')) {
+		return FALSE;
+	}
+
+	return TRUE;
+}

+ 97 - 0
board/xilinx/common/xversion.h

@@ -0,0 +1,97 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************
+*
+* This file contains the interface for the XVersion component. This
+* component represents a version ID.  It is encapsulated within a component
+* so that it's type and implementation can change without affecting users of
+* it.
+*
+* The version is formatted as X.YYZ where X = 0 - 9, Y = 00 - 99, Z = a - z
+* X is the major revision, YY is the minor revision, and Z is the
+* compatability revision.
+*
+* Packed versions are also utilized for the configuration ROM such that
+* memory is minimized. A packed version consumes only 16 bits and is
+* formatted as follows.
+*
+* <pre>
+* Revision                  Range       Bit Positions
+*
+* Major Revision            0 - 9       Bits 15 - 12
+* Minor Revision            0 - 99      Bits 11 - 5
+* Compatability Revision    a - z       Bits 4 - 0
+* </pre>
+*
+******************************************************************************/
+
+#ifndef XVERSION_H		/* prevent circular inclusions */
+#define XVERSION_H		/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xstatus.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/* the following data type is used to hold a null terminated version string
+ * consisting of the following format, "X.YYX"
+ */
+typedef s8 XVersion[6];
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+void XVersion_UnPack(XVersion * InstancePtr, u16 PackedVersion);
+
+XStatus XVersion_Pack(XVersion * InstancePtr, u16 * PackedVersion);
+
+u32 XVersion_IsEqual(XVersion * InstancePtr, XVersion * VersionPtr);
+
+void XVersion_ToString(XVersion * InstancePtr, s8 * StringPtr);
+
+XStatus XVersion_FromString(XVersion * InstancePtr, s8 * StringPtr);
+
+void XVersion_Copy(XVersion * InstancePtr, XVersion * VersionPtr);
+
+#endif				/* end of protection macro */

+ 57 - 0
board/xilinx/ml300/Makefile

@@ -0,0 +1,57 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+CFLAGS   += -I../ml300 -I../common -I../xilinx_enet
+
+LIB	= lib$(BOARD).a
+
+OBJS	= $(BOARD).o serial.o \
+	  ../xilinx_enet/emac_adapter.o ../xilinx_enet/xemac.o \
+	  ../xilinx_enet/xemac_options.o ../xilinx_enet/xemac_polled.o \
+	  ../xilinx_enet/xemac_intr.o ../xilinx_enet/xemac_g.o \
+	  ../xilinx_enet/xemac_intr_dma.o \
+	  ../common/xbasic_types.o ../common/xdma_channel.o \
+	  ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \
+	  ../common/xversion.o
+
+SOBJS	= init.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 $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################

+ 29 - 0
board/xilinx/ml300/config.mk

@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# esd ADCIOP boards
+#
+
+#TEXT_BASE = 0xFFFE0000
+TEXT_BASE = 0x04000000

+ 48 - 0
board/xilinx/ml300/init.S

@@ -0,0 +1,48 @@
+/*
+ * init.S: Stubs for U-Boot initialization
+ *
+ *     Author: Xilinx, Inc.
+ *
+ *
+ *     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.
+ *
+ *
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+ *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+ *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+ *     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ *     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ *     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+ *     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+ *     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ *     FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *     Xilinx hardware products are not intended for use in life support
+ *     appliances, devices, or systems. Use in such applications is
+ *     expressly prohibited.
+ *
+ *
+ *     (c) Copyright 2002-2004 Xilinx Inc.
+ *     All rights reserved.
+ *
+ *
+ *     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.,
+ *     675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+	.globl ext_bus_cntlr_init
+ext_bus_cntlr_init:
+	blr
+
+	.globl sdram_init
+sdram_init:
+	blr

+ 109 - 0
board/xilinx/ml300/ml300.c

@@ -0,0 +1,109 @@
+/*
+ * ml300.c: U-Boot platform support for Xilinx ML300 board
+ *
+ *     Author: Xilinx, Inc.
+ *
+ *
+ *     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.
+ *
+ *
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+ *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+ *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+ *     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ *     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ *     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+ *     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+ *     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ *     FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *     Xilinx hardware products are not intended for use in life support
+ *     appliances, devices, or systems. Use in such applications is
+ *     expressly prohibited.
+ *
+ *
+ *     (c) Copyright 2002-2004 Xilinx Inc.
+ *     All rights reserved.
+ *
+ *
+ *     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.,
+ *     675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include "xparameters.h"
+
+int
+board_pre_init(void)
+{
+	return 0;
+}
+
+int
+checkboard(void)
+{
+	unsigned char *s = getenv("serial#");
+	unsigned char *e;
+
+	if (!s || strncmp(s, "ML300", 9)) {
+		printf("### No HW ID - assuming ML300");
+	} else {
+		for (e = s; *e; ++e) {
+			if (*e == ' ')
+				break;
+		}
+
+		for (; s < e; ++s) {
+			putc(*s);
+		}
+	}
+
+	putc('\n');
+
+	return (0);
+}
+
+long int
+initdram(int board_type)
+{
+	return 128 * 1024 * 1024;
+}
+
+int
+testdram(void)
+{
+	printf("test: xxx MB - ok\n");
+
+	return (0);
+}
+
+/* implement functions originally in cpu/ppc4xx/speed.c */
+void
+get_sys_info(sys_info_t * sysInfo)
+{
+	sysInfo->freqProcessor = XPAR_CORE_CLOCK_FREQ_HZ;
+
+	/* only correct if the PLB and OPB run at the same frequency */
+	sysInfo->freqPLB = XPAR_UARTNS550_0_CLOCK_FREQ_HZ;
+	sysInfo->freqPCI = XPAR_UARTNS550_0_CLOCK_FREQ_HZ / 3;
+}
+
+ulong
+get_PCI_freq(void)
+{
+	ulong val;
+	PPC405_SYS_INFO sys_info;
+
+	get_sys_info(&sys_info);
+	val = sys_info.freqPCI;
+	return val;
+}

+ 155 - 0
board/xilinx/ml300/serial.c

@@ -0,0 +1,155 @@
+/*
+ *     Author: Xilinx, Inc.
+ *
+ *
+ *     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.
+ *
+ *
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+ *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+ *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+ *     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ *     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ *     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+ *     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+ *     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ *     FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *     Xilinx hardware products are not intended for use in life support
+ *     appliances, devices, or systems. Use in such applications is
+ *     expressly prohibited.
+ *
+ *
+ *     (c) Copyright 2002-2004 Xilinx Inc.
+ *     All rights reserved.
+ *
+ *
+ *     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.,
+ *     675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <asm/u-boot.h>
+#include <asm/processor.h>
+#include <common.h>
+#include <command.h>
+#include <configs/ml300.h>
+#include "xparameters.h"
+
+#define USE_CHAN1 \
+	((defined XPAR_UARTNS550_0_BASEADDR) && (defined CFG_INIT_CHAN1))
+#define USE_CHAN2 \
+	((defined XPAR_UARTNS550_1_BASEADDR) && (defined CFG_INIT_CHAN2))
+
+#if USE_CHAN1
+#include <ns16550.h>
+#endif
+
+#if USE_CHAN1
+const NS16550_t COM_PORTS[] = { (NS16550_t) (XPAR_UARTNS550_0_BASEADDR + 3)
+#if USE_CHAN2
+	    , (NS16550_t) (XPAR_UARTNS550_1_BASEADDR + 3)
+#endif
+};
+#endif
+
+int
+serial_init(void)
+{
+#if USE_CHAN1
+	DECLARE_GLOBAL_DATA_PTR;
+	int clock_divisor;
+
+	clock_divisor = XPAR_UARTNS550_0_CLOCK_FREQ_HZ / 16 / gd->baudrate;
+	(void) NS16550_init(COM_PORTS[0], clock_divisor);
+#if USE_CHAN2
+	clock_divisor = XPAR_UARTNS550_1_CLOCK_FREQ_HZ / 16 / gd->baudrate;
+	(void) NS16550_init(COM_PORTS[1], clock_divisor);
+#endif
+#endif
+	return 0;
+
+}
+
+void
+serial_putc(const char c)
+{
+	if (c == '\n')
+		NS16550_putc(COM_PORTS[CFG_DUART_CHAN], '\r');
+
+	NS16550_putc(COM_PORTS[CFG_DUART_CHAN], c);
+}
+
+int
+serial_getc(void)
+{
+	return NS16550_getc(COM_PORTS[CFG_DUART_CHAN]);
+}
+
+int
+serial_tstc(void)
+{
+	return NS16550_tstc(COM_PORTS[CFG_DUART_CHAN]);
+}
+
+void
+serial_setbrg(void)
+{
+#if USE_CHAN1
+	DECLARE_GLOBAL_DATA_PTR;
+	int clock_divisor;
+
+	clock_divisor = XPAR_UARTNS550_0_CLOCK_FREQ_HZ / 16 / gd->baudrate;
+	NS16550_reinit(COM_PORTS[0], clock_divisor);
+#if USE_CHAN2
+	clock_divisor = XPAR_UARTNS550_1_CLOCK_FREQ_HZ / 16 / gd->baudrate;
+	NS16550_reinit(COM_PORTS[1], clock_divisor);
+#endif
+#endif
+}
+
+void
+serial_puts(const char *s)
+{
+	while (*s) {
+		serial_putc(*s++);
+	}
+}
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+void
+kgdb_serial_init(void)
+{
+}
+
+void
+putDebugChar(int c)
+{
+	serial_putc(c);
+}
+
+void
+putDebugStr(const char *str)
+{
+	serial_puts(str);
+}
+
+int
+getDebugChar(void)
+{
+	return serial_getc();
+}
+
+void
+kgdb_interruptible(int yes)
+{
+	return;
+}
+#endif				/* CFG_CMD_KGDB */

+ 41 - 0
board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes

@@ -0,0 +1,41 @@
+#!/bin/bash
+
+if[$
+# -ne 1 ]
+   then echo "usage: Ltypes filename" > &2 exit 2 fi FILE = "$1"
+#TMPFILE='mktemp "${FILE}.XXXXXX"' || exit 1
+   TMPFILE = $ {
+   FILE}
+
+   . ` date "+%s" ` touch $TMPFILE || exit 1
+# Change all the Xilinx types to Linux types and put the result into a temp file
+   sed
+   - e 's/\bXTRUE\b/TRUE/g'
+   - e 's/\bXFALSE\b/FALSE/g'
+   - e 's/\bXNULL\b/NULL/g'
+   - e 's/<asm/delay.h>/<asm\/delay.h>/g'
+   - e 's/\bXENV_USLEEP\b/udelay/g'
+   - e 's/\bXuint8\b/u8/g'
+   - e 's/\bXuint16\b/u16/g'
+   - e 's/\bXuint32\b/u32/g'
+   - e 's/\bXint8\b/s8/g'
+   - e 's/\bXint16\b/s16/g'
+   - e 's/\bXint32\b/s32/g' - e 's/\bXboolean\b/u32/g' "${FILE}" > "${TMPFILE}"
+# Overlay the original file with the temp file
+   mv "${TMPFILE}" "${FILE}"
+# Are we doing xbasic_types.h?
+   if["${FILE##*/}" = xbasic_types.h]
+   then
+# Remember as you're reading this that we've already gone through the prior
+# sed script.  We need to do some other things to xbasic_types.h:
+#   1) Add ifndefs around TRUE and FALSE defines
+#   2) Remove definition of NULL as NULL
+#   3) Replace most of the primitive types section with a #include
+   sed - e '/u32 true/,/#define false/Ic\
+#ifndef TRUE\
+#define TRUE 1\
+#endif\
+#ifndef FALSE\
+#define FALSE 0\
+#endif' - e '/#define[[:space:]][[:space:]]*NULL[[:space:]][[:space:]]*NULL/d' - e '/typedef[[:space:]][[:space:]]*unsigned[[:space:]][[:space:]]*char[[:space:]][[:space:]]*u8/,/typedef[[:space:]][[:space:]]*unsigned[[:space:]][[:space:]]*long[[:space:]][[:space:]]*u32.*boolean/c\
+#include <linux/types.h>' "${FILE}" > "${TMPFILE}" mv "${TMPFILE}" "${FILE}" fi

+ 48 - 0
board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld

@@ -0,0 +1,48 @@
+# (c) Copyright 2004 Xilinx Inc.
+#     Author: Xilinx, Inc.
+#
+#
+#     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.
+#
+#
+#     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+#     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+#     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+#     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+#     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+#     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+#     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+#     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+#     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+#     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+#     FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+#     Xilinx hardware products are not intended for use in life support
+#     appliances, devices, or systems. Use in such applications is
+#     expressly prohibited.
+#
+#
+#     (c) Copyright 2002-2004 Xilinx Inc.
+#     All rights reserved.
+#
+#
+#     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.,
+#     675 Mass Ave, Cambridge, MA 02139, USA.
+
+OPTION psf_version = 2.1;
+
+BEGIN LIBRARY uboot OPTION DRC = uboot_drc;
+
+BEGIN ARRAY connected_periphs PROPERTY desc = "Peripherals connected to U-Boot";
+PROPERTY size = 0;
+PARAM name = periph_name, desc = "Name of Peripheral connected", type = string;
+END ARRAY
+    PARAMETER name = TARGET_DIR, desc =
+    "Target Directory for U-Boot BSP", type = string;
+
+END LIBRARY

+ 298 - 0
board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl

@@ -0,0 +1,298 @@
+#
+#      Author: Xilinx, Inc.
+#      
+#      
+#      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.
+#      
+#      
+#      XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+#      COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+#      ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+#      XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+#      FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+#      ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+#      XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+#      THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+#      WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+#      CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+#      FITNESS FOR A PARTICULAR PURPOSE.
+#      
+#      
+#      Xilinx hardware products are not intended for use in life support
+#      appliances, devices, or systems. Use in such applications is
+#      expressly prohibited.
+#      
+#      
+#      (c) Copyright 2002-2004 Xilinx Inc.
+#      All rights reserved.
+#      
+#      
+#      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.,
+#      675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# Globals
+lappend drvlist
+set ltypes "../../../sw_services/uboot_v1_00_a/data/Ltypes"
+
+proc uboot_drc {lib_handle} {
+    puts "U-Boot DRC..."
+}
+
+proc generate {libname} {
+    
+    global drvlist
+    
+    # Get list of peripherals connected to uboot
+    set conn_periphs [xget_handle $libname "ARRAY" "connected_periphs"]
+    #lappend drvlist
+    if {[string compare -nocase $conn_periphs ""] != 0} {
+	set conn_periphs_elems [xget_handle $conn_periphs "ELEMENTS" "*"]
+	# For each periph
+	foreach periph_elem $conn_periphs_elems {
+	    set periph [xget_value $periph_elem "PARAMETER" "periph_name"]
+	    # 1. Get driver
+	    set drv [xget_swhandle $periph]
+	    set posn [lsearch -exact $drvlist $drv]
+	    if {$posn == -1} {
+		lappend drvlist $drv
+	    }
+	}
+	
+	set file_handle [xopen_include_file "xparameters.h"]
+	puts $file_handle "\n/******************************************************************/\n"
+	puts $file_handle "/* U-Boot Redefines */"
+	puts $file_handle "\n/******************************************************************/\n"
+	close $file_handle
+	
+	foreach drv $drvlist {
+	    set drvname [xget_value $drv "NAME"]
+	    
+	    #Redefines xparameters.h
+	    if {[string compare -nocase $drvname "uartns550"] == 0} {
+		xredefine_uartns550 $drv "xparameters.h"
+	    }  elseif {[string compare -nocase $drvname "emac"] == 0} {
+		xredefine_emac $drv "xparameters.h"
+	    }
+	}
+    }
+    
+    # define core_clock
+    xredefine_params $libname "xparameters.h" "CORE_CLOCK_FREQ_HZ"
+}
+
+proc xget_corefreq {} {
+    set processor [xget_processor] 
+    set name [xget_value $processor "NAME"]
+    puts "procname : $name"
+    set processor_driver [xget_swhandle [xget_value $processor "NAME"]]
+    puts "procdrv : $processor_driver"
+    if {[string compare -nocase $processor_driver ""] != 0} {
+	set arg "CORE_CLOCK_FREQ_HZ"
+	#set retval [xget_value $processor_driver "PARAMETER" $arg]
+	set retval [xget_dname [xget_value $processor_driver "NAME"] $arg]
+	return $retval
+    }
+}
+
+# procedure that adds # defines to xparameters.h as XPAR_argument
+proc xredefine_params {handle file_name args} {
+    
+    puts "xredfine ..."
+    # Open include file
+    set file_handle [xopen_include_file $file_name]
+    puts "args : $args"
+
+    foreach arg $args {
+	if {[string compare -nocase $arg "CORE_CLOCK_FREQ_HZ"] == 0} {
+	    set value [xget_corefreq]
+	    puts "corefreq : $value"
+	} else {
+	    set value [xget_value $handle "PARAMETER" $arg]
+	    puts "value : $value"
+	}
+	
+	if {$value != ""} {
+	    set value [xformat_addr_string $value $arg]
+	    set name [string toupper $arg]
+	    set name [format "XPAR_%s" $name]
+	    puts $file_handle "#define $name $value"
+	}
+    }
+
+    puts $file_handle "\n/******************************************************************/\n"
+    close $file_handle
+}
+
+# uart redefines...
+proc xredefine_uartns550 {drvhandle file_name} {
+    
+    xredefine_include_file $drvhandle $file_name "uartns550" "C_BASEADDR" "C_HIGHADDR" "CLOCK_HZ" "DEVICE_ID"
+    
+}
+
+proc xredefine_emac {drvhandle file_name} {
+    
+    xredefine_include_file $drvhandle $file_name "emac" "C_BASEADDR" "C_HIGHADDR" "C_DMA_PRESENT" "C_MII_EXIST" "C_ERR_COUNT_EXIST" "DEVICE_ID"
+    
+}
+
+#######################
+
+proc xredefine_include_file {drv_handle file_name drv_string args} {
+    
+    # Open include file
+    set file_handle [xopen_include_file $file_name]
+    
+    # Get all peripherals connected to this driver
+    set periphs [xget_periphs $drv_handle] 
+    
+    set pname [format "XPAR_%s_" [string toupper $drv_string]]
+    
+    # Print all parameters for all peripherals
+    set device_id 0
+    set sub_periphs 1
+    foreach periph $periphs {
+	puts "$periph : $drv_string : $sub_periphs"
+
+	for {set i 0} {$i < $sub_periphs} {incr i} {
+	    foreach arg $args {
+		set name "${pname}${device_id}_"
+	    
+		if {[string compare -nocase "CLOCK_HZ" $arg] == 0} {
+		    set xdrv_string [format "%s%s" "X" $drv_string]
+		    set value [xget_dname $xdrv_string $arg]
+		    set name "${name}CLOCK_FREQ_HZ"
+		} else {
+		    if {[string match C_* $arg]} {
+			set name [format "%s%s" $name [string range $arg 2 end]]
+		    } else {
+			set name "${name}${arg}"
+		    }
+		    set value [xget_name $periph $arg]
+		}
+
+		if {[string compare -nocase "uartns550" $drv_string] == 0} {
+		    if {[string compare -nocase "C_BASEADDR" $arg] == 0} {
+			set value [format "(%s%s%s)" $value "+" "0x1000"]
+		    }
+		}
+
+		puts $file_handle "#define $name $value"
+		if {[string compare -nocase "DEVICE_ID" $arg] == 0} {
+		    incr device_id
+		}
+	    }
+	}
+    }		
+    puts $file_handle "\n/******************************************************************/\n"
+    close $file_handle
+}
+
+##################################################
+# procedure post_generate
+# This generates the drivers directory for uboot
+# and runs the ltypes script
+##################################################
+
+proc post_generate {lib_handle} {
+    
+    global drvlist
+    
+    # Create U-Boot tree structure
+    set pwd [pwd]
+    set common_dir "uboot/board/xilinx/common"
+    set xilinx_enet_dir "uboot/board/xilinx/xilinx_enet"
+    set ml300_dir  "uboot/board/xilinx/ml300"
+    
+    exec bash -c "mkdir -p $common_dir $xilinx_enet_dir $ml300_dir"
+    
+    # Copy files for xilinx_ocp
+    xcopy_commonfiles
+
+    foreach drv $drvlist {
+	set drvname [xget_value $drv "NAME"]
+	set ver [xget_value $drv "PARAMETER" "DRIVER_VER"]
+	set ver [string map {. _} $ver]
+	set dirname [format "%s_v%s" $drvname $ver]
+	
+	if {[string compare -nocase $drvname "emac"] == 0} {
+	    xcopy_emac $drv $dirname
+	}
+    }
+    
+    # Call Ltypes Script here
+    set uboot "uboot"
+    xltype_file $uboot
+
+    # Move xparameters.h around
+    exec bash -c "cp ../../include/xparameters.h $ml300_dir"
+
+    # copy the whole U-Boot BSP to its final destination
+    set value [xget_value $lib_handle "PARAMETER" TARGET_DIR]
+    puts "TARGET_DIR : $value"
+
+    if {$value != ""} {
+        if {[file isdirectory $value] == 0} {
+            exec bash -c "mkdir -p $value"
+        }
+        exec bash -c "cp -Rp uboot/* $value"
+    }
+}
+
+proc xcopy_commonfiles {} {
+
+    global drvlist
+
+    set common_dir "uboot/board/xilinx/common"
+    
+    foreach drv $drvlist {
+	set depends [xget_value $drv "OPTION" "DEPENDS"]
+	foreach dep $depends {
+	    puts "dep : $dep"
+	    if {[file isdirectory "../$dep"] == 1} {
+		exec bash -c "cp -f ../$dep/src/*.c $common_dir"
+		exec bash -c "cp -f ../$dep/src/*.h $common_dir"
+	    }
+	}
+    }
+    
+}
+
+proc xcopy_emac {drv_handle dirname} {
+    set emac "board/xilinx/xilinx_enet"
+    xcopy_dir $dirname $emac
+}
+
+proc xcopy_dir {srcdir dstdir} {
+    
+    set dstdirname [format "%s%s" "uboot/" $dstdir]
+    if {[file isdirectory "../$srcdir"] == 1} {
+	# Copy files from src to dst
+	exec bash -c "mkdir -p $dstdirname"
+	exec bash -c "cp -f ../$srcdir/src/*.c $dstdirname"
+	exec bash -c "cp -f ../$srcdir/src/*.h $dstdirname"
+    } else {
+	puts "$srcdir does not exist ..."
+    }
+}
+
+
+proc xltype_file {filename} {
+
+    global ltypes
+
+    puts $filename
+
+    if {[file isdirectory $filename]} {
+	foreach entry [glob -nocomplain [file join $filename *]] {
+	    xltype_file $entry
+	}
+    } else {
+	exec bash -c "$ltypes $filename"
+    }
+    
+}

+ 146 - 0
board/xilinx/ml300/u-boot.lds

@@ -0,0 +1,146 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+ENTRY(_start)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    /* WARNING - the following is hand-optimized to fit within	*/
+    /* the sector layout of our flash chips!	XXX FIXME XXX	*/
+/*
+    cpu/ppc4xx/start.o	(.text)
+    board/xilinx/ml300/init.o	(.text)
+    cpu/ppc4xx/kgdb.o	(.text)
+    cpu/ppc4xx/traps.o	(.text)
+    cpu/ppc4xx/interrupts.o	(.text)
+    cpu/ppc4xx/serial.o	(.text)
+    cpu/ppc4xx/cpu_init.o	(.text)
+    cpu/ppc4xx/speed.o	(.text)
+    cpu/ppc4xx/405gp_enet.o	(.text)
+    common/dlmalloc.o	(.text)
+    lib_generic/crc32.o		(.text)
+    lib_ppc/extable.o	(.text)
+    lib_generic/zlib.o		(.text)
+*/
+/*    . = env_offset;*/
+/*    common/environment.o(.text)*/
+
+    *(.text)
+    *(.fixup)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(.rodata)
+    *(.rodata1)
+    *(.rodata.str1.4)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}

+ 135 - 0
board/xilinx/ml300/u-boot.lds.debug

@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    /* WARNING - the following is hand-optimized to fit within	*/
+    /* the sector layout of our flash chips!	XXX FIXME XXX	*/
+
+    mpc8xx/start.o	(.text)
+    common/dlmalloc.o	(.text)
+    lib_generic/vsprintf.o	(.text)
+    lib_generic/crc32.o		(.text)
+    lib_ppc/extable.o	(.text)
+
+    common/environment.o(.text)
+
+    *(.text)
+    *(.fixup)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(.rodata)
+    *(.rodata1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}

+ 216 - 0
board/xilinx/ml300/xparameters.h

@@ -0,0 +1,216 @@
+/*******************************************************************
+*
+* CAUTION: This file is automatically generated by libgen.
+* Version: Xilinx EDK 6.1.2 EDK_G.14
+* DO NOT EDIT.
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Description: Driver parameters
+*
+*******************************************************************/
+
+#define XPAR_XPCI_NUM_INSTANCES 1
+#define XPAR_XPCI_CLOCK_HZ 33333333
+#define XPAR_OPB_PCI_REF_0_DEVICE_ID 0
+#define XPAR_OPB_PCI_REF_0_BASEADDR 0x20000000
+#define XPAR_OPB_PCI_REF_0_HIGHADDR 0x3FFFFFFF
+#define XPAR_OPB_PCI_REF_0_CONFIG_ADDR 0x3C000000
+#define XPAR_OPB_PCI_REF_0_CONFIG_DATA 0x3C000004
+#define XPAR_OPB_PCI_REF_0_LCONFIG_ADDR 0x3E000000
+#define XPAR_OPB_PCI_REF_0_MEM_BASEADDR 0x20000000
+#define XPAR_OPB_PCI_REF_0_MEM_HIGHADDR 0x37FFFFFF
+#define XPAR_OPB_PCI_REF_0_IO_BASEADDR 0x38000000
+#define XPAR_OPB_PCI_REF_0_IO_HIGHADDR 0x3BFFFFFF
+
+/******************************************************************/
+
+#define XPAR_XEMAC_NUM_INSTANCES 1
+#define XPAR_OPB_ETHERNET_0_BASEADDR 0x60000000
+#define XPAR_OPB_ETHERNET_0_HIGHADDR 0x60003FFF
+#define XPAR_OPB_ETHERNET_0_DEVICE_ID 0
+#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1
+#define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1
+#define XPAR_OPB_ETHERNET_0_MII_EXIST 1
+
+/******************************************************************/
+
+#define XPAR_MY_OPB_GPIO_0_DEVICE_ID_0 0
+#define XPAR_MY_OPB_GPIO_0_BASEADDR_0 0x90000000
+#define XPAR_MY_OPB_GPIO_0_HIGHADDR_0 (0x90000000+0x7)
+#define XPAR_MY_OPB_GPIO_0_DEVICE_ID_1 1
+#define XPAR_MY_OPB_GPIO_0_BASEADDR_1 (0x90000000+0x8)
+#define XPAR_MY_OPB_GPIO_0_HIGHADDR_1 (0x90000000+0x1F)
+#define XPAR_XGPIO_NUM_INSTANCES 2
+
+/******************************************************************/
+
+#define XPAR_XIIC_NUM_INSTANCES 1
+#define XPAR_OPB_IIC_0_BASEADDR 0xA8000000
+#define XPAR_OPB_IIC_0_HIGHADDR 0xA80001FF
+#define XPAR_OPB_IIC_0_DEVICE_ID 0
+#define XPAR_OPB_IIC_0_TEN_BIT_ADR 0
+
+/******************************************************************/
+
+#define XPAR_XUARTNS550_NUM_INSTANCES 2
+#define XPAR_XUARTNS550_CLOCK_HZ 100000000
+#define XPAR_OPB_UART16550_0_BASEADDR 0xA0000000
+#define XPAR_OPB_UART16550_0_HIGHADDR 0xA0001FFF
+#define XPAR_OPB_UART16550_0_DEVICE_ID 0
+#define XPAR_OPB_UART16550_1_BASEADDR 0xA0010000
+#define XPAR_OPB_UART16550_1_HIGHADDR 0xA0011FFF
+#define XPAR_OPB_UART16550_1_DEVICE_ID 1
+
+/******************************************************************/
+
+#define XPAR_XSPI_NUM_INSTANCES 1
+#define XPAR_OPB_SPI_0_BASEADDR 0xA4000000
+#define XPAR_OPB_SPI_0_HIGHADDR 0xA400007F
+#define XPAR_OPB_SPI_0_DEVICE_ID 0
+#define XPAR_OPB_SPI_0_FIFO_EXIST 1
+#define XPAR_OPB_SPI_0_SPI_SLAVE_ONLY 0
+#define XPAR_OPB_SPI_0_NUM_SS_BITS 1
+
+/******************************************************************/
+
+#define XPAR_XPS2_NUM_INSTANCES 2
+#define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_0 0
+#define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_0 0xA9000000
+#define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_0 (0xA9000000+0x3F)
+#define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_1 1
+#define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_1 (0xA9000000+0x1000)
+#define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_1 (0xA9000000+0x103F)
+
+/******************************************************************/
+
+#define XPAR_XTOUCHSCREEN_NUM_INSTANCES 1
+#define XPAR_OPB_TSD_REF_0_BASEADDR 0xAA000000
+#define XPAR_OPB_TSD_REF_0_HIGHADDR 0xAA000007
+#define XPAR_OPB_TSD_REF_0_DEVICE_ID 0
+
+/******************************************************************/
+
+#define XPAR_OPB_AC97_CONTROLLER_REF_0_BASEADDR 0xA6000000
+#define XPAR_OPB_AC97_CONTROLLER_REF_0_HIGHADDR 0xA60000FF
+#define XPAR_OPB_PAR_PORT_REF_0_BASEADDR 0x90010000
+#define XPAR_OPB_PAR_PORT_REF_0_HIGHADDR 0x900100FF
+#define XPAR_PLB_DDR_0_BASEADDR 0x00000000
+#define XPAR_PLB_DDR_0_HIGHADDR 0x0FFFFFFF
+
+/******************************************************************/
+
+#define XPAR_XINTC_HAS_IPR 1
+#define XPAR_INTC_MAX_NUM_INTR_INPUTS 18
+#define XPAR_XINTC_USE_DCR 0
+#define XPAR_XINTC_NUM_INSTANCES 1
+#define XPAR_DCR_INTC_0_BASEADDR 0xD0000FC0
+#define XPAR_DCR_INTC_0_HIGHADDR 0xD0000FDF
+#define XPAR_DCR_INTC_0_DEVICE_ID 0
+#define XPAR_DCR_INTC_0_KIND_OF_INTR 0x00038000
+
+/******************************************************************/
+
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_PHY_MII_INT_INTR 0
+#define XPAR_DCR_INTC_0_OPB_ETHERNET_0_IP2INTC_IRPT_INTR 1
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_TEMP_CRIT_INTR 2
+#define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_IRQ_INTR 3
+#define XPAR_DCR_INTC_0_OPB_IIC_0_IP2INTC_IRPT_INTR 4
+#define XPAR_DCR_INTC_0_OPB_SYSACE_0_SYSACE_IRQ_INTR 5
+#define XPAR_DCR_INTC_0_OPB_UART16550_0_IP2INTC_IRPT_INTR 6
+#define XPAR_DCR_INTC_0_OPB_UART16550_1_IP2INTC_IRPT_INTR 7
+#define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR1_INTR 8
+#define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR2_INTR 9
+#define XPAR_DCR_INTC_0_OPB_SPI_0_IP2INTC_IRPT_INTR 10
+#define XPAR_DCR_INTC_0_OPB_TSD_REF_0_INTR_INTR 11
+#define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_PLAYBACK_INTERRUPT_INTR 12
+#define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_RECORD_INTERRUPT_INTR 13
+#define XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR 14
+#define XPAR_DCR_INTC_0_PLB2OPB_BRIDGE_0_BUS_ERROR_DET_INTR 15
+#define XPAR_DCR_INTC_0_PLB_V34_0_BUS_ERROR_DET_INTR 16
+#define XPAR_DCR_INTC_0_OPB2PLB_BRIDGE_0_BUS_ERROR_DET_INTR 17
+
+/******************************************************************/
+
+#define XPAR_XTFT_NUM_INSTANCES 1
+#define XPAR_PLB_TFT_CNTLR_REF_0_DCR_BASEADDR 0xD0000200
+#define XPAR_PLB_TFT_CNTLR_REF_0_DCR_HIGHADDR 0xD0000207
+#define XPAR_PLB_TFT_CNTLR_REF_0_DEVICE_ID 0
+
+/******************************************************************/
+
+#define XPAR_XSYSACE_MEM_WIDTH 8
+#define XPAR_XSYSACE_NUM_INSTANCES 1
+#define XPAR_OPB_SYSACE_0_BASEADDR 0xCF000000
+#define XPAR_OPB_SYSACE_0_HIGHADDR 0xCF0001FF
+#define XPAR_OPB_SYSACE_0_DEVICE_ID 0
+#define XPAR_OPB_SYSACE_0_MEM_WIDTH 8
+
+/******************************************************************/
+
+#define STDIN_BASEADDRESS 0xA0000000
+#define STDOUT_BASEADDRESS 0xA0000000
+#define XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ 300000000
+
+/******************************************************************/
+
+/* U-Boot Redefines */
+
+/******************************************************************/
+
+#define XPAR_UARTNS550_0_BASEADDR (XPAR_OPB_UART16550_0_BASEADDR+0x1000)
+#define XPAR_UARTNS550_0_HIGHADDR XPAR_OPB_UART16550_0_HIGHADDR
+#define XPAR_UARTNS550_0_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ
+#define XPAR_UARTNS550_0_DEVICE_ID XPAR_OPB_UART16550_0_DEVICE_ID
+#define XPAR_UARTNS550_1_BASEADDR (XPAR_OPB_UART16550_1_BASEADDR+0x1000)
+#define XPAR_UARTNS550_1_HIGHADDR XPAR_OPB_UART16550_1_HIGHADDR
+#define XPAR_UARTNS550_1_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ
+#define XPAR_UARTNS550_1_DEVICE_ID XPAR_OPB_UART16550_1_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_EMAC_0_BASEADDR XPAR_OPB_ETHERNET_0_BASEADDR
+#define XPAR_EMAC_0_HIGHADDR XPAR_OPB_ETHERNET_0_HIGHADDR
+#define XPAR_EMAC_0_DMA_PRESENT XPAR_OPB_ETHERNET_0_DMA_PRESENT
+#define XPAR_EMAC_0_MII_EXIST XPAR_OPB_ETHERNET_0_MII_EXIST
+#define XPAR_EMAC_0_ERR_COUNT_EXIST XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST
+#define XPAR_EMAC_0_DEVICE_ID XPAR_OPB_ETHERNET_0_DEVICE_ID
+
+/******************************************************************/
+
+#define XPAR_CORE_CLOCK_FREQ_HZ XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ
+
+/******************************************************************/

+ 153 - 0
board/xilinx/xilinx_enet/emac_adapter.c

@@ -0,0 +1,153 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+
+#include <common.h>
+#include <net.h>
+#include <configs/ml300.h>
+#include "xparameters.h"
+#include "xemac.h"
+
+#if defined(XPAR_EMAC_0_DEVICE_ID)
+/*
+ * ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from
+ * PKTSIZE and PKTSIZE_ALIGN (include/net.h)
+ */
+
+#define ENET_MAX_MTU           PKTSIZE
+#define ENET_MAX_MTU_ALIGNED   PKTSIZE_ALIGN
+#define ENET_ADDR_LENGTH       6
+
+static XEmac Emac;
+static char etherrxbuff[PKTSIZE_ALIGN];	/* Receive buffer */
+
+/* hardcoded MAC address for the Xilinx EMAC Core */
+static u8 EMACAddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 };
+
+static int initialized = 0;
+
+void
+eth_halt(void)
+{
+	if (initialized)
+		(void) XEmac_Stop(&Emac);
+}
+
+int
+eth_init(bd_t * bis)
+{
+	u32 Options;
+	XStatus Result;
+
+#ifdef DEBUG
+	printf("EMAC Initialization Started\n\r");
+#endif
+
+	Result = XEmac_Initialize(&Emac, XPAR_EMAC_0_DEVICE_ID);
+	if (Result != XST_SUCCESS) {
+		return 0;
+	}
+
+	/* make sure the Emac is stopped before it is started */
+	(void) XEmac_Stop(&Emac);
+
+	memcpy(bis->bi_enetaddr, EMACAddr, 6);
+	Result = XEmac_SetMacAddress(&Emac, EMACAddr);
+	if (Result != XST_SUCCESS) {
+		return 0;
+	}
+
+	Options =
+	    (XEM_POLLED_OPTION | XEM_UNICAST_OPTION | XEM_BROADCAST_OPTION |
+	     XEM_FDUPLEX_OPTION | XEM_INSERT_FCS_OPTION |
+	     XEM_INSERT_PAD_OPTION);
+	Result = XEmac_SetOptions(&Emac, Options);
+	if (Result != XST_SUCCESS) {
+		return 0;
+	}
+
+	Result = XEmac_Start(&Emac);
+	if (Result != XST_SUCCESS) {
+		return 0;
+	}
+#ifdef DEBUG
+	printf("EMAC Initialization complete\n\r");
+#endif
+
+	initialized = 1;
+
+	return (0);
+}
+
+/*-----------------------------------------------------------------------------+
++-----------------------------------------------------------------------------*/
+int
+eth_send(volatile void *ptr, int len)
+{
+	XStatus Result;
+
+	if (len > ENET_MAX_MTU)
+		len = ENET_MAX_MTU;
+
+	Result = XEmac_PollSend(&Emac, (u8 *) ptr, len);
+	if (Result == XST_SUCCESS) {
+		return (1);
+	} else {
+		printf("Error while sending frame\n\r");
+		return (0);
+	}
+
+}
+
+int
+eth_rx(void)
+{
+	u32 RecvFrameLength;
+	XStatus Result;
+
+	RecvFrameLength = PKTSIZE;
+	Result = XEmac_PollRecv(&Emac, (u8 *) etherrxbuff, &RecvFrameLength);
+	if (Result == XST_SUCCESS) {
+		NetReceive(etherrxbuff, RecvFrameLength);
+		return (1);
+	} else {
+		return (0);
+	}
+}
+
+#endif

+ 844 - 0
board/xilinx/xilinx_enet/xemac.c

@@ -0,0 +1,844 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemac.c
+*
+* The XEmac driver. Functions in this file are the minimum required functions
+* for this driver. See xemac.h for a detailed description of the driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a rpm  07/31/01 First release
+* 1.00b rpm  02/20/02 Repartitioned files and functions
+* 1.00b rpm  07/23/02 Removed the PHY reset from Initialize()
+* 1.00b rmm  09/23/02 Removed commented code in Initialize(). Recycled as
+*                     XEmac_mPhyReset macro in xemac_l.h.
+* 1.00c rpm  12/05/02 New version includes support for simple DMA
+* 1.00c rpm  12/12/02 Changed location of IsStarted assignment in XEmac_Start
+*                     to be sure the flag is set before the device and
+*                     interrupts are enabled.
+* 1.00c rpm  02/03/03 SelfTest was not clearing polled mode. Take driver out
+*                     of polled mode in XEmac_Reset() to fix this problem.
+* 1.00c rmm  05/13/03 Fixed diab compiler warnings relating to asserts.
+* </pre>
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xemac_i.h"
+#include "xio.h"
+#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+static XStatus ConfigureDma(XEmac * InstancePtr);
+static XStatus ConfigureFifo(XEmac * InstancePtr);
+static void StubFifoHandler(void *CallBackRef);
+static void StubErrorHandler(void *CallBackRef, XStatus ErrorCode);
+static void StubSgHandler(void *CallBackRef, XBufDescriptor * BdPtr,
+			  u32 NumBds);
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+/**
+*
+* Initialize a specific XEmac instance/driver.  The initialization entails:
+* - Initialize fields of the XEmac structure
+* - Clear the Ethernet statistics for this device
+* - Initialize the IPIF component with its register base address
+* - Configure the FIFO components with their register base addresses.
+* - If the device is configured with DMA, configure the DMA channel components
+*   with their register base addresses. At some later time, memory pools for
+*   the scatter-gather descriptor lists may be passed to the driver.
+* - Reset the Ethernet MAC
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param DeviceId is the unique id of the device controlled by this XEmac
+*        instance.  Passing in a device id associates the generic XEmac
+*        instance to a specific device, as chosen by the caller or application
+*        developer.
+*
+* @return
+*
+* - XST_SUCCESS if initialization was successful
+* - XST_DEVICE_IS_STARTED if the device has already been started
+* - XST_DEVICE_NOT_FOUND if device configuration information was not found for
+*   a device with the supplied device ID.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XEmac_Initialize(XEmac * InstancePtr, u16 DeviceId)
+{
+	XStatus Result;
+	XEmac_Config *ConfigPtr;	/* configuration information */
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+
+	/*
+	 * If the device is started, disallow the initialize and return a status
+	 * indicating it is started.  This allows the user to stop the device
+	 * and reinitialize, but prevents a user from inadvertently initializing
+	 */
+	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STARTED;
+	}
+
+	/*
+	 * Lookup the device configuration in the temporary CROM table. Use this
+	 * configuration info down below when initializing this component.
+	 */
+	ConfigPtr = XEmac_LookupConfig(DeviceId);
+	if (ConfigPtr == NULL) {
+		return XST_DEVICE_NOT_FOUND;
+	}
+
+	/*
+	 * Set some default values
+	 */
+	InstancePtr->IsReady = 0;
+	InstancePtr->IsStarted = 0;
+	InstancePtr->IpIfDmaConfig = ConfigPtr->IpIfDmaConfig;
+	InstancePtr->HasMii = ConfigPtr->HasMii;
+	InstancePtr->HasMulticastHash = FALSE;
+
+	/* Always default polled to false, let user configure this mode */
+	InstancePtr->IsPolled = FALSE;
+	InstancePtr->FifoRecvHandler = StubFifoHandler;
+	InstancePtr->FifoSendHandler = StubFifoHandler;
+	InstancePtr->ErrorHandler = StubErrorHandler;
+	InstancePtr->SgRecvHandler = StubSgHandler;
+	InstancePtr->SgSendHandler = StubSgHandler;
+
+	/*
+	 * Clear the statistics for this driver
+	 */
+	XEmac_mClearStruct((u8 *) & InstancePtr->Stats, sizeof (XEmac_Stats));
+
+	/*
+	 * Initialize the device register base addresses
+	 */
+	InstancePtr->BaseAddress = ConfigPtr->BaseAddress;
+
+	/*
+	 * Configure the send and receive FIFOs in the MAC
+	 */
+	Result = ConfigureFifo(InstancePtr);
+	if (Result != XST_SUCCESS) {
+		return Result;
+	}
+
+	/*
+	 * If the device is configured for DMA, configure the send and receive DMA
+	 * channels in the MAC.
+	 */
+	if (XEmac_mIsDma(InstancePtr)) {
+		Result = ConfigureDma(InstancePtr);
+		if (Result != XST_SUCCESS) {
+			return Result;
+		}
+	}
+
+	/*
+	 * Indicate the component is now ready to use. Note that this is done before
+	 * we reset the device and the PHY below, which may seem a bit odd. The
+	 * choice was made to move it here rather than remove the asserts in various
+	 * functions (e.g., Reset() and all functions that it calls).  Applications
+	 * that use multiple threads, one to initialize the XEmac driver and one
+	 * waiting on the IsReady condition could have a problem with this sequence.
+	 */
+	InstancePtr->IsReady = XCOMPONENT_IS_READY;
+
+	/*
+	 * Reset the MAC to get it into its initial state. It is expected that
+	 * device configuration by the user will take place after this
+	 * initialization is done, but before the device is started.
+	 */
+	XEmac_Reset(InstancePtr);
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Start the Ethernet controller as follows:
+*   - If not in polled mode
+*       - Set the internal interrupt enable registers appropriately
+*       - Enable interrupts within the device itself. Note that connection of
+*         the driver's interrupt handler to the interrupt source (typically
+*         done using the interrupt controller component) is done by the higher
+*         layer software.
+*       - If the device is configured with scatter-gather DMA, start the DMA
+*         channels if the descriptor lists are not empty
+*   - Enable the transmitter
+*   - Enable the receiver
+*
+* The PHY is enabled after driver initialization. We assume the upper layer
+* software has configured it and the EMAC appropriately before this function
+* is called.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* - XST_SUCCESS if the device was started successfully
+* - XST_NO_CALLBACK if a callback function has not yet been registered using
+*   the SetxxxHandler function. This is required if in interrupt mode.
+* - XST_DEVICE_IS_STARTED if the device is already started
+* - XST_DMA_SG_NO_LIST if configured for scatter-gather DMA and a descriptor
+*   list has not yet been created for the send or receive channel.
+*
+* @note
+*
+* The driver tries to match the hardware configuration. So if the hardware
+* is configured with scatter-gather DMA, the driver expects to start the
+* scatter-gather channels and expects that the user has set up the buffer
+* descriptor lists already. If the user expects to use the driver in a mode
+* different than how the hardware is configured, the user should modify the
+* configuration table to reflect the mode to be used. Modifying the config
+* table is a workaround for now until we get some experience with how users
+* are intending to use the hardware in its different configurations. For
+* example, if the hardware is built with scatter-gather DMA but the user is
+* intending to use only simple DMA, the user either needs to modify the config
+* table as a workaround or rebuild the hardware with only simple DMA.
+*
+* This function makes use of internal resources that are shared between the
+* Start, Stop, and SetOptions functions. So if one task might be setting device
+* options while another is trying to start the device, the user is required to
+* provide protection of this shared data (typically using a semaphore).
+*
+******************************************************************************/
+XStatus
+XEmac_Start(XEmac * InstancePtr)
+{
+	u32 ControlReg;
+	XStatus Result;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * If it is already started, return a status indicating so
+	 */
+	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STARTED;
+	}
+
+	/*
+	 * If not polled, enable interrupts
+	 */
+	if (!InstancePtr->IsPolled) {
+		/*
+		 * Verify that the callbacks have been registered, then enable
+		 * interrupts
+		 */
+		if (XEmac_mIsSgDma(InstancePtr)) {
+			if ((InstancePtr->SgRecvHandler == StubSgHandler) ||
+			    (InstancePtr->SgSendHandler == StubSgHandler)) {
+				return XST_NO_CALLBACK;
+			}
+
+			/* Enable IPIF interrupts */
+			XIIF_V123B_WRITE_DIER(InstancePtr->BaseAddress,
+					      XEM_IPIF_DMA_DFT_MASK |
+					      XIIF_V123B_ERROR_MASK);
+			XIIF_V123B_WRITE_IIER(InstancePtr->BaseAddress,
+					      XEM_EIR_DFT_SG_MASK);
+
+			/* Enable scatter-gather DMA interrupts */
+			XDmaChannel_SetIntrEnable(&InstancePtr->RecvChannel,
+						  XEM_DMA_SG_INTR_MASK);
+			XDmaChannel_SetIntrEnable(&InstancePtr->SendChannel,
+						  XEM_DMA_SG_INTR_MASK);
+		} else {
+			if ((InstancePtr->FifoRecvHandler == StubFifoHandler) ||
+			    (InstancePtr->FifoSendHandler == StubFifoHandler)) {
+				return XST_NO_CALLBACK;
+			}
+
+			/* Enable IPIF interrupts (used by simple DMA also) */
+			XIIF_V123B_WRITE_DIER(InstancePtr->BaseAddress,
+					      XEM_IPIF_FIFO_DFT_MASK |
+					      XIIF_V123B_ERROR_MASK);
+			XIIF_V123B_WRITE_IIER(InstancePtr->BaseAddress,
+					      XEM_EIR_DFT_FIFO_MASK);
+		}
+
+		/* Enable the global IPIF interrupt output */
+		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+	}
+
+	/*
+	 * Indicate that the device is started before we enable the transmitter
+	 * or receiver. This needs to be done before because as soon as the
+	 * receiver is enabled we may get an interrupt, and there are functions
+	 * in the interrupt handling path that rely on the IsStarted flag.
+	 */
+	InstancePtr->IsStarted = XCOMPONENT_IS_STARTED;
+
+	/*
+	 * Enable the transmitter, and receiver (do a read/modify/write to preserve
+	 * current settings). There is no critical section here since this register
+	 * is not modified during interrupt context.
+	 */
+	ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET);
+	ControlReg &= ~(XEM_ECR_XMIT_RESET_MASK | XEM_ECR_RECV_RESET_MASK);
+	ControlReg |= (XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK);
+
+	XIo_Out32(InstancePtr->BaseAddress + XEM_ECR_OFFSET, ControlReg);
+
+	/*
+	 * If configured with scatter-gather DMA and not polled, restart the
+	 * DMA channels in case there are buffers ready to be sent or received into.
+	 * The DMA SgStart function uses data that can be modified during interrupt
+	 * context, so a critical section is required here.
+	 */
+	if ((XEmac_mIsSgDma(InstancePtr)) && (!InstancePtr->IsPolled)) {
+		XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
+
+		/*
+		 * The only error we care about is if the list has not yet been
+		 * created, or on receive, if no buffer descriptors have been
+		 * added yet (the list is empty). Other errors are benign at this point.
+		 */
+		Result = XDmaChannel_SgStart(&InstancePtr->RecvChannel);
+		if ((Result == XST_DMA_SG_NO_LIST)
+		    || (Result == XST_DMA_SG_LIST_EMPTY)) {
+			XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+			return Result;
+		}
+
+		Result = XDmaChannel_SgStart(&InstancePtr->SendChannel);
+		if (Result == XST_DMA_SG_NO_LIST) {
+			XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+			return Result;
+		}
+
+		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+	}
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Stop the Ethernet MAC as follows:
+*   - If the device is configured with scatter-gather DMA, stop the DMA
+*     channels (wait for acknowledgment of stop)
+*   - Disable the transmitter and receiver
+*   - Disable interrupts if not in polled mode (the higher layer software is
+*     responsible for disabling interrupts at the interrupt controller)
+*
+* The PHY is left enabled after a Stop is called.
+*
+* If the device is configured for scatter-gather DMA, the DMA engine stops at
+* the next buffer descriptor in its list. The remaining descriptors in the list
+* are not removed, so anything in the list will be transmitted or received when
+* the device is restarted. The side effect of doing this is that the last
+* buffer descriptor processed by the DMA engine before stopping may not be the
+* last descriptor in the Ethernet frame. So when the device is restarted, a
+* partial frame (i.e., a bad frame) may be transmitted/received. This is only a
+* concern if a frame can span multiple buffer descriptors, which is dependent
+* on the size of the network buffers.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* - XST_SUCCESS if the device was stopped successfully
+* - XST_DEVICE_IS_STOPPED if the device is already stopped
+*
+* @note
+*
+* This function makes use of internal resources that are shared between the
+* Start, Stop, and SetOptions functions. So if one task might be setting device
+* options while another is trying to start the device, the user is required to
+* provide protection of this shared data (typically using a semaphore).
+*
+******************************************************************************/
+XStatus
+XEmac_Stop(XEmac * InstancePtr)
+{
+	u32 ControlReg;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * If the device is already stopped, do nothing but return a status
+	 * indicating so
+	 */
+	if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STOPPED;
+	}
+
+	/*
+	 * If configured for scatter-gather DMA, stop the DMA channels. Ignore
+	 * the XST_DMA_SG_IS_STOPPED return code. There is a critical section
+	 * here between SgStart and SgStop, and SgStart can be called in interrupt
+	 * context, so disable interrupts while calling SgStop.
+	 */
+	if (XEmac_mIsSgDma(InstancePtr)) {
+		XBufDescriptor *BdTemp;	/* temporary descriptor pointer */
+
+		XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
+
+		(void) XDmaChannel_SgStop(&InstancePtr->SendChannel, &BdTemp);
+		(void) XDmaChannel_SgStop(&InstancePtr->RecvChannel, &BdTemp);
+
+		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+	}
+
+	/*
+	 * Disable the transmitter and receiver. There is no critical section
+	 * here since this register is not modified during interrupt context.
+	 */
+	ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET);
+	ControlReg &= ~(XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK);
+	XIo_Out32(InstancePtr->BaseAddress + XEM_ECR_OFFSET, ControlReg);
+
+	/*
+	 * If not in polled mode, disable interrupts for IPIF (includes MAC and
+	 * DMAs)
+	 */
+	if (!InstancePtr->IsPolled) {
+		XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
+	}
+
+	InstancePtr->IsStarted = 0;
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Reset the Ethernet MAC. This is a graceful reset in that the device is stopped
+* first. Resets the DMA channels, the FIFOs, the transmitter, and the receiver.
+* The PHY is not reset. Any frames in the scatter-gather descriptor lists will
+* remain in the lists. The side effect of doing this is that after a reset and
+* following a restart of the device, frames that were in the list before the
+* reset may be transmitted or received. Reset must only be called after the
+* driver has been initialized.
+*
+* The driver is also taken out of polled mode if polled mode was set. The user
+* is responsbile for re-configuring the driver into polled mode after the
+* reset if desired.
+*
+* The configuration after this reset is as follows:
+*   - Half duplex
+*   - Disabled transmitter and receiver
+*   - Enabled PHY (the PHY is not reset)
+*   - MAC transmitter does pad insertion, FCS insertion, and source address
+*     overwrite.
+*   - MAC receiver does not strip padding or FCS
+*   - Interframe Gap as recommended by IEEE Std. 802.3 (96 bit times)
+*   - Unicast addressing enabled
+*   - Broadcast addressing enabled
+*   - Multicast addressing disabled (addresses are preserved)
+*   - Promiscuous addressing disabled
+*   - Default packet threshold and packet wait bound register values for
+*     scatter-gather DMA operation
+*   - MAC address of all zeros
+*   - Non-polled mode
+*
+* The upper layer software is responsible for re-configuring (if necessary)
+* and restarting the MAC after the reset. Note that the PHY is not reset. PHY
+* control is left to the upper layer software. Note also that driver statistics
+* are not cleared on reset. It is up to the upper layer software to clear the
+* statistics if needed.
+*
+* When a reset is required due to an internal error, the driver notifies the
+* upper layer software of this need through the ErrorHandler callback and
+* specific status codes.  The upper layer software is responsible for calling
+* this Reset function and then re-configuring the device.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+* @internal
+*
+* The reset is accomplished by setting the IPIF reset register.  This takes
+* care of resetting all hardware blocks, including the MAC.
+*
+******************************************************************************/
+void
+XEmac_Reset(XEmac * InstancePtr)
+{
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Stop the device first
+	 */
+	(void) XEmac_Stop(InstancePtr);
+
+	/*
+	 * Take the driver out of polled mode
+	 */
+	InstancePtr->IsPolled = FALSE;
+
+	/*
+	 * Reset the entire IPIF at once.  If we choose someday to reset each
+	 * hardware block separately, the reset should occur in the direction of
+	 * data flow. For example, for the send direction the reset order is DMA
+	 * first, then FIFO, then the MAC transmitter.
+	 */
+	XIIF_V123B_RESET(InstancePtr->BaseAddress);
+
+	if (XEmac_mIsSgDma(InstancePtr)) {
+		/*
+		 * After reset, configure the scatter-gather DMA packet threshold and
+		 * packet wait bound registers to default values. Ignore the return
+		 * values of these functions since they only return error if the device
+		 * is not stopped.
+		 */
+		(void) XEmac_SetPktThreshold(InstancePtr, XEM_SEND,
+					     XEM_SGDMA_DFT_THRESHOLD);
+		(void) XEmac_SetPktThreshold(InstancePtr, XEM_RECV,
+					     XEM_SGDMA_DFT_THRESHOLD);
+		(void) XEmac_SetPktWaitBound(InstancePtr, XEM_SEND,
+					     XEM_SGDMA_DFT_WAITBOUND);
+		(void) XEmac_SetPktWaitBound(InstancePtr, XEM_RECV,
+					     XEM_SGDMA_DFT_WAITBOUND);
+	}
+}
+
+/*****************************************************************************/
+/**
+*
+* Set the MAC address for this driver/device.  The address is a 48-bit value.
+* The device must be stopped before calling this function.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param AddressPtr is a pointer to a 6-byte MAC address.
+*
+* @return
+*
+* - XST_SUCCESS if the MAC address was set successfully
+* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XEmac_SetMacAddress(XEmac * InstancePtr, u8 * AddressPtr)
+{
+	u32 MacAddr = 0;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(AddressPtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * The device must be stopped before setting the MAC address
+	 */
+	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STARTED;
+	}
+
+	/*
+	 * Set the device station address high and low registers
+	 */
+	MacAddr = (AddressPtr[0] << 8) | AddressPtr[1];
+	XIo_Out32(InstancePtr->BaseAddress + XEM_SAH_OFFSET, MacAddr);
+
+	MacAddr = (AddressPtr[2] << 24) | (AddressPtr[3] << 16) |
+	    (AddressPtr[4] << 8) | AddressPtr[5];
+
+	XIo_Out32(InstancePtr->BaseAddress + XEM_SAL_OFFSET, MacAddr);
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Get the MAC address for this driver/device.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param BufferPtr is an output parameter, and is a pointer to a buffer into
+*        which the current MAC address will be copied. The buffer must be at
+*        least 6 bytes.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XEmac_GetMacAddress(XEmac * InstancePtr, u8 * BufferPtr)
+{
+	u32 MacAddrHi;
+	u32 MacAddrLo;
+
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(BufferPtr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	MacAddrHi = XIo_In32(InstancePtr->BaseAddress + XEM_SAH_OFFSET);
+	MacAddrLo = XIo_In32(InstancePtr->BaseAddress + XEM_SAL_OFFSET);
+
+	BufferPtr[0] = (u8) (MacAddrHi >> 8);
+	BufferPtr[1] = (u8) MacAddrHi;
+	BufferPtr[2] = (u8) (MacAddrLo >> 24);
+	BufferPtr[3] = (u8) (MacAddrLo >> 16);
+	BufferPtr[4] = (u8) (MacAddrLo >> 8);
+	BufferPtr[5] = (u8) MacAddrLo;
+}
+
+/******************************************************************************/
+/**
+*
+* Configure DMA capabilities.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* - XST_SUCCESS  if successful initialization of DMA
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static XStatus
+ConfigureDma(XEmac * InstancePtr)
+{
+	XStatus Result;
+
+	/*
+	 * Initialize the DMA channels with their base addresses. We assume
+	 * scatter-gather DMA is the only possible configuration. Descriptor space
+	 * will need to be set later by the upper layer.
+	 */
+	Result = XDmaChannel_Initialize(&InstancePtr->RecvChannel,
+					InstancePtr->BaseAddress +
+					XEM_DMA_RECV_OFFSET);
+	if (Result != XST_SUCCESS) {
+		return Result;
+	}
+
+	Result = XDmaChannel_Initialize(&InstancePtr->SendChannel,
+					InstancePtr->BaseAddress +
+					XEM_DMA_SEND_OFFSET);
+
+	return Result;
+}
+
+/******************************************************************************/
+/**
+*
+* Configure the send and receive FIFO components with their base addresses
+* and interrupt masks.  Currently the base addresses are defined constants.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* XST_SUCCESS if successful initialization of the packet FIFOs
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static XStatus
+ConfigureFifo(XEmac * InstancePtr)
+{
+	XStatus Result;
+
+	/*
+	 * Return status from the packet FIFOs initialization is ignored since
+	 * they always return success.
+	 */
+	Result = XPacketFifoV100b_Initialize(&InstancePtr->RecvFifo,
+					     InstancePtr->BaseAddress +
+					     XEM_PFIFO_RXREG_OFFSET,
+					     InstancePtr->BaseAddress +
+					     XEM_PFIFO_RXDATA_OFFSET);
+	if (Result != XST_SUCCESS) {
+		return Result;
+	}
+
+	Result = XPacketFifoV100b_Initialize(&InstancePtr->SendFifo,
+					     InstancePtr->BaseAddress +
+					     XEM_PFIFO_TXREG_OFFSET,
+					     InstancePtr->BaseAddress +
+					     XEM_PFIFO_TXDATA_OFFSET);
+	return Result;
+}
+
+/******************************************************************************/
+/**
+*
+* This is a stub for the scatter-gather send and recv callbacks. The stub
+* is here in case the upper layers forget to set the handlers.
+*
+* @param CallBackRef is a pointer to the upper layer callback reference
+* @param BdPtr is a pointer to the first buffer descriptor in a list
+* @param NumBds is the number of descriptors in the list.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static void
+StubSgHandler(void *CallBackRef, XBufDescriptor * BdPtr, u32 NumBds)
+{
+	XASSERT_VOID_ALWAYS();
+}
+
+/******************************************************************************/
+/**
+*
+* This is a stub for the non-DMA send and recv callbacks.  The stub is here in
+* case the upper layers forget to set the handlers.
+*
+* @param CallBackRef is a pointer to the upper layer callback reference
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static void
+StubFifoHandler(void *CallBackRef)
+{
+	XASSERT_VOID_ALWAYS();
+}
+
+/******************************************************************************/
+/**
+*
+* This is a stub for the asynchronous error callback.  The stub is here in
+* case the upper layers forget to set the handler.
+*
+* @param CallBackRef is a pointer to the upper layer callback reference
+* @param ErrorCode is the Xilinx error code, indicating the cause of the error
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static void
+StubErrorHandler(void *CallBackRef, XStatus ErrorCode)
+{
+	XASSERT_VOID_ALWAYS();
+}
+
+/*****************************************************************************/
+/**
+*
+* Lookup the device configuration based on the unique device ID.  The table
+* EmacConfigTable contains the configuration info for each device in the system.
+*
+* @param DeviceId is the unique device ID of the device being looked up.
+*
+* @return
+*
+* A pointer to the configuration table entry corresponding to the given
+* device ID, or NULL if no match is found.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XEmac_Config *
+XEmac_LookupConfig(u16 DeviceId)
+{
+	XEmac_Config *CfgPtr = NULL;
+	int i;
+
+	for (i = 0; i < XPAR_XEMAC_NUM_INSTANCES; i++) {
+		if (XEmac_ConfigTable[i].DeviceId == DeviceId) {
+			CfgPtr = &XEmac_ConfigTable[i];
+			break;
+		}
+	}
+
+	return CfgPtr;
+}

+ 673 - 0
board/xilinx/xilinx_enet/xemac.h

@@ -0,0 +1,673 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemac.h
+*
+* The Xilinx Ethernet driver component.	 This component supports the Xilinx
+* Ethernet 10/100 MAC (EMAC).
+*
+* The Xilinx Ethernet 10/100 MAC supports the following features:
+*   - Simple and scatter-gather DMA operations, as well as simple memory
+*     mapped direct I/O interface (FIFOs).
+*   - Media Independent Interface (MII) for connection to external
+*     10/100 Mbps PHY transceivers.
+*   - MII management control reads and writes with MII PHYs
+*   - Independent internal transmit and receive FIFOs
+*   - CSMA/CD compliant operations for half-duplex modes
+*   - Programmable PHY reset signal
+*   - Unicast, broadcast, and promiscuous address filtering (no multicast yet)
+*   - Internal loopback
+*   - Automatic source address insertion or overwrite (programmable)
+*   - Automatic FCS insertion and stripping (programmable)
+*   - Automatic pad insertion and stripping (programmable)
+*   - Pause frame (flow control) detection in full-duplex mode
+*   - Programmable interframe gap
+*   - VLAN frame support.
+*   - Pause frame support
+*
+* The device driver supports all the features listed above.
+*
+* <b>Driver Description</b>
+*
+* The device driver enables higher layer software (e.g., an application) to
+* communicate to the EMAC. The driver handles transmission and reception of
+* Ethernet frames, as well as configuration of the controller. It does not
+* handle protocol stack functionality such as Link Layer Control (LLC) or the
+* Address Resolution Protocol (ARP). The protocol stack that makes use of the
+* driver handles this functionality. This implies that the driver is simply a
+* pass-through mechanism between a protocol stack and the EMAC. A single device
+* driver can support multiple EMACs.
+*
+* The driver is designed for a zero-copy buffer scheme. That is, the driver will
+* not copy buffers. This avoids potential throughput bottlenecks within the
+* driver.
+*
+* Since the driver is a simple pass-through mechanism between a protocol stack
+* and the EMAC, no assembly or disassembly of Ethernet frames is done at the
+* driver-level. This assumes that the protocol stack passes a correctly
+* formatted Ethernet frame to the driver for transmission, and that the driver
+* does not validate the contents of an incoming frame
+*
+* <b>PHY Communication</b>
+*
+* The driver provides rudimentary read and write functions to allow the higher
+* layer software to access the PHY. The EMAC provides MII registers for the
+* driver to access. This management interface can be parameterized away in the
+* FPGA implementation process. If this is the case, the PHY read and write
+* functions of the driver return XST_NO_FEATURE.
+*
+* External loopback is usually supported at the PHY. It is up to the user to
+* turn external loopback on or off at the PHY. The driver simply provides pass-
+* through functions for configuring the PHY. The driver does not read, write,
+* or reset the PHY on its own. All control of the PHY must be done by the user.
+*
+* <b>Asynchronous Callbacks</b>
+*
+* The driver services interrupts and passes Ethernet frames to the higher layer
+* software through asynchronous callback functions. When using the driver
+* directly (i.e., not with the RTOS protocol stack), the higher layer
+* software must register its callback functions during initialization. The
+* driver requires callback functions for received frames, for confirmation of
+* transmitted frames, and for asynchronous errors.
+*
+* <b>Interrupts</b>
+*
+* The driver has no dependencies on the interrupt controller. The driver
+* provides two interrupt handlers.  XEmac_IntrHandlerDma() handles interrupts
+* when the EMAC is configured with scatter-gather DMA.	XEmac_IntrHandlerFifo()
+* handles interrupts when the EMAC is configured for direct FIFO I/O or simple
+* DMA.	Either of these routines can be connected to the system interrupt
+* controller by the user.
+*
+* <b>Interrupt Frequency</b>
+*
+* When the EMAC is configured with scatter-gather DMA, the frequency of
+* interrupts can be controlled with the interrupt coalescing features of the
+* scatter-gather DMA engine. The frequency of interrupts can be adjusted using
+* the driver API functions for setting the packet count threshold and the packet
+* wait bound values.
+*
+* The scatter-gather DMA engine only interrupts when the packet count threshold
+* is reached, instead of interrupting for each packet. A packet is a generic
+* term used by the scatter-gather DMA engine, and is equivalent to an Ethernet
+* frame in our case.
+*
+* The packet wait bound is a timer value used during interrupt coalescing to
+* trigger an interrupt when not enough packets have been received to reach the
+* packet count threshold.
+*
+* These values can be tuned by the user to meet their needs. If there appear to
+* be interrupt latency problems or delays in packet arrival that are longer than
+* might be expected, the user should verify that the packet count threshold is
+* set low enough to receive interrupts before the wait bound timer goes off.
+*
+* <b>Device Reset</b>
+*
+* Some errors that can occur in the device require a device reset. These errors
+* are listed in the XEmac_SetErrorHandler() function header. The user's error
+* handler is responsible for resetting the device and re-configuring it based on
+* its needs (the driver does not save the current configuration). When
+* integrating into an RTOS, these reset and re-configure obligations are
+* taken care of by the Xilinx adapter software if it exists for that RTOS.
+*
+* <b>Device Configuration</b>
+*
+* The device can be configured in various ways during the FPGA implementation
+* process.  Configuration parameters are stored in the xemac_g.c files.
+* A table is defined where each entry contains configuration information
+* for an EMAC device.  This information includes such things as the base address
+* of the memory-mapped device, the base addresses of IPIF, DMA, and FIFO modules
+* within the device, and whether the device has DMA, counter registers,
+* multicast support, MII support, and flow control.
+*
+* The driver tries to use the features built into the device. So if, for
+* example, the hardware is configured with scatter-gather DMA, the driver
+* expects to start the scatter-gather channels and expects that the user has set
+* up the buffer descriptor lists already. If the user expects to use the driver
+* in a mode different than how the hardware is configured, the user should
+* modify the configuration table to reflect the mode to be used. Modifying the
+* configuration table is a workaround for now until we get some experience with
+* how users are intending to use the hardware in its different configurations.
+* For example, if the hardware is built with scatter-gather DMA but the user is
+* intending to use only simple DMA, the user either needs to modify the config
+* table as a workaround or rebuild the hardware with only simple DMA. The
+* recommendation at this point is to build the hardware with the features you
+* intend to use. If you're inclined to modify the table, do so before the call
+* to XEmac_Initialize().  Here is a snippet of code that changes a device to
+* simple DMA (the hardware needs to have DMA for this to work of course):
+* <pre>
+*	 XEmac_Config *ConfigPtr;
+*
+*	 ConfigPtr = XEmac_LookupConfig(DeviceId);
+*	 ConfigPtr->IpIfDmaConfig = XEM_CFG_SIMPLE_DMA;
+* </pre>
+*
+* <b>Simple DMA</b>
+*
+* Simple DMA is supported through the FIFO functions, FifoSend and FifoRecv, of
+* the driver (i.e., there is no separate interface for it). The driver makes use
+* of the DMA engine for a simple DMA transfer if the device is configured with
+* DMA, otherwise it uses the FIFOs directly. While the simple DMA interface is
+* therefore transparent to the user, the caching of network buffers is not.
+* If the device is configured with DMA and the FIFO interface is used, the user
+* must ensure that the network buffers are not cached or are cache coherent,
+* since DMA will be used to transfer to and from the Emac device. If the device
+* is configured with DMA and the user really wants to use the FIFOs directly,
+* the user should rebuild the hardware without DMA. If unable to do this, there
+* is a workaround (described above in Device Configuration) to modify the
+* configuration table of the driver to fake the driver into thinking the device
+* has no DMA. A code snippet follows:
+* <pre>
+*	 XEmac_Config *ConfigPtr;
+*
+*	 ConfigPtr = XEmac_LookupConfig(DeviceId);
+*	 ConfigPtr->IpIfDmaConfig = XEM_CFG_NO_DMA;
+* </pre>
+*
+* <b>Asserts</b>
+*
+* Asserts are used within all Xilinx drivers to enforce constraints on argument
+* values. Asserts can be turned off on a system-wide basis by defining, at
+* compile time, the NDEBUG identifier. By default, asserts are turned on and it
+* is recommended that users leave asserts on during development.
+*
+* <b>Building the driver</b>
+*
+* The XEmac driver is composed of several source files. Why so many?  This
+* allows the user to build and link only those parts of the driver that are
+* necessary. Since the EMAC hardware can be configured in various ways (e.g.,
+* with or without DMA), the driver too can be built with varying features.
+* For the most part, this means that besides always linking in xemac.c, you
+* link in only the driver functionality you want. Some of the choices you have
+* are polled vs. interrupt, interrupt with FIFOs only vs. interrupt with DMA,
+* self-test diagnostics, and driver statistics. Note that currently the DMA code
+* must be linked in, even if you don't have DMA in the device.
+*
+* @note
+*
+* Xilinx drivers are typically composed of two components, one is the driver
+* and the other is the adapter.	 The driver is independent of OS and processor
+* and is intended to be highly portable.  The adapter is OS-specific and
+* facilitates communication between the driver and an OS.
+* <br><br>
+* This driver is intended to be RTOS and processor independent.	 It works
+* with physical addresses only.	 Any needs for dynamic memory management,
+* threads or thread mutual exclusion, virtual memory, or cache control must
+* be satisfied by the layer above this driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver	Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a rpm  07/31/01 First release
+* 1.00b rpm  02/20/02 Repartitioned files and functions
+* 1.00b rpm  10/08/02 Replaced HasSgDma boolean with IpifDmaConfig enumerated
+*		      configuration parameter
+* 1.00c rpm  12/05/02 New version includes support for simple DMA and the delay
+*		      argument to SgSend
+* 1.00c rpm  02/03/03 The XST_DMA_SG_COUNT_EXCEEDED return code was removed
+*		      from SetPktThreshold in the internal DMA driver. Also
+*		      avoided compiler warnings by initializing Result in the
+*		      DMA interrupt service routines.
+* </pre>
+*
+******************************************************************************/
+
+#ifndef XEMAC_H			/* prevent circular inclusions */
+#define XEMAC_H			/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xstatus.h"
+#include "xparameters.h"
+#include "xpacket_fifo_v1_00_b.h"	/* Uses v1.00b of Packet Fifo */
+#include "xdma_channel.h"
+
+/************************** Constant Definitions *****************************/
+
+/*
+ * Device information
+ */
+#define XEM_DEVICE_NAME	    "xemac"
+#define XEM_DEVICE_DESC	    "Xilinx Ethernet 10/100 MAC"
+
+/** @name Configuration options
+ *
+ * Device configuration options (see the XEmac_SetOptions() and
+ * XEmac_GetOptions() for information on how to use these options)
+ * @{
+ */
+/**
+ * <pre>
+ *   XEM_BROADCAST_OPTION	 Broadcast addressing on or off (default is on)
+ *   XEM_UNICAST_OPTION		 Unicast addressing on or off (default is on)
+ *   XEM_PROMISC_OPTION		 Promiscuous addressing on or off (default is off)
+ *   XEM_FDUPLEX_OPTION		 Full duplex on or off (default is off)
+ *   XEM_POLLED_OPTION		 Polled mode on or off (default is off)
+ *   XEM_LOOPBACK_OPTION	 Internal loopback on or off (default is off)
+ *   XEM_FLOW_CONTROL_OPTION	 Interpret pause frames in full duplex mode
+ *				 (default is off)
+ *   XEM_INSERT_PAD_OPTION	 Pad short frames on transmit (default is on)
+ *   XEM_INSERT_FCS_OPTION	 Insert FCS (CRC) on transmit (default is on)
+ *   XEM_INSERT_ADDR_OPTION	 Insert source address on transmit (default is on)
+ *   XEM_OVWRT_ADDR_OPTION	 Overwrite source address on transmit. This is
+ *				 only used if source address insertion is on.
+ *				 (default is on)
+ *   XEM_STRIP_PAD_FCS_OPTION	 Strip FCS and padding from received frames
+ *				 (default is off)
+  * </pre>
+ */
+#define XEM_UNICAST_OPTION	  0x00000001UL
+#define XEM_BROADCAST_OPTION	  0x00000002UL
+#define XEM_PROMISC_OPTION	  0x00000004UL
+#define XEM_FDUPLEX_OPTION	  0x00000008UL
+#define XEM_POLLED_OPTION	  0x00000010UL
+#define XEM_LOOPBACK_OPTION	  0x00000020UL
+#define XEM_FLOW_CONTROL_OPTION	  0x00000080UL
+#define XEM_INSERT_PAD_OPTION	  0x00000100UL
+#define XEM_INSERT_FCS_OPTION	  0x00000200UL
+#define XEM_INSERT_ADDR_OPTION	  0x00000400UL
+#define XEM_OVWRT_ADDR_OPTION	  0x00000800UL
+#define XEM_STRIP_PAD_FCS_OPTION  0x00002000UL
+/*@}*/
+/*
+ * Not supported yet:
+ *   XEM_MULTICAST_OPTION	 Multicast addressing on or off (default is off)
+ */
+/* NOT SUPPORTED YET... */
+#define XEM_MULTICAST_OPTION	  0x00000040UL
+
+/*
+ * Some default values for interrupt coalescing within the scatter-gather
+ * DMA engine.
+ */
+#define XEM_SGDMA_DFT_THRESHOLD	    1	/* Default pkt threshold */
+#define XEM_SGDMA_MAX_THRESHOLD	    255 /* Maximum pkt theshold */
+#define XEM_SGDMA_DFT_WAITBOUND	    5	/* Default pkt wait bound (msec) */
+#define XEM_SGDMA_MAX_WAITBOUND	    1023	/* Maximum pkt wait bound (msec) */
+
+/*
+ * Direction identifiers. These are used for setting values like packet
+ * thresholds and wait bound for specific channels
+ */
+#define XEM_SEND    1
+#define XEM_RECV    2
+
+/*
+ * Arguments to SgSend function to indicate whether to hold off starting
+ * the scatter-gather engine.
+ */
+#define XEM_SGDMA_NODELAY     0 /* start SG DMA immediately */
+#define XEM_SGDMA_DELAY	      1 /* do not start SG DMA */
+
+/*
+ * Constants to determine the configuration of the hardware device. They are
+ * used to allow the driver to verify it can operate with the hardware.
+ */
+#define XEM_CFG_NO_IPIF		    0	/* Not supported by the driver */
+#define XEM_CFG_NO_DMA		    1	/* No DMA */
+#define XEM_CFG_SIMPLE_DMA	    2	/* Simple DMA */
+#define XEM_CFG_DMA_SG		    3	/* DMA scatter gather */
+
+/*
+ * The next few constants help upper layers determine the size of memory
+ * pools used for Ethernet buffers and descriptor lists.
+ */
+#define XEM_MAC_ADDR_SIZE   6	/* six-byte MAC address */
+#define XEM_MTU		    1500	/* max size of Ethernet frame */
+#define XEM_HDR_SIZE	    14	/* size of Ethernet header */
+#define XEM_HDR_VLAN_SIZE   18	/* size of Ethernet header with VLAN */
+#define XEM_TRL_SIZE	    4	/* size of Ethernet trailer (FCS) */
+#define XEM_MAX_FRAME_SIZE  (XEM_MTU + XEM_HDR_SIZE + XEM_TRL_SIZE)
+#define XEM_MAX_VLAN_FRAME_SIZE	 (XEM_MTU + XEM_HDR_VLAN_SIZE + XEM_TRL_SIZE)
+
+/*
+ * Define a default number of send and receive buffers
+ */
+#define XEM_MIN_RECV_BUFS   32	/* minimum # of recv buffers */
+#define XEM_DFT_RECV_BUFS   64	/* default # of recv buffers */
+
+#define XEM_MIN_SEND_BUFS   16	/* minimum # of send buffers */
+#define XEM_DFT_SEND_BUFS   32	/* default # of send buffers */
+
+#define XEM_MIN_BUFFERS	    (XEM_MIN_RECV_BUFS + XEM_MIN_SEND_BUFS)
+#define XEM_DFT_BUFFERS	    (XEM_DFT_RECV_BUFS + XEM_DFT_SEND_BUFS)
+
+/*
+ * Define the number of send and receive buffer descriptors, used for
+ * scatter-gather DMA
+ */
+#define XEM_MIN_RECV_DESC   16	/* minimum # of recv descriptors */
+#define XEM_DFT_RECV_DESC   32	/* default # of recv descriptors */
+
+#define XEM_MIN_SEND_DESC   8	/* minimum # of send descriptors */
+#define XEM_DFT_SEND_DESC   16	/* default # of send descriptors */
+
+/**************************** Type Definitions *******************************/
+
+/**
+ * Ethernet statistics (see XEmac_GetStats() and XEmac_ClearStats())
+ */
+typedef struct {
+	u32 XmitFrames;		 /**< Number of frames transmitted */
+	u32 XmitBytes;		 /**< Number of bytes transmitted */
+	u32 XmitLateCollisionErrors;
+				 /**< Number of transmission failures
+					  due to late collisions */
+	u32 XmitExcessDeferral;	 /**< Number of transmission failures
+					  due o excess collision deferrals */
+	u32 XmitOverrunErrors;	 /**< Number of transmit overrun errors */
+	u32 XmitUnderrunErrors;	 /**< Number of transmit underrun errors */
+	u32 RecvFrames;		 /**< Number of frames received */
+	u32 RecvBytes;		 /**< Number of bytes received */
+	u32 RecvFcsErrors;	 /**< Number of frames discarded due
+					  to FCS errors */
+	u32 RecvAlignmentErrors; /**< Number of frames received with
+					  alignment errors */
+	u32 RecvOverrunErrors;	 /**< Number of frames discarded due
+					  to overrun errors */
+	u32 RecvUnderrunErrors;	 /**< Number of recv underrun errors */
+	u32 RecvMissedFrameErrors;
+				 /**< Number of frames missed by MAC */
+	u32 RecvCollisionErrors; /**< Number of frames discarded due
+					  to collisions */
+	u32 RecvLengthFieldErrors;
+				 /**< Number of frames discarded with
+					  invalid length field */
+	u32 RecvShortErrors;	 /**< Number of short frames discarded */
+	u32 RecvLongErrors;	 /**< Number of long frames discarded */
+	u32 DmaErrors;		 /**< Number of DMA errors since init */
+	u32 FifoErrors;		 /**< Number of FIFO errors since init */
+	u32 RecvInterrupts;	 /**< Number of receive interrupts */
+	u32 XmitInterrupts;	 /**< Number of transmit interrupts */
+	u32 EmacInterrupts;	 /**< Number of MAC (device) interrupts */
+	u32 TotalIntrs;		 /**< Total interrupts */
+} XEmac_Stats;
+
+/**
+ * This typedef contains configuration information for a device.
+ */
+typedef struct {
+	u16 DeviceId;	    /**< Unique ID  of device */
+	u32 BaseAddress;    /**< Register base address */
+	u32 HasCounters;   /**< Does device have counters? */
+	u8 IpIfDmaConfig;   /**< IPIF/DMA hardware configuration */
+	u32 HasMii;	   /**< Does device support MII? */
+
+} XEmac_Config;
+
+/** @name Typedefs for callbacks
+ * Callback functions.
+ * @{
+ */
+/**
+ * Callback when data is sent or received with scatter-gather DMA.
+ *
+ * @param CallBackRef is a callback reference passed in by the upper layer
+ *	  when setting the callback functions, and passed back to the upper
+ *	  layer when the callback is invoked.
+ * @param BdPtr is a pointer to the first buffer descriptor in a list of
+ *	  buffer descriptors.
+ * @param NumBds is the number of buffer descriptors in the list pointed
+ *	  to by BdPtr.
+ */
+typedef void (*XEmac_SgHandler) (void *CallBackRef, XBufDescriptor * BdPtr,
+				 u32 NumBds);
+
+/**
+ * Callback when data is sent or received with direct FIFO communication or
+ * simple DMA. The user typically defines two callacks, one for send and one
+ * for receive.
+ *
+ * @param CallBackRef is a callback reference passed in by the upper layer
+ *	  when setting the callback functions, and passed back to the upper
+ *	  layer when the callback is invoked.
+ */
+typedef void (*XEmac_FifoHandler) (void *CallBackRef);
+
+/**
+ * Callback when an asynchronous error occurs.
+ *
+ * @param CallBackRef is a callback reference passed in by the upper layer
+ *	  when setting the callback functions, and passed back to the upper
+ *	  layer when the callback is invoked.
+ * @param ErrorCode is a Xilinx error code defined in xstatus.h.  Also see
+ *	  XEmac_SetErrorHandler() for a description of possible errors.
+ */
+typedef void (*XEmac_ErrorHandler) (void *CallBackRef, XStatus ErrorCode);
+/*@}*/
+
+/**
+ * The XEmac driver instance data. The user is required to allocate a
+ * variable of this type for every EMAC device in the system. A pointer
+ * to a variable of this type is then passed to the driver API functions.
+ */
+typedef struct {
+	u32 BaseAddress;	/* Base address (of IPIF) */
+	u32 IsStarted;		/* Device is currently started */
+	u32 IsReady;		/* Device is initialized and ready */
+	u32 IsPolled;		/* Device is in polled mode */
+	u8 IpIfDmaConfig;	/* IPIF/DMA hardware configuration */
+	u32 HasMii;		/* Does device support MII? */
+	u32 HasMulticastHash;	/* Does device support multicast hash table? */
+
+	XEmac_Stats Stats;
+	XPacketFifoV100b RecvFifo;	/* FIFO used to receive frames */
+	XPacketFifoV100b SendFifo;	/* FIFO used to send frames */
+
+	/*
+	 * Callbacks
+	 */
+	XEmac_FifoHandler FifoRecvHandler;	/* for non-DMA/simple DMA interrupts */
+	void *FifoRecvRef;
+	XEmac_FifoHandler FifoSendHandler;	/* for non-DMA/simple DMA interrupts */
+	void *FifoSendRef;
+	XEmac_ErrorHandler ErrorHandler;	/* for asynchronous errors */
+	void *ErrorRef;
+
+	XDmaChannel RecvChannel;	/* DMA receive channel driver */
+	XDmaChannel SendChannel;	/* DMA send channel driver */
+
+	XEmac_SgHandler SgRecvHandler;	/* callback for scatter-gather DMA */
+	void *SgRecvRef;
+	XEmac_SgHandler SgSendHandler;	/* callback for scatter-gather DMA */
+	void *SgSendRef;
+} XEmac;
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/*****************************************************************************/
+/**
+*
+* This macro determines if the device is currently configured for
+* scatter-gather DMA.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* Boolean TRUE if the device is configured for scatter-gather DMA, or FALSE
+* if it is not.
+*
+* @note
+*
+* Signature: u32 XEmac_mIsSgDma(XEmac *InstancePtr)
+*
+******************************************************************************/
+#define XEmac_mIsSgDma(InstancePtr) \
+	    ((InstancePtr)->IpIfDmaConfig == XEM_CFG_DMA_SG)
+
+/*****************************************************************************/
+/**
+*
+* This macro determines if the device is currently configured for simple DMA.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* Boolean TRUE if the device is configured for simple DMA, or FALSE otherwise
+*
+* @note
+*
+* Signature: u32 XEmac_mIsSimpleDma(XEmac *InstancePtr)
+*
+******************************************************************************/
+#define XEmac_mIsSimpleDma(InstancePtr) \
+	    ((InstancePtr)->IpIfDmaConfig == XEM_CFG_SIMPLE_DMA)
+
+/*****************************************************************************/
+/**
+*
+* This macro determines if the device is currently configured with DMA (either
+* simple DMA or scatter-gather DMA)
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* Boolean TRUE if the device is configured with DMA, or FALSE otherwise
+*
+* @note
+*
+* Signature: u32 XEmac_mIsDma(XEmac *InstancePtr)
+*
+******************************************************************************/
+#define XEmac_mIsDma(InstancePtr) \
+	    (XEmac_mIsSimpleDma(InstancePtr) || XEmac_mIsSgDma(InstancePtr))
+
+/************************** Function Prototypes ******************************/
+
+/*
+ * Initialization functions in xemac.c
+ */
+XStatus XEmac_Initialize(XEmac * InstancePtr, u16 DeviceId);
+XStatus XEmac_Start(XEmac * InstancePtr);
+XStatus XEmac_Stop(XEmac * InstancePtr);
+void XEmac_Reset(XEmac * InstancePtr);
+XEmac_Config *XEmac_LookupConfig(u16 DeviceId);
+
+/*
+ * Diagnostic functions in xemac_selftest.c
+ */
+XStatus XEmac_SelfTest(XEmac * InstancePtr);
+
+/*
+ * Polled functions in xemac_polled.c
+ */
+XStatus XEmac_PollSend(XEmac * InstancePtr, u8 * BufPtr, u32 ByteCount);
+XStatus XEmac_PollRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr);
+
+/*
+ * Interrupts with scatter-gather DMA functions in xemac_intr_dma.c
+ */
+XStatus XEmac_SgSend(XEmac * InstancePtr, XBufDescriptor * BdPtr, int Delay);
+XStatus XEmac_SgRecv(XEmac * InstancePtr, XBufDescriptor * BdPtr);
+XStatus XEmac_SetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 Threshold);
+XStatus XEmac_GetPktThreshold(XEmac * InstancePtr, u32 Direction,
+			      u8 * ThreshPtr);
+XStatus XEmac_SetPktWaitBound(XEmac * InstancePtr, u32 Direction,
+			      u32 TimerValue);
+XStatus XEmac_GetPktWaitBound(XEmac * InstancePtr, u32 Direction,
+			      u32 * WaitPtr);
+XStatus XEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr,
+			     u32 ByteCount);
+XStatus XEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr,
+			     u32 ByteCount);
+void XEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef,
+			    XEmac_SgHandler FuncPtr);
+void XEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef,
+			    XEmac_SgHandler FuncPtr);
+
+void XEmac_IntrHandlerDma(void *InstancePtr);	/* interrupt handler */
+
+/*
+ * Interrupts with direct FIFO functions in xemac_intr_fifo.c. Also used
+ * for simple DMA.
+ */
+XStatus XEmac_FifoSend(XEmac * InstancePtr, u8 * BufPtr, u32 ByteCount);
+XStatus XEmac_FifoRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr);
+void XEmac_SetFifoRecvHandler(XEmac * InstancePtr, void *CallBackRef,
+			      XEmac_FifoHandler FuncPtr);
+void XEmac_SetFifoSendHandler(XEmac * InstancePtr, void *CallBackRef,
+			      XEmac_FifoHandler FuncPtr);
+
+void XEmac_IntrHandlerFifo(void *InstancePtr);	/* interrupt handler */
+
+/*
+ * General interrupt-related functions in xemac_intr.c
+ */
+void XEmac_SetErrorHandler(XEmac * InstancePtr, void *CallBackRef,
+			   XEmac_ErrorHandler FuncPtr);
+
+/*
+ * MAC configuration in xemac_options.c
+ */
+XStatus XEmac_SetOptions(XEmac * InstancePtr, u32 OptionFlag);
+u32 XEmac_GetOptions(XEmac * InstancePtr);
+XStatus XEmac_SetMacAddress(XEmac * InstancePtr, u8 * AddressPtr);
+void XEmac_GetMacAddress(XEmac * InstancePtr, u8 * BufferPtr);
+XStatus XEmac_SetInterframeGap(XEmac * InstancePtr, u8 Part1, u8 Part2);
+void XEmac_GetInterframeGap(XEmac * InstancePtr, u8 * Part1Ptr, u8 * Part2Ptr);
+
+/*
+ * Multicast functions in xemac_multicast.c (not supported by EMAC yet)
+ */
+XStatus XEmac_MulticastAdd(XEmac * InstancePtr, u8 * AddressPtr);
+XStatus XEmac_MulticastClear(XEmac * InstancePtr);
+
+/*
+ * PHY configuration in xemac_phy.c
+ */
+XStatus XEmac_PhyRead(XEmac * InstancePtr, u32 PhyAddress,
+		      u32 RegisterNum, u16 * PhyDataPtr);
+XStatus XEmac_PhyWrite(XEmac * InstancePtr, u32 PhyAddress,
+		       u32 RegisterNum, u16 PhyData);
+
+/*
+ * Statistics in xemac_stats.c
+ */
+void XEmac_GetStats(XEmac * InstancePtr, XEmac_Stats * StatsPtr);
+void XEmac_ClearStats(XEmac * InstancePtr);
+
+#endif				/* end of protection macro */

+ 60 - 0
board/xilinx/xilinx_enet/xemac_g.c

@@ -0,0 +1,60 @@
+/*******************************************************************
+*
+* CAUTION: This file is automatically generated by libgen.
+* Version: Xilinx EDK 6.1.2 EDK_G.14
+* DO NOT EDIT.
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* Description: Driver configuration
+*
+*******************************************************************/
+
+#include "xparameters.h"
+#include "xemac.h"
+
+/*
+* The configuration table for devices
+*/
+
+XEmac_Config XEmac_ConfigTable[] = {
+	{
+	 XPAR_OPB_ETHERNET_0_DEVICE_ID,
+	 XPAR_OPB_ETHERNET_0_BASEADDR,
+	 XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST,
+	 XPAR_OPB_ETHERNET_0_DMA_PRESENT,
+	 XPAR_OPB_ETHERNET_0_MII_EXIST}
+};

+ 207 - 0
board/xilinx/xilinx_enet/xemac_i.h

@@ -0,0 +1,207 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemac_i.h
+*
+* This header file contains internal identifiers, which are those shared
+* between XEmac components.  The identifiers in this file are not intended for
+* use external to the driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver	Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rpm  07/31/01 First release
+* 1.00b rpm  02/20/02 Repartitioned files and functions
+* 1.00b rpm  04/29/02 Moved register definitions to xemac_l.h
+* 1.00c rpm  12/05/02 New version includes support for simple DMA
+* </pre>
+*
+******************************************************************************/
+
+#ifndef XEMAC_I_H		/* prevent circular inclusions */
+#define XEMAC_I_H		/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xemac.h"
+#include "xemac_l.h"
+
+/************************** Constant Definitions *****************************/
+
+/*
+ * Default buffer descriptor control word masks. The default send BD control
+ * is set for incrementing the source address by one for each byte transferred,
+ * and specify that the destination address (FIFO) is local to the device. The
+ * default receive BD control is set for incrementing the destination address
+ * by one for each byte transferred, and specify that the source address is
+ * local to the device.
+ */
+#define XEM_DFT_SEND_BD_MASK	(XDC_DMACR_SOURCE_INCR_MASK | \
+				 XDC_DMACR_DEST_LOCAL_MASK)
+#define XEM_DFT_RECV_BD_MASK	(XDC_DMACR_DEST_INCR_MASK |  \
+				 XDC_DMACR_SOURCE_LOCAL_MASK)
+
+/*
+ * Masks for the IPIF Device Interrupt enable and status registers.
+ */
+#define XEM_IPIF_EMAC_MASK	0x00000004UL	/* MAC interrupt */
+#define XEM_IPIF_SEND_DMA_MASK	0x00000008UL	/* Send DMA interrupt */
+#define XEM_IPIF_RECV_DMA_MASK	0x00000010UL	/* Receive DMA interrupt */
+#define XEM_IPIF_RECV_FIFO_MASK 0x00000020UL	/* Receive FIFO interrupt */
+#define XEM_IPIF_SEND_FIFO_MASK 0x00000040UL	/* Send FIFO interrupt */
+
+/*
+ * Default IPIF Device Interrupt mask when configured for DMA
+ */
+#define XEM_IPIF_DMA_DFT_MASK	(XEM_IPIF_SEND_DMA_MASK |   \
+				 XEM_IPIF_RECV_DMA_MASK |   \
+				 XEM_IPIF_EMAC_MASK |	    \
+				 XEM_IPIF_SEND_FIFO_MASK |  \
+				 XEM_IPIF_RECV_FIFO_MASK)
+
+/*
+ * Default IPIF Device Interrupt mask when configured without DMA
+ */
+#define XEM_IPIF_FIFO_DFT_MASK	(XEM_IPIF_EMAC_MASK |	    \
+				 XEM_IPIF_SEND_FIFO_MASK |  \
+				 XEM_IPIF_RECV_FIFO_MASK)
+
+#define XEM_IPIF_DMA_DEV_INTR_COUNT   7 /* Number of interrupt sources */
+#define XEM_IPIF_FIFO_DEV_INTR_COUNT  5 /* Number of interrupt sources */
+#define XEM_IPIF_DEVICE_INTR_COUNT  7	/* Number of interrupt sources */
+#define XEM_IPIF_IP_INTR_COUNT	    22	/* Number of MAC interrupts */
+
+/* a mask for all transmit interrupts, used in polled mode */
+#define XEM_EIR_XMIT_ALL_MASK	(XEM_EIR_XMIT_DONE_MASK |	    \
+				 XEM_EIR_XMIT_ERROR_MASK |	    \
+				 XEM_EIR_XMIT_SFIFO_EMPTY_MASK |    \
+				 XEM_EIR_XMIT_LFIFO_FULL_MASK)
+
+/* a mask for all receive interrupts, used in polled mode */
+#define XEM_EIR_RECV_ALL_MASK	(XEM_EIR_RECV_DONE_MASK |	    \
+				 XEM_EIR_RECV_ERROR_MASK |	    \
+				 XEM_EIR_RECV_LFIFO_EMPTY_MASK |    \
+				 XEM_EIR_RECV_LFIFO_OVER_MASK |	    \
+				 XEM_EIR_RECV_LFIFO_UNDER_MASK |    \
+				 XEM_EIR_RECV_DFIFO_OVER_MASK |	    \
+				 XEM_EIR_RECV_MISSED_FRAME_MASK |   \
+				 XEM_EIR_RECV_COLLISION_MASK |	    \
+				 XEM_EIR_RECV_FCS_ERROR_MASK |	    \
+				 XEM_EIR_RECV_LEN_ERROR_MASK |	    \
+				 XEM_EIR_RECV_SHORT_ERROR_MASK |    \
+				 XEM_EIR_RECV_LONG_ERROR_MASK |	    \
+				 XEM_EIR_RECV_ALIGN_ERROR_MASK)
+
+/* a default interrupt mask for scatter-gather DMA operation */
+#define XEM_EIR_DFT_SG_MASK    (XEM_EIR_RECV_ERROR_MASK |	    \
+				XEM_EIR_RECV_LFIFO_OVER_MASK |	    \
+				XEM_EIR_RECV_LFIFO_UNDER_MASK |	    \
+				XEM_EIR_XMIT_SFIFO_OVER_MASK |	    \
+				XEM_EIR_XMIT_SFIFO_UNDER_MASK |	    \
+				XEM_EIR_XMIT_LFIFO_OVER_MASK |	    \
+				XEM_EIR_XMIT_LFIFO_UNDER_MASK |	    \
+				XEM_EIR_RECV_DFIFO_OVER_MASK |	    \
+				XEM_EIR_RECV_MISSED_FRAME_MASK |    \
+				XEM_EIR_RECV_COLLISION_MASK |	    \
+				XEM_EIR_RECV_FCS_ERROR_MASK |	    \
+				XEM_EIR_RECV_LEN_ERROR_MASK |	    \
+				XEM_EIR_RECV_SHORT_ERROR_MASK |	    \
+				XEM_EIR_RECV_LONG_ERROR_MASK |	    \
+				XEM_EIR_RECV_ALIGN_ERROR_MASK)
+
+/* a default interrupt mask for non-DMA operation (direct FIFOs) */
+#define XEM_EIR_DFT_FIFO_MASK  (XEM_EIR_XMIT_DONE_MASK |	    \
+				XEM_EIR_RECV_DONE_MASK |	    \
+				XEM_EIR_DFT_SG_MASK)
+
+/*
+ * Mask for the DMA interrupt enable and status registers when configured
+ * for scatter-gather DMA.
+ */
+#define XEM_DMA_SG_INTR_MASK	(XDC_IXR_DMA_ERROR_MASK	 |	\
+				 XDC_IXR_PKT_THRESHOLD_MASK |	\
+				 XDC_IXR_PKT_WAIT_BOUND_MASK |	\
+				 XDC_IXR_SG_END_MASK)
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/*****************************************************************************/
+/*
+*
+* Clears a structure of given size, in bytes, by setting each byte to 0.
+*
+* @param StructPtr is a pointer to the structure to be cleared.
+* @param NumBytes is the number of bytes in the structure.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* Signature: void XEmac_mClearStruct(u8 *StructPtr, unsigned int NumBytes)
+*
+******************************************************************************/
+#define XEmac_mClearStruct(StructPtr, NumBytes)	    \
+{						    \
+    int i;					    \
+    u8 *BytePtr = (u8 *)(StructPtr);	    \
+    for (i=0; i < (unsigned int)(NumBytes); i++)    \
+    {						    \
+	*BytePtr++ = 0;				    \
+    }						    \
+}
+
+/************************** Variable Definitions *****************************/
+
+extern XEmac_Config XEmac_ConfigTable[];
+
+/************************** Function Prototypes ******************************/
+
+void XEmac_CheckEmacError(XEmac * InstancePtr, u32 IntrStatus);
+void XEmac_CheckFifoRecvError(XEmac * InstancePtr);
+void XEmac_CheckFifoSendError(XEmac * InstancePtr);
+
+#endif				/* end of protection macro */

+ 402 - 0
board/xilinx/xilinx_enet/xemac_intr.c

@@ -0,0 +1,402 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemac_intr.c
+*
+* This file contains general interrupt-related functions of the XEmac driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rpm  07/31/01 First release
+* 1.00b rpm  02/20/02 Repartitioned files and functions
+* 1.00c rpm  12/05/02 New version includes support for simple DMA
+* 1.00c rpm  03/31/03 Added comment to indicate that no Receive Length FIFO
+*                     overrun interrupts occur in v1.00l and later of the EMAC
+*                     device. This avoids the need to reset the device on
+*                     receive overruns.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xemac_i.h"
+#include "xio.h"
+#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+*
+* Set the callback function for handling asynchronous errors.  The upper layer
+* software should call this function during initialization.
+*
+* The error callback is invoked by the driver within interrupt context, so it
+* needs to do its job quickly. If there are potentially slow operations within
+* the callback, these should be done at task-level.
+*
+* The Xilinx errors that must be handled by the callback are:
+* - XST_DMA_ERROR indicates an unrecoverable DMA error occurred. This is
+*   typically a bus error or bus timeout. The handler must reset and
+*   re-configure the device.
+* - XST_FIFO_ERROR indicates an unrecoverable FIFO error occurred. This is a
+*   deadlock condition in the packet FIFO. The handler must reset and
+*   re-configure the device.
+* - XST_RESET_ERROR indicates an unrecoverable MAC error occurred, usually an
+*   overrun or underrun. The handler must reset and re-configure the device.
+* - XST_DMA_SG_NO_LIST indicates an attempt was made to access a scatter-gather
+*   DMA list that has not yet been created.
+* - XST_DMA_SG_LIST_EMPTY indicates the driver tried to get a descriptor from
+*   the receive descriptor list, but the list was empty.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param CallBackRef is a reference pointer to be passed back to the adapter in
+*        the callback. This helps the adapter correlate the callback to a
+*        particular driver.
+* @param FuncPtr is the pointer to the callback function.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XEmac_SetErrorHandler(XEmac * InstancePtr, void *CallBackRef,
+		      XEmac_ErrorHandler FuncPtr)
+{
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(FuncPtr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	InstancePtr->ErrorHandler = FuncPtr;
+	InstancePtr->ErrorRef = CallBackRef;
+}
+
+/****************************************************************************/
+/*
+*
+* Check the interrupt status bits of the Ethernet MAC for errors. Errors
+* currently handled are:
+* - Receive length FIFO overrun. Indicates data was lost due to the receive
+*   length FIFO becoming full during the reception of a packet. Only a device
+*   reset clears this condition.
+* - Receive length FIFO underrun. An attempt to read an empty FIFO. Only a
+*   device reset clears this condition.
+* - Transmit status FIFO overrun. Indicates data was lost due to the transmit
+*   status FIFO becoming full following the transmission of a packet. Only a
+*   device reset clears this condition.
+* - Transmit status FIFO underrun. An attempt to read an empty FIFO. Only a
+*   device reset clears this condition.
+* - Transmit length FIFO overrun. Indicates data was lost due to the transmit
+*   length FIFO becoming full following the transmission of a packet. Only a
+*   device reset clears this condition.
+* - Transmit length FIFO underrun. An attempt to read an empty FIFO. Only a
+*   device reset clears this condition.
+* - Receive data FIFO overrun. Indicates data was lost due to the receive data
+*   FIFO becoming full during the reception of a packet.
+* - Receive data errors:
+*   - Receive missed frame error. Valid data was lost by the MAC.
+*   - Receive collision error. Data was lost by the MAC due to a collision.
+*   - Receive FCS error.  Data was dicarded by the MAC due to FCS error.
+*   - Receive length field error. Data was dicarded by the MAC due to an invalid
+*     length field in the packet.
+*   - Receive short error. Data was dicarded by the MAC because a packet was
+*     shorter than allowed.
+*   - Receive long error. Data was dicarded by the MAC because a packet was
+*     longer than allowed.
+*   - Receive alignment error. Data was truncated by the MAC because its length
+*     was not byte-aligned.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param IntrStatus is the contents of the interrupt status register to be checked
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* This function is intended for internal use only.
+*
+******************************************************************************/
+void
+XEmac_CheckEmacError(XEmac * InstancePtr, u32 IntrStatus)
+{
+	u32 ResetError = FALSE;
+
+	/*
+	 * First check for receive fifo overrun/underrun errors. Most require a
+	 * reset by the user to clear, but the data FIFO overrun error does not.
+	 */
+	if (IntrStatus & XEM_EIR_RECV_DFIFO_OVER_MASK) {
+		InstancePtr->Stats.RecvOverrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+	}
+
+	if (IntrStatus & XEM_EIR_RECV_LFIFO_OVER_MASK) {
+		/*
+		 * Receive Length FIFO overrun interrupts no longer occur in v1.00l
+		 * and later of the EMAC device. Frames are just dropped by the EMAC
+		 * if the length FIFO is full. The user would notice the Receive Missed
+		 * Frame count incrementing without any other errors being reported.
+		 * This code is left here for backward compatibility with v1.00k and
+		 * older EMAC devices.
+		 */
+		InstancePtr->Stats.RecvOverrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+		ResetError = TRUE;	/* requires a reset */
+	}
+
+	if (IntrStatus & XEM_EIR_RECV_LFIFO_UNDER_MASK) {
+		InstancePtr->Stats.RecvUnderrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+		ResetError = TRUE;	/* requires a reset */
+	}
+
+	/*
+	 * Now check for general receive errors. Get the latest count where
+	 * available, otherwise just bump the statistic so we know the interrupt
+	 * occurred.
+	 */
+	if (IntrStatus & XEM_EIR_RECV_ERROR_MASK) {
+		if (IntrStatus & XEM_EIR_RECV_MISSED_FRAME_MASK) {
+			/*
+			 * Caused by length FIFO or data FIFO overruns on receive side
+			 */
+			InstancePtr->Stats.RecvMissedFrameErrors =
+			    XIo_In32(InstancePtr->BaseAddress +
+				     XEM_RMFC_OFFSET);
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_COLLISION_MASK) {
+			InstancePtr->Stats.RecvCollisionErrors =
+			    XIo_In32(InstancePtr->BaseAddress + XEM_RCC_OFFSET);
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_FCS_ERROR_MASK) {
+			InstancePtr->Stats.RecvFcsErrors =
+			    XIo_In32(InstancePtr->BaseAddress +
+				     XEM_RFCSEC_OFFSET);
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_LEN_ERROR_MASK) {
+			InstancePtr->Stats.RecvLengthFieldErrors++;
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_SHORT_ERROR_MASK) {
+			InstancePtr->Stats.RecvShortErrors++;
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_LONG_ERROR_MASK) {
+			InstancePtr->Stats.RecvLongErrors++;
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_ALIGN_ERROR_MASK) {
+			InstancePtr->Stats.RecvAlignmentErrors =
+			    XIo_In32(InstancePtr->BaseAddress +
+				     XEM_RAEC_OFFSET);
+		}
+
+		/*
+		 * Bump recv interrupts stats only if not scatter-gather DMA (this
+		 * stat gets bumped elsewhere in that case)
+		 */
+		if (!XEmac_mIsSgDma(InstancePtr)) {
+			InstancePtr->Stats.RecvInterrupts++;	/* TODO: double bump? */
+		}
+
+	}
+
+	/*
+	 * Check for transmit errors. These apply to both DMA and non-DMA modes
+	 * of operation. The entire device should be reset after overruns or
+	 * underruns.
+	 */
+	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK |
+			  XEM_EIR_XMIT_LFIFO_OVER_MASK)) {
+		InstancePtr->Stats.XmitOverrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+		ResetError = TRUE;
+	}
+
+	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK |
+			  XEM_EIR_XMIT_LFIFO_UNDER_MASK)) {
+		InstancePtr->Stats.XmitUnderrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+		ResetError = TRUE;
+	}
+
+	if (ResetError) {
+		/*
+		 * If a reset error occurred, disable the EMAC interrupts since the
+		 * reset-causing interrupt(s) is latched in the EMAC - meaning it will
+		 * keep occurring until the device is reset. In order to give the higher
+		 * layer software time to reset the device, we have to disable the
+		 * overrun/underrun interrupts until that happens. We trust that the
+		 * higher layer resets the device. We are able to get away with disabling
+		 * all EMAC interrupts since the only interrupts it generates are for
+		 * error conditions, and we don't care about any more errors right now.
+		 */
+		XIIF_V123B_WRITE_IIER(InstancePtr->BaseAddress, 0);
+
+		/*
+		 * Invoke the error handler callback, which should result in a reset
+		 * of the device by the upper layer software.
+		 */
+		InstancePtr->ErrorHandler(InstancePtr->ErrorRef,
+					  XST_RESET_ERROR);
+	}
+}
+
+/*****************************************************************************/
+/*
+*
+* Check the receive packet FIFO for errors. FIFO error interrupts are:
+* - Deadlock.  See the XPacketFifo component for a description of deadlock on a
+*   FIFO.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* Although the function returns void, it can return an asynchronous error to the
+* application through the error handler.  It can return XST_FIFO_ERROR if a FIFO
+* error occurred.
+*
+* @note
+*
+* This function is intended for internal use only.
+*
+******************************************************************************/
+void
+XEmac_CheckFifoRecvError(XEmac * InstancePtr)
+{
+	/*
+	 * Although the deadlock is currently the only interrupt from a packet
+	 * FIFO, make sure it is deadlocked before taking action. There is no
+	 * need to clear this interrupt since it requires a reset of the device.
+	 */
+	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->RecvFifo)) {
+		u32 IntrEnable;
+
+		InstancePtr->Stats.FifoErrors++;
+
+		/*
+		 * Invoke the error callback function, which should result in a reset
+		 * of the device by the upper layer software. We first need to disable
+		 * the FIFO interrupt, since otherwise the upper layer thread that
+		 * handles the reset may never run because this interrupt condition
+		 * doesn't go away until a reset occurs (there is no way to ack it).
+		 */
+		IntrEnable = XIIF_V123B_READ_DIER(InstancePtr->BaseAddress);
+		XIIF_V123B_WRITE_DIER(InstancePtr->BaseAddress,
+				      IntrEnable & ~XEM_IPIF_RECV_FIFO_MASK);
+
+		InstancePtr->ErrorHandler(InstancePtr->ErrorRef,
+					  XST_FIFO_ERROR);
+	}
+}
+
+/*****************************************************************************/
+/*
+*
+* Check the send packet FIFO for errors. FIFO error interrupts are:
+* - Deadlock. See the XPacketFifo component for a description of deadlock on a
+*   FIFO.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* Although the function returns void, it can return an asynchronous error to the
+* application through the error handler.  It can return XST_FIFO_ERROR if a FIFO
+* error occurred.
+*
+* @note
+*
+* This function is intended for internal use only.
+*
+******************************************************************************/
+void
+XEmac_CheckFifoSendError(XEmac * InstancePtr)
+{
+	/*
+	 * Although the deadlock is currently the only interrupt from a packet
+	 * FIFO, make sure it is deadlocked before taking action. There is no
+	 * need to clear this interrupt since it requires a reset of the device.
+	 */
+	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->SendFifo)) {
+		u32 IntrEnable;
+
+		InstancePtr->Stats.FifoErrors++;
+
+		/*
+		 * Invoke the error callback function, which should result in a reset
+		 * of the device by the upper layer software. We first need to disable
+		 * the FIFO interrupt, since otherwise the upper layer thread that
+		 * handles the reset may never run because this interrupt condition
+		 * doesn't go away until a reset occurs (there is no way to ack it).
+		 */
+		IntrEnable = XIIF_V123B_READ_DIER(InstancePtr->BaseAddress);
+		XIIF_V123B_WRITE_DIER(InstancePtr->BaseAddress,
+				      IntrEnable & ~XEM_IPIF_SEND_FIFO_MASK);
+
+		InstancePtr->ErrorHandler(InstancePtr->ErrorRef,
+					  XST_FIFO_ERROR);
+	}
+}

+ 1344 - 0
board/xilinx/xilinx_enet/xemac_intr_dma.c

@@ -0,0 +1,1344 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemac_intr_dma.c
+*
+* Contains functions used in interrupt mode when configured with scatter-gather
+* DMA.
+*
+* The interrupt handler, XEmac_IntrHandlerDma(), must be connected by the user
+* to the interrupt controller.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a rpm  07/31/01 First release
+* 1.00b rpm  02/20/02 Repartitioned files and functions
+* 1.00c rpm  12/05/02 New version includes support for simple DMA and the delay
+*                     argument to SgSend
+* 1.00c rpm  02/03/03 The XST_DMA_SG_COUNT_EXCEEDED return code was removed
+*                     from SetPktThreshold in the internal DMA driver. Also
+*                     avoided compiler warnings by initializing Result in the
+*                     interrupt service routines.
+* 1.00c rpm  03/26/03 Fixed a problem in the interrupt service routines where
+*                     the interrupt status was toggled clear after a call to
+*                     ErrorHandler, but if ErrorHandler reset the device the
+*                     toggle actually asserted the interrupt because the
+*                     reset had cleared it.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xemac_i.h"
+#include "xio.h"
+#include "xbuf_descriptor.h"
+#include "xdma_channel.h"
+#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+static void HandleDmaRecvIntr(XEmac * InstancePtr);
+static void HandleDmaSendIntr(XEmac * InstancePtr);
+static void HandleEmacDmaIntr(XEmac * InstancePtr);
+
+/*****************************************************************************/
+/**
+*
+* Send an Ethernet frame using scatter-gather DMA. The caller attaches the
+* frame to one or more buffer descriptors, then calls this function once for
+* each descriptor. The caller is responsible for allocating and setting up the
+* descriptor. An entire Ethernet frame may or may not be contained within one
+* descriptor.  This function simply inserts the descriptor into the scatter-
+* gather engine's transmit list. The caller is responsible for providing mutual
+* exclusion to guarantee that a frame is contiguous in the transmit list. The
+* buffer attached to the descriptor must be word-aligned.
+*
+* The driver updates the descriptor with the device control register before
+* being inserted into the transmit list.  If this is the last descriptor in
+* the frame, the inserts are committed, which means the descriptors for this
+* frame are now available for transmission.
+*
+* It is assumed that the upper layer software supplies a correctly formatted
+* Ethernet frame, including the destination and source addresses, the
+* type/length field, and the data field.  It is also assumed that upper layer
+* software does not append FCS at the end of the frame.
+*
+* The buffer attached to the descriptor must be word-aligned on the front end.
+*
+* This call is non-blocking.  Notification of error or successful transmission
+* is done asynchronously through the send or error callback function.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param BdPtr is the address of a descriptor to be inserted into the transmit
+*        ring.
+* @param Delay indicates whether to start the scatter-gather DMA channel
+*        immediately, or whether to wait. This allows the user to build up a
+*        list of more than one descriptor before starting the transmission of
+*        the packets, which allows the application to keep up with DMA and have
+*        a constant stream of frames being transmitted. Use XEM_SGDMA_NODELAY or
+*        XEM_SGDMA_DELAY, defined in xemac.h, as the value of this argument. If
+*        the user chooses to delay and build a list, the user must call this
+*        function with the XEM_SGDMA_NODELAY option or call XEmac_Start() to
+*        kick off the tranmissions.
+*
+* @return
+*
+* - XST_SUCCESS if the buffer was successfull sent
+* - XST_DEVICE_IS_STOPPED if the Ethernet MAC has not been started yet
+* - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode
+* - XST_DMA_SG_LIST_FULL if the descriptor list for the DMA channel is full
+* - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into
+*   the list because a locked descriptor exists at the insert point
+* - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the
+*   list, the DMA channel believes there are no new descriptors to commit. If
+*   this is ever encountered, there is likely a thread mutual exclusion problem
+*   on transmit.
+*
+* @note
+*
+* This function is not thread-safe. The user must provide mutually exclusive
+* access to this function if there are to be multiple threads that can call it.
+*
+* @internal
+*
+* A status that should never be returned from this function, although
+* the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device
+* requires a list to be created, and this function requires the device to be
+* started.
+*
+******************************************************************************/
+XStatus
+XEmac_SgSend(XEmac * InstancePtr, XBufDescriptor * BdPtr, int Delay)
+{
+	XStatus Result;
+	u32 BdControl;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BdPtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Be sure the device is configured for scatter-gather DMA, then be sure
+	 * it is started.
+	 */
+	if (!XEmac_mIsSgDma(InstancePtr)) {
+		return XST_NOT_SGDMA;
+	}
+
+	/*
+	 * Set some descriptor control word defaults (source address increment
+	 * and local destination address) and the destination address
+	 * (the FIFO).  These are the same for every transmit descriptor.
+	 */
+	BdControl = XBufDescriptor_GetControl(BdPtr);
+	XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_SEND_BD_MASK);
+
+	XBufDescriptor_SetDestAddress(BdPtr,
+				      InstancePtr->BaseAddress +
+				      XEM_PFIFO_TXDATA_OFFSET);
+
+	/*
+	 * Put the descriptor in the send list. The DMA component accesses data
+	 * here that can also be modified in interrupt context, so a critical
+	 * section is required.
+	 */
+	XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
+
+	Result = XDmaChannel_PutDescriptor(&InstancePtr->SendChannel, BdPtr);
+	if (Result != XST_SUCCESS) {
+		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+		return Result;
+	}
+
+	/*
+	 * If this is the last buffer in the frame, commit the inserts and start
+	 * the DMA engine if necessary
+	 */
+	if (XBufDescriptor_IsLastControl(BdPtr)) {
+		Result = XDmaChannel_CommitPuts(&InstancePtr->SendChannel);
+		if (Result != XST_SUCCESS) {
+			XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+			return Result;
+		}
+
+		if (Delay == XEM_SGDMA_NODELAY) {
+			/*
+			 * Start the DMA channel. Ignore the return status since we know the
+			 * list exists and has at least one entry and we don't care if the
+			 * channel is already started.  The DMA component accesses data here
+			 * that can be modified at interrupt or task levels, so a critical
+			 * section is required.
+			 */
+			(void) XDmaChannel_SgStart(&InstancePtr->SendChannel);
+		}
+	}
+
+	XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Add a descriptor, with an attached empty buffer, into the receive descriptor
+* list. The buffer attached to the descriptor must be word-aligned. This is
+* used by the upper layer software during initialization when first setting up
+* the receive descriptors, and also during reception of frames to replace
+* filled buffers with empty buffers. This function can be called when the
+* device is started or stopped. Note that it does start the scatter-gather DMA
+* engine.  Although this is not necessary during initialization, it is not a
+* problem during initialization because the MAC receiver is not yet started.
+*
+* The buffer attached to the descriptor must be word-aligned on both the front
+* end and the back end.
+*
+* Notification of received frames are done asynchronously through the receive
+* callback function.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param BdPtr is a pointer to the buffer descriptor that will be added to the
+*        descriptor list.
+*
+* @return
+*
+* - XST_SUCCESS if a descriptor was successfully returned to the driver
+* - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode
+* - XST_DMA_SG_LIST_FULL if the receive descriptor list is full
+* - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into
+*   the list because a locked descriptor exists at the insert point.
+* - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the
+*   list, the DMA channel believes there are no new descriptors to commit.
+*
+* @internal
+*
+* A status that should never be returned from this function, although
+* the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device
+* requires a list to be created, and this function requires the device to be
+* started.
+*
+******************************************************************************/
+XStatus
+XEmac_SgRecv(XEmac * InstancePtr, XBufDescriptor * BdPtr)
+{
+	XStatus Result;
+	u32 BdControl;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BdPtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Be sure the device is configured for scatter-gather DMA
+	 */
+	if (!XEmac_mIsSgDma(InstancePtr)) {
+		return XST_NOT_SGDMA;
+	}
+
+	/*
+	 * Set some descriptor control word defaults (destination address increment
+	 * and local source address) and the source address (the FIFO). These are
+	 * the same for every receive descriptor.
+	 */
+	BdControl = XBufDescriptor_GetControl(BdPtr);
+	XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_RECV_BD_MASK);
+	XBufDescriptor_SetSrcAddress(BdPtr,
+				     InstancePtr->BaseAddress +
+				     XEM_PFIFO_RXDATA_OFFSET);
+
+	/*
+	 * Put the descriptor into the channel's descriptor list and commit.
+	 * Although this function is likely called within interrupt context, there
+	 * is the possibility that the upper layer software queues it to a task.
+	 * In this case, a critical section is needed here to protect shared data
+	 * in the DMA component.
+	 */
+	XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
+
+	Result = XDmaChannel_PutDescriptor(&InstancePtr->RecvChannel, BdPtr);
+	if (Result != XST_SUCCESS) {
+		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+		return Result;
+	}
+
+	Result = XDmaChannel_CommitPuts(&InstancePtr->RecvChannel);
+	if (Result != XST_SUCCESS) {
+		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+		return Result;
+	}
+
+	/*
+	 * Start the DMA channel. Ignore the return status since we know the list
+	 * exists and has at least one entry and we don't care if the channel is
+	 * already started. The DMA component accesses data here that can be
+	 * modified at interrupt or task levels, so a critical section is required.
+	 */
+	(void) XDmaChannel_SgStart(&InstancePtr->RecvChannel);
+
+	XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* The interrupt handler for the Ethernet driver when configured with scatter-
+* gather DMA.
+*
+* Get the interrupt status from the IpIf to determine the source of the
+* interrupt.  The source can be: MAC, Recv Packet FIFO, Send Packet FIFO, Recv
+* DMA channel, or Send DMA channel. The packet FIFOs only interrupt during
+* "deadlock" conditions.
+*
+* @param InstancePtr is a pointer to the XEmac instance that just interrupted.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XEmac_IntrHandlerDma(void *InstancePtr)
+{
+	u32 IntrStatus;
+	XEmac *EmacPtr = (XEmac *) InstancePtr;
+
+	EmacPtr->Stats.TotalIntrs++;
+
+	/*
+	 * Get the interrupt status from the IPIF. There is no clearing of
+	 * interrupts in the IPIF. Interrupts must be cleared at the source.
+	 */
+	IntrStatus = XIIF_V123B_READ_DIPR(EmacPtr->BaseAddress);
+
+	/*
+	 * See which type of interrupt is being requested, and service it
+	 */
+	if (IntrStatus & XEM_IPIF_RECV_DMA_MASK) {	/* Receive DMA interrupt */
+		EmacPtr->Stats.RecvInterrupts++;
+		HandleDmaRecvIntr(EmacPtr);
+	}
+
+	if (IntrStatus & XEM_IPIF_SEND_DMA_MASK) {	/* Send DMA interrupt */
+		EmacPtr->Stats.XmitInterrupts++;
+		HandleDmaSendIntr(EmacPtr);
+	}
+
+	if (IntrStatus & XEM_IPIF_EMAC_MASK) {	/* MAC interrupt */
+		EmacPtr->Stats.EmacInterrupts++;
+		HandleEmacDmaIntr(EmacPtr);
+	}
+
+	if (IntrStatus & XEM_IPIF_RECV_FIFO_MASK) {	/* Receive FIFO interrupt */
+		EmacPtr->Stats.RecvInterrupts++;
+		XEmac_CheckFifoRecvError(EmacPtr);
+	}
+
+	if (IntrStatus & XEM_IPIF_SEND_FIFO_MASK) {	/* Send FIFO interrupt */
+		EmacPtr->Stats.XmitInterrupts++;
+		XEmac_CheckFifoSendError(EmacPtr);
+	}
+
+	if (IntrStatus & XIIF_V123B_ERROR_MASK) {
+		/*
+		 * An error occurred internal to the IPIF. This is more of a debug and
+		 * integration issue rather than a production error. Don't do anything
+		 * other than clear it, which provides a spot for software to trap
+		 * on the interrupt and begin debugging.
+		 */
+		XIIF_V123B_WRITE_DISR(EmacPtr->BaseAddress,
+				      XIIF_V123B_ERROR_MASK);
+	}
+}
+
+/*****************************************************************************/
+/**
+*
+* Set the packet count threshold for this device. The device must be stopped
+* before setting the threshold. The packet count threshold is used for interrupt
+* coalescing, which reduces the frequency of interrupts from the device to the
+* processor. In this case, the scatter-gather DMA engine only interrupts when
+* the packet count threshold is reached, instead of interrupting for each packet.
+* A packet is a generic term used by the scatter-gather DMA engine, and is
+* equivalent to an Ethernet frame in our case.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param Direction indicates the channel, send or receive, from which the
+*        threshold register is read.
+* @param Threshold is the value of the packet threshold count used during
+*        interrupt coalescing. A value of 0 disables the use of packet threshold
+*        by the hardware.
+*
+* @return
+*
+* - XST_SUCCESS if the threshold was successfully set
+* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
+* - XST_DEVICE_IS_STARTED if the device has not been stopped
+* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
+*   asserts would also catch this error.
+*
+* @note
+*
+* The packet threshold could be set to larger than the number of descriptors
+* allocated to the DMA channel. In this case, the wait bound will take over
+* and always indicate data arrival. There was a check in this function that
+* returned an error if the treshold was larger than the number of descriptors,
+* but that was removed because users would then have to set the threshold
+* only after they set descriptor space, which is an order dependency that
+* caused confustion.
+*
+******************************************************************************/
+XStatus
+XEmac_SetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 Threshold)
+{
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Be sure device is configured for scatter-gather DMA and has been stopped
+	 */
+	if (!XEmac_mIsSgDma(InstancePtr)) {
+		return XST_NOT_SGDMA;
+	}
+
+	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STARTED;
+	}
+
+	/*
+	 * Based on the direction, set the packet threshold in the
+	 * corresponding DMA channel component.  Default to the receive
+	 * channel threshold register (if an invalid Direction is passed).
+	 */
+	switch (Direction) {
+	case XEM_SEND:
+		return XDmaChannel_SetPktThreshold(&InstancePtr->SendChannel,
+						   Threshold);
+
+	case XEM_RECV:
+		return XDmaChannel_SetPktThreshold(&InstancePtr->RecvChannel,
+						   Threshold);
+
+	default:
+		return XST_INVALID_PARAM;
+	}
+}
+
+/*****************************************************************************/
+/**
+*
+* Get the value of the packet count threshold for this driver/device. The packet
+* count threshold is used for interrupt coalescing, which reduces the frequency
+* of interrupts from the device to the processor. In this case, the
+* scatter-gather DMA engine only interrupts when the packet count threshold is
+* reached, instead of interrupting for each packet. A packet is a generic term
+* used by the scatter-gather DMA engine, and is equivalent to an Ethernet frame
+* in our case.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param Direction indicates the channel, send or receive, from which the
+*        threshold register is read.
+* @param ThreshPtr is a pointer to the byte into which the current value of the
+*        packet threshold register will be copied. An output parameter. A value
+*        of 0 indicates the use of packet threshold by the hardware is disabled.
+*
+* @return
+*
+* - XST_SUCCESS if the packet threshold was retrieved successfully
+* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
+* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
+*   asserts would also catch this error.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XEmac_GetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 * ThreshPtr)
+{
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
+	XASSERT_NONVOID(ThreshPtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	if (!XEmac_mIsSgDma(InstancePtr)) {
+		return XST_NOT_SGDMA;
+	}
+
+	/*
+	 * Based on the direction, return the packet threshold set in the
+	 * corresponding DMA channel component.  Default to the value in
+	 * the receive channel threshold register (if an invalid Direction
+	 * is passed).
+	 */
+	switch (Direction) {
+	case XEM_SEND:
+		*ThreshPtr =
+		    XDmaChannel_GetPktThreshold(&InstancePtr->SendChannel);
+		break;
+
+	case XEM_RECV:
+		*ThreshPtr =
+		    XDmaChannel_GetPktThreshold(&InstancePtr->RecvChannel);
+		break;
+
+	default:
+		return XST_INVALID_PARAM;
+	}
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Set the packet wait bound timer for this driver/device. The device must be
+* stopped before setting the timer value. The packet wait bound is used during
+* interrupt coalescing to trigger an interrupt when not enough packets have been
+* received to reach the packet count threshold. A packet is a generic term used
+* by the scatter-gather DMA engine, and is equivalent to an Ethernet frame in
+* our case. The timer is in milliseconds.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param Direction indicates the channel, send or receive, from which the
+*        threshold register is read.
+* @param TimerValue is the value of the packet wait bound used during interrupt
+*        coalescing. It is in milliseconds in the range 0  - 1023. A value of 0
+*        disables the packet wait bound timer.
+*
+* @return
+*
+* - XST_SUCCESS if the packet wait bound was set successfully
+* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
+* - XST_DEVICE_IS_STARTED if the device has not been stopped
+* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
+*   asserts would also catch this error.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XEmac_SetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 TimerValue)
+{
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
+	XASSERT_NONVOID(TimerValue <= XEM_SGDMA_MAX_WAITBOUND);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Be sure device is configured for scatter-gather DMA and has been stopped
+	 */
+	if (!XEmac_mIsSgDma(InstancePtr)) {
+		return XST_NOT_SGDMA;
+	}
+
+	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STARTED;
+	}
+
+	/*
+	 * Based on the direction, set the packet wait bound in the
+	 * corresponding DMA channel component.  Default to the receive
+	 * channel wait bound register (if an invalid Direction is passed).
+	 */
+	switch (Direction) {
+	case XEM_SEND:
+		XDmaChannel_SetPktWaitBound(&InstancePtr->SendChannel,
+					    TimerValue);
+		break;
+
+	case XEM_RECV:
+		XDmaChannel_SetPktWaitBound(&InstancePtr->RecvChannel,
+					    TimerValue);
+		break;
+
+	default:
+		return XST_INVALID_PARAM;
+	}
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Get the packet wait bound timer for this driver/device. The packet wait bound
+* is used during interrupt coalescing to trigger an interrupt when not enough
+* packets have been received to reach the packet count threshold. A packet is a
+* generic term used by the scatter-gather DMA engine, and is equivalent to an
+* Ethernet frame in our case. The timer is in milliseconds.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param Direction indicates the channel, send or receive, from which the
+*        threshold register is read.
+* @param WaitPtr is a pointer to the byte into which the current value of the
+*        packet wait bound register will be copied. An output parameter. Units
+*        are in milliseconds in the range 0  - 1023. A value of 0 indicates the
+*        packet wait bound timer is disabled.
+*
+* @return
+*
+* - XST_SUCCESS if the packet wait bound was retrieved successfully
+* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
+* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
+*   asserts would also catch this error.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XEmac_GetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 * WaitPtr)
+{
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
+	XASSERT_NONVOID(WaitPtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	if (!XEmac_mIsSgDma(InstancePtr)) {
+		return XST_NOT_SGDMA;
+	}
+
+	/*
+	 * Based on the direction, return the packet wait bound set in the
+	 * corresponding DMA channel component.  Default to the value in
+	 * the receive channel wait bound register (if an invalid Direction
+	 * is passed).
+	 */
+	switch (Direction) {
+	case XEM_SEND:
+		*WaitPtr =
+		    XDmaChannel_GetPktWaitBound(&InstancePtr->SendChannel);
+		break;
+
+	case XEM_RECV:
+		*WaitPtr =
+		    XDmaChannel_GetPktWaitBound(&InstancePtr->RecvChannel);
+		break;
+
+	default:
+		return XST_INVALID_PARAM;
+	}
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Give the driver the memory space to be used for the scatter-gather DMA
+* receive descriptor list. This function should only be called once, during
+* initialization of the Ethernet driver. The memory space must be big enough
+* to hold some number of descriptors, depending on the needs of the system.
+* The xemac.h file defines minimum and default numbers of descriptors
+* which can be used to allocate this memory space.
+*
+* The memory space must be word-aligned. An assert will occur if asserts are
+* turned on and the memory is not word-aligned.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param MemoryPtr is a pointer to the word-aligned memory.
+* @param ByteCount is the length, in bytes, of the memory space.
+*
+* @return
+*
+* - XST_SUCCESS if the space was initialized successfully
+* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
+* - XST_DMA_SG_LIST_EXISTS if this list space has already been created
+*
+* @note
+*
+* If the device is configured for scatter-gather DMA, this function must be
+* called AFTER the XEmac_Initialize() function because the DMA channel
+* components must be initialized before the memory space is set.
+*
+******************************************************************************/
+XStatus
+XEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount)
+{
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(MemoryPtr != NULL);
+	XASSERT_NONVOID(ByteCount != 0);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	if (!XEmac_mIsSgDma(InstancePtr)) {
+		return XST_NOT_SGDMA;
+	}
+
+	return XDmaChannel_CreateSgList(&InstancePtr->RecvChannel, MemoryPtr,
+					ByteCount);
+}
+
+/*****************************************************************************/
+/**
+*
+* Give the driver the memory space to be used for the scatter-gather DMA
+* transmit descriptor list. This function should only be called once, during
+* initialization of the Ethernet driver. The memory space must be big enough
+* to hold some number of descriptors, depending on the needs of the system.
+* The xemac.h file defines minimum and default numbers of descriptors
+* which can be used to allocate this memory space.
+*
+* The memory space must be word-aligned. An assert will occur if asserts are
+* turned on and the memory is not word-aligned.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param MemoryPtr is a pointer to the word-aligned memory.
+* @param ByteCount is the length, in bytes, of the memory space.
+*
+* @return
+*
+* - XST_SUCCESS if the space was initialized successfully
+* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
+* - XST_DMA_SG_LIST_EXISTS if this list space has already been created
+*
+* @note
+*
+* If the device is configured for scatter-gather DMA, this function must be
+* called AFTER the XEmac_Initialize() function because the DMA channel
+* components must be initialized before the memory space is set.
+*
+******************************************************************************/
+XStatus
+XEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount)
+{
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(MemoryPtr != NULL);
+	XASSERT_NONVOID(ByteCount != 0);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	if (!XEmac_mIsSgDma(InstancePtr)) {
+		return XST_NOT_SGDMA;
+	}
+
+	return XDmaChannel_CreateSgList(&InstancePtr->SendChannel, MemoryPtr,
+					ByteCount);
+}
+
+/*****************************************************************************/
+/**
+*
+* Set the callback function for handling received frames in scatter-gather DMA
+* mode.  The upper layer software should call this function during
+* initialization.  The callback is called once per frame received. The head of
+* a descriptor list is passed in along with the number of descriptors in the
+* list. Before leaving the callback, the upper layer software should attach a
+* new buffer to each descriptor in the list.
+*
+* The callback is invoked by the driver within interrupt context, so it needs
+* to do its job quickly. Sending the received frame up the protocol stack
+* should be done at task-level. If there are other potentially slow operations
+* within the callback, these too should be done at task-level.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param CallBackRef is a reference pointer to be passed back to the adapter in
+*        the callback. This helps the adapter correlate the callback to a
+*        particular driver.
+* @param FuncPtr is the pointer to the callback function.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef,
+		       XEmac_SgHandler FuncPtr)
+{
+	/*
+	 * Asserted IsDmaSg here instead of run-time check because there is really
+	 * no ill-effects of setting these when not configured for scatter-gather.
+	 */
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(FuncPtr != NULL);
+	XASSERT_VOID(XEmac_mIsSgDma(InstancePtr));
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	InstancePtr->SgRecvHandler = FuncPtr;
+	InstancePtr->SgRecvRef = CallBackRef;
+}
+
+/*****************************************************************************/
+/**
+*
+* Set the callback function for handling confirmation of transmitted frames in
+* scatter-gather DMA mode.  The upper layer software should call this function
+* during initialization.  The callback is called once per frame sent. The head
+* of a descriptor list is passed in along with the number of descriptors in
+* the list. The callback is responsible for freeing buffers attached to these
+* descriptors.
+*
+* The callback is invoked by the driver within interrupt context, so it needs
+* to do its job quickly. If there are potentially slow operations within the
+* callback, these should be done at task-level.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param CallBackRef is a reference pointer to be passed back to the adapter in
+*        the callback. This helps the adapter correlate the callback to a
+*        particular driver.
+* @param FuncPtr is the pointer to the callback function.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void
+XEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef,
+		       XEmac_SgHandler FuncPtr)
+{
+	/*
+	 * Asserted IsDmaSg here instead of run-time check because there is really
+	 * no ill-effects of setting these when not configured for scatter-gather.
+	 */
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(FuncPtr != NULL);
+	XASSERT_VOID(XEmac_mIsSgDma(InstancePtr));
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	InstancePtr->SgSendHandler = FuncPtr;
+	InstancePtr->SgSendRef = CallBackRef;
+}
+
+/*****************************************************************************/
+/*
+*
+* Handle an interrupt from the DMA receive channel. DMA interrupts are:
+*
+* - DMA error. DMA encountered a bus error or timeout. This is a fatal error
+*   that requires reset of the channel.  The driver calls the error handler
+*   of the upper layer software with an error code indicating the device should
+*   be reset.
+* - Packet count threshold reached.  For scatter-gather operations, indicates
+*   the threshold for the number of packets not serviced by software has been
+*   reached. The driver behaves as follows:
+*       - Get the value of the packet counter, which tells us how many packets
+*         are ready to be serviced
+*       - For each packet
+*           - For each descriptor, remove it from the scatter-gather list
+*           - Check for the last descriptor in the frame, and if set
+*               - Bump frame statistics
+*               - Call the scatter-gather receive callback function
+*               - Decrement the packet counter by one
+*       Note that there are no receive errors reported in the status word of
+*       the buffer descriptor.  If receive errors occur, the MAC drops the
+*       packet, and we only find out about the errors through various error
+*       count registers.
+* - Packet wait bound reached.  For scatter-gather, indicates the time to wait
+*   for the next packet has expired.  The driver follows the same logic as when
+*   the packet count threshold interrupt is received.
+* - Scatter-gather end acknowledge.  Hardware has reached the end of the
+*   descriptor list.  The driver follows the same logic as when the packet count
+*   threshold interrupt is received. In addition, the driver restarts the DMA
+*   scatter-gather channel in case there are newly inserted descriptors.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* Although the function returns void, there are asynchronous errors that can
+* be generated (by calling the ErrorHandler) from this function.  These are:
+* - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from the
+*   DMA channel, but there was not one ready for software.
+* - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a fatal
+*   error that requires reset.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static void
+HandleDmaRecvIntr(XEmac * InstancePtr)
+{
+	u32 IntrStatus;
+
+	/*
+	 * Read the interrupt status
+	 */
+	IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->RecvChannel);
+
+	/*
+	 * For packet threshold or wait bound interrupts, process desciptors. Also
+	 * process descriptors on a SG end acknowledgement, which means the end of
+	 * the descriptor list has been reached by the hardware. For receive, this
+	 * is potentially trouble since it means the descriptor list is full,
+	 * unless software can process enough packets quickly enough so the
+	 * hardware has room to put new packets.
+	 */
+	if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK |
+			  XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) {
+		XStatus Result = XST_SUCCESS;
+		u32 NumFrames;
+		u32 NumProcessed;
+		u32 NumBuffers;
+		u32 NumBytes;
+		u32 IsLast;
+		XBufDescriptor *FirstBdPtr;
+		XBufDescriptor *BdPtr;
+
+		/*
+		 * Get the number of unserviced packets
+		 */
+		NumFrames = XDmaChannel_GetPktCount(&InstancePtr->RecvChannel);
+
+		for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) {
+			IsLast = FALSE;
+			FirstBdPtr = NULL;
+			NumBuffers = 0;
+			NumBytes = 0;
+
+			/*
+			 * For each packet, get the descriptor from the list. On the
+			 * last one in the frame, make the callback to the upper layer.
+			 */
+			while (!IsLast) {
+				Result =
+				    XDmaChannel_GetDescriptor(&InstancePtr->
+							      RecvChannel,
+							      &BdPtr);
+				if (Result != XST_SUCCESS) {
+					/*
+					 * An error getting a buffer descriptor from the list.
+					 * This should not happen, but if it does, report it to
+					 * the error callback and break out of the loops to service
+					 * other interrupts.
+					 */
+					InstancePtr->ErrorHandler(InstancePtr->
+								  ErrorRef,
+								  Result);
+					break;
+				}
+
+				/*
+				 * Keep a pointer to the first descriptor in the list, as it
+				 * will be passed to the upper layers in a bit. By the fact
+				 * that we received this packet means no errors occurred, so
+				 * no need to check the device status word for errors.
+				 */
+				if (FirstBdPtr == NULL) {
+					FirstBdPtr = BdPtr;
+				}
+
+				NumBytes += XBufDescriptor_GetLength(BdPtr);
+
+				/*
+				 * Check to see if this is the last descriptor in the frame,
+				 * and if so, set the IsLast flag to get out of the loop.
+				 */
+				if (XBufDescriptor_IsLastStatus(BdPtr)) {
+					IsLast = TRUE;
+				}
+
+				/*
+				 * Bump the number of buffers in this packet
+				 */
+				NumBuffers++;
+
+			}	/* end while loop */
+
+			/*
+			 * Check for error that occurred inside the while loop, and break
+			 * out of the for loop if there was one so other interrupts can
+			 * be serviced.
+			 */
+			if (Result != XST_SUCCESS) {
+				break;
+			}
+
+			InstancePtr->Stats.RecvFrames++;
+			InstancePtr->Stats.RecvBytes += NumBytes;
+
+			/*
+			 * Make the callback to the upper layers, passing it the first
+			 * descriptor in the packet and the number of descriptors in the
+			 * packet.
+			 */
+			InstancePtr->SgRecvHandler(InstancePtr->SgRecvRef,
+						   FirstBdPtr, NumBuffers);
+
+			/*
+			 * Decrement the packet count register to reflect the fact we
+			 * just processed a packet
+			 */
+			XDmaChannel_DecrementPktCount(&InstancePtr->
+						      RecvChannel);
+
+		}		/* end for loop */
+
+		/*
+		 * If the interrupt was an end-ack, check the descriptor list again to
+		 * see if it is empty. If not, go ahead and restart the scatter-gather
+		 * channel. This is to fix a possible race condition where, on receive,
+		 * the driver attempted to start a scatter-gather channel that was
+		 * already started, which resulted in no action from the XDmaChannel
+		 * component. But, just after the XDmaChannel component saw that the
+		 * hardware was already started, the hardware stopped because it
+		 * reached the end of the list.  In that case, this interrupt is
+		 * generated and we can restart the hardware here.
+		 */
+		if (IntrStatus & XDC_IXR_SG_END_MASK) {
+			/*
+			 * Ignore the return status since we know the list exists and we
+			 * don't care if the list is empty or the channel is already started.
+			 */
+			(void) XDmaChannel_SgStart(&InstancePtr->RecvChannel);
+		}
+	}
+
+	/*
+	 * All interrupts are handled (except the error below) so acknowledge
+	 * (clear) the interrupts by writing the value read above back to the status
+	 * register. The packet count interrupt must be acknowledged after the
+	 * decrement, otherwise it will come right back. We clear the interrupts
+	 * before we handle the error interrupt because the ErrorHandler should
+	 * result in a reset, which clears the interrupt status register. So we
+	 * don't want to toggle the interrupt back on by writing the interrupt
+	 * status register with an old value after a reset.
+	 */
+	XDmaChannel_SetIntrStatus(&InstancePtr->RecvChannel, IntrStatus);
+
+	/*
+	 * Check for DMA errors and call the error callback function if an error
+	 * occurred (DMA bus or timeout error), which should result in a reset of
+	 * the device by the upper layer software.
+	 */
+	if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) {
+		InstancePtr->Stats.DmaErrors++;
+		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);
+	}
+}
+
+/*****************************************************************************/
+/*
+*
+* Handle an interrupt from the DMA send channel. DMA interrupts are:
+*
+* - DMA error. DMA encountered a bus error or timeout. This is a fatal error
+*   that requires reset of the channel.  The driver calls the error handler
+*   of the upper layer software with an error code indicating the device should
+*   be reset.
+* - Packet count threshold reached.  For scatter-gather operations, indicates
+*   the threshold for the number of packets not serviced by software has been
+*   reached. The driver behaves as follows:
+*       - Get the value of the packet counter, which tells us how many packets
+*         are ready to be serviced
+*       - For each packet
+*           - For each descriptor, remove it from the scatter-gather list
+*           - Check for the last descriptor in the frame, and if set
+*               - Bump frame statistics
+*               - Call the scatter-gather receive callback function
+*               - Decrement the packet counter by one
+*       Note that there are no receive errors reported in the status word of
+*       the buffer descriptor.  If receive errors occur, the MAC drops the
+*       packet, and we only find out about the errors through various error
+*       count registers.
+* - Packet wait bound reached.  For scatter-gather, indicates the time to wait
+*   for the next packet has expired.  The driver follows the same logic as when
+*   the packet count threshold interrupt is received.
+* - Scatter-gather end acknowledge.  Hardware has reached the end of the
+*   descriptor list.  The driver follows the same logic as when the packet count
+*   threshold interrupt is received. In addition, the driver restarts the DMA
+*   scatter-gather channel in case there are newly inserted descriptors.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* Although the function returns void, there are asynchronous errors
+* that can be generated from this function.  These are:
+* - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from
+*   the DMA channel, but there was not one ready for software.
+* - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a
+*   fatal error that requires reset.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static void
+HandleDmaSendIntr(XEmac * InstancePtr)
+{
+	u32 IntrStatus;
+
+	/*
+	 * Read the interrupt status
+	 */
+	IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->SendChannel);
+
+	/*
+	 * For packet threshold or wait bound interrupt, process descriptors. Also
+	 * process descriptors on a SG end acknowledgement, which means the end of
+	 * the descriptor list has been reached by the hardware. For transmit,
+	 * this is a normal condition during times of light traffic.  In fact, the
+	 * wait bound interrupt may be masked for transmit since the end-ack would
+	 * always occur before the wait bound expires.
+	 */
+	if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK |
+			  XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) {
+		XStatus Result = XST_SUCCESS;
+		u32 NumFrames;
+		u32 NumProcessed;
+		u32 NumBuffers;
+		u32 NumBytes;
+		u32 IsLast;
+		XBufDescriptor *FirstBdPtr;
+		XBufDescriptor *BdPtr;
+
+		/*
+		 * Get the number of unserviced packets
+		 */
+		NumFrames = XDmaChannel_GetPktCount(&InstancePtr->SendChannel);
+
+		for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) {
+			IsLast = FALSE;
+			FirstBdPtr = NULL;
+			NumBuffers = 0;
+			NumBytes = 0;
+
+			/*
+			 * For each frame, traverse the descriptor list and look for
+			 * errors. On the last one in the frame, make the callback.
+			 */
+			while (!IsLast) {
+				Result =
+				    XDmaChannel_GetDescriptor(&InstancePtr->
+							      SendChannel,
+							      &BdPtr);
+				if (Result != XST_SUCCESS) {
+					/*
+					 * An error getting a buffer descriptor from the list.
+					 * This should not happen, but if it does, report it to
+					 * the error callback and break out of the loops to service
+					 * other interrupts
+					 */
+					InstancePtr->ErrorHandler(InstancePtr->
+								  ErrorRef,
+								  Result);
+					break;
+				}
+
+				/*
+				 * Keep a pointer to the first descriptor in the list and
+				 * check the device status for errors. The device status is
+				 * only available in the first descriptor of a packet.
+				 */
+				if (FirstBdPtr == NULL) {
+					u32 XmitStatus;
+
+					FirstBdPtr = BdPtr;
+
+					XmitStatus =
+					    XBufDescriptor_GetDeviceStatus
+					    (BdPtr);
+					if (XmitStatus &
+					    XEM_TSR_EXCESS_DEFERRAL_MASK) {
+						InstancePtr->Stats.
+						    XmitExcessDeferral++;
+					}
+
+					if (XmitStatus &
+					    XEM_TSR_LATE_COLLISION_MASK) {
+						InstancePtr->Stats.
+						    XmitLateCollisionErrors++;
+					}
+				}
+
+				NumBytes += XBufDescriptor_GetLength(BdPtr);
+
+				/*
+				 * Check to see if this is the last descriptor in the frame,
+				 * and if so, set the IsLast flag to get out of the loop. The
+				 * transmit channel must check the last bit in the control
+				 * word, not the status word (the DMA engine does not update
+				 * the last bit in the status word for the transmit direction).
+				 */
+				if (XBufDescriptor_IsLastControl(BdPtr)) {
+					IsLast = TRUE;
+				}
+
+				/*
+				 * Bump the number of buffers in this packet
+				 */
+				NumBuffers++;
+
+			}	/* end while loop */
+
+			/*
+			 * Check for error that occurred inside the while loop, and break
+			 * out of the for loop if there was one so other interrupts can
+			 * be serviced.
+			 */
+			if (Result != XST_SUCCESS) {
+				break;
+			}
+
+			InstancePtr->Stats.XmitFrames++;
+			InstancePtr->Stats.XmitBytes += NumBytes;
+
+			/*
+			 * Make the callback to the upper layers, passing it the first
+			 * descriptor in the packet and the number of descriptors in the
+			 * packet.
+			 */
+			InstancePtr->SgSendHandler(InstancePtr->SgSendRef,
+						   FirstBdPtr, NumBuffers);
+
+			/*
+			 * Decrement the packet count register to reflect the fact we
+			 * just processed a packet
+			 */
+			XDmaChannel_DecrementPktCount(&InstancePtr->
+						      SendChannel);
+
+		}		/* end for loop */
+
+		/*
+		 * If the interrupt was an end-ack, check the descriptor list again to
+		 * see if it is empty. If not, go ahead and restart the scatter-gather
+		 * channel. This is to fix a possible race condition where, on transmit,
+		 * the driver attempted to start a scatter-gather channel that was
+		 * already started, which resulted in no action from the XDmaChannel
+		 * component. But, just after the XDmaChannel component saw that the
+		 * hardware was already started, the hardware stopped because it
+		 * reached the end of the list.  In that case, this interrupt is
+		 * generated and we can restart the hardware here.
+		 */
+		if (IntrStatus & XDC_IXR_SG_END_MASK) {
+			/*
+			 * Ignore the return status since we know the list exists and we
+			 * don't care if the list is empty or the channel is already started.
+			 */
+			(void) XDmaChannel_SgStart(&InstancePtr->SendChannel);
+		}
+	}
+
+	/*
+	 * All interrupts are handled (except the error below) so acknowledge
+	 * (clear) the interrupts by writing the value read above back to the status
+	 * register. The packet count interrupt must be acknowledged after the
+	 * decrement, otherwise it will come right back. We clear the interrupts
+	 * before we handle the error interrupt because the ErrorHandler should
+	 * result in a reset, which clears the interrupt status register. So we
+	 * don't want to toggle the interrupt back on by writing the interrupt
+	 * status register with an old value after a reset.
+	 */
+	XDmaChannel_SetIntrStatus(&InstancePtr->SendChannel, IntrStatus);
+
+	/*
+	 * Check for DMA errors and call the error callback function if an error
+	 * occurred (DMA bus or timeout error), which should result in a reset of
+	 * the device by the upper layer software.
+	 */
+	if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) {
+		InstancePtr->Stats.DmaErrors++;
+		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);
+	}
+}
+
+/*****************************************************************************/
+/*
+*
+* Handle an interrupt from the Ethernet MAC when configured with scatter-gather
+* DMA. The only interrupts handled in this case are errors.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+static void
+HandleEmacDmaIntr(XEmac * InstancePtr)
+{
+	u32 IntrStatus;
+
+	/*
+	 * When configured with DMA, the EMAC generates interrupts only when errors
+	 * occur. We clear the interrupts immediately so that any latched status
+	 * interrupt bits will reflect the true status of the device, and so any
+	 * pulsed interrupts (non-status) generated during the Isr will not be lost.
+	 */
+	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
+	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus);
+
+	/*
+	 * Check the MAC for errors
+	 */
+	XEmac_CheckEmacError(InstancePtr, IntrStatus);
+}

+ 462 - 0
board/xilinx/xilinx_enet/xemac_l.h

@@ -0,0 +1,462 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemac_l.h
+*
+* This header file contains identifiers and low-level driver functions (or
+* macros) that can be used to access the device.  High-level driver functions
+* are defined in xemac.h.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver	Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b rpm  04/26/02 First release
+* 1.00b rmm  09/23/02 Added XEmac_mPhyReset macro
+* 1.00c rpm  12/05/02 New version includes support for simple DMA
+* </pre>
+*
+******************************************************************************/
+
+#ifndef XEMAC_L_H		/* prevent circular inclusions */
+#define XEMAC_L_H		/* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xio.h"
+
+/************************** Constant Definitions *****************************/
+
+/* Offset of the MAC registers from the IPIF base address */
+#define XEM_REG_OFFSET	   0x1100UL
+
+/*
+ * Register offsets for the Ethernet MAC. Each register is 32 bits.
+ */
+#define XEM_EMIR_OFFSET	  (XEM_REG_OFFSET + 0x0)	/* EMAC Module ID */
+#define XEM_ECR_OFFSET	  (XEM_REG_OFFSET + 0x4)	/* MAC Control */
+#define XEM_IFGP_OFFSET	  (XEM_REG_OFFSET + 0x8)	/* Interframe Gap */
+#define XEM_SAH_OFFSET	  (XEM_REG_OFFSET + 0xC)	/* Station addr, high */
+#define XEM_SAL_OFFSET	  (XEM_REG_OFFSET + 0x10)	/* Station addr, low */
+#define XEM_MGTCR_OFFSET  (XEM_REG_OFFSET + 0x14)	/* MII mgmt control */
+#define XEM_MGTDR_OFFSET  (XEM_REG_OFFSET + 0x18)	/* MII mgmt data */
+#define XEM_RPLR_OFFSET	  (XEM_REG_OFFSET + 0x1C)	/* Rx packet length */
+#define XEM_TPLR_OFFSET	  (XEM_REG_OFFSET + 0x20)	/* Tx packet length */
+#define XEM_TSR_OFFSET	  (XEM_REG_OFFSET + 0x24)	/* Tx status */
+#define XEM_RMFC_OFFSET	  (XEM_REG_OFFSET + 0x28)	/* Rx missed frames */
+#define XEM_RCC_OFFSET	  (XEM_REG_OFFSET + 0x2C)	/* Rx collisions */
+#define XEM_RFCSEC_OFFSET (XEM_REG_OFFSET + 0x30)	/* Rx FCS errors */
+#define XEM_RAEC_OFFSET	  (XEM_REG_OFFSET + 0x34)	/* Rx alignment errors */
+#define XEM_TEDC_OFFSET	  (XEM_REG_OFFSET + 0x38)	/* Transmit excess
+							 * deferral cnt */
+
+/*
+ * Register offsets for the IPIF components
+ */
+#define XEM_ISR_OFFSET		 0x20UL /* Interrupt status */
+
+#define XEM_DMA_OFFSET		 0x2300UL
+#define XEM_DMA_SEND_OFFSET	 (XEM_DMA_OFFSET + 0x0) /* DMA send channel */
+#define XEM_DMA_RECV_OFFSET	 (XEM_DMA_OFFSET + 0x40)	/* DMA recv channel */
+
+#define XEM_PFIFO_OFFSET	 0x2000UL
+#define XEM_PFIFO_TXREG_OFFSET	 (XEM_PFIFO_OFFSET + 0x0)	/* Tx registers */
+#define XEM_PFIFO_RXREG_OFFSET	 (XEM_PFIFO_OFFSET + 0x10)	/* Rx registers */
+#define XEM_PFIFO_TXDATA_OFFSET	 (XEM_PFIFO_OFFSET + 0x100)	/* Tx keyhole */
+#define XEM_PFIFO_RXDATA_OFFSET	 (XEM_PFIFO_OFFSET + 0x200)	/* Rx keyhole */
+
+/*
+ * EMAC Module Identification Register (EMIR)
+ */
+#define XEM_EMIR_VERSION_MASK	 0xFFFF0000UL	/* Device version */
+#define XEM_EMIR_TYPE_MASK	 0x0000FF00UL	/* Device type */
+
+/*
+ * EMAC Control Register (ECR)
+ */
+#define XEM_ECR_FULL_DUPLEX_MASK	 0x80000000UL	/* Full duplex mode */
+#define XEM_ECR_XMIT_RESET_MASK		 0x40000000UL	/* Reset transmitter */
+#define XEM_ECR_XMIT_ENABLE_MASK	 0x20000000UL	/* Enable transmitter */
+#define XEM_ECR_RECV_RESET_MASK		 0x10000000UL	/* Reset receiver */
+#define XEM_ECR_RECV_ENABLE_MASK	 0x08000000UL	/* Enable receiver */
+#define XEM_ECR_PHY_ENABLE_MASK		 0x04000000UL	/* Enable PHY */
+#define XEM_ECR_XMIT_PAD_ENABLE_MASK	 0x02000000UL	/* Enable xmit pad insert */
+#define XEM_ECR_XMIT_FCS_ENABLE_MASK	 0x01000000UL	/* Enable xmit FCS insert */
+#define XEM_ECR_XMIT_ADDR_INSERT_MASK	 0x00800000UL	/* Enable xmit source addr
+							 * insertion */
+#define XEM_ECR_XMIT_ERROR_INSERT_MASK	 0x00400000UL	/* Insert xmit error */
+#define XEM_ECR_XMIT_ADDR_OVWRT_MASK	 0x00200000UL	/* Enable xmit source addr
+							 * overwrite */
+#define XEM_ECR_LOOPBACK_MASK		 0x00100000UL	/* Enable internal
+							 * loopback */
+#define XEM_ECR_RECV_STRIP_ENABLE_MASK	 0x00080000UL	/* Enable recv pad/fcs strip */
+#define XEM_ECR_UNICAST_ENABLE_MASK	 0x00020000UL	/* Enable unicast addr */
+#define XEM_ECR_MULTI_ENABLE_MASK	 0x00010000UL	/* Enable multicast addr */
+#define XEM_ECR_BROAD_ENABLE_MASK	 0x00008000UL	/* Enable broadcast addr */
+#define XEM_ECR_PROMISC_ENABLE_MASK	 0x00004000UL	/* Enable promiscuous mode */
+#define XEM_ECR_RECV_ALL_MASK		 0x00002000UL	/* Receive all frames */
+#define XEM_ECR_RESERVED2_MASK		 0x00001000UL	/* Reserved */
+#define XEM_ECR_MULTI_HASH_ENABLE_MASK	 0x00000800UL	/* Enable multicast hash */
+#define XEM_ECR_PAUSE_FRAME_MASK	 0x00000400UL	/* Interpret pause frames */
+#define XEM_ECR_CLEAR_HASH_MASK		 0x00000200UL	/* Clear hash table */
+#define XEM_ECR_ADD_HASH_ADDR_MASK	 0x00000100UL	/* Add hash table address */
+
+/*
+ * Interframe Gap Register (IFGR)
+ */
+#define XEM_IFGP_PART1_MASK	    0xF8000000UL	/* Interframe Gap Part1 */
+#define XEM_IFGP_PART1_SHIFT	    27
+#define XEM_IFGP_PART2_MASK	    0x07C00000UL	/* Interframe Gap Part2 */
+#define XEM_IFGP_PART2_SHIFT	    22
+
+/*
+ * Station Address High Register (SAH)
+ */
+#define XEM_SAH_ADDR_MASK	    0x0000FFFFUL	/* Station address high bytes */
+
+/*
+ * Station Address Low Register (SAL)
+ */
+#define XEM_SAL_ADDR_MASK	    0xFFFFFFFFUL	/* Station address low bytes */
+
+/*
+ * MII Management Control Register (MGTCR)
+ */
+#define XEM_MGTCR_START_MASK	    0x80000000UL	/* Start/Busy */
+#define XEM_MGTCR_RW_NOT_MASK	    0x40000000UL	/* Read/Write Not (direction) */
+#define XEM_MGTCR_PHY_ADDR_MASK	    0x3E000000UL	/* PHY address */
+#define XEM_MGTCR_PHY_ADDR_SHIFT    25	/* PHY address shift */
+#define XEM_MGTCR_REG_ADDR_MASK	    0x01F00000UL	/* Register address */
+#define XEM_MGTCR_REG_ADDR_SHIFT    20	/* Register addr shift */
+#define XEM_MGTCR_MII_ENABLE_MASK   0x00080000UL	/* Enable MII from EMAC */
+#define XEM_MGTCR_RD_ERROR_MASK	    0x00040000UL	/* MII mgmt read error */
+
+/*
+ * MII Management Data Register (MGTDR)
+ */
+#define XEM_MGTDR_DATA_MASK	    0x0000FFFFUL	/* MII data */
+
+/*
+ * Receive Packet Length Register (RPLR)
+ */
+#define XEM_RPLR_LENGTH_MASK	    0x0000FFFFUL	/* Receive packet length */
+
+/*
+ * Transmit Packet Length Register (TPLR)
+ */
+#define XEM_TPLR_LENGTH_MASK	    0x0000FFFFUL	/* Transmit packet length */
+
+/*
+ * Transmit Status Register (TSR)
+ */
+#define XEM_TSR_EXCESS_DEFERRAL_MASK 0x80000000UL	/* Transmit excess deferral */
+#define XEM_TSR_FIFO_UNDERRUN_MASK   0x40000000UL	/* Packet FIFO underrun */
+#define XEM_TSR_ATTEMPTS_MASK	     0x3E000000UL	/* Transmission attempts */
+#define XEM_TSR_LATE_COLLISION_MASK  0x01000000UL	/* Transmit late collision */
+
+/*
+ * Receive Missed Frame Count (RMFC)
+ */
+#define XEM_RMFC_DATA_MASK	    0x0000FFFFUL
+
+/*
+ * Receive Collision Count (RCC)
+ */
+#define XEM_RCC_DATA_MASK	    0x0000FFFFUL
+
+/*
+ * Receive FCS Error Count (RFCSEC)
+ */
+#define XEM_RFCSEC_DATA_MASK	    0x0000FFFFUL
+
+/*
+ * Receive Alignment Error Count (RALN)
+ */
+#define XEM_RAEC_DATA_MASK	    0x0000FFFFUL
+
+/*
+ * Transmit Excess Deferral Count (TEDC)
+ */
+#define XEM_TEDC_DATA_MASK	    0x0000FFFFUL
+
+/*
+ * EMAC Interrupt Registers (Status and Enable) masks. These registers are
+ * part of the IPIF IP Interrupt registers
+ */
+#define XEM_EIR_XMIT_DONE_MASK	       0x00000001UL	/* Xmit complete */
+#define XEM_EIR_RECV_DONE_MASK	       0x00000002UL	/* Recv complete */
+#define XEM_EIR_XMIT_ERROR_MASK	       0x00000004UL	/* Xmit error */
+#define XEM_EIR_RECV_ERROR_MASK	       0x00000008UL	/* Recv error */
+#define XEM_EIR_XMIT_SFIFO_EMPTY_MASK  0x00000010UL	/* Xmit status fifo empty */
+#define XEM_EIR_RECV_LFIFO_EMPTY_MASK  0x00000020UL	/* Recv length fifo empty */
+#define XEM_EIR_XMIT_LFIFO_FULL_MASK   0x00000040UL	/* Xmit length fifo full */
+#define XEM_EIR_RECV_LFIFO_OVER_MASK   0x00000080UL	/* Recv length fifo
+							 * overrun */
+#define XEM_EIR_RECV_LFIFO_UNDER_MASK  0x00000100UL	/* Recv length fifo
+							 * underrun */
+#define XEM_EIR_XMIT_SFIFO_OVER_MASK   0x00000200UL	/* Xmit status fifo
+							 * overrun */
+#define XEM_EIR_XMIT_SFIFO_UNDER_MASK  0x00000400UL	/* Transmit status fifo
+							 * underrun */
+#define XEM_EIR_XMIT_LFIFO_OVER_MASK   0x00000800UL	/* Transmit length fifo
+							 * overrun */
+#define XEM_EIR_XMIT_LFIFO_UNDER_MASK  0x00001000UL	/* Transmit length fifo
+							 * underrun */
+#define XEM_EIR_XMIT_PAUSE_MASK	       0x00002000UL	/* Transmit pause pkt
+							 * received */
+#define XEM_EIR_RECV_DFIFO_OVER_MASK   0x00004000UL	/* Receive data fifo
+							 * overrun */
+#define XEM_EIR_RECV_MISSED_FRAME_MASK 0x00008000UL	/* Receive missed frame
+							 * error */
+#define XEM_EIR_RECV_COLLISION_MASK    0x00010000UL	/* Receive collision
+							 * error */
+#define XEM_EIR_RECV_FCS_ERROR_MASK    0x00020000UL	/* Receive FCS error */
+#define XEM_EIR_RECV_LEN_ERROR_MASK    0x00040000UL	/* Receive length field
+							 * error */
+#define XEM_EIR_RECV_SHORT_ERROR_MASK  0x00080000UL	/* Receive short frame
+							 * error */
+#define XEM_EIR_RECV_LONG_ERROR_MASK   0x00100000UL	/* Receive long frame
+							 * error */
+#define XEM_EIR_RECV_ALIGN_ERROR_MASK  0x00200000UL	/* Receive alignment
+							 * error */
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/*****************************************************************************
+*
+* Low-level driver macros and functions. The list below provides signatures
+* to help the user use the macros.
+*
+* u32 XEmac_mReadReg(u32 BaseAddress, int RegOffset)
+* void XEmac_mWriteReg(u32 BaseAddress, int RegOffset, u32 Mask)
+*
+* void XEmac_mSetControlReg(u32 BaseAddress, u32 Mask)
+* void XEmac_mSetMacAddress(u32 BaseAddress, u8 *AddressPtr)
+*
+* void XEmac_mEnable(u32 BaseAddress)
+* void XEmac_mDisable(u32 BaseAddress)
+*
+* u32 XEmac_mIsTxDone(u32 BaseAddress)
+* u32 XEmac_mIsRxEmpty(u32 BaseAddress)
+*
+* void XEmac_SendFrame(u32 BaseAddress, u8 *FramePtr, int Size)
+* int XEmac_RecvFrame(u32 BaseAddress, u8 *FramePtr)
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/**
+*
+* Read the given register.
+*
+* @param    BaseAddress is the base address of the device
+* @param    RegOffset is the register offset to be read
+*
+* @return   The 32-bit value of the register
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mReadReg(BaseAddress, RegOffset) \
+		    XIo_In32((BaseAddress) + (RegOffset))
+
+/****************************************************************************/
+/**
+*
+* Write the given register.
+*
+* @param    BaseAddress is the base address of the device
+* @param    RegOffset is the register offset to be written
+* @param    Data is the 32-bit value to write to the register
+*
+* @return   None.
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mWriteReg(BaseAddress, RegOffset, Data) \
+		    XIo_Out32((BaseAddress) + (RegOffset), (Data))
+
+/****************************************************************************/
+/**
+*
+* Set the contents of the control register. Use the XEM_ECR_* constants
+* defined above to create the bit-mask to be written to the register.
+*
+* @param    BaseAddress is the base address of the device
+* @param    Mask is the 16-bit value to write to the control register
+*
+* @return   None.
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mSetControlReg(BaseAddress, Mask) \
+		    XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, (Mask))
+
+/****************************************************************************/
+/**
+*
+* Set the station address of the EMAC device.
+*
+* @param    BaseAddress is the base address of the device
+* @param    AddressPtr is a pointer to a 6-byte MAC address
+*
+* @return   None.
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mSetMacAddress(BaseAddress, AddressPtr)		    \
+{								    \
+    u32 MacAddr;						\
+								    \
+    MacAddr = ((AddressPtr)[0] << 8) | (AddressPtr)[1];		    \
+    XIo_Out32((BaseAddress) + XEM_SAH_OFFSET, MacAddr);		    \
+								    \
+    MacAddr = ((AddressPtr)[2] << 24) | ((AddressPtr)[3] << 16) |   \
+	      ((AddressPtr)[4] << 8) | (AddressPtr)[5];		    \
+								    \
+    XIo_Out32((BaseAddress) + XEM_SAL_OFFSET, MacAddr);		    \
+}
+
+/****************************************************************************/
+/**
+*
+* Enable the transmitter and receiver. Preserve the contents of the control
+* register.
+*
+* @param    BaseAddress is the base address of the device
+*
+* @return   None.
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mEnable(BaseAddress) \
+{ \
+    u32 Control; \
+    Control = XIo_In32((BaseAddress) + XEM_ECR_OFFSET); \
+    Control &= ~(XEM_ECR_XMIT_RESET_MASK | XEM_ECR_RECV_RESET_MASK); \
+    Control |= (XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK); \
+    XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, Control); \
+}
+
+/****************************************************************************/
+/**
+*
+* Disable the transmitter and receiver. Preserve the contents of the control
+* register.
+*
+* @param    BaseAddress is the base address of the device
+*
+* @return   None.
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mDisable(BaseAddress) \
+		XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, \
+		    XIo_In32((BaseAddress) + XEM_ECR_OFFSET) & \
+		    ~(XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK))
+
+/****************************************************************************/
+/**
+*
+* Check to see if the transmission is complete.
+*
+* @param    BaseAddress is the base address of the device
+*
+* @return   TRUE if it is done, or FALSE if it is not.
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mIsTxDone(BaseAddress) \
+	     (XIo_In32((BaseAddress) + XEM_ISR_OFFSET) & XEM_EIR_XMIT_DONE_MASK)
+
+/****************************************************************************/
+/**
+*
+* Check to see if the receive FIFO is empty.
+*
+* @param    BaseAddress is the base address of the device
+*
+* @return   TRUE if it is empty, or FALSE if it is not.
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mIsRxEmpty(BaseAddress) \
+	  (!(XIo_In32((BaseAddress) + XEM_ISR_OFFSET) & XEM_EIR_RECV_DONE_MASK))
+
+/****************************************************************************/
+/**
+*
+* Reset MII compliant PHY
+*
+* @param    BaseAddress is the base address of the device
+*
+* @return   None.
+*
+* @note	    None.
+*
+*****************************************************************************/
+#define XEmac_mPhyReset(BaseAddress) \
+{ \
+    u32 Control;				    \
+    Control = XIo_In32((BaseAddress) + XEM_ECR_OFFSET); \
+    Control &= ~XEM_ECR_PHY_ENABLE_MASK;		\
+    XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, Control); \
+    Control |= XEM_ECR_PHY_ENABLE_MASK;			\
+    XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, Control); \
+}
+
+/************************** Function Prototypes ******************************/
+
+void XEmac_SendFrame(u32 BaseAddress, u8 * FramePtr, int Size);
+int XEmac_RecvFrame(u32 BaseAddress, u8 * FramePtr);
+
+#endif				/* end of protection macro */

+ 318 - 0
board/xilinx/xilinx_enet/xemac_options.c

@@ -0,0 +1,318 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemac_options.c
+*
+* Functions in this file handle configuration of the XEmac driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rpm  07/31/01 First release
+* 1.00b rpm  02/20/02 Repartitioned files and functions
+* 1.00c rpm  12/05/02 New version includes support for simple DMA
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xemac_i.h"
+#include "xio.h"
+
+/************************** Constant Definitions *****************************/
+
+#define XEM_MAX_IFG         32	/* Maximum Interframe gap value */
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/*
+ * A table of options and masks. This table maps the user-visible options with
+ * the control register masks. It is used in Set/GetOptions as an alternative
+ * to a series of if/else pairs. Note that the polled options does not have a
+ * corresponding entry in the control register, so it does not exist in the
+ * table.
+ */
+typedef struct {
+	u32 Option;
+	u32 Mask;
+} OptionMap;
+
+static OptionMap OptionsTable[] = {
+	{XEM_UNICAST_OPTION, XEM_ECR_UNICAST_ENABLE_MASK},
+	{XEM_BROADCAST_OPTION, XEM_ECR_BROAD_ENABLE_MASK},
+	{XEM_PROMISC_OPTION, XEM_ECR_PROMISC_ENABLE_MASK},
+	{XEM_FDUPLEX_OPTION, XEM_ECR_FULL_DUPLEX_MASK},
+	{XEM_LOOPBACK_OPTION, XEM_ECR_LOOPBACK_MASK},
+	{XEM_MULTICAST_OPTION, XEM_ECR_MULTI_ENABLE_MASK},
+	{XEM_FLOW_CONTROL_OPTION, XEM_ECR_PAUSE_FRAME_MASK},
+	{XEM_INSERT_PAD_OPTION, XEM_ECR_XMIT_PAD_ENABLE_MASK},
+	{XEM_INSERT_FCS_OPTION, XEM_ECR_XMIT_FCS_ENABLE_MASK},
+	{XEM_INSERT_ADDR_OPTION, XEM_ECR_XMIT_ADDR_INSERT_MASK},
+	{XEM_OVWRT_ADDR_OPTION, XEM_ECR_XMIT_ADDR_OVWRT_MASK},
+	{XEM_STRIP_PAD_FCS_OPTION, XEM_ECR_RECV_STRIP_ENABLE_MASK}
+};
+
+#define XEM_NUM_OPTIONS     (sizeof(OptionsTable) / sizeof(OptionMap))
+
+/*****************************************************************************/
+/**
+*
+* Set Ethernet driver/device options.  The device must be stopped before
+* calling this function.  The options are contained within a bit-mask with each
+* bit representing an option (i.e., you can OR the options together). A one (1)
+* in the bit-mask turns an option on, and a zero (0) turns the option off.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param OptionsFlag is a bit-mask representing the Ethernet options to turn on
+*        or off. See xemac.h for a description of the available options.
+*
+* @return
+*
+* - XST_SUCCESS if the options were set successfully
+* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
+*
+* @note
+*
+* This function is not thread-safe and makes use of internal resources that are
+* shared between the Start, Stop, and SetOptions functions, so if one task
+* might be setting device options while another is trying to start the device,
+* protection of this shared data (typically using a semaphore) is required.
+*
+******************************************************************************/
+XStatus
+XEmac_SetOptions(XEmac * InstancePtr, u32 OptionsFlag)
+{
+	u32 ControlReg;
+	int Index;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STARTED;
+	}
+
+	ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET);
+
+	/*
+	 * Loop through the options table, turning the option on or off
+	 * depending on whether the bit is set in the incoming options flag.
+	 */
+	for (Index = 0; Index < XEM_NUM_OPTIONS; Index++) {
+		if (OptionsFlag & OptionsTable[Index].Option) {
+			ControlReg |= OptionsTable[Index].Mask;	/* turn it on */
+		} else {
+			ControlReg &= ~OptionsTable[Index].Mask;	/* turn it off */
+		}
+	}
+
+	/*
+	 * TODO: need to validate addr-overwrite only if addr-insert?
+	 */
+
+	/*
+	 * Now write the control register. Leave it to the upper layers
+	 * to restart the device.
+	 */
+	XIo_Out32(InstancePtr->BaseAddress + XEM_ECR_OFFSET, ControlReg);
+
+	/*
+	 * Check the polled option
+	 */
+	if (OptionsFlag & XEM_POLLED_OPTION) {
+		InstancePtr->IsPolled = TRUE;
+	} else {
+		InstancePtr->IsPolled = FALSE;
+	}
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Get Ethernet driver/device options. The 32-bit value returned is a bit-mask
+* representing the options.  A one (1) in the bit-mask means the option is on,
+* and a zero (0) means the option is off.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+*
+* @return
+*
+* The 32-bit value of the Ethernet options. The value is a bit-mask
+* representing all options that are currently enabled. See xemac.h for a
+* description of the available options.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+u32
+XEmac_GetOptions(XEmac * InstancePtr)
+{
+	u32 OptionsFlag = 0;
+	u32 ControlReg;
+	int Index;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Get the control register to determine which options are currently set.
+	 */
+	ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET);
+
+	/*
+	 * Loop through the options table to determine which options are set
+	 */
+	for (Index = 0; Index < XEM_NUM_OPTIONS; Index++) {
+		if (ControlReg & OptionsTable[Index].Mask) {
+			OptionsFlag |= OptionsTable[Index].Option;
+		}
+	}
+
+	if (InstancePtr->IsPolled) {
+		OptionsFlag |= XEM_POLLED_OPTION;
+	}
+
+	return OptionsFlag;
+}
+
+/*****************************************************************************/
+/**
+*
+* Set the Interframe Gap (IFG), which is the time the MAC delays between
+* transmitting frames.  There are two parts required.  The total interframe gap
+* is the total of the two parts.  The values provided for the Part1 and Part2
+* parameters are multiplied by 4 to obtain the bit-time interval. The first
+* part should be the first 2/3 of the total interframe gap. The MAC will reset
+* the interframe gap timer if carrier sense becomes true during the period
+* defined by interframe gap Part1. Part1 may be shorter than 2/3 the total and
+* can be as small as zero. The second part should be the last 1/3 of the total
+* interframe gap, but can be as large as the total interframe gap. The MAC
+* will not reset the interframe gap timer if carrier sense becomes true during
+* the period defined by interframe gap Part2.
+*
+* The device must be stopped before setting the interframe gap.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param Part1 is the interframe gap part 1 (which will be multiplied by 4 to
+*        get the bit-time interval).
+* @param Part2 is the interframe gap part 2 (which will be multiplied by 4 to
+*        get the bit-time interval).
+*
+* @return
+*
+* - XST_SUCCESS if the interframe gap was set successfully
+* - XST_DEVICE_IS_STARTED if the device has not been stopped
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus
+XEmac_SetInterframeGap(XEmac * InstancePtr, u8 Part1, u8 Part2)
+{
+	u32 Ifg;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(Part1 < XEM_MAX_IFG);
+	XASSERT_NONVOID(Part2 < XEM_MAX_IFG);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Be sure device has been stopped
+	 */
+	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STARTED;
+	}
+
+	Ifg = Part1 << XEM_IFGP_PART1_SHIFT;
+	Ifg |= (Part2 << XEM_IFGP_PART2_SHIFT);
+	XIo_Out32(InstancePtr->BaseAddress + XEM_IFGP_OFFSET, Ifg);
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Get the interframe gap, parts 1 and 2. See the description of interframe gap
+* above in XEmac_SetInterframeGap().
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param Part1Ptr is a pointer to an 8-bit buffer into which the interframe gap
+*        part 1 value will be copied.
+* @param Part2Ptr is a pointer to an 8-bit buffer into which the interframe gap
+*        part 2 value will be copied.
+*
+* @return
+*
+* None. The values of the interframe gap parts are copied into the
+* output parameters.
+*
+******************************************************************************/
+void
+XEmac_GetInterframeGap(XEmac * InstancePtr, u8 * Part1Ptr, u8 * Part2Ptr)
+{
+	u32 Ifg;
+
+	XASSERT_VOID(InstancePtr != NULL);
+	XASSERT_VOID(Part1Ptr != NULL);
+	XASSERT_VOID(Part2Ptr != NULL);
+	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	Ifg = XIo_In32(InstancePtr->BaseAddress + XEM_IFGP_OFFSET);
+	*Part1Ptr = (Ifg & XEM_IFGP_PART1_MASK) >> XEM_IFGP_PART1_SHIFT;
+	*Part2Ptr = (Ifg & XEM_IFGP_PART2_MASK) >> XEM_IFGP_PART2_SHIFT;
+}

+ 482 - 0
board/xilinx/xilinx_enet/xemac_polled.c

@@ -0,0 +1,482 @@
+/******************************************************************************
+*
+*     Author: Xilinx, Inc.
+*
+*
+*     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.
+*
+*
+*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
+*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+*     FITNESS FOR A PARTICULAR PURPOSE.
+*
+*
+*     Xilinx hardware products are not intended for use in life support
+*     appliances, devices, or systems. Use in such applications is
+*     expressly prohibited.
+*
+*
+*     (c) Copyright 2002-2004 Xilinx Inc.
+*     All rights reserved.
+*
+*
+*     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.,
+*     675 Mass Ave, Cambridge, MA 02139, USA.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemac_polled.c
+*
+* Contains functions used when the driver is in polled mode. Use the
+* XEmac_SetOptions() function to put the driver into polled mode.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rpm  07/31/01 First release
+* 1.00b rpm  02/20/02 Repartitioned files and functions
+* 1.00c rpm  12/05/02 New version includes support for simple DMA
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xemac_i.h"
+#include "xio.h"
+#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+*
+* Send an Ethernet frame in polled mode.  The device/driver must be in polled
+* mode before calling this function. The driver writes the frame directly to
+* the MAC's packet FIFO, then enters a loop checking the device status for
+* completion or error. Statistics are updated if an error occurs. The buffer
+* to be sent must be word-aligned.
+*
+* It is assumed that the upper layer software supplies a correctly formatted
+* Ethernet frame, including the destination and source addresses, the
+* type/length field, and the data field.  It is also assumed that upper layer
+* software does not append FCS at the end of the frame.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param BufPtr is a pointer to a word-aligned buffer containing the Ethernet
+*        frame to be sent.
+* @param ByteCount is the size of the Ethernet frame.
+*
+* @return
+*
+* - XST_SUCCESS if the frame was sent successfully
+* - XST_DEVICE_IS_STOPPED if the device has not yet been started
+* - XST_NOT_POLLED if the device is not in polled mode
+* - XST_FIFO_NO_ROOM if there is no room in the EMAC's length FIFO for this frame
+* - XST_FIFO_ERROR if the FIFO was overrun or underrun. This error is critical
+*   and requires the caller to reset the device.
+* - XST_EMAC_COLLISION if the send failed due to excess deferral or late
+*   collision
+*
+* @note
+*
+* There is the possibility that this function will not return if the hardware
+* is broken (i.e., it never sets the status bit indicating that transmission is
+* done). If this is of concern to the user, the user should provide protection
+* from this problem - perhaps by using a different timer thread to monitor the
+* PollSend thread. On a 10Mbps MAC, it takes about 1.21 msecs to transmit a
+* maximum size Ethernet frame (1518 bytes). On a 100Mbps MAC, it takes about
+* 121 usecs to transmit a maximum size Ethernet frame.
+*
+* @internal
+*
+* The EMAC uses FIFOs behind its length and status registers. For this reason,
+* it is important to keep the length, status, and data FIFOs in sync when
+* reading or writing to them.
+*
+******************************************************************************/
+XStatus
+XEmac_PollSend(XEmac * InstancePtr, u8 * BufPtr, u32 ByteCount)
+{
+	u32 IntrStatus;
+	u32 XmitStatus;
+	XStatus Result;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BufPtr != NULL);
+	XASSERT_NONVOID(ByteCount > XEM_HDR_SIZE);	/* send at least 1 byte */
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Be sure the device is configured for polled mode and it is started
+	 */
+	if (!InstancePtr->IsPolled) {
+		return XST_NOT_POLLED;
+	}
+
+	if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STOPPED;
+	}
+
+	/*
+	 * Check for overruns and underruns for the transmit status and length
+	 * FIFOs and make sure the send packet FIFO is not deadlocked. Any of these
+	 * conditions is bad enough that we do not want to continue. The upper layer
+	 * software should reset the device to resolve the error.
+	 */
+	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
+
+	/*
+	 * Overrun errors
+	 */
+	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK |
+			  XEM_EIR_XMIT_LFIFO_OVER_MASK)) {
+		InstancePtr->Stats.XmitOverrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+		return XST_FIFO_ERROR;
+	}
+
+	/*
+	 * Underrun errors
+	 */
+	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK |
+			  XEM_EIR_XMIT_LFIFO_UNDER_MASK)) {
+		InstancePtr->Stats.XmitUnderrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+		return XST_FIFO_ERROR;
+	}
+
+	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->SendFifo)) {
+		InstancePtr->Stats.FifoErrors++;
+		return XST_FIFO_ERROR;
+	}
+
+	/*
+	 * Before writing to the data FIFO, make sure the length FIFO is not
+	 * full.  The data FIFO might not be full yet even though the length FIFO
+	 * is. This avoids an overrun condition on the length FIFO and keeps the
+	 * FIFOs in sync.
+	 */
+	if (IntrStatus & XEM_EIR_XMIT_LFIFO_FULL_MASK) {
+		/*
+		 * Clear the latched LFIFO_FULL bit so next time around the most
+		 * current status is represented
+		 */
+		XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
+				      XEM_EIR_XMIT_LFIFO_FULL_MASK);
+		return XST_FIFO_NO_ROOM;
+	}
+
+	/*
+	 * This is a non-blocking write. The packet FIFO returns an error if there
+	 * is not enough room in the FIFO for this frame.
+	 */
+	Result =
+	    XPacketFifoV100b_Write(&InstancePtr->SendFifo, BufPtr, ByteCount);
+	if (Result != XST_SUCCESS) {
+		return Result;
+	}
+
+	/*
+	 * Loop on the MAC's status to wait for any pause to complete.
+	 */
+	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
+
+	while ((IntrStatus & XEM_EIR_XMIT_PAUSE_MASK) != 0) {
+		IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
+		/*
+		   * Clear the pause status from the transmit status register
+		 */
+		XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
+				      IntrStatus & XEM_EIR_XMIT_PAUSE_MASK);
+	}
+
+	/*
+	 * Set the MAC's transmit packet length register to tell it to transmit
+	 */
+	XIo_Out32(InstancePtr->BaseAddress + XEM_TPLR_OFFSET, ByteCount);
+
+	/*
+	 * Loop on the MAC's status to wait for the transmit to complete. The
+	 * transmit status is in the FIFO when the XMIT_DONE bit is set.
+	 */
+	do {
+		IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
+	}
+	while ((IntrStatus & XEM_EIR_XMIT_DONE_MASK) == 0);
+
+	XmitStatus = XIo_In32(InstancePtr->BaseAddress + XEM_TSR_OFFSET);
+
+	InstancePtr->Stats.XmitFrames++;
+	InstancePtr->Stats.XmitBytes += ByteCount;
+
+	/*
+	 * Check for various errors, bump statistics, and return an error status.
+	 */
+
+	/*
+	 * Overrun errors
+	 */
+	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK |
+			  XEM_EIR_XMIT_LFIFO_OVER_MASK)) {
+		InstancePtr->Stats.XmitOverrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+		return XST_FIFO_ERROR;
+	}
+
+	/*
+	 * Underrun errors
+	 */
+	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK |
+			  XEM_EIR_XMIT_LFIFO_UNDER_MASK)) {
+		InstancePtr->Stats.XmitUnderrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+		return XST_FIFO_ERROR;
+	}
+
+	/*
+	 * Clear the interrupt status register of transmit statuses
+	 */
+	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
+			      IntrStatus & XEM_EIR_XMIT_ALL_MASK);
+
+	/*
+	 * Collision errors are stored in the transmit status register
+	 * instead of the interrupt status register
+	 */
+	if (XmitStatus & XEM_TSR_EXCESS_DEFERRAL_MASK) {
+		InstancePtr->Stats.XmitExcessDeferral++;
+		return XST_EMAC_COLLISION_ERROR;
+	}
+
+	if (XmitStatus & XEM_TSR_LATE_COLLISION_MASK) {
+		InstancePtr->Stats.XmitLateCollisionErrors++;
+		return XST_EMAC_COLLISION_ERROR;
+	}
+
+	return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Receive an Ethernet frame in polled mode. The device/driver must be in polled
+* mode before calling this function. The driver receives the frame directly
+* from the MAC's packet FIFO. This is a non-blocking receive, in that if there
+* is no frame ready to be received at the device, the function returns with an
+* error. The MAC's error status is not checked, so statistics are not updated
+* for polled receive. The buffer into which the frame will be received must be
+* word-aligned.
+*
+* @param InstancePtr is a pointer to the XEmac instance to be worked on.
+* @param BufPtr is a pointer to a word-aligned buffer into which the received
+*        Ethernet frame will be copied.
+* @param ByteCountPtr is both an input and an output parameter. It is a pointer
+*        to a 32-bit word that contains the size of the buffer on entry into the
+*        function and the size the received frame on return from the function.
+*
+* @return
+*
+* - XST_SUCCESS if the frame was sent successfully
+* - XST_DEVICE_IS_STOPPED if the device has not yet been started
+* - XST_NOT_POLLED if the device is not in polled mode
+* - XST_NO_DATA if there is no frame to be received from the FIFO
+* - XST_BUFFER_TOO_SMALL if the buffer to receive the frame is too small for
+*   the frame waiting in the FIFO.
+*
+* @note
+*
+* Input buffer must be big enough to hold the largest Ethernet frame. Buffer
+* must also be 32-bit aligned.
+*
+* @internal
+*
+* The EMAC uses FIFOs behind its length and status registers. For this reason,
+* it is important to keep the length, status, and data FIFOs in sync when
+* reading or writing to them.
+*
+******************************************************************************/
+XStatus
+XEmac_PollRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr)
+{
+	XStatus Result;
+	u32 PktLength;
+	u32 IntrStatus;
+
+	XASSERT_NONVOID(InstancePtr != NULL);
+	XASSERT_NONVOID(BufPtr != NULL);
+	XASSERT_NONVOID(ByteCountPtr != NULL);
+	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+	/*
+	 * Be sure the device is configured for polled mode and it is started
+	 */
+	if (!InstancePtr->IsPolled) {
+		return XST_NOT_POLLED;
+	}
+
+	if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
+		return XST_DEVICE_IS_STOPPED;
+	}
+
+	/*
+	 * Make sure the buffer is big enough to hold the maximum frame size.
+	 * We need to do this because as soon as we read the MAC's packet length
+	 * register, which is actually a FIFO, we remove that length from the
+	 * FIFO.  We do not want to read the length FIFO without also reading the
+	 * data FIFO since this would get the FIFOs out of sync.  So we have to
+	 * make this restriction.
+	 */
+	if (*ByteCountPtr < XEM_MAX_FRAME_SIZE) {
+		return XST_BUFFER_TOO_SMALL;
+	}
+
+	/*
+	 * First check for packet FIFO deadlock and return an error if it has
+	 * occurred. A reset by the caller is necessary to correct this problem.
+	 */
+	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->RecvFifo)) {
+		InstancePtr->Stats.FifoErrors++;
+		return XST_FIFO_ERROR;
+	}
+
+	/*
+	 * Get the interrupt status to know what happened (whether an error occurred
+	 * and/or whether frames have been received successfully). When clearing the
+	 * intr status register, clear only statuses that pertain to receive.
+	 */
+	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
+	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
+			      IntrStatus & XEM_EIR_RECV_ALL_MASK);
+
+	/*
+	 * Check receive errors and bump statistics so the caller will have a clue
+	 * as to why data may not have been received. We continue on if an error
+	 * occurred since there still may be frames that were received successfully.
+	 */
+	if (IntrStatus & (XEM_EIR_RECV_LFIFO_OVER_MASK |
+			  XEM_EIR_RECV_DFIFO_OVER_MASK)) {
+		InstancePtr->Stats.RecvOverrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+	}
+
+	if (IntrStatus & XEM_EIR_RECV_LFIFO_UNDER_MASK) {
+		InstancePtr->Stats.RecvUnderrunErrors++;
+		InstancePtr->Stats.FifoErrors++;
+	}
+
+	/*
+	 * General receive errors
+	 */
+	if (IntrStatus & XEM_EIR_RECV_ERROR_MASK) {
+		if (IntrStatus & XEM_EIR_RECV_MISSED_FRAME_MASK) {
+			InstancePtr->Stats.RecvMissedFrameErrors =
+			    XIo_In32(InstancePtr->BaseAddress +
+				     XEM_RMFC_OFFSET);
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_COLLISION_MASK) {
+			InstancePtr->Stats.RecvCollisionErrors =
+			    XIo_In32(InstancePtr->BaseAddress + XEM_RCC_OFFSET);
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_FCS_ERROR_MASK) {
+			InstancePtr->Stats.RecvFcsErrors =
+			    XIo_In32(InstancePtr->BaseAddress +
+				     XEM_RFCSEC_OFFSET);
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_LEN_ERROR_MASK) {
+			InstancePtr->Stats.RecvLengthFieldErrors++;
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_SHORT_ERROR_MASK) {
+			InstancePtr->Stats.RecvShortErrors++;
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_LONG_ERROR_MASK) {
+			InstancePtr->Stats.RecvLongErrors++;
+		}
+
+		if (IntrStatus & XEM_EIR_RECV_ALIGN_ERROR_MASK) {
+			InstancePtr->Stats.RecvAlignmentErrors =
+			    XIo_In32(InstancePtr->BaseAddress +
+				     XEM_RAEC_OFFSET);
+		}
+	}
+
+	/*
+	 * Before reading from the length FIFO, make sure the length FIFO is not
+	 * empty. We could cause an underrun error if we try to read from an
+	 * empty FIFO.
+	 */
+	if ((IntrStatus & XEM_EIR_RECV_DONE_MASK) == 0) {
+		return XST_NO_DATA;
+	}
+
+	/*
+	 * Determine, from the MAC, the length of the next packet available
+	 * in the data FIFO (there should be a non-zero length here)
+	 */
+	PktLength = XIo_In32(InstancePtr->BaseAddress + XEM_RPLR_OFFSET);
+	if (PktLength == 0) {
+		return XST_NO_DATA;
+	}
+
+	/*
+	 * Write the RECV_DONE bit in the status register to clear it. This bit
+	 * indicates the RPLR is non-empty, and we know it's set at this point.
+	 * We clear it so that subsequent entry into this routine will reflect the
+	 * current status. This is done because the non-empty bit is latched in the
+	 * IPIF, which means it may indicate a non-empty condition even though
+	 * there is something in the FIFO.
+	 */
+	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, XEM_EIR_RECV_DONE_MASK);
+
+	/*
+	 * We assume that the MAC never has a length bigger than the largest
+	 * Ethernet frame, so no need to make another check here.
+	 */
+
+	/*
+	 * This is a non-blocking read. The FIFO returns an error if there is
+	 * not at least the requested amount of data in the FIFO.
+	 */
+	Result =
+	    XPacketFifoV100b_Read(&InstancePtr->RecvFifo, BufPtr, PktLength);
+	if (Result != XST_SUCCESS) {
+		return Result;
+	}
+
+	InstancePtr->Stats.RecvFrames++;
+	InstancePtr->Stats.RecvBytes += PktLength;
+
+	*ByteCountPtr = PktLength;
+
+	return XST_SUCCESS;
+}

+ 4 - 4
common/cmd_bdinfo.c

@@ -59,13 +59,13 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 	print_num ("immr_base",	    bd->bi_immr_base	);
 #endif
 	print_num ("bootflags",	    bd->bi_bootflags	);
-#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP)
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300)
 	print_str ("procfreq",	    strmhz(buf, bd->bi_procfreq));
 	print_str ("plb_busfreq",	    strmhz(buf, bd->bi_plb_busfreq));
-#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300)
 	print_str ("pci_busfreq",	    strmhz(buf, bd->bi_pci_busfreq));
 #endif
-#else	/* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP */
+#else	/* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300 */
 #if defined(CONFIG_8260) || defined(CONFIG_MPC8560)
 	print_str ("vco",	    strmhz(buf, bd->bi_vco));
 	print_str ("sccfreq",	    strmhz(buf, bd->bi_sccfreq));
@@ -76,7 +76,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 	print_str ("cpmfreq",	    strmhz(buf, bd->bi_cpmfreq));
 #endif
 	print_str ("busfreq",	    strmhz(buf, bd->bi_busfreq));
-#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP */
+#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300 */
 	printf ("ethaddr     =");
 	for (i=0; i<6; ++i) {
 		printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);

+ 1 - 1
cpu/arm925t/interrupts.c

@@ -237,7 +237,7 @@ void udelay (unsigned long usec)
 	}
 
 	tmp = get_timer (0);		/* get current timestamp */
-	if( (tmo + tmp) < tmp ) 	/* if setting this fordward will roll time stamp */
+	if( (tmo + tmp + 1) < tmp ) 	/* if setting this fordward will roll time stamp */
 		reset_timer_masked ();	/* reset "advancing" timestamp to 0, set lastdec value */
 	else
 		tmo += tmp;		/* else, set advancing stamp wake up time */

+ 1 - 1
cpu/arm926ejs/interrupts.c

@@ -229,7 +229,7 @@ void udelay (unsigned long usec)
 	}
 
 	tmp = get_timer (0);		/* get current timestamp */
-	if( (tmo + tmp) < tmp ) 	/* if setting this fordward will roll time stamp */
+	if( (tmo + tmp + 1) < tmp ) 	/* if setting this fordward will roll time stamp */
 		reset_timer_masked ();	/* reset "advancing" timestamp to 0, set lastdec value */
 	else
 		tmo += tmp;		/* else, set advancing stamp wake up time */

+ 2 - 0
cpu/nios/interrupts.c

@@ -30,6 +30,7 @@
 #include <asm/ptrace.h>
 #include <common.h>
 #include <command.h>
+#include <watchdog.h>
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
 #endif
@@ -54,6 +55,7 @@ void reset_timer (void)
 
 ulong get_timer (ulong base)
 {
+	WATCHDOG_RESET ();
 	return (timestamp - base);
 }
 

+ 3 - 2
cpu/nios/serial.c

@@ -23,6 +23,7 @@
 
 
 #include <common.h>
+#include <watchdog.h>
 #include <nios-io.h>
 
 
@@ -62,7 +63,7 @@ void serial_putc( char c )
 	if (c == '\n')
 		serial_putc('\r');
 	while( (uart->status & NIOS_UART_TRDY) == 0 )
-		;
+		WATCHDOG_RESET ();
 	uart->txdata = (unsigned char)c;
 }
 
@@ -81,6 +82,6 @@ int serial_tstc( void )
 int serial_getc( void )
 {
 	while( serial_tstc() == 0 )
-		;
+		WATCHDOG_RESET ();
 	return( uart->rxdata & 0x00ff );
 }

+ 4 - 0
cpu/ppc4xx/speed.c

@@ -299,6 +299,10 @@ ulong get_OPB_freq (void)
 	return sys_info.freqOPB;
 }
 
+#elif defined(CONFIG_XILINX_ML300)
+extern void get_sys_info (sys_info_t * sysInfo);
+extern ulong get_PCI_freq (void);
+
 #elif defined(CONFIG_405)
 
 void get_sys_info (sys_info_t * sysInfo) {

+ 128 - 0
doc/README.ml300

@@ -0,0 +1,128 @@
+Xilinx ML300 platform
+=====================
+
+0. Introduction
+---------------
+
+The Xilinx ML300 board is based on the Virtex-II Pro FPGA with
+integrated IBM PowerPC 405 core. The board is normally booted from
+System ACE CF. U-Boot is then run out of main memory.
+
+An FPGA is a configurable and thus very flexible device. To
+accommodate for this flexibility this port of U-Boot includes the
+required means to regenerate the drivers and configuration files if
+you decide to change the hardware design. The required steps are
+described below.
+
+
+1. Requirements
+---------------
+
+To compile and run U-Boot on the Xilinx ML300 platform you need the
+following items.
+
+- A Xilinx ML300 platform (see http://www.xilinx.com/ml300)
+- EDK and ISE development tools (shipping with ML300)
+- Parallel4 cable (shipping with ML300)
+- The EDK reference design for ML300. You can get this as design #6 from
+  http://www.xilinx.com/ise/embedded/edk_examples.htm
+- A BOOTP/TFTP server
+
+
+2. Quick Start
+--------------
+
+To compile and run U-Boot on ML300 follow the steps below. Make sure
+to consult the documentation for U-Boot, EDK, and the EDK reference
+design for ML300 if you have any questions.
+
+1. Implement the EDK reference design for ML300. You can use any of
+   the project files, for example from a xygwin shell:
+   $ xps -nw system_linux.xmp
+   XPS% run init_bram
+2. Configure and compile U-Boot. Change into the root directory of
+   U-Boot and run:
+   $ export CROSS_COMPILE=powerpc-eabi-
+   $ make ml300_config
+   $ make
+3. Set up the ML300, connect the Parallel4 and the serial cable. Start
+   a terminal on your host computer and set the communication
+   parameters to 9600,8N1,no handshake.
+4. Set up the BOOTP/TFTP server on your host machine. U-Boot is
+   preconfigured to use a fixed HW MAC address of 00:0A:35:00:22:01.
+5. Download the bitstream to the ML300.
+6. Use XMD to download and run U-Boot on the ML300:
+   $ xmd
+   XMD% ppcconnect
+   XMD% dow u-boot
+   XMD% run
+
+You can now make an ACE file out of bitstream and U-Boot:
+   $ xmd genace.tcl -jprog -board ml300 -hw  \
+     implementation/download.bit -elf u-boot -ace top.ace
+
+Put the ACE file onto the MicroDrive, for example into xilinx/myace,
+and reboot ML300.
+
+
+3. Generating a Custom BSP for U-Boot
+-------------------------------------
+
+If you decide to change the EDK reference design for ML300 or if you
+build a new design from scratch either with the Base System Builder in
+XPS or all by hand you most likely will change the base addresses for
+the Uart and the Ethernet peripheral. If you do so you will have two
+options:
+
+1. Edit boards/xilinx/ml300/xparameters.h to reflect the changes you
+   made to your hardware.
+2. Use the MLD technology provided by Xilinx Platform Studio to make
+   the changes automatically. To do so go to the root directory of the
+   EDK reference design for ML300. Copy the Linux project file and the
+   Linux software configuration file:
+   $ cp system_linux.xmp system_uboot.xmp
+   $ cp system_linux.mss system_uboot.mss
+
+   Edit system_uboot.xmp and and have it point to system_uboot.mss for
+   the software configuration.
+
+   Then, copy the sw_services directory in
+   boards/xilinx/ml300/sw_services to the root directory of the EDK
+   reference design for ML300.
+   $ cp -R <uboot dir>/boards/xilinx/ml300/sw_services <edk dir>
+
+   Modify system_uboot.mss. Look for the Linux library definition
+   and change it to generate a BSP for U-Boot. An example, might look
+   like this:
+
+   BEGIN LIBRARY
+    PARAMETER LIBRARY_NAME = uboot
+    PARAMETER LIBRARY_VER = 1.00.a
+    PARAMETER CONNECTED_PERIPHS = (opb_uart16550_0,opb_ethernet_0)
+    PARAMETER TARGET_DIR = <uboot dir>
+   END
+
+   Now, you are ready to generate the Xilinx ML300 BSP for U-Boot:
+   $ xps -nw system_uboot.xmp
+   XPS% run libs
+
+   If all goes well the new configuration has been copied into the
+   right places within the U-Boot source tree. Recompile U-Boot and
+   run it on the ML300.
+
+
+4. ToDo
+-------
+
+- Add support for all other peripherals on ML300.
+- Read the MAC address out of the IIC EEPROM.
+- Store the bootargs in the IIC EEPROM.
+
+
+5. References
+-------------
+
+ML300:			http://www.xilinx.com/ml300
+EDK:			http://www.xilinx.com/edk
+ISE:			http://www.xilinx.com/ise
+Reference Design:	http://www.xilinx.com/ise/embedded/edk_examples.htm

+ 63 - 94
drivers/cfi_flash.c

@@ -46,7 +46,9 @@
 
 #include <common.h>
 #include <asm/processor.h>
+#include <linux/byteorder/swab.h>
 #ifdef	CFG_FLASH_CFI_DRIVER
+
 /*
  * This file implements a Common Flash Interface (CFI) driver for U-Boot.
  * The width of the port and the width of the chips are determined at initialization.
@@ -164,31 +166,24 @@ typedef unsigned long flash_sect_t;
 
 static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c);
 static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf);
-static void flash_write_cmd (flash_info_t * info, flash_sect_t sect,
-			     uint offset, uchar cmd);
+static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
 static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect);
-static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset,
-			  uchar cmd);
-static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset,
-			uchar cmd);
-static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset,
-			 uchar cmd);
+static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
+static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
+static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
 static int flash_detect_cfi (flash_info_t * info);
 static ulong flash_get_size (ulong base, int banknum);
-static int flash_write_cfiword (flash_info_t * info, ulong dest,
-				cfiword_t cword);
+static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);
 static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
 				    ulong tout, char *prompt);
 #ifdef CFG_FLASH_USE_BUFFER_WRITE
-static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
-				  int len);
+static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len);
 #endif
 
 /*-----------------------------------------------------------------------
  * create an address based on the offset and the port width
  */
-inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect,
-			       uint offset)
+inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)
 {
 	return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
 }
@@ -230,7 +225,6 @@ static void flash_printqry (flash_info_t * info, flash_sect_t sect)
 		debug ("\n");
 	}
 }
-
 #endif
 
 
@@ -286,7 +280,6 @@ ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)
  */
 ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
 {
-
 	uchar *addr;
 	ulong retval;
 
@@ -304,8 +297,7 @@ ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
 #endif
 #if defined(__LITTLE_ENDIAN)
 	retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) |
-		(addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)]
-						 << 8);
+		(addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8);
 #else
 	retval = (addr[(2 * info->portwidth) - 1] << 24) |
 		(addr[(info->portwidth) - 1] << 16) |
@@ -327,7 +319,8 @@ unsigned long flash_init (void)
 		flash_info[i].flash_id = FLASH_UNKNOWN;
 		size += flash_info[i].size = flash_get_size (bank_base[i], i);
 		if (flash_info[i].flash_id == FLASH_UNKNOWN) {
-			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", i, flash_info[i].size, flash_info[i].size << 20);
+			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
+				i, flash_info[i].size, flash_info[i].size << 20);
 		}
 	}
 
@@ -377,21 +370,16 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
 			switch (info->vendor) {
 			case CFI_CMDSET_INTEL_STANDARD:
 			case CFI_CMDSET_INTEL_EXTENDED:
-				flash_write_cmd (info, sect, 0,
-						 FLASH_CMD_CLEAR_STATUS);
-				flash_write_cmd (info, sect, 0,
-						 FLASH_CMD_BLOCK_ERASE);
-				flash_write_cmd (info, sect, 0,
-						 FLASH_CMD_ERASE_CONFIRM);
+				flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS);
+				flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE);
+				flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
 				break;
 			case CFI_CMDSET_AMD_STANDARD:
 			case CFI_CMDSET_AMD_EXTENDED:
 				flash_unlock_seq (info, sect);
-				flash_write_cmd (info, sect, 0x555,
-						 AMD_CMD_ERASE_START);
+				flash_write_cmd (info, sect, 0x555, AMD_CMD_ERASE_START);
 				flash_unlock_seq (info, sect);
-				flash_write_cmd (info, sect, 0,
-						 AMD_CMD_ERASE_SECTOR);
+				flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR);
 				break;
 			default:
 				debug ("Unkown flash vendor %d\n",
@@ -425,7 +413,11 @@ void flash_print_info (flash_info_t * info)
 		(info->portwidth << 3), (info->chipwidth << 3));
 	printf ("  Size: %ld MB in %d Sectors\n",
 		info->size >> 20, info->sector_count);
-	printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", info->erase_blk_tout, info->write_tout, info->buffer_write_tout, info->buffer_size);
+	printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n",
+		info->erase_blk_tout,
+		info->write_tout,
+		info->buffer_write_tout,
+		info->buffer_size);
 
 	printf ("  Sector Start Addresses:");
 	for (i = 0; i < info->sector_count; ++i) {
@@ -605,7 +597,6 @@ int flash_real_protect (flash_info_t * info, long sector, int prot)
 			}
 		}
 	}
-
 	return retcode;
 }
 
@@ -706,16 +697,12 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
 			retcode = ERR_INVAL;
 			printf ("Flash %s error at address %lx\n", prompt,
 				info->start[sector]);
-			if (flash_isset
-			    (info, sector, 0,
-			     FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
+			if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
 				printf ("Command Sequence Error.\n");
-			} else if (flash_isset
-				   (info, sector, 0, FLASH_STATUS_ECLBS)) {
+			} else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {
 				printf ("Block Erase Error.\n");
 				retcode = ERR_NOT_ERASED;
-			} else if (flash_isset
-				   (info, sector, 0, FLASH_STATUS_PSLBS)) {
+			} else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {
 				printf ("Locking Error\n");
 			}
 			if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
@@ -762,16 +749,28 @@ static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
 	int i;
 
 #if defined(__LITTLE_ENDIAN)
-	ushort stmp;
+	ushort stmpw;
+	uint   stmpi;
 #endif
 	uchar *cp = (uchar *) cmdbuf;
 
 	for (i = 0; i < info->portwidth; i++)
 		*cp++ = ((i + 1) % info->chipwidth) ? '\0' : cmd;
 #if defined(__LITTLE_ENDIAN)
-	if (info->portwidth == 2) {
-		stmp = *(ushort *) cmdbuf;
-		*(ushort *) cmdbuf = swab16 (stmp);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		break;
+	case FLASH_CFI_16BIT:
+		stmpw = *(ushort *) cmdbuf;
+		*(ushort *) cmdbuf = __swab16 (stmpw);
+		break;
+	case FLASH_CFI_32BIT:
+		stmpi = *(uint *) cmdbuf;
+		*(uint *) cmdbuf = __swab32 (stmpi);
+		break;
+	default:
+		printf("WARNING: flash_make_cmd: unsuppported LittleEndian mode\n");
+		break;
 	}
 #endif
 }
@@ -779,8 +778,7 @@ static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
 /*
  * Write a proper sized command to the correct address
  */
-static void flash_write_cmd (flash_info_t * info, flash_sect_t sect,
-			     uint offset, uchar cmd)
+static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
 {
 
 	volatile cfiptr_t addr;
@@ -831,8 +829,7 @@ static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
 
 /*-----------------------------------------------------------------------
  */
-static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset,
-			  uchar cmd)
+static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
 {
 	cfiptr_t cptr;
 	cfiword_t cword;
@@ -877,8 +874,7 @@ static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset,
 
 /*-----------------------------------------------------------------------
  */
-static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset,
-			uchar cmd)
+static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
 {
 	cfiptr_t cptr;
 	cfiword_t cword;
@@ -908,8 +904,7 @@ static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset,
 
 /*-----------------------------------------------------------------------
  */
-static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset,
-			 uchar cmd)
+static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
 {
 	cfiptr_t cptr;
 	cfiword_t cword;
@@ -953,27 +948,18 @@ static int flash_detect_cfi (flash_info_t * info)
 		     info->chipwidth <= info->portwidth;
 		     info->chipwidth <<= 1) {
 			flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
-			flash_write_cmd (info, 0, FLASH_OFFSET_CFI,
-					 FLASH_CMD_CFI);
-			if (flash_isequal
-			    (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
-			    && flash_isequal (info, 0,
-					      FLASH_OFFSET_CFI_RESP + 1, 'R')
-			    && flash_isequal (info, 0,
-					      FLASH_OFFSET_CFI_RESP + 2,
-					      'Y')) {
-				info->interface =
-					flash_read_ushort (info, 0,
-							   FLASH_OFFSET_INTERFACE);
+			flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI);
+			if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
+			    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
+			    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
+				info->interface = flash_read_ushort (info, 0, FLASH_OFFSET_INTERFACE);
 				debug ("device interface is %d\n",
 				       info->interface);
 				debug ("found port %d chip %d ",
 				       info->portwidth, info->chipwidth);
 				debug ("port %d bits chip %d bits\n",
-				       info->
-				       portwidth << CFI_FLASH_SHIFT_WIDTH,
-				       info->
-				       chipwidth << CFI_FLASH_SHIFT_WIDTH);
+				       info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+				       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
 				return 1;
 			}
 		}
@@ -1001,9 +987,7 @@ static ulong flash_get_size (ulong base, int banknum)
 	info->start[0] = base;
 
 	if (flash_detect_cfi (info)) {
-		info->vendor =
-			flash_read_ushort (info, 0,
-					   FLASH_OFFSET_PRIMARY_VENDOR);
+		info->vendor = flash_read_ushort (info, 0, FLASH_OFFSET_PRIMARY_VENDOR);
 #ifdef DEBUG
 		flash_printqry (info, 0);
 #endif
@@ -1026,9 +1010,7 @@ static ulong flash_get_size (ulong base, int banknum)
 		    && (info->chipwidth == FLASH_CFI_BY8)) {
 			size_ratio >>= 1;
 		}
-		num_erase_regions =
-			flash_read_uchar (info,
-					  FLASH_OFFSET_NUM_ERASE_REGIONS);
+		num_erase_regions = flash_read_uchar (info, FLASH_OFFSET_NUM_ERASE_REGIONS);
 		debug ("size_ratio %d port %d bits chip %d bits\n",
 		       size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
 		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
@@ -1037,7 +1019,8 @@ static ulong flash_get_size (ulong base, int banknum)
 		sector = base;
 		for (i = 0; i < num_erase_regions; i++) {
 			if (i > NUM_ERASE_REGIONS) {
-				printf ("%d erase regions found, only %d used\n", num_erase_regions, NUM_ERASE_REGIONS);
+				printf ("%d erase regions found, only %d used\n",
+					num_erase_regions, NUM_ERASE_REGIONS);
 				break;
 			}
 			tmp = flash_read_long (info, 0,
@@ -1047,7 +1030,8 @@ static ulong flash_get_size (ulong base, int banknum)
 				(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
 			tmp >>= 16;
 			erase_region_count = (tmp & 0xffff) + 1;
-			printf ("erase_region_count = %d erase_region_size = %d\n", erase_region_count, erase_region_size);
+			printf ("erase_region_count = %d erase_region_size = %d\n",
+				erase_region_count, erase_region_size);
 			for (j = 0; j < erase_region_count; j++) {
 				info->start[sect_cnt] = sector;
 				sector += (erase_region_size * size_ratio);
@@ -1061,29 +1045,14 @@ static ulong flash_get_size (ulong base, int banknum)
 
 		info->sector_count = sect_cnt;
 		/* multiply the size by the number of chips */
-		info->size =
-			(1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) *
-			size_ratio;
-		info->buffer_size =
-			(1 <<
-			 flash_read_ushort (info, 0,
-					    FLASH_OFFSET_BUFFER_SIZE));
+		info->size = (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * size_ratio;
+		info->buffer_size = (1 << flash_read_ushort (info, 0, FLASH_OFFSET_BUFFER_SIZE));
 		tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT);
-		info->erase_blk_tout =
-			(tmp *
-			 (1 <<
-			  flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
+		info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
 		tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT);
-		info->buffer_write_tout =
-			(tmp *
-			 (1 <<
-			  flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
+		info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
 		tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT);
-		info->write_tout =
-			(tmp *
-			 (1 <<
-			  flash_read_uchar (info,
-					    FLASH_OFFSET_WMAX_TOUT))) / 1000;
+		info->write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT))) / 1000;
 		info->flash_id = FLASH_MAN_CFI;
 	}
 

+ 154 - 0
include/configs/ml300.h

@@ -0,0 +1,154 @@
+/*
+ * ML300.h: ML300 specific config options
+ *
+ * http://www.xilinx.com/ml300
+ *
+ * Derived from : ML2.h
+ *
+ *     Author: Xilinx, Inc.
+ *
+ *
+ *     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.
+ *
+ *
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
+ *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
+ *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR
+ *     OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ *     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ *     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
+ *     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
+ *     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ *     FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *     Xilinx products are not intended for use in life support appliances,
+ *     devices, or systems. Use in such applications is expressly prohibited.
+ *
+ *
+ *     (c) Copyright 2002 Xilinx Inc.
+ *     All rights reserved.
+ *
+ *
+ *     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.,
+ *     675 Mass Ave, Cambridge, MA 02139, USA.
+  *
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/* #define DEBUG */
+/* #define ET_DEBUG 1 */
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_405		1	/* This is a PPC405 CPU		*/
+#define CONFIG_4xx		1	/* ...member of PPC4xx family	*/
+#define CONFIG_XILINX_ML300	1	/* ...on a Xilinx ML300 board	*/
+
+#define CFG_ENV_IS_NOWHERE	1	/* environment is in RAM */
+#define CFG_NO_FLASH		1	/* no flash */
+#define CFG_ENV_SIZE		0x2000
+#define CONFIG_BAUDRATE		9600
+#define CONFIG_BOOTDELAY	3	/* autoboot after 3 seconds	*/
+
+#define CONFIG_BOOTCOMMAND	"bootp" /* autoboot command	*/
+
+#define CONFIG_BOOTARGS		"console=ttyS0,9600 ip=off " \
+				"root=/dev/xsysace/disc0/part3 rw"
+
+#define CONFIG_LOADS_ECHO	1	/* echo on for serial download	*/
+#define CFG_LOADS_BAUD_CHANGE	1	/* allow baudrate change	*/
+
+#define REMOVE_COMMANDS	       (CFG_CMD_FLASH | CFG_CMD_LOADS | CFG_CMD_FAT | \
+				CFG_CMD_IMLS )
+#define CONFIG_COMMANDS	       ((CONFIG_CMD_DFL | CFG_CMD_NET) \
+				& ~REMOVE_COMMANDS)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/* #define CONFIG_SYS_CLK_FREQ XPAR_CORE_CLOCK_FREQ_HZ */
+/* 300000000 */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP		/* undef to save memory		*/
+#define CFG_PROMPT	"=> "	/* Monitor Command Prompt	*/
+
+#define CFG_CBSIZE	256	/* Console I/O Buffer Size	*/
+
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)	/* Print Buffer Size */
+#define CFG_MAXARGS	16	/* max number of command args	*/
+#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size	*/
+
+#define CFG_MEMTEST_START	0x0400000	/* memtest works on	*/
+#define CFG_MEMTEST_END		0x0C00000	/* 4 ... 12 MB in DRAM	*/
+
+#define CFG_DUART_CHAN		0
+#define CFG_NS16550_REG_SIZE -4
+#define CFG_NS16550 1
+#define CFG_INIT_CHAN1	 1
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE  \
+    {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
+
+#define CFG_LOAD_ADDR		0x400000	/* default load address */
+#define CFG_EXTBDINFO		1	/* To use extended board_into (bd_t) */
+
+#define CFG_HZ		1000	/* decrementer freq: 1 ms ticks */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE		0x00000000
+#define CFG_MONITOR_BASE	0x04000000
+#define CFG_MONITOR_LEN		(192 * 1024)	/* Reserve 196 kB for Monitor	*/
+#define CFG_MALLOC_LEN		(128 * 1024)	/* Reserve 128 kB for malloc()	*/
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ		(8 << 20)	/* Initial Memory map for Linux */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE		16384	/* For IBM 405 CPUs	*/
+#define CFG_CACHELINE_SIZE	32	/* ...			*/
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+
+#define CFG_INIT_RAM_ADDR	0x800000  /* inside of SDRAM */
+#define CFG_INIT_RAM_END	0x2000	  /* End of used area in RAM */
+#define CFG_GBL_DATA_SIZE	128	  /* size in bytes reserved for initial data */
+#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD	0x01	/* Normal Power-On: Boot from FLASH	*/
+#define BOOTFLAG_WARM	0x02	/* Software reboot			*/
+
+#endif				/* __CONFIG_H */

+ 1 - 1
include/configs/omap1610h2.h

@@ -73,7 +73,7 @@
 #define CFG_NS16550_REG_SIZE	(-4)
 #define CFG_NS16550_CLK	(48000000)		/* can be 12M/32Khz or 48Mhz */
 #define CFG_NS16550_COM1	0xfffb0000	/* uart1, bluetooth uart */
-						
+
 /*
  * select serial console configuration
  */

+ 4 - 0
include/watchdog.h

@@ -31,6 +31,10 @@
 #  error "Configuration error: CONFIG_HW_WATCHDOG and CONFIG_WATCHDOG can't be used together."
 #endif
 
+#if defined(__ASSEMBLY__) && defined(__NIOS__)
+#  error "Configuration error: WATCHDOG_RESET inside assembler not supported for Nios platforms."
+#endif
+
 /*
  * Hardware watchdog
  */

+ 5 - 0
lib_nios/board.c

@@ -139,13 +139,16 @@ void board_init (void)
 	bd->bi_baudrate	= CONFIG_BAUDRATE;
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+		WATCHDOG_RESET ();
 		if ((*init_fnc_ptr) () != 0) {
 			hang ();
 		}
 	}
 
+	WATCHDOG_RESET ();
 	bd->bi_flashsize = flash_init();
 
+	WATCHDOG_RESET ();
 	mem_malloc_init();
 	malloc_bin_reloc();
 	env_relocate();
@@ -157,12 +160,14 @@ void board_init (void)
 		if (s) s = (*e) ? e + 1 : e;
 	}
 
+	WATCHDOG_RESET ();
 	devices_init();
 	jumptable_init();
 	console_init_r();
 	/*
 	 */
 
+	WATCHDOG_RESET ();
 	interrupt_init ();
 
 #ifdef CONFIG_STATUS_LED

+ 2 - 0
lib_nios/time.c

@@ -22,6 +22,7 @@
  */
 
 #include <common.h>
+#include <watchdog.h>
 
 
 extern void dly_clks( unsigned long ticks );
@@ -33,5 +34,6 @@ void udelay(unsigned long usec)
 	 * cpu clocks.
 	 */
 	unsigned long cnt = (CONFIG_SYS_CLK_FREQ/1000000) * usec;
+	WATCHDOG_RESET ();	/* trigger watchdog if needed */
 	dly_clks (cnt);
 }

+ 2 - 0
lib_ppc/board.c

@@ -515,6 +515,8 @@ void board_init_f (ulong bootflag)
 #endif
 	bd->bi_iic_fast[0] = 0;
 	bd->bi_iic_fast[1] = 0;
+#elif defined(CONFIG_XILINX_ML300)
+	bd->bi_pci_busfreq = get_PCI_freq ();
 #endif
 #endif
 

+ 1 - 1
nios_config.mk

@@ -22,4 +22,4 @@
 # MA 02111-1307 USA
 #
 
-PLATFORM_CPPFLAGS += -m32 -DCONFIG_NIOS -ffixed-g7
+PLATFORM_CPPFLAGS += -m32 -DCONFIG_NIOS -D__NIOS__ -ffixed-g7