summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e0b55f2)
raw | patch | inline | side by side (parent: e0b55f2)
author | Bill Mills <wmills@ti.com> | |
Tue, 14 Sep 2010 22:02:49 +0000 (18:02 -0400) | ||
committer | Bill Mills <wmills@ti.com> | |
Tue, 14 Sep 2010 22:02:49 +0000 (18:02 -0400) |
Signed-off-by: Bill Mills <wmills@ti.com>
152 files changed:
diff --git a/.gitignore b/.gitignore
index 7d18c5e5a219cd60c72af2176818a214ba9bcd03..4d3f8bd8e5a228732c24ae8d9fcde67268e908a8 100644 (file)
--- a/.gitignore
+++ b/.gitignore
junk/
logs/
hacky-stuff/cgtools
-
-
diff --git a/src/arch/c64x/types.h b/src/arch/c64x/types.h
--- /dev/null
+++ b/src/arch/c64x/types.h
@@ -0,0 +1,68 @@
+#ifndef _TYPES_H
+#define _TYPES_H
+/*******************************************************************************
+ * FILE PURPOSE: DSP specific C type definitions.
+ *******************************************************************************
+ * FILE NAME: swpform.h
+ *
+ * DESCRIPTION: Defines general use types for DSP.
+ *
+ * @file types.h
+ *
+ * @brief
+ * This file provides architecture specific typedefs
+ *
+ ******************************************************************************/
+
+
+#include <stdlib.h> /* Defines NULL */
+
+/* a signed 16-bit integer */
+typedef short int16;
+typedef unsigned short uint16;
+
+typedef int int32;
+typedef unsigned int uint32;
+
+typedef char char8;
+typedef unsigned char uchar8;
+
+typedef char int8;
+typedef unsigned char uint8;
+
+
+typedef unsigned char word;
+
+typedef short BOOL;
+typedef short bool;
+typedef short Bool;
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+
+/* tistdtypes.h types used from the emac driver */
+typedef unsigned char Uint8;
+typedef char Int8;
+typedef int Int32;
+typedef unsigned short Uint16;
+typedef unsigned int Uint32;
+
+/* TI boot types */
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+
+
+/* Types from evm driver */
+typedef volatile unsigned int VUint32;
+typedef volatile unsigned char VUint8;
+
+/* Types from the ethernet driver */
+typedef unsigned int IPN;
+
+#endif /* types.h */
diff --git a/src/cfg/c6455/iblcfg.h b/src/cfg/c6455/iblcfg.h
--- /dev/null
+++ b/src/cfg/c6455/iblcfg.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ * FILE PURPOSE: Provide build time configurations for the IBL
+ **************************************************************************
+ * FILE NAME: iblcfg.h
+ *
+ * DESCRIPTION: Build time configuration
+ *
+ * @file iblcfg.h
+ *
+ * @brief
+ * Build time configurations for the c6455 ibl are defined
+ *
+ ***************************************************************************/
+#ifndef IBLCFG_H
+#define IBLCFG_H
+
+/**
+ * @brief The maximum number of UDP sockets in the system
+ */
+#define MAX_UDP_SOCKET 3
+
+
+/**
+ * @brief The maximum number of timers in the system
+ */
+#define MAX_TIMER_BLOCKS 5
+
+
+/**
+ * @brief The size in bytes of the internal stream buffer
+ */
+#define MAX_SIZE_STREAM_BUFFER 1024
+
+
+/**
+ * @brief The maximum number of functions supported for BIS mode
+ */
+#define MAX_BIS_FUNCTION_SUPPORT 3
+
+
+
+
+
+
+#endif
+
+
diff --git a/src/cfg/c6472/iblcfg.h b/src/cfg/c6472/iblcfg.h
--- /dev/null
+++ b/src/cfg/c6472/iblcfg.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+ * FILE PURPOSE: Provide build time configurations for the IBL
+ **************************************************************************
+ * FILE NAME: iblcfg.h
+ *
+ * DESCRIPTION: Build time configuration
+ *
+ * @file iblcfg.h
+ *
+ * @brief
+ * Build time configurations for the c6472 ibl are defined
+ *
+ ***************************************************************************/
+#ifndef IBLCFG_H
+#define IBLCFG_H
+
+/**
+ * @brief The maximum number of UDP sockets in the system
+ */
+#define MAX_UDP_SOCKET 3
+
+
+/**
+ * @brief The maximum number of timers in the system
+ */
+#define MAX_TIMER_BLOCKS 5
+
+
+/**
+ * @brief The size in bytes of the internal stream buffer
+ */
+#define MAX_SIZE_STREAM_BUFFER 1024
+
+
+/**
+ * @brief The maximum number of functions supported for BIS mode
+ */
+#define MAX_BIS_FUNCTION_SUPPORT 3
+
+
+/**
+ * @brief No I/O sections accepted in boot table format
+ */
+#define BOOTCONFIG_NO_BTBL_IO
+
+/**
+ * @brief The I2C bus address and data address of the ibl table.
+ */
+#define IBL_I2C_DEV_FREQ_MHZ 625
+#define IBL_I2C_CLK_FREQ_KHZ 100
+#define IBL_I2C_OWN_ADDR 10
+#define IBL_I2C_CFG_ADDR_DELAY 0x100 /* Delay between sending the address and reading data */
+#define IBL_I2C_CFG_EEPROM_BUS_ADDR 0x50
+#define IBL_I2C_CFG_TABLE_DATA_ADDR (0x10000 - 0x300)
+
+
+
+
+
+#endif
+
+
diff --git a/src/device/c6455/c6455.c b/src/device/c6455/c6455.c
--- /dev/null
+++ b/src/device/c6455/c6455.c
@@ -0,0 +1,41 @@
+/************************************************************************************
+ * FILE PURPOSE: C6455 Device Specific functions
+ ************************************************************************************
+ * FILE NAME: c6455.c
+ *
+ * DESCRIPTION: Implements the device specific functions for the IBL
+ *
+ * @file c6455.c
+ *
+ * @brief
+ * This file implements the device specific functions for the IBL
+ *
+ ************************************************************************************/
+#include "ibl.h"
+#include "device.h"
+
+
+/**
+ * @brief The default boot configuration table is filled in
+ *
+ * @details
+ * A default ibl configuraiton table is provided when one is not found
+ * preloaded.
+ */
+void deviceLoadDefaultIblTable (void)
+{
+
+ ibl.ethConfig.ethPriority = ibl_HIGHEST_PRIORITY;
+ ibl.ethConfig.port = 0;
+ ibl.ethConfig.doBootp = TRUE;
+ ibl.ethConfig.bootFormat = ibl_BOOT_FORMAT_AUTO;
+
+ memset (ibl.ethConfig.ethInfo, 0, sizeof(ibl.ethConfig.ethInfo));
+}
+
+
+
+
+
+
+
diff --git a/src/device/c6455/target.h b/src/device/c6455/target.h
--- /dev/null
@@ -0,0 +1,32 @@
+/**************************************************************************
+ * FILE PURPOSE: Target specific definitions
+ **************************************************************************
+ * FILE NAME: target.h
+ *
+ * DESCRIPTION: This file defines target specific values used by low level
+ * drivers.
+ *
+ * @file target.h
+ *
+ * @brief
+ * Low level target specific values are defined
+ *
+ ***************************************************************************/
+
+
+#define EMAC_BASE_ADDRESS 0x02C80000u
+#define _EMAC_DSC_BASE_ADDR 0x02c82000u
+#define TIMER0_BASE 0x02940000u
+
+
+#define TIMER_INPUT_DIVIDER 6 /* Timer driven from cpu clock / 6 */
+
+
+/* Leave mdio disabled */
+#define dev_mdio_open() 1
+
+
+
+
+
+
diff --git a/src/device/c6472/c6472.c b/src/device/c6472/c6472.c
--- /dev/null
+++ b/src/device/c6472/c6472.c
@@ -0,0 +1,299 @@
+/************************************************************************************
+ * FILE PURPOSE: C6472 Device Specific functions
+ ************************************************************************************
+ * FILE NAME: c6472.c
+ *
+ * DESCRIPTION: Implements the device specific functions for the IBL
+ *
+ * @file c6472.c
+ *
+ * @brief
+ * This file implements the device specific functions for the IBL
+ *
+ ************************************************************************************/
+#include "ibl.h"
+#include "device.h"
+#include "pllapi.h"
+#include "emif31api.h"
+#include "pscapi.h"
+#include "gpio.h"
+#include <string.h>
+
+extern cregister unsigned int DNUM;
+
+
+/**
+ * @brief The default boot configuration table is filled in
+ *
+ * @details
+ * A default ibl configuraiton table is provided when one is not found
+ * preloaded.
+ */
+void deviceLoadDefaultIblTable (void)
+{
+ uint32 macA, macB;
+
+#if 0 /* This is really the default. Switching to a direct tftp boot until I have a bootp server
+ * on a private lan for test */
+ ibl.ethConfig[0].ethPriority = ibl_LOWEST_PRIORITY;
+ ibl.ethConfig[0].port = 0;
+ ibl.ethConfig[0].doBootp = TRUE;
+ ibl.ethConfig[0].bootFormat = ibl_BOOT_FORMAT_AUTO;
+
+ memset (&ibl.ethConfig[0].ethInfo, 0, sizeof(ibl.ethConfig[0].ethInfo));
+#endif
+
+ /* This is the temporary code */
+ ibl.ethConfig[0].ethPriority = ibl_LOWEST_PRIORITY;
+ ibl.ethConfig[0].port = 0;
+ ibl.ethConfig[0].doBootp = FALSE;
+ ibl.ethConfig[0].useBootpServerIp = FALSE;
+ ibl.ethConfig[0].useBootpFileName = FALSE;
+ ibl.ethConfig[0].bootFormat = ibl_BOOT_FORMAT_NAME;
+
+ memset (&ibl.ethConfig[0].ethInfo, 0, sizeof(ibl.ethConfig[0].ethInfo));
+
+ ibl.ethConfig[0].ethInfo.ipAddr[0] = 10;
+ ibl.ethConfig[0].ethInfo.ipAddr[1] = 218;
+ ibl.ethConfig[0].ethInfo.ipAddr[2] = 109;
+ ibl.ethConfig[0].ethInfo.ipAddr[3] = 21;
+
+ ibl.ethConfig[0].ethInfo.serverIp[0] = 10;
+ ibl.ethConfig[0].ethInfo.serverIp[1] = 218;
+ ibl.ethConfig[0].ethInfo.serverIp[2] = 109;
+ ibl.ethConfig[0].ethInfo.serverIp[3] = 196;
+
+ ibl.ethConfig[0].ethInfo.gatewayIp[0] = 10;
+ ibl.ethConfig[0].ethInfo.gatewayIp[1] = 218;
+ ibl.ethConfig[0].ethInfo.gatewayIp[2] = 109;
+ ibl.ethConfig[0].ethInfo.gatewayIp[3] = 1;
+
+ /* Leave hw address as 0 */
+
+ strcpy (ibl.ethConfig[0].ethInfo.fileName, "test2_little.out");
+
+ ibl.ethConfig[0].blob.startAddress = 0x00200000; /* Base address of SL2 */
+ ibl.ethConfig[0].blob.sizeBytes = 0x000c0000; /* All of SL2 */
+ ibl.ethConfig[0].blob.branchAddress = 0x00200000; /* Base of SL2 */
+
+
+
+ macA = *((uint32 *)0x2a80700);
+ macB = *((uint32 *)0x2a80704);
+
+ ibl.ethConfig[0].ethInfo.hwAddress[0] = (macA >> 24) & 0xff;
+ ibl.ethConfig[0].ethInfo.hwAddress[1] = (macA >> 16) & 0xff;
+ ibl.ethConfig[0].ethInfo.hwAddress[2] = (macA >> 8) & 0xff;
+ ibl.ethConfig[0].ethInfo.hwAddress[3] = (macA >> 0) & 0xff;
+ ibl.ethConfig[0].ethInfo.hwAddress[4] = (macB >> 24) & 0xff;
+ ibl.ethConfig[0].ethInfo.hwAddress[5] = (macB >> 16) & 0xff;
+
+
+ ibl.ethConfig[1].ethPriority = ibl_DEVICE_NOBOOT;
+
+
+ /* MDIO configuration */
+ ibl.mdioConfig.nMdioOps = 8;
+ ibl.mdioConfig.mdioClkDiv = 0x20;
+ ibl.mdioConfig.interDelay = 1400; /* ~2ms at 700 MHz */
+
+ ibl.mdioConfig.mdio[0] = (1 << 30) | (27 << 21) | (24 << 16) | 0x848b;
+ ibl.mdioConfig.mdio[1] = (1 << 30) | (20 << 21) | (24 << 16) | 0x0ce0;
+ ibl.mdioConfig.mdio[2] = (1 << 30) | (24 << 21) | (24 << 16) | 0x4101;
+ ibl.mdioConfig.mdio[3] = (1 << 30) | ( 0 << 21) | (24 << 16) | 0x9140;
+
+ ibl.mdioConfig.mdio[4] = (1 << 30) | (27 << 21) | (25 << 16) | 0x848b;
+ ibl.mdioConfig.mdio[5] = (1 << 30) | (20 << 21) | (25 << 16) | 0x0ce0;
+ ibl.mdioConfig.mdio[6] = (1 << 30) | (24 << 21) | (25 << 16) | 0x4101;
+ ibl.mdioConfig.mdio[7] = (1 << 30) | ( 0 << 21) | (25 << 16) | 0x9140;
+
+
+ /* Main Pll configuration */
+ ibl.pllConfig[ibl_MAIN_PLL].doEnable = TRUE;
+ ibl.pllConfig[ibl_MAIN_PLL].prediv = 1;
+ ibl.pllConfig[ibl_MAIN_PLL].mult = 28;
+ ibl.pllConfig[ibl_MAIN_PLL].postdiv = 1;
+
+ ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz = 500;
+
+ /* The DDR PLL. The multipliers/dividers are fixed, so are really dont cares */
+ ibl.pllConfig[ibl_DDR_PLL].doEnable = TRUE;
+
+ /* The network PLL. The multipliers/dividers are fixed */
+ ibl.pllConfig[ibl_NET_PLL].doEnable = TRUE;
+
+ /* EMIF configuration */
+ ibl.ddrConfig.uEmif.emif3p1.sdcfg = 0x00538832; /* timing, 32bit wide */
+ ibl.ddrConfig.uEmif.emif3p1.sdrfc = 0x0000073B; /* Refresh 533Mhz */
+ ibl.ddrConfig.uEmif.emif3p1.sdtim1 = 0x47245BD2; /* Timing 1 */
+ ibl.ddrConfig.uEmif.emif3p1.sdtim2 = 0x0125DC44; /* Timing 2 */
+ ibl.ddrConfig.uEmif.emif3p1.dmcctl = 0x50001906; /* PHY read latency for CAS 5 is 5 + 2 - 1 */
+
+
+ /* NAND configuration for the MT29F1G08 flash */
+ ibl.nandConfig.nandPriority = ibl_HIGHEST_PRIORITY;
+ ibl.nandConfig.bootFormat = ibl_BOOT_FORMAT_COFF;
+
+ ibl.nandConfig.nandInfo.busWidthBits = 8;
+ ibl.nandConfig.nandInfo.pageSizeBytes = 2048;
+ ibl.nandConfig.nandInfo.pageEccBytes = 64;
+ ibl.nandConfig.nandInfo.pagesPerBlock = 64;
+ ibl.nandConfig.nandInfo.totalBlocks = 1024;
+
+ ibl.nandConfig.nandInfo.addressBytes = 4;
+ ibl.nandConfig.nandInfo.lsbFirst = TRUE;
+ ibl.nandConfig.nandInfo.blockOffset = 22;
+ ibl.nandConfig.nandInfo.pageOffset = 16;
+ ibl.nandConfig.nandInfo.columnOffset = 0;
+
+ ibl.nandConfig.nandInfo.resetCommand = 0xff;
+ ibl.nandConfig.nandInfo.readCommandPre = 0;
+ ibl.nandConfig.nandInfo.readCommandPost = 0x30;
+ ibl.nandConfig.nandInfo.postCommand = TRUE;
+
+
+}
+
+/**
+ * @brief Determine if an address is local
+ *
+ * @details
+ * Examines an input address to determine if it is a local address
+ */
+bool address_is_local (Uint32 addr)
+{
+ /* L2 */
+ if ((addr >= 0x00800000) && (addr < 0x00898000))
+ return (TRUE);
+
+ /* L1P */
+ if ((addr >= 0x00e00000) && (addr < 0x00e08000))
+ return (TRUE);
+
+ /* L2D */
+ if ((addr >= 0x00f00000) && (addr < 0x00f08000))
+ return (TRUE);
+
+ return (FALSE);
+
+}
+
+
+/**
+ * @brief Convert a local l1d, l1p or l2 address to a global address
+ *
+ * @details
+ * The global address is formed. If the address is not local then
+ * the input address is returned
+ */
+Uint32 deviceLocalAddrToGlobal (Uint32 addr)
+{
+
+ if (address_is_local (addr))
+ addr = (1 << 28) | (DNUM << 24) | addr;
+
+ return (addr);
+
+}
+
+
+/**
+ * @brief Configure the PLLs
+ *
+ * @details
+ * The three PLLs are enabled. Only the main PLL has the ability to configure
+ * the multiplier and dividers.
+ */
+void devicePllConfig (void)
+{
+ if (ibl.pllConfig[ibl_MAIN_PLL].doEnable == TRUE)
+ hwPllSetPll (MAIN_PLL,
+ ibl.pllConfig[ibl_MAIN_PLL].prediv,
+ ibl.pllConfig[ibl_MAIN_PLL].mult,
+ ibl.pllConfig[ibl_MAIN_PLL].postdiv);
+
+ if (ibl.pllConfig[ibl_DDR_PLL].doEnable == TRUE)
+ hwPllEnable (DDR_PLL);
+
+ if (ibl.pllConfig[ibl_NET_PLL].doEnable == TRUE)
+ hwPllEnable (NET_PLL);
+
+
+}
+
+/**
+ * @brief
+ * Enable the DDR
+ *
+ * @details
+ * The DDR controller on the c6472 is an emif 3.1. The controller is
+ * initialized directly with the supplied values
+ */
+void deviceDdrConfig (void)
+{
+ if (ibl.ddrConfig.configDdr != 0)
+ hwEmif3p1Enable (&ibl.ddrConfig.uEmif.emif3p1);
+
+}
+
+
+/**
+ * @brief Power up a peripheral
+ *
+ * @details
+ * Boot peripherals are powered up
+ */
+int32 devicePowerPeriph (int32 modNum)
+{
+ /* If the input value is < 0 there is nothing to power up */
+ if (modNum < 0)
+ return (0);
+
+
+ if (modNum >= TARGET_PWR_MAX_MOD)
+ return (-1);
+
+ return ((int32)pscEnableModule(modNum));
+
+}
+
+
+/**
+ * @brief Enable the pass through version of the nand controller
+ *
+ * @details On the evm the nand controller is enabled by setting
+ * gpio 14 high
+ */
+int32 deviceConfigureForNand(void)
+{
+ hwGpioSetDirection(NAND_MODE_GPIO, GPIO_OUT);
+ hwGpioSetOutput(NAND_MODE_GPIO);
+ return (0);
+
+}
+
+
+/**
+ * @brief
+ * The e-fuse mac address is loaded
+ */
+void deviceLoadDefaultEthAddress (uint8 *maddr)
+{
+ uint32 macA, macB;
+
+ /* Read the e-fuse mac address */
+ macA = *((uint32 *)0x2a80700);
+ macB = *((uint32 *)0x2a80704);
+
+ maddr[0] = (macA >> 24) & 0xff;
+ maddr[1] = (macA >> 16) & 0xff;
+ maddr[2] = (macA >> 8) & 0xff;
+ maddr[3] = (macA >> 0) & 0xff;
+ maddr[4] = (macB >> 24) & 0xff;
+ maddr[5] = (macB >> 16) & 0xff;
+}
+
+
+
+
+
diff --git a/src/device/c6472/target.h b/src/device/c6472/target.h
--- /dev/null
@@ -0,0 +1,142 @@
+/**************************************************************************
+ * FILE PURPOSE: Target specific definitions
+ **************************************************************************
+ * FILE NAME: target.h
+ *
+ * DESCRIPTION: This file defines target specific values used by low level
+ * drivers.
+ *
+ * @file target.h
+ *
+ * @brief
+ * Low level target specific values are defined
+ *
+ ***************************************************************************/
+
+
+/**
+ * @brief
+ * Device EMAC definitions
+ */
+#define TARGET_DEVICE_CPMAC
+
+#define TARGET_EMAC_N_PORTS 2
+
+#define TARGET_EMAC_BASE_ADDRESSES { 0x02c80000u, 0x02cc0000u }
+#define TARGET_EMAC_DSC_BASE_ADDR { 0x02c82000u, 0x02cc2000u }
+
+/* Leave mdio disabled */
+#define dev_mdio_open() 1
+
+
+/**
+ * @brief
+ * Device Timer definitions
+ */
+#define TIMER0_BASE 0x025e0000u
+
+#define TIMER_INPUT_DIVIDER 6 /* Timer driven from cpu clock / 6 */
+
+
+/**
+ * @def MAIN_PLL
+ */
+#define MAIN_PLL 0 /**< The index to the main PLL */
+
+/**
+ * @def NET_PLL
+ */
+#define NET_PLL 1 /**< The index to the network PLL */
+
+/**
+ * @def DDR_PLL
+ */
+#define DDR_PLL 2 /**< The index to the DDR PLL */
+
+
+/**
+ * @brief
+ * Device PLL definitions
+ */
+#define DEVICE_PLL_BASE(x) ((x) == MAIN_PLL ? 0x29a0000 : ((x) == NET_PLL ? 0x29c0000 : 0x29c0400))
+
+
+/**
+ * @brief
+ * Device PSC definitions
+ */
+#define DEVICE_PSC_BASE 0x02ae0000u
+
+/**
+ * @brief
+ * The PSC number for ethernet port 0 is 7, and for port 1 it is 8 */
+#define TARGET_PWR_ETH(x) ((x) == 0 ? 7 : 8)
+
+/**
+ * @brief
+ * The nand is done through gpio, which is always powered up.
+ * A value < 0 tells the low level psc driver to simply return success
+ */
+#define TARGET_PWR_NAND -1
+
+
+/**
+ * @brief
+ * Device DDR controller definitions
+ */
+#define DEVICE_DDR_BASE 0x78000000
+
+/**
+ * @brief
+ * The highest module number
+ */
+#define TARGET_PWR_MAX_MOD 13
+
+
+/**
+ * @brief
+ * The base address of MDIO
+ */
+#define TARGET_MDIO_BASE 0x2c81800
+
+/**
+ * @brief
+ * GPIO address
+ */
+#define GPIO_GPIOPID_REG 0x02B00000
+#define GPIO_GPIOEMU_REG 0x02B00004
+#define GPIO_BINTEN_REG 0x02B00008
+#define GPIO_DIR_REG 0x02B00010
+#define GPIO_OUT_DATA_REG 0x02B00014
+#define GPIO_SET_DATA_REG 0x02B00018
+#define GPIO_CLEAR_DATA_REG 0x02B0001C
+#define GPIO_IN_DATA_REG 0x02B00020
+#define GPIO_SET_RIS_TRIG_REG 0x02B00024
+#define GPIO_CLR_RIS_TRIG_REG 0x02B00028
+#define GPIO_SET_FAL_TRIG_REG 0x02B0002C
+#define GPIO_CLR_FAL_TRIG_REG 0x02B00030
+
+/**
+ * @brief
+ * GPIO pin mapping
+ */
+#define NAND_CLE_GPIO_PIN GPIO_8 // High: Command Cycle occuring
+#define NAND_ALE_GPIO_PIN GPIO_9 // High: Address input cycle oddcuring
+#define NAND_NWE_GPIO_PIN GPIO_10
+#define NAND_NRE_GPIO_PIN GPIO_12
+#define NAND_NCE_GPIO_PIN GPIO_13
+#define NAND_MODE_GPIO GPIO_14
+
+/**
+ * @brief
+ * The standard NAND delay must be big enough to handle the highest possible
+ * operating frequency of the device */
+#define TARGET_NAND_STD_DELAY 25 // In cpu cycles
+
+/**
+ * @brief
+ * The base address of the I2C peripheral, and the module divisor of the cpu clock
+ */
+#define DEVICE_I2C_BASE 0x02b04000
+#define DEVICE_I2C_MODULE_DIVISOR 6
+
diff --git a/src/device/c64x/make/makefile b/src/device/c64x/make/makefile
--- /dev/null
@@ -0,0 +1,57 @@
+#*************************************************************************
+#* FILE PURPOSE: Build the IBL device specific module
+#*************************************************************************
+#* FILE NAME: makefile
+#*
+#* DESCRIPTION: Makes the device specific modules
+#*
+#*************************************************************************
+
+ifndef IBL_ROOT
+ export IBL_ROOT=../../..
+endif
+
+ECODIR= $(IBL_ROOT)/device
+
+ifeq ($(TARGET),c6472)
+ CSRC= c6472.c
+endif
+
+ifeq ($(TARGET),c6455)
+ CSRC= c6455.c
+endif
+
+.PHONY: device
+
+
+include $(IBL_ROOT)/make/$(ARCH)/makeeco.mk
+
+
+C6X_C_DIR= $(IBL_ROOT)/device/$(TARGET)
+C6X_C_DIR+= ;$(IBL_ROOT)/device
+C6X_C_DIR+= ;$(IBL_ROOT)
+C6X_C_DIR+= ;$(IBL_ROOT)/arch/$(ARCH)
+C6X_C_DIR+= ;$(STDINC)
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/plls
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/pscs
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/gpio
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/ddrs/emif31
+export C6X_C_DIR
+
+vpath % $(IBL_ROOT)/device/$(TARGET)
+
+
+device: gen_cdefdep makefile $(OBJS)
+
+
+$(OBJS): cdefdep
+
+
+gen_cdefdep:
+ @echo CSRC= $(CSRC)
+ @echo Checking command line dependencies
+ @echo $(ENDIAN) $(TARGET) $(ARCH) > cdefdep.tmp
+ @sh -c 'if diff -q cdefdep.tmp cdefdep ; then echo same ; else $(CP) cdefdep.tmp cdefdep ; fi '
+
+
+
diff --git a/src/device/device.h b/src/device/device.h
--- /dev/null
+++ b/src/device/device.h
@@ -0,0 +1,95 @@
+/**********************************************************************************
+ * FILE PURPOSE: Define the device interface
+ **********************************************************************************
+ * FILE NAME: device.h
+ *
+ * DESCRIPTION: This file defines the device wrapper used by IBL modules
+ *
+ * @file device.h
+ *
+ * @brief
+ * The device wrapper API is defined
+ *
+ ***********************************************************************************/
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include "types.h"
+
+
+/* The target specific file is pointed to via make control. There will be a different
+ target.h file for each platform */
+#include "target.h"
+
+
+
+/**
+ * @brief
+ * Fill in the ibl structure with default values
+ *
+ * @details
+ * If the ibl table is not pre-loaded during the initial boot, then
+ * each device will load a default table.
+ */
+void deviceLoadDefaultIblTable(void);
+
+
+/**
+ * @brief
+ * Convert a local address to a global address
+ *
+ * @details
+ * a local memory address (l1d, l1p, l2) is converted to a global address
+ */
+Uint32 deviceLocalAddrToGlobal (Uint32 local);
+
+
+/**
+ * @brief Configure the PLLs
+ *
+ * @details
+ * The three PLLs are enabled. Only the main PLL has the ability to configure
+ * the multiplier and dividers.
+ */
+void devicePllConfig (void);
+
+
+/**
+ * @brief
+ * Power up a peripheral
+ *
+ * @details
+ * The specified module (and domain if required) is power up
+ */
+int32 devicePowerPeriph (int32 modNum);
+
+
+/**
+ * @brief Enable the DDR controller
+ *
+ * @details
+ * The DDR controller is enabled (optionally)
+ */
+void deviceDdrConfig (void);
+
+
+/**
+ * @brief
+ * Perform device level configuration for nand boot
+ *
+ * @detials
+ * Board/chip specific initializations
+ */
+int32 deviceConfigureForNand(void);
+
+/**
+ * @brief
+ * Load the default ethernet address
+ *
+ * @details
+ * The mac address from e-fuse is loaded
+ */
+void deviceLoadDefaultEthAddress (uint8 *maddr);
+
+#endif
+
diff --git a/src/driver/c64x/make/makefile b/src/driver/c64x/make/makefile
--- /dev/null
@@ -0,0 +1,68 @@
+#*******************************************************************
+#* FILE NAME: makefile
+#*
+#* DESCRIPTION: Makes the peripheral driver modules
+#*
+#*******************************************************************
+
+ifndef IBL_ROOT
+ export IBL_ROOT=../../..
+endif
+
+ECODIR= $(IBL_ROOT)/driver
+
+
+# The ethernet driver
+ETHDIR= eth
+ETHSRC= net.c arp.c ip.c udp.c bootp.c tftp.c
+
+# The stream driver
+STRMDIR= stream
+STRMSRC= stream.c
+
+# The timer driver
+TIMDIR= timer
+TIMSRC= timer.c
+
+# The nand driver
+NANDDIR= nand
+NANDSRC= nand.c
+
+CSRC= $(ETHSRC) $(STRMSRC) $(TIMSRC) $(NANDSRC)
+
+.PHONY: driver
+
+
+include $(IBL_ROOT)/make/$(ARCH)/makeeco.mk
+
+
+C6X_C_DIR= $(IBL_ROOT)
+C6X_C_DIR+= ;$(IBL_ROOT)/arch/$(ARCH)
+C6X_C_DIR+= ;$(ECODIR)
+C6X_C_DIR+= ;$(STDINC)
+C6X_C_DIR+= ;$(IBL_ROOT)/driver/timer
+C6X_C_DIR+= ;$(IBL_ROOT)/driver/stream
+C6X_C_DIR+= ;$(IBL_ROOT)/driver/nand
+C6X_C_DIR+= ;$(IBL_ROOT)/cfg/$(TARGET)
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/timer
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands
+export C6X_C_DIR
+
+vpath % $(ECODIR)/$(ETHDIR); $(ECODIR)/$(STRMDIR); $(ECODIR)/$(TIMDIR); $(ECODIR)/$(NANDDIR)
+
+
+driver: gen_cdefdep makefile $(OBJS)
+
+$(OBJS): cdefdep
+
+
+gen_cdefdep:
+ @echo Checking command line dependencies
+ @echo $(ENDIAN) $(TARGET) > cdefdep.tmp
+ @sh -c 'if diff -q cdefdep.tmp cdefdep ; then echo same ; else $(CP) cdefdep.tmp cdefdep ; fi '
+
+
+
+
+
+
diff --git a/src/driver/eth/arp.c b/src/driver/eth/arp.c
--- /dev/null
+++ b/src/driver/eth/arp.c
@@ -0,0 +1,313 @@
+/**
+ * @file arp.c
+ *
+ * @brief
+ * The file implements the NET Module ARP functionality.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include <string.h>
+
+
+/**********************************************************************
+ *************************** LOCAL Structures *************************
+ **********************************************************************/
+
+/**
+ * @brief
+ * The structure describes the ARP Cache
+ *
+ * @details
+ * This describes the ARP Cache which keeps track of the IPv4 address and
+ * the corresponding Layer2 MAC Address.
+ */
+typedef struct NET_ARP_CACHE
+{
+ /**
+ * @brief This is the MAC Address i.e. Layer2 address matching the
+ * corresponding IP Address.
+ */
+ Uint8 mac_address[6];
+
+ /**
+ * @brief This is the IP Address stored in network order.
+ */
+ IPN ip_address;
+
+ /**
+ * @brief When the upper layers tries to send a packet and
+ * the MAC Address is not resolved; packets are stored in this
+ * temporary area. The ARP stack sends out an ARP request packet
+ * and resolves the IP address. Once the resolution is done pending
+ * packets are transmitted.
+ */
+ Uint8 pending_packet[NET_MAX_MTU];
+
+ /**
+ * @brief This is the length of the pending packet. A value of 0
+ * indicates that there is no pending packet in the ARP cache.
+ */
+ Uint16 pending_packet_len;
+}NET_ARP_CACHE;
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @brief This is the ARP cache; which keeps track of the IP Address to
+ * MAC Address mapping.
+ */
+NET_ARP_CACHE net_arp_cache;
+
+/**********************************************************************
+ **************************** ARP Functions ***************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * This function is called by the IP Layer to resolve the layer3
+ * address to a layer2 MAC address. The function checks the ARP cache
+ * for a match but if no entry exists then the functions sends out
+ * an ARP request and it places this packet into the pending queue.
+ *
+ * @param[in] dst_ip
+ * This is the destination IP address of the packet.
+ * @param[in] ptr_iphdr
+ * This is the pointer to the IP header
+ * @param[in] l3_pkt_size
+ * This is the size of the packet (including the IP Header)
+ *
+ * @retval
+ * Not Applicable.
+ */
+void arp_resolve (IPN dst_ip, IPHDR* ptr_iphdr, Uint16 l3_pkt_size)
+{
+ ARPHDR* ptr_arphdr;
+ ETHHDR* ptr_ethhdr;
+ Uint8 BroadcastMac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ /* Special Case: Are we sending the packet to 255.255.255.255? */
+ if (dst_ip == (IPN)0xFFFFFFFF)
+ {
+ /* YES. This implies that the destination MAC Address in the packet is the Broadcast address
+ * We dont need to lookup the cache. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_iphdr, (void *)&BroadcastMac[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* We now have a completed Ethernet packet; send it across. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + l3_pkt_size);
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+ return;
+ }
+
+ /* Check if the destination IP Address matches the ARP cache */
+ if (net_arp_cache.ip_address == dst_ip)
+ {
+ /* Make sure the MAC Address in the CACHE has been resolved i.e. Non-Zero. */
+ if ( (net_arp_cache.mac_address[0] != 0x00) || (net_arp_cache.mac_address[1] != 0x00) ||
+ (net_arp_cache.mac_address[2] != 0x00) || (net_arp_cache.mac_address[3] != 0x00) ||
+ (net_arp_cache.mac_address[4] != 0x00) || (net_arp_cache.mac_address[5] != 0x00) )
+ {
+ /* Perfect; the MAC Address is already resolved.
+ * We can simply use the ARP CACHE MAC address to create the layer2 header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_iphdr, (void *)&net_arp_cache.mac_address[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* We now have a completed Ethernet packet; send it across. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + l3_pkt_size);
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+ return;
+ }
+ }
+
+ /* Initialize the ARP Cache: The cache did not have information for the resolution to work
+ * Reset the cache and start again. */
+ memset ((void *)&net_arp_cache, 0, sizeof(NET_ARP_CACHE));
+
+ /* Populate the ARP Cache */
+ net_arp_cache.ip_address = dst_ip;
+ net_arp_cache.pending_packet_len = l3_pkt_size;
+ memcpy ((void *)&net_arp_cache.pending_packet[0], (void *)ptr_iphdr, l3_pkt_size);
+
+ /* Free up the packet now; we have already stored it in the ARP cache. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+
+ /* Allocate a new packet to send out the ARP request. */
+ ptr_arphdr = (ARPHDR *)net_alloc_tx_packet(sizeof(ARPHDR));
+ if (ptr_arphdr == NULL)
+ return;
+
+ /* Populate the ARP Header. */
+ ptr_arphdr->HardType = htons(0x1);
+ ptr_arphdr->ProtocolType = htons(0x800);
+ ptr_arphdr->HardSize = 0x6;
+ ptr_arphdr->ProtocolSize = 0x4;
+ ptr_arphdr->Op = htons(0x1);
+
+ /* Populate the Source IP/MAC Address */
+ memcpy ((void *)&ptr_arphdr->SrcAddr[0], (void *)&netmcb.net_device.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPSrc[0], (void *)&netmcb.net_device.ip_address, 4);
+
+ /* Populate the Target IP/MAC Address: This is set to 0 since the cache has been reset above. */
+ memcpy ((void *)&ptr_arphdr->DstAddr[0], (void *)&net_arp_cache.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPDst[0], (void *)&dst_ip, 4);
+
+ /* Create the Ethernet header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_arphdr, &BroadcastMac[0], 0x806);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + sizeof(ARPHDR));
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_arphdr);
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function handles the reception and processing of ARP packets.
+ *
+ * @param[in] ptr_arphdr
+ * This is the pointer to the received ARP header.
+ * @param[in] num_bytes
+ * This is the size of the ARP packet.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 arp_receive (ARPHDR* ptr_arphdr, Int32 num_bytes)
+{
+ Uint32 IPAddress;
+ Uint8* ptr_pending_pkt;
+ ETHHDR* ptr_ethhdr;
+
+ /* Extract the intended target and convert it to host format. */
+ IPAddress = READ32(ptr_arphdr->IPDst);
+
+ /* Ensure that the packet has not been looped back and we received our own frame. */
+ if ((ptr_arphdr->SrcAddr[0] == netmcb.net_device.mac_address[0]) &&
+ (ptr_arphdr->SrcAddr[1] == netmcb.net_device.mac_address[1]) &&
+ (ptr_arphdr->SrcAddr[2] == netmcb.net_device.mac_address[2]) &&
+ (ptr_arphdr->SrcAddr[3] == netmcb.net_device.mac_address[3]) &&
+ (ptr_arphdr->SrcAddr[4] == netmcb.net_device.mac_address[4]) &&
+ (ptr_arphdr->SrcAddr[5] == netmcb.net_device.mac_address[5]))
+ {
+ /* We received our own frame; ignore this. */
+ return -1;
+ }
+
+ /* Check if the packet is meant for us? If it not meant for us we drop the packet. */
+ if (IPAddress != netmcb.net_device.ip_address)
+ return -1;
+
+ /* The ARP packet was meant for us; we need to update the ARP cache with the request. */
+ net_arp_cache.ip_address = READ32(ptr_arphdr->IPSrc);
+ memcpy ((void *)&net_arp_cache.mac_address[0], (void *)&ptr_arphdr->SrcAddr[0], 6);
+
+ /* Check if the packet is an ARP request? */
+ if (ptr_arphdr->Op == htons(0x1))
+ {
+ /* YES. We need to send out an ARP Reply; so create the packet.
+ * Ensure that the Layer3 headers are aligned on the 4 byte boundary
+ * and yet we have sufficient space for the Ethernet header. */
+ ptr_arphdr = (ARPHDR *)net_alloc_tx_packet(sizeof(ARPHDR));
+ if (ptr_arphdr == NULL)
+ return -1;
+
+ /* Populate the ARP Header. */
+ ptr_arphdr->HardType = htons(0x1);
+ ptr_arphdr->ProtocolType = htons(0x800);
+ ptr_arphdr->HardSize = 0x6;
+ ptr_arphdr->ProtocolSize = 0x4;
+ ptr_arphdr->Op = htons(0x2);
+
+ /* Populate the Source IP/MAC Address in the ARP Header */
+ memcpy ((void *)&ptr_arphdr->SrcAddr[0], (void *)&netmcb.net_device.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPSrc[0], (void *)&netmcb.net_device.ip_address, 4);
+
+ /* Populate the Target IP/MAC Address in the ARP Header */
+ memcpy ((void *)&ptr_arphdr->DstAddr[0], (void *)&net_arp_cache.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPDst[0], (void *)&net_arp_cache.ip_address, 4);
+
+ /* Create the Ethernet header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_arphdr, &net_arp_cache.mac_address[0], 0x806);
+ if (ptr_ethhdr == NULL)
+ return -1;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + sizeof(ARPHDR));
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_arphdr);
+ }
+
+ /* Check if there are any packet awaiting resolution? */
+ if (net_arp_cache.pending_packet_len != 0)
+ {
+ /* There was a packet in the ARP cache which was awaiting resolution.
+ * We need to send out the packet now. */
+ ptr_pending_pkt = net_alloc_tx_packet(net_arp_cache.pending_packet_len);
+ if (ptr_pending_pkt == NULL)
+ return -1;
+
+ /* We now copy the contents of this packet from the ARP cache */
+ memcpy ((void *)ptr_pending_pkt, (void *)&net_arp_cache.pending_packet[0],
+ net_arp_cache.pending_packet_len);
+
+ /* We create the Ethernet header.
+ * Only IPv4 packets await resolution. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_pending_pkt, &net_arp_cache.mac_address[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return -1;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + net_arp_cache.pending_packet_len);
+
+ /* The pending packet in the cache has been sent out. */
+ net_arp_cache.pending_packet_len = 0;
+
+ /* The packet has been transmitted and can be cleaned up. */
+ net_free_tx_packet (ptr_pending_pkt);
+ }
+
+ /* ARP Packet has been successfully processed. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function initializes the ARP Module in the NET Boot module.
+ *
+ * @retval
+ * Not Applicable
+ */
+void arp_init (void)
+{
+ memset (&net_arp_cache, 0, sizeof(NET_ARP_CACHE));
+ return;
+}
+
+
+
diff --git a/src/driver/eth/arp.pretimer.c b/src/driver/eth/arp.pretimer.c
--- /dev/null
@@ -0,0 +1,313 @@
+/**
+ * @file arp.c
+ *
+ * @brief
+ * The file implements the NET Module ARP functionality.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include <string.h>
+
+
+/**********************************************************************
+ *************************** LOCAL Structures *************************
+ **********************************************************************/
+
+/**
+ * @brief
+ * The structure describes the ARP Cache
+ *
+ * @details
+ * This describes the ARP Cache which keeps track of the IPv4 address and
+ * the corresponding Layer2 MAC Address.
+ */
+typedef struct NET_ARP_CACHE
+{
+ /**
+ * @brief This is the MAC Address i.e. Layer2 address matching the
+ * corresponding IP Address.
+ */
+ Uint8 mac_address[6];
+
+ /**
+ * @brief This is the IP Address stored in network order.
+ */
+ IPN ip_address;
+
+ /**
+ * @brief When the upper layers tries to send a packet and
+ * the MAC Address is not resolved; packets are stored in this
+ * temporary area. The ARP stack sends out an ARP request packet
+ * and resolves the IP address. Once the resolution is done pending
+ * packets are transmitted.
+ */
+ Uint8 pending_packet[NET_MAX_MTU];
+
+ /**
+ * @brief This is the length of the pending packet. A value of 0
+ * indicates that there is no pending packet in the ARP cache.
+ */
+ Uint16 pending_packet_len;
+}NET_ARP_CACHE;
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @brief This is the ARP cache; which keeps track of the IP Address to
+ * MAC Address mapping.
+ */
+NET_ARP_CACHE net_arp_cache;
+
+/**********************************************************************
+ **************************** ARP Functions ***************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * This function is called by the IP Layer to resolve the layer3
+ * address to a layer2 MAC address. The function checks the ARP cache
+ * for a match but if no entry exists then the functions sends out
+ * an ARP request and it places this packet into the pending queue.
+ *
+ * @param[in] dst_ip
+ * This is the destination IP address of the packet.
+ * @param[in] ptr_iphdr
+ * This is the pointer to the IP header
+ * @param[in] l3_pkt_size
+ * This is the size of the packet (including the IP Header)
+ *
+ * @retval
+ * Not Applicable.
+ */
+void arp_resolve (IPN dst_ip, IPHDR* ptr_iphdr, Uint16 l3_pkt_size)
+{
+ ARPHDR* ptr_arphdr;
+ ETHHDR* ptr_ethhdr;
+ Uint8 BroadcastMac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ /* Special Case: Are we sending the packet to 255.255.255.255? */
+ if (dst_ip == (IPN)0xFFFFFFFF)
+ {
+ /* YES. This implies that the destination MAC Address in the packet is the Broadcast address
+ * We dont need to lookup the cache. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_iphdr, (void *)&BroadcastMac[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* We now have a completed Ethernet packet; send it across. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + l3_pkt_size);
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+ return;
+ }
+
+ /* Check if the destination IP Address matches the ARP cache */
+ if (net_arp_cache.ip_address == dst_ip)
+ {
+ /* Make sure the MAC Address in the CACHE has been resolved i.e. Non-Zero. */
+ if ( (net_arp_cache.mac_address[0] != 0x00) || (net_arp_cache.mac_address[1] != 0x00) ||
+ (net_arp_cache.mac_address[2] != 0x00) || (net_arp_cache.mac_address[3] != 0x00) ||
+ (net_arp_cache.mac_address[4] != 0x00) || (net_arp_cache.mac_address[5] != 0x00) )
+ {
+ /* Perfect; the MAC Address is already resolved.
+ * We can simply use the ARP CACHE MAC address to create the layer2 header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_iphdr, (void *)&net_arp_cache.mac_address[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* We now have a completed Ethernet packet; send it across. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + l3_pkt_size);
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+ return;
+ }
+ }
+
+ /* Initialize the ARP Cache: The cache did not have information for the resolution to work
+ * Reset the cache and start again. */
+ memset ((void *)&net_arp_cache, 0, sizeof(NET_ARP_CACHE));
+
+ /* Populate the ARP Cache */
+ net_arp_cache.ip_address = dst_ip;
+ net_arp_cache.pending_packet_len = l3_pkt_size;
+ memcpy ((void *)&net_arp_cache.pending_packet[0], (void *)ptr_iphdr, l3_pkt_size);
+
+ /* Free up the packet now; we have already stored it in the ARP cache. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+
+ /* Allocate a new packet to send out the ARP request. */
+ ptr_arphdr = (ARPHDR *)net_alloc_tx_packet(sizeof(ARPHDR));
+ if (ptr_arphdr == NULL)
+ return;
+
+ /* Populate the ARP Header. */
+ ptr_arphdr->HardType = htons(0x1);
+ ptr_arphdr->ProtocolType = htons(0x800);
+ ptr_arphdr->HardSize = 0x6;
+ ptr_arphdr->ProtocolSize = 0x4;
+ ptr_arphdr->Op = htons(0x1);
+
+ /* Populate the Source IP/MAC Address */
+ memcpy ((void *)&ptr_arphdr->SrcAddr[0], (void *)&netmcb.net_device.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPSrc[0], (void *)&netmcb.net_device.ip_address, 4);
+
+ /* Populate the Target IP/MAC Address: This is set to 0 since the cache has been reset above. */
+ memcpy ((void *)&ptr_arphdr->DstAddr[0], (void *)&net_arp_cache.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPDst[0], (void *)&dst_ip, 4);
+
+ /* Create the Ethernet header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_arphdr, &BroadcastMac[0], 0x806);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + sizeof(ARPHDR));
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_arphdr);
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function handles the reception and processing of ARP packets.
+ *
+ * @param[in] ptr_arphdr
+ * This is the pointer to the received ARP header.
+ * @param[in] num_bytes
+ * This is the size of the ARP packet.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 arp_receive (ARPHDR* ptr_arphdr, Int32 num_bytes)
+{
+ Uint32 IPAddress;
+ Uint8* ptr_pending_pkt;
+ ETHHDR* ptr_ethhdr;
+
+ /* Extract the intended target and convert it to host format. */
+ IPAddress = READ32(ptr_arphdr->IPDst);
+
+ /* Ensure that the packet has not been looped back and we received our own frame. */
+ if ((ptr_arphdr->SrcAddr[0] == netmcb.net_device.mac_address[0]) &&
+ (ptr_arphdr->SrcAddr[1] == netmcb.net_device.mac_address[1]) &&
+ (ptr_arphdr->SrcAddr[2] == netmcb.net_device.mac_address[2]) &&
+ (ptr_arphdr->SrcAddr[3] == netmcb.net_device.mac_address[3]) &&
+ (ptr_arphdr->SrcAddr[4] == netmcb.net_device.mac_address[4]) &&
+ (ptr_arphdr->SrcAddr[5] == netmcb.net_device.mac_address[5]))
+ {
+ /* We received our own frame; ignore this. */
+ return -1;
+ }
+
+ /* Check if the packet is meant for us? If it not meant for us we drop the packet. */
+ if (IPAddress != netmcb.net_device.ip_address)
+ return -1;
+
+ /* The ARP packet was meant for us; we need to update the ARP cache with the request. */
+ net_arp_cache.ip_address = READ32(ptr_arphdr->IPSrc);
+ memcpy ((void *)&net_arp_cache.mac_address[0], (void *)&ptr_arphdr->SrcAddr[0], 6);
+
+ /* Check if the packet is an ARP request? */
+ if (ptr_arphdr->Op == htons(0x1))
+ {
+ /* YES. We need to send out an ARP Reply; so create the packet.
+ * Ensure that the Layer3 headers are aligned on the 4 byte boundary
+ * and yet we have sufficient space for the Ethernet header. */
+ ptr_arphdr = (ARPHDR *)net_alloc_tx_packet(sizeof(ARPHDR));
+ if (ptr_arphdr == NULL)
+ return -1;
+
+ /* Populate the ARP Header. */
+ ptr_arphdr->HardType = htons(0x1);
+ ptr_arphdr->ProtocolType = htons(0x800);
+ ptr_arphdr->HardSize = 0x6;
+ ptr_arphdr->ProtocolSize = 0x4;
+ ptr_arphdr->Op = htons(0x2);
+
+ /* Populate the Source IP/MAC Address in the ARP Header */
+ memcpy ((void *)&ptr_arphdr->SrcAddr[0], (void *)&netmcb.net_device.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPSrc[0], (void *)&netmcb.net_device.ip_address, 4);
+
+ /* Populate the Target IP/MAC Address in the ARP Header */
+ memcpy ((void *)&ptr_arphdr->DstAddr[0], (void *)&net_arp_cache.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPDst[0], (void *)&net_arp_cache.ip_address, 4);
+
+ /* Create the Ethernet header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_arphdr, &net_arp_cache.mac_address[0], 0x806);
+ if (ptr_ethhdr == NULL)
+ return -1;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + sizeof(ARPHDR));
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_arphdr);
+ }
+
+ /* Check if there are any packet awaiting resolution? */
+ if (net_arp_cache.pending_packet_len != 0)
+ {
+ /* There was a packet in the ARP cache which was awaiting resolution.
+ * We need to send out the packet now. */
+ ptr_pending_pkt = net_alloc_tx_packet(net_arp_cache.pending_packet_len);
+ if (ptr_pending_pkt == NULL)
+ return -1;
+
+ /* We now copy the contents of this packet from the ARP cache */
+ memcpy ((void *)ptr_pending_pkt, (void *)&net_arp_cache.pending_packet[0],
+ net_arp_cache.pending_packet_len);
+
+ /* We create the Ethernet header.
+ * Only IPv4 packets await resolution. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_pending_pkt, &net_arp_cache.mac_address[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return -1;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + net_arp_cache.pending_packet_len);
+
+ /* The pending packet in the cache has been sent out. */
+ net_arp_cache.pending_packet_len = 0;
+
+ /* The packet has been transmitted and can be cleaned up. */
+ net_free_tx_packet (ptr_pending_pkt);
+ }
+
+ /* ARP Packet has been successfully processed. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function initializes the ARP Module in the NET Boot module.
+ *
+ * @retval
+ * Not Applicable
+ */
+void arp_init (void)
+{
+ memset (&net_arp_cache, 0, sizeof(NET_ARP_CACHE));
+ return;
+}
+
+
+
diff --git a/src/driver/eth/arp.timer.c b/src/driver/eth/arp.timer.c
--- /dev/null
@@ -0,0 +1,352 @@
+/**
+ * @file arp.c
+ *
+ * @brief
+ * The file implements the NET Module ARP functionality.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include "timer.h"
+#include <string.h>
+
+
+/**********************************************************************
+ *************************** LOCAL Structures *************************
+ **********************************************************************/
+
+/**
+ * @brief
+ * The structure describes the ARP Cache
+ *
+ * @details
+ * This describes the ARP Cache which keeps track of the IPv4 address and
+ * the corresponding Layer2 MAC Address.
+ */
+typedef struct NET_ARP_CACHE
+{
+ /**
+ * @brief This is the MAC Address i.e. Layer2 address matching the
+ * corresponding IP Address.
+ */
+ Uint8 mac_address[6];
+
+ /**
+ * @brief This is the IP Address stored in network order.
+ */
+ IPN ip_address;
+
+ /**
+ * @brief When the upper layers tries to send a packet and
+ * the MAC Address is not resolved; packets are stored in this
+ * temporary area. The ARP stack sends out an ARP request packet
+ * and resolves the IP address. Once the resolution is done pending
+ * packets are transmitted.
+ */
+ Uint8 pending_packet[NET_MAX_MTU];
+
+ /**
+ * @brief This is the length of the pending packet. A value of 0
+ * indicates that there is no pending packet in the ARP cache.
+ */
+ Uint16 pending_packet_len;
+
+ /**
+ * @brief The timer used to handle arp request timeouts
+ */
+ Int32 timer;
+
+ /**
+ * @brief The number of times an arp request was resent
+ */
+ Uint32 resend_count;
+
+}NET_ARP_CACHE;
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @brief This is the ARP cache; which keeps track of the IP Address to
+ * MAC Address mapping.
+ */
+NET_ARP_CACHE net_arp_cache;
+
+/**********************************************************************
+ **************************** ARP Functions ***************************
+ **********************************************************************/
+
+void arp_send (void)
+{
+ ARPHDR* ptr_arphdr;
+ ETHHDR* ptr_ethhdr;
+ Uint8 BroadcastMac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ /* If the address has been resolved then the arp reply was received, despite the timeout */
+ if ( (net_arp_cache.mac_address[0] != 0x00) || (net_arp_cache.mac_address[1] != 0x00) ||
+ (net_arp_cache.mac_address[2] != 0x00) || (net_arp_cache.mac_address[3] != 0x00) ||
+ (net_arp_cache.mac_address[4] != 0x00) || (net_arp_cache.mac_address[5] != 0x00) )
+ return;
+
+ /* Allocate a new packet to send out the ARP request. */
+ ptr_arphdr = (ARPHDR *)net_alloc_tx_packet(sizeof(ARPHDR));
+ if (ptr_arphdr == NULL)
+ return;
+
+ /* Populate the ARP Header. */
+ ptr_arphdr->HardType = htons(0x1);
+ ptr_arphdr->ProtocolType = htons(0x800);
+ ptr_arphdr->HardSize = 0x6;
+ ptr_arphdr->ProtocolSize = 0x4;
+ ptr_arphdr->Op = htons(0x1);
+
+ /* Populate the Source IP/MAC Address */
+ memcpy ((void *)&ptr_arphdr->SrcAddr[0], (void *)&netmcb.net_device.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPSrc[0], (void *)&netmcb.net_device.ip_address, 4);
+
+ /* Populate the Target IP/MAC Address: This is likely set to 0 since the cache has been reset on the first send. */
+ memcpy ((void *)&ptr_arphdr->DstAddr[0], (void *)&net_arp_cache.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPDst[0], (void *)&net_arp_cache.ip_address, 4);
+
+ /* Create the Ethernet header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_arphdr, &BroadcastMac[0], 0x806);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + sizeof(ARPHDR));
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_arphdr);
+
+}
+
+void arp_timer_expiry (void)
+{
+ /* ARP request timeout. Resend */
+ arp_send();
+
+ net_arp_cache.resend_count += 1;
+}
+
+/**
+ * @b Description
+ * @n
+ * This function is called by the IP Layer to resolve the layer3
+ * address to a layer2 MAC address. The function checks the ARP cache
+ * for a match but if no entry exists then the functions sends out
+ * an ARP request and it places this packet into the pending queue.
+ *
+ * @param[in] dst_ip
+ * This is the destination IP address of the packet.
+ * @param[in] ptr_iphdr
+ * This is the pointer to the IP header
+ * @param[in] l3_pkt_size
+ * This is the size of the packet (including the IP Header)
+ *
+ * @retval
+ * Not Applicable.
+ */
+void arp_resolve (IPN dst_ip, IPHDR* ptr_iphdr, Uint16 l3_pkt_size)
+{
+ ETHHDR* ptr_ethhdr;
+ Uint8 BroadcastMac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ /* Special Case: Are we sending the packet to 255.255.255.255? */
+ if (dst_ip == (IPN)0xFFFFFFFF)
+ {
+ /* YES. This implies that the destination MAC Address in the packet is the Broadcast address
+ * We dont need to lookup the cache. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_iphdr, (void *)&BroadcastMac[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* We now have a completed Ethernet packet; send it across. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + l3_pkt_size);
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+ return;
+ }
+
+ /* Check if the destination IP Address matches the ARP cache */
+ if (net_arp_cache.ip_address == dst_ip)
+ {
+ /* Make sure the MAC Address in the CACHE has been resolved i.e. Non-Zero. */
+ if ( (net_arp_cache.mac_address[0] != 0x00) || (net_arp_cache.mac_address[1] != 0x00) ||
+ (net_arp_cache.mac_address[2] != 0x00) || (net_arp_cache.mac_address[3] != 0x00) ||
+ (net_arp_cache.mac_address[4] != 0x00) || (net_arp_cache.mac_address[5] != 0x00) )
+ {
+ /* Perfect; the MAC Address is already resolved.
+ * We can simply use the ARP CACHE MAC address to create the layer2 header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_iphdr, (void *)&net_arp_cache.mac_address[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return;
+
+ /* We now have a completed Ethernet packet; send it across. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + l3_pkt_size);
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+ return;
+ }
+ }
+
+ /* Initialize the ARP Cache: The cache did not have information for the resolution to work
+ * Reset the cache and start again. */
+ memset ((void *)&net_arp_cache, 0, sizeof(NET_ARP_CACHE));
+
+ /* Populate the ARP Cache */
+ net_arp_cache.ip_address = dst_ip;
+ net_arp_cache.pending_packet_len = l3_pkt_size;
+ memcpy ((void *)&net_arp_cache.pending_packet[0], (void *)ptr_iphdr, l3_pkt_size);
+
+ /* Free up the packet now; we have already stored it in the ARP cache. */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+
+ net_arp_cache.timer = timer_add (ARP_TIMEOUT, arp_timer_expiry);
+
+ arp_send ();
+
+}
+
+/**
+ * @b Description
+ * @n
+ * The function handles the reception and processing of ARP packets.
+ *
+ * @param[in] ptr_arphdr
+ * This is the pointer to the received ARP header.
+ * @param[in] num_bytes
+ * This is the size of the ARP packet.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 arp_receive (ARPHDR* ptr_arphdr, Int32 num_bytes)
+{
+ Uint32 IPAddress;
+ Uint8* ptr_pending_pkt;
+ ETHHDR* ptr_ethhdr;
+
+ /* Extract the intended target and convert it to host format. */
+ IPAddress = READ32(ptr_arphdr->IPDst);
+
+ /* Ensure that the packet has not been looped back and we received our own frame. */
+ if ((ptr_arphdr->SrcAddr[0] == netmcb.net_device.mac_address[0]) &&
+ (ptr_arphdr->SrcAddr[1] == netmcb.net_device.mac_address[1]) &&
+ (ptr_arphdr->SrcAddr[2] == netmcb.net_device.mac_address[2]) &&
+ (ptr_arphdr->SrcAddr[3] == netmcb.net_device.mac_address[3]) &&
+ (ptr_arphdr->SrcAddr[4] == netmcb.net_device.mac_address[4]) &&
+ (ptr_arphdr->SrcAddr[5] == netmcb.net_device.mac_address[5]))
+ {
+ /* We received our own frame; ignore this. */
+ return -1;
+ }
+
+ /* Check if the packet is meant for us? If it not meant for us we drop the packet. */
+ if (IPAddress != netmcb.net_device.ip_address)
+ return -1;
+
+ /* The ARP packet was meant for us; we need to update the ARP cache with the request. */
+ net_arp_cache.ip_address = READ32(ptr_arphdr->IPSrc);
+ memcpy ((void *)&net_arp_cache.mac_address[0], (void *)&ptr_arphdr->SrcAddr[0], 6);
+
+ /* Check if the packet is an ARP request? */
+ if (ptr_arphdr->Op == htons(0x1))
+ {
+ /* YES. We need to send out an ARP Reply; so create the packet.
+ * Ensure that the Layer3 headers are aligned on the 4 byte boundary
+ * and yet we have sufficient space for the Ethernet header. */
+ ptr_arphdr = (ARPHDR *)net_alloc_tx_packet(sizeof(ARPHDR));
+ if (ptr_arphdr == NULL)
+ return -1;
+
+ /* Populate the ARP Header. */
+ ptr_arphdr->HardType = htons(0x1);
+ ptr_arphdr->ProtocolType = htons(0x800);
+ ptr_arphdr->HardSize = 0x6;
+ ptr_arphdr->ProtocolSize = 0x4;
+ ptr_arphdr->Op = htons(0x2);
+
+ /* Populate the Source IP/MAC Address in the ARP Header */
+ memcpy ((void *)&ptr_arphdr->SrcAddr[0], (void *)&netmcb.net_device.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPSrc[0], (void *)&netmcb.net_device.ip_address, 4);
+
+ /* Populate the Target IP/MAC Address in the ARP Header */
+ memcpy ((void *)&ptr_arphdr->DstAddr[0], (void *)&net_arp_cache.mac_address[0], 6);
+ memcpy ((void *)&ptr_arphdr->IPDst[0], (void *)&net_arp_cache.ip_address, 4);
+
+ /* Create the Ethernet header. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_arphdr, &net_arp_cache.mac_address[0], 0x806);
+ if (ptr_ethhdr == NULL)
+ return -1;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + sizeof(ARPHDR));
+
+ /* The packet has been transmitted and we can clean it up now. */
+ net_free_tx_packet ((Uint8 *)ptr_arphdr);
+ }
+
+ /* Check if there are any packet awaiting resolution? */
+ if (net_arp_cache.pending_packet_len != 0)
+ {
+ /* There was a packet in the ARP cache which was awaiting resolution.
+ * We need to send out the packet now. */
+ ptr_pending_pkt = net_alloc_tx_packet(net_arp_cache.pending_packet_len);
+ if (ptr_pending_pkt == NULL)
+ return -1;
+
+ /* We now copy the contents of this packet from the ARP cache */
+ memcpy ((void *)ptr_pending_pkt, (void *)&net_arp_cache.pending_packet[0],
+ net_arp_cache.pending_packet_len);
+
+ /* We create the Ethernet header.
+ * Only IPv4 packets await resolution. */
+ ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_pending_pkt, &net_arp_cache.mac_address[0], 0x800);
+ if (ptr_ethhdr == NULL)
+ return -1;
+
+ /* Send the packet out. */
+ net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + net_arp_cache.pending_packet_len);
+
+ /* The pending packet in the cache has been sent out. */
+ net_arp_cache.pending_packet_len = 0;
+
+ /* The packet has been transmitted and can be cleaned up. */
+ net_free_tx_packet (ptr_pending_pkt);
+
+ timer_delete (net_arp_cache.timer);
+ }
+
+ /* ARP Packet has been successfully processed. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function initializes the ARP Module in the NET Boot module.
+ *
+ * @retval
+ * Not Applicable
+ */
+void arp_init (void)
+{
+ memset (&net_arp_cache, 0, sizeof(NET_ARP_CACHE));
+ return;
+}
+
+
+
diff --git a/src/driver/eth/bootp.c b/src/driver/eth/bootp.c
--- /dev/null
+++ b/src/driver/eth/bootp.c
@@ -0,0 +1,377 @@
+/**
+ * @file bootp.c
+ *
+ * @brief
+ * The file implements the NET Module BOOTP functionality.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include "timer.h"
+#include "stream.h"
+#include <string.h>
+
+
+/**********************************************************************
+ *************************** LOCAL Structures *************************
+ **********************************************************************/
+
+/**
+ * @brief
+ * The structure describes the BOOTP Master Control Block.
+ *
+ * @details
+ * The BOOTP Master control block stores information used by the
+ * BOOTP module.
+ */
+typedef struct BOOTP_MCB
+{
+ /**
+ * @brief This is the BOOTP header which is populated and sent across
+ * to the server.
+ */
+ BOOTPHDR boothdr;
+
+ /**
+ * @brief This is the BOOTP handle to the UDP socket.
+ */
+ Int32 sock;
+
+ /**
+ * @brief This is the number of BOOTP requests sent out.
+ */
+ Int32 num_request;
+
+ /**
+ * @brief This is the BOOTP timer handle.
+ */
+ Int32 bootp_timer;
+
+ /**
+ * @brief The optional application call back when the
+ * bootp file name and IP address has been received.
+ */
+ void (*asyncComplete)(void *);
+
+}BOOTP_MCB;
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @brief This is the global master control block for the BOOTP module
+ * and stores all the necessary information.
+ */
+BOOTP_MCB bootpmcb;
+
+/**********************************************************************
+ **************************** BOOTP Functions *************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * This is a call back function registered with the TIMER module
+ * to be called if there is a timeout and no BOOTP reply is
+ * received.
+ *
+ * @retval
+ * Not Applicable.
+ */
+static void bootp_tmr_expiry (void)
+{
+ BOOTPHDR* ptr_bootphdr;
+
+ /* Get the pointer to the BOOTP Header. */
+ ptr_bootphdr = &bootpmcb.boothdr;
+
+ /* Populate the BOOTP header with all the information we have. */
+ ptr_bootphdr->op = BOOTP_OP_REQUEST;
+ ptr_bootphdr->htype = BOOTP_HTYPE_ETHERNET;
+ ptr_bootphdr->hlen = 6;
+ ptr_bootphdr->xid = htonl(0x1);
+ memcpy ((void *)&ptr_bootphdr->chaddr, (void *)&netmcb.net_device.mac_address[0], 6);
+
+ /* The packet has been populated; send it to the server. */
+ udp_sock_send (bootpmcb.sock, (Uint8 *)ptr_bootphdr, sizeof(BOOTPHDR));
+
+ /* Increment the number of requests sent out. */
+ bootpmcb.num_request++;
+
+ /* We need to delete the current timer and create another with the backoff strategy. */
+ timer_delete (bootpmcb.bootp_timer);
+
+ /* Check if we have exceeded the max. permissible? */
+ if (bootpmcb.num_request > BOOTP_MAX_RETRIES)
+ {
+ /* Error: Maximum retransmissions have been exceeded; indicate error. */
+ mprintf ("BOOTP Failure: Max Retransmissions exceeded\n");
+ net_set_error ();
+ udp_sock_close(bootpmcb.sock);
+ return;
+ }
+
+ /* Create the new backoff timer. */
+ bootpmcb.bootp_timer = timer_add (BOOTP_SEED_TIMEOUT*bootpmcb.num_request, bootp_tmr_expiry);
+ if (bootpmcb.bootp_timer < 0)
+ {
+ /* Error: Unable to create the new backoff timer; indicate error. */
+ mprintf ("BOOTP Failure: Backoff timer failed\n");
+ net_set_error ();
+ stream_close();
+ udp_sock_close(bootpmcb.sock);
+ return;
+ }
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * This is a call back function registered with the UDP module to
+ * be invoked when a BOOTP packet is received.
+ *
+ * @param[in] sock
+ * This is the socket handle on which packet was received.
+ * @param[in] ptr_data
+ * This is the pointer to the BOOTP data payload.
+ * @param[in] num_bytes
+ * This is the number of bytes of BOOTP data received.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 bootp_receive (Int32 sock, Uint8* ptr_data, Int32 num_bytes)
+{
+ BOOTPHDR* ptr_bootphdr;
+ Int32 index = 0;
+ IPN subnetmask = BOOTP_DEFAULT_MASK;
+ IPN defaultRouter = 0;
+ IPN serverIP = 0;
+
+ /* Received a BOOTP packet from the UDP stack. */
+ ptr_bootphdr = (BOOTPHDR *)ptr_data;
+
+ /* Check if this is a BOOTP reply packet? */
+ if (ptr_bootphdr->op != BOOTP_OP_REPLY)
+ return -1;
+
+ /* Ensure the transaction id matches the one we sent out. */
+ if (ptr_bootphdr->xid != bootpmcb.boothdr.xid)
+ return -1;
+
+ /* Ensure the MAC Address matches our MAC Address */
+ if ((ptr_bootphdr->chaddr[0] != netmcb.net_device.mac_address[0]) ||
+ (ptr_bootphdr->chaddr[1] != netmcb.net_device.mac_address[1]) ||
+ (ptr_bootphdr->chaddr[2] != netmcb.net_device.mac_address[2]) ||
+ (ptr_bootphdr->chaddr[3] != netmcb.net_device.mac_address[3]) ||
+ (ptr_bootphdr->chaddr[4] != netmcb.net_device.mac_address[4]) ||
+ (ptr_bootphdr->chaddr[5] != netmcb.net_device.mac_address[5]))
+ {
+ /* The MAC Address do not match. Ignore the reply packet */
+ return -1;
+ }
+
+ /* Cycle through the options; we are only interested in retreiving the SUBNET Mask option
+ * Since we need to configure the routing table. */
+ while (index < 64)
+ {
+ /* Get the option tag and process it appropriately. */
+ switch (ptr_bootphdr->options[index])
+ {
+ case 0x0:
+ {
+ /* Padding option. Skip this. */
+ index++;
+ break;
+ }
+ case 0x1:
+ {
+ /* SUBNET option. Got it! We dont need to parse anymore. */
+ subnetmask = ((ptr_bootphdr->options[index+2] << 24) |
+ (ptr_bootphdr->options[index+3] << 16) |
+ (ptr_bootphdr->options[index+4] << 8) |
+ (ptr_bootphdr->options[index+5]));
+
+ /* Jump to the next option. */
+ index = index + ptr_bootphdr->options[index + 1] + 2;
+ break;
+ }
+ case 0x3:
+ {
+ /* ROUTER option. Got it! We dont need to parse anymore. */
+ defaultRouter = ((ptr_bootphdr->options[index+2] << 24) |
+ (ptr_bootphdr->options[index+3] << 16) |
+ (ptr_bootphdr->options[index+4] << 8) |
+ (ptr_bootphdr->options[index+5]));
+
+ /* Jump to the next option. */
+ index = index + ptr_bootphdr->options[index + 1] + 2;
+ break;
+ }
+ case 150:
+ {
+ /* TFTP Server IP Address: */
+ serverIP = ((ptr_bootphdr->options[index+2] << 24) |
+ (ptr_bootphdr->options[index+3] << 16) |
+ (ptr_bootphdr->options[index+4] << 8) |
+ (ptr_bootphdr->options[index+5]));
+
+ /* Convert to host order; so that it is in SYNC with "siaddr" field below. */
+ serverIP = ntohl(serverIP);
+
+ /* Jump to the next option. */
+ index = index + ptr_bootphdr->options[index + 1] + 2;
+ break;
+ }
+ case 0xFF:
+ {
+ /* End option. Terminate the loop. */
+ index = 64;
+ break;
+ }
+ default:
+ {
+ /* Any other option is not handled; but we need to skip it */
+ index = index + ptr_bootphdr->options[index + 1] + 2;
+ break;
+ }
+ }
+ }
+
+ /* The BOOTP Reply looks good. Kill the BOOTP timer. */
+ timer_delete (bootpmcb.bootp_timer);
+
+ /* Check if we have received the TFTP Server IP address or not? If not we assume
+ * that the TFTP Server and BOOTP Server address are one and the same. */
+ if (serverIP == 0x0)
+ serverIP = ptr_bootphdr->siaddr;
+
+ /* We have all the information with us from the BOOTP Reply Packet.
+ * a) IP Address
+ * b) Subnet Mask
+ * c) TFTP File Name.
+ * d) TFTP Server IP
+ * Lets configure the IPv4 Routing Table with the appropriate information and
+ * also configure the global netdevice structure. */
+ netmcb.net_device.ip_address = ptr_bootphdr->yiaddr;
+
+ if (netmcb.net_device.use_bootp_server_ip == TRUE)
+ netmcb.net_device.server_ip = serverIP;
+
+ netmcb.net_device.net_mask = htonl(subnetmask);
+ ip_add_route (FLG_RT_NETWORK, netmcb.net_device.ip_address, netmcb.net_device.net_mask, 0);
+
+ if (netmcb.net_device.use_bootp_file_name == TRUE)
+ memcpy (netmcb.net_device.file_name, ptr_bootphdr->file, sizeof(netmcb.net_device.file_name));
+
+ /* Check if we had received a default router? */
+ if (defaultRouter != 0)
+ ip_add_route (FLG_RT_DEFAULT, 0x0, 0x0, htonl(defaultRouter));
+
+ /* DEBUG Message: */
+ mprintf ("*****************************\n");
+ mprintf ("BOOTP Complete\n");
+ mprintf (" IP Address : 0x%x\n", ntohl(netmcb.net_device.ip_address));
+ mprintf (" Net Mask : 0x%x\n", subnetmask);
+ mprintf (" Default Router: 0x%x\n", defaultRouter);
+ mprintf (" Server IP : 0x%x\n", ntohl(serverIP));
+ mprintf (" File Name : %s\n", ptr_bootphdr->file);
+ mprintf ("*****************************\n");
+
+ /* Close the BOOTP sockets. */
+ stream_close();
+ udp_sock_close (sock);
+
+ /* Optional call back with bootp params */
+ if (bootpmcb.asyncComplete != NULL)
+ (*bootpmcb.asyncComplete)((void *)&netmcb.net_device);
+
+ /* Initiate the TFTP Transfer. */
+ tftp_get_file (netmcb.net_device.server_ip, (char *)netmcb.net_device.file_name);
+
+ /* BOOTP Reply has been processed. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is used to initialize the BOOTP client.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void bootp_init (void (*asyncComplete)(void *))
+{
+ BOOTPHDR* ptr_bootphdr;
+ SOCKET socket;
+
+ /* Initialize the BOOT MCB */
+ memset ((void *)&bootpmcb, 0, sizeof(BOOTP_MCB));
+
+ bootpmcb.asyncComplete = asyncComplete;
+
+
+ /* Populate the socket structure and register this with the UDP module. */
+ socket.local_port = BOOTP_CLIENT_PORT;
+ socket.remote_port = BOOTP_SERVER_PORT;
+ socket.remote_address = 0xFFFFFFFF;
+ socket.app_fn = bootp_receive;
+
+ /* Open the BOOTP socket. */
+ bootpmcb.sock = udp_sock_open (&socket);
+ if (bootpmcb.sock < 0)
+ {
+ /* Error: Socket could not be opened. */
+ mprintf ("ERROR: BOOTP SOCK Open Failed\n");
+ net_set_error ();
+ return;
+ }
+
+ /* Open the stream to receive packets */
+ stream_open(TFTP_DATA_SIZE);
+
+ /* Get the pointer to the BOOTP Header. */
+ ptr_bootphdr = &bootpmcb.boothdr;
+
+ /* Populate the BOOTP header with all the information we have. */
+ ptr_bootphdr->op = BOOTP_OP_REQUEST;
+ ptr_bootphdr->htype = BOOTP_HTYPE_ETHERNET;
+ ptr_bootphdr->hlen = 6;
+ ptr_bootphdr->xid = htonl(0x1);
+ memcpy ((void *)&ptr_bootphdr->chaddr, (void *)&netmcb.net_device.mac_address[0], 6);
+
+ /* The packet has been populated; send it to the server. */
+ udp_sock_send (bootpmcb.sock, (Uint8 *)ptr_bootphdr, sizeof(BOOTPHDR));
+
+ /* Increment the number of requests sent out. */
+ bootpmcb.num_request++;
+
+ /* Create the BOOTP Timer; if timer creation fails then BOOTP Retransmissions
+ * will not work and so we treat this as a fatal error. */
+ bootpmcb.bootp_timer = timer_add (BOOTP_SEED_TIMEOUT, bootp_tmr_expiry);
+ if (bootpmcb.bootp_timer < 0)
+ {
+ /* Error: Timer could not be created; we need to close the socket and signal error. */
+ mprintf ("ERROR: BOOTP ADD Timer Failed\n");
+ stream_close();
+ udp_sock_close (bootpmcb.sock);
+ net_set_error ();
+ return;
+ }
+ return;
+}
+
+
+
diff --git a/src/driver/eth/icmp.c b/src/driver/eth/icmp.c
--- /dev/null
+++ b/src/driver/eth/icmp.c
@@ -0,0 +1,133 @@
+/**
+ * @file icmp.c
+ *
+ * @brief
+ * The file implements the NET Module ICMP functionality.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include <blf.h>
+#include "netif.h"
+
+#ifdef INCLUDE_BLF_NET_MODULE
+#ifdef INCLUDE_BLF_NET_ICMP
+
+/**
+ * @b Description
+ * @n
+ * The function computes the ICMP checksum and populates the ICMP
+ * Checksum field.
+ *
+ * @param[in] ptr_icmp_hdr
+ * This is the pointer to the ICMP header.
+ * @param[in] size
+ * This is the total size of the ICMP packet including header and data
+ * payload.
+ *
+ * @retval
+ * Not Applicable.
+ */
+static void icmp_checksum (ICMPHDR *ptr_icmp_hdr, Uint16 size)
+{
+ Int32 tmp1;
+ Uint16* pw;
+ Uint32 TSum;
+
+ /* Checksum field is NULL in checksum calculations */
+ ptr_icmp_hdr->Checksum = 0;
+
+ /* Checksum the header */
+ pw = (Uint16 *)ptr_icmp_hdr;
+ TSum = 0;
+ for( tmp1=size; tmp1 > 1; tmp1 -= 2 )
+ TSum += (Uint32)*pw++;
+#ifdef BIGENDIAN
+ if( tmp1 )
+ TSum += (Uint32)(*pw & 0xFF00);
+#else
+ if( tmp1 )
+ TSum += (Uint32)(*pw & 0x00FF);
+#endif
+ TSum = (TSum&0xFFFF) + (TSum>>16);
+ TSum = (TSum&0xFFFF) + (TSum>>16);
+ TSum = ~TSum;
+
+ /* Note checksum is Net/Host byte order independent */
+ ptr_icmp_hdr->Checksum = (Uint16)TSum;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function handles the processing of ICMP packets.
+ *
+ * @param[in] ptr_iphdr
+ * This is the pointer to the IP header.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void icmp_receive (IPHDR* ptr_iphdr)
+{
+ ICMPHDR* ptr_icmphdr;
+ Uint16 checksum;
+ Uint16 l4_pkt_size;
+ ICMPHDR* ptr_reply_hdr;
+ IPHDR* ptr_reply_iphdr;
+
+ /* Get the pointer to the ICMP header. */
+ ptr_icmphdr = (ICMPHDR *) ((Uint8 *)ptr_iphdr + IPHDR_SIZE);
+
+ /* Compute the l4 packet size. */
+ l4_pkt_size = ntohs(ptr_iphdr->TotalLen) - IPHDR_SIZE;
+
+ /* We only handle ICMP echo requests */
+ if (ptr_icmphdr->Type != ICMP_ECHO_REQUEST_TYPE)
+ return;
+
+ /* Validate the checksum */
+ checksum = ptr_icmphdr->Checksum;
+ if (checksum == 0xFFFF)
+ checksum = 0;
+ icmp_checksum (ptr_icmphdr, l4_pkt_size);
+ if( checksum != ptr_icmphdr->Checksum )
+ return;
+
+ /* OK; control comes here implies that a valid ICMP ECHO request
+ * packet was received. Now we send back the ECHO reply; so lets
+ * allocate a new transmit packet. */
+ ptr_reply_iphdr = (IPHDR *)net_alloc_tx_packet (l4_pkt_size + IPHDR_SIZE);
+ if (ptr_reply_iphdr == NULL)
+ return;
+
+ /* We can blindly copy the 'original' IP packet to the 'reply' IP packet. */
+ utl_memcpy ((void *)ptr_reply_iphdr, (void *)ptr_iphdr, (l4_pkt_size + IPHDR_SIZE));
+
+ /* Get the pointer to the new header.
+ * The new header starts after the IP header. */
+ ptr_reply_hdr = (ICMPHDR *)((Uint8 *)ptr_reply_iphdr + IPHDR_SIZE);
+
+ /* This is an ECHO reply packet; so lets overwrite the field. */
+ ptr_reply_hdr->Type = ICMP_ECHO_REPLY_TYPE;
+
+ /* Compute the new ICMP checksum and overwrite it in the header. */
+ icmp_checksum (ptr_reply_hdr, l4_pkt_size);
+
+ /* Swap the source and destination address in the REPLY packet. */
+ ptr_reply_iphdr->IPSrc = ptr_iphdr->IPDst;
+ ptr_reply_iphdr->IPDst = ptr_iphdr->IPSrc;
+
+ /* Packet looks good. Send to the IP layer for transmission. */
+ ip_send (ptr_reply_iphdr, l4_pkt_size + IPHDR_SIZE);
+ return;
+}
+
+#endif /* INCLUDE_BLF_NET_ICMP */
+#endif /* INCLUDE_BLF_NET_MODULE */
+
+
diff --git a/src/driver/eth/ip.c b/src/driver/eth/ip.c
--- /dev/null
+++ b/src/driver/eth/ip.c
@@ -0,0 +1,394 @@
+/**
+ * @file ip.c
+ *
+ * @brief
+ * The file implements the NET Module IPv4 functionality.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include <string.h>
+
+
+/**
+ * @brief This is the size of the NET Boot Module Routing table.
+ * This definition should never be modified. If changed then the API
+ * for adding/deleting routes will also need to be modified.
+ */
+#define MAX_RT_TABLE_SIZE 2
+
+/**
+ * @brief This is the global routing table which is used by
+ * the stack to determine the route on which the packet needs to
+ * be transmitted.
+ */
+RT_ENTRY rt_table[MAX_RT_TABLE_SIZE];
+
+/**********************************************************************
+ **************************** IP Functions ****************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * The function adds a route to the routing table. Default routes are
+ * always added to the last entry in the routing table. There is no
+ * duplicate route checking done here and if an entry exists it is
+ * overriden with the new values.
+ *
+ * @param[in] flag
+ * Flag properties associated with the route
+ * @param[in] ip_address
+ * IP Address associated with the route.
+ * @param[in] net_mask
+ * Network Mask associated with the route
+ * @param[in] next_hop
+ * Next Hop Address associated with the route. This is applicable
+ * for default gateways. For network routes this is ignored.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 ip_add_route (Uint32 flag, IPN ip_address, IPN net_mask, IPN next_hop)
+{
+ RT_ENTRY* ptr_rt;
+
+ /* Basic Sanity Check: The flag should be correct! */
+ if ((flag != FLG_RT_NETWORK) && (flag != FLG_RT_DEFAULT))
+ return -1;
+
+ /* Check if the flag is a network route being added? */
+ if (flag == FLG_RT_NETWORK)
+ {
+ /* Network route is being added. */
+ ptr_rt = &rt_table[0];
+
+ /* Populate the routing entry. */
+ ptr_rt->flags = FLG_RT_NETWORK;
+ ptr_rt->ip_addr = ip_address;
+ ptr_rt->net_mask = net_mask;
+ ptr_rt->net_addr = ip_address & net_mask;
+ ptr_rt->next_hop = ip_address;
+ }
+ else
+ {
+ /* Default route is being added. */
+ ptr_rt = &rt_table[1];
+
+ /* Populate the routing entry. */
+ ptr_rt->flags = FLG_RT_DEFAULT;
+ ptr_rt->ip_addr = 0x0;
+ ptr_rt->net_mask = 0x0;
+ ptr_rt->net_addr = 0x0;
+ ptr_rt->next_hop = next_hop;
+ }
+
+ /* Routes were added successfully. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function checks the routing table to determine a
+ * suitable route which needs to be taken to send out the
+ * packet.
+ *
+ * @param[in] ip_address
+ * IP Address for which the route is being looked up.
+ *
+ * @retval
+ * Success - Pointer to the routing entry being used.
+ * @retval
+ * Error - NULL (There is no route which can be used)
+ */
+RT_ENTRY* ip_lookup_route (IPN ip_address)
+{
+ Int32 index = 0;
+ RT_ENTRY* ptr_rt;
+ IPN network_address;
+
+ /* Cycle through the routing table. */
+ for (index = 0; index < MAX_RT_TABLE_SIZE; index++)
+ {
+ /* Get the pointer to the routing table entry. */
+ ptr_rt = &rt_table[index];
+
+ /* Check if there is a valid entry or not? */
+ if (ptr_rt->flags & (FLG_RT_NETWORK | FLG_RT_DEFAULT))
+ {
+ /* Valid routing entry was found; calculate the network address
+ * with respect to the route netmask and match it. */
+ network_address = ip_address & ptr_rt->net_mask;
+
+ /* Check if this matches the same network to which we are sending the packet. */
+ if (network_address == ptr_rt->net_addr)
+ {
+ /* YES. Perfect; we can return this routing entry. */
+ return ptr_rt;
+ }
+ }
+ }
+
+ /* Control comes here indicates that there was no routing entry which could be used. */
+ return NULL;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function deletes the routing table entry.
+ *
+ * @param[in] flag
+ * This is the routing entry which is being deleted.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void ip_del_route (Uint32 flag)
+{
+ RT_ENTRY* ptr_rt;
+
+ /* Check if the flag is a network route being added? */
+ if (flag == FLG_RT_NETWORK)
+ {
+ /* Network route is being deleted. */
+ ptr_rt = &rt_table[0];
+ }
+ else
+ {
+ if (flag == FLG_RT_DEFAULT)
+ {
+ /* Default route is being deleted. */
+ ptr_rt = &rt_table[0];
+ }
+ else
+ {
+ /* Invalid Flag combination passed. */
+ return;
+ }
+ }
+
+ /* Simply reset all the fields */
+ memset ((void *)ptr_rt, 0, sizeof(RT_ENTRY));
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function computes the IP checksum. The computed checksum
+ * is populated in the IP header.
+ *
+ * @param[in] ptr_iphdr
+ * This is the pointer to the IPv4 header for which the checksum
+ * is computed.
+ *
+ * @retval
+ * Not Applicable.
+ */
+static void ip_checksum(IPHDR *ptr_iphdr)
+{
+ Int32 tmp1;
+ Uint16 *pw;
+ Uint32 TSum = 0;
+
+ /* Get header size in 4 byte chunks */
+ tmp1 = ptr_iphdr->VerLen & 0xF;
+
+ /* Checksum field is NULL in checksum calculations */
+ ptr_iphdr->Checksum = 0;
+
+ /* Checksum the header */
+ pw = (Uint16 *)ptr_iphdr;
+ do {
+ TSum += (Uint32)*pw++;
+ TSum += (Uint32)*pw++;
+ } while( --tmp1 );
+ TSum = (TSum&0xFFFF) + (TSum>>16);
+ TSum = (TSum&0xFFFF) + (TSum>>16);
+ TSum = ~TSum;
+
+ /* Note checksum is Net/Host byte order independent */
+ ptr_iphdr->Checksum = (Uint16)TSum;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function handles the processing of IPv4 packets.
+ *
+ * @param[in] ptr_iphdr
+ * This is the pointer to the IPv4 header.
+ * @param[in] num_bytes
+ * This is the total number of bytes which includes the IPv4 header
+ * and data payload.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 ip_receive (IPHDR* ptr_iphdr, Int32 num_bytes)
+{
+ Uint32 checksum;
+
+ /* Basic IPv4 Packet Validations: Ensure that this is an IPv4 packet. */
+ if ((ptr_iphdr->VerLen & 0xF0) != 0x40)
+ return -1;
+
+ /* Validate the length of the received packet; it cannot be greater
+ * than the total length of the received packet. */
+ if (ntohs(ptr_iphdr->TotalLen) > num_bytes)
+ return -1;
+
+ /* Checksum validation. */
+ checksum = ptr_iphdr->Checksum;
+ if (checksum == 0xFFFF )
+ checksum = 0;
+ ip_checksum (ptr_iphdr);
+ if (checksum != ptr_iphdr->Checksum )
+ return -1;
+
+ /* We dont handle any IP option processing.
+ * Thus if the IP header length is greater than 20 bytes the packet is dropped. */
+ if (((ptr_iphdr->VerLen & 0xF) << 2) != IPHDR_SIZE)
+ return -1;
+
+ /* We accept only the following packets:-
+ * a) Destination Address is the address of the NET Boot module.
+ * b) Destination Address is the a special 255.255.255.255 address for BOOTP Reply*/
+ if ((ptr_iphdr->IPDst != netmcb.net_device.ip_address) && (ptr_iphdr->IPDst != 0xFFFFFFFF))
+ return -1;
+
+ /* Pass the packet to the layer4 receive handlers. */
+ switch (ptr_iphdr->Protocol)
+ {
+#ifdef INCLUDE_BLF_NET_ICMP
+ case IPPROTO_ICMP:
+ {
+ icmp_receive (ptr_iphdr);
+ break;
+ }
+#endif /* INCLUDE_BLF_NET_ICMP */
+ case IPPROTO_UDP:
+ {
+ /* UDP Packet. */
+ if (udp_receive (ptr_iphdr) < 0)
+ net_stats.rx_udp_dropped++;
+ break;
+ }
+ default:
+ {
+ /* No other protocol is handled. */
+ return -1;
+ }
+ }
+
+ /* Packet has been successfully processed at the IP layer. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called from the layer4 protocol to send
+ * out an IPv4 packet.
+ *
+ * @param[in] ptr_iphdr
+ * This is the pointer to the IPv4 header + payload which includes
+ * the layer4 header and actual data payload.
+ * The layer4 protocol is supposed to populate the following IPv4 fields:-
+ * - Protocol
+ * - Destination IP
+ * The rest of the fields in the IPv4 header are populated by this function.
+ *
+ * @param[in] size
+ * This is the total number of bytes which includes the layer4 header
+ * and data payload and the IPv4 header.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void ip_send (IPHDR* ptr_iphdr, Uint16 size)
+{
+ RT_ENTRY* ptr_rt;
+ IPN next_hop_address;
+
+ /* Special Case: If the IP Address of the packet is 255.255.255.255
+ * we dont need to check the routing table. */
+ if (ptr_iphdr->IPDst != 0xFFFFFFFF)
+ {
+ /* Lookup the routing table for a routing entry. */
+ ptr_rt = ip_lookup_route (ptr_iphdr->IPDst);
+ if (ptr_rt == NULL)
+ {
+ /* There is no route which exists to send the packet. Drop it! */
+ net_free_tx_packet ((Uint8 *)ptr_iphdr);
+ return;
+ }
+
+ /* Control comes here indicating that a route exists and the packet
+ * can be sent out. There are 2 types of routes in the system:-
+ * a) Network Routes which are directly attached and in this case
+ * the next hop ip address is the same as the destination IP address
+ * b) Default Routes which is the address of the default gateway to which
+ * we need to send the packet since the destination network is not
+ * directly connected.
+ * So here we determine the next hop address based on the route type. */
+ if (ptr_rt->flags == FLG_RT_NETWORK)
+ next_hop_address = ptr_iphdr->IPDst;
+ else
+ next_hop_address = ptr_rt->next_hop;
+ }
+ else
+ {
+ /* This is a BOOTP request being sent out to 255.255.255.255. Set the
+ * next hop address to be the same. */
+ next_hop_address = ptr_iphdr->IPDst;
+ }
+
+ /* Ensure all the fields in the IPv4 header are populated correctly */
+ ptr_iphdr->VerLen = 0x45;
+ ptr_iphdr->Tos = 0;
+ ptr_iphdr->Id = netmcb.ipID++;
+ ptr_iphdr->FlagOff = 0;
+ ptr_iphdr->Ttl = 64;
+ ptr_iphdr->TotalLen = htons(size);
+ ptr_iphdr->IPSrc = netmcb.net_device.ip_address;
+
+ /* Here we recompute the IP Checksum. */
+ ip_checksum (ptr_iphdr);
+
+ /* Layer2 resolution is done on the Next hop address. */
+ arp_resolve (next_hop_address, ptr_iphdr, size);
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function initializes the IP Module in the NET Boot module.
+ *
+ * @retval
+ * Not Applicable
+ */
+void ip_init (void)
+{
+ /* Reset the routing table */
+ memset (&rt_table, 0, sizeof(rt_table));
+ return;
+}
+
+
+
diff --git a/src/driver/eth/net.c b/src/driver/eth/net.c
--- /dev/null
+++ b/src/driver/eth/net.c
@@ -0,0 +1,686 @@
+/**
+ * @file net.c
+ *
+ * @brief
+ * The file implements the NET Boot Module.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include "timer.h"
+#include "stream.h"
+#include <string.h>
+
+
+/**********************************************************************
+ *************************** Local Functions **************************
+ **********************************************************************/
+static Int32 net_open (void* ptr_driver, void (*asyncComplete)(void *));
+static Int32 net_close(void);
+static Int32 net_read (Uint8* ptr_buf, Uint32 num_bytes);
+static Int32 net_peek (Uint8* ptr_buf, Uint32 num_bytes);
+static Int32 net_seek (Int32 loc, Int32 from);
+static Int32 net_query (void);
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @defgroup net_op
+ *
+ * @ingroup net_op
+ * @{
+ *
+ * @brief
+ * Internal definition to distinguish a read from a peek
+ *
+ */
+
+/**
+ * @def NET_READ
+ */
+#define NET_READ 400 /**< Read from the net device */
+
+/**
+ * @def NET_PEEK
+ */
+#define NET_PEEK 420 /**< Peek from the net device */
+
+/* @} */
+
+
+/**
+ * @brief This is the NETWORK Master control block which keeps track
+ * of all the Network boot module related information.
+ */
+NET_MCB netmcb;
+
+/**
+ * @brief This keeps track of the network statistics.
+ */
+NET_STATS net_stats;
+
+/**
+ * @brief This is the global Network Boot Module function table which
+ * implements the Boot Module Interface with the kernel.
+ */
+BOOT_MODULE_FXN_TABLE net_boot_module =
+{
+ net_open, /* Open API */
+ net_close, /* Close API */
+ net_read, /* Read API */
+ NULL, /* Write API (NULL: This is not interactive) */
+ net_peek, /* Peek API */
+ net_seek, /* Seek API */
+ net_query /* Query API */
+};
+
+/**********************************************************************
+ **************************** NET Functions ***************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * The function is used to allocate a packet for transmission. This
+ * is called by the higher layer protocols when a packet needs to
+ * be transmitted. The function ensures there is sufficient space
+ * allocated at the beginning of the packet for the Ethernet header.
+ * Since the pointer returned by this API is used to store L3/L4 headers
+ * it always returns a 4 byte aligned buffer data pointer.
+ *
+ * @param[in] packet_len
+ * Length of the packet being transmitted.
+ *
+ * @retval
+ * Success - Pointer to the L3 header.
+ * @retval
+ * Error - NULL
+ */
+Uint8* net_alloc_tx_packet(Int32 packet_len)
+{
+ /* Sanity Check: Ensure the packet being allocated does not exceed the
+ * max buffer size that we have. */
+ if (packet_len > NET_MAX_MTU)
+ return NULL;
+
+ /* Sanity Check: Ensure that the packet is available for use. */
+ if (netmcb.txuse == 1)
+ return NULL;
+
+ /* Mark the packet as being in use. */
+ netmcb.txuse = 1;
+
+ /* Reset the contents of the packet */
+ memset ((void *)&netmcb.tx_packet[0], 0, sizeof(netmcb.tx_packet));
+
+ /* Reserve some space at the head of the packet for the Ethernet headers. */
+ return &netmcb.tx_packet[16];
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called to free up a previously allocated transmit
+ * packet.
+ *
+ * @param[in] ptr
+ * Pointer to the packet being cleaned.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void net_free_tx_packet (Uint8* ptr)
+{
+ /* Sanity Checks: Ensure that the packet being cleaned is the same as the one
+ * which was allocated. */
+ if (ptr != &netmcb.tx_packet[16])
+ mprintf ("ERROR: NET Free Transmit packet detected corruption\n");
+
+ /* Sanity Checks: Ensure that there is no double free. */
+ if (netmcb.txuse == 0)
+ mprintf ("ERROR: NET Free Transmit packet detected double free\n");
+
+ /* Mark the transmit packet as free and available. */
+ netmcb.txuse = 0;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is used to append an Ethernet header on the packet.
+ * The source MAC Address in the packet is always the one which was
+ * registered by the driver. Higher layer protocol authors need to
+ * use the 'net_alloc_tx_packet' API to get a transmit buffer.
+ *
+ * @param[in] ptr_l3_hdr
+ * This is the pointer to the layer3 header.
+ * @param[in] dst_mac
+ * The destination MAC address
+ * @param[in] protocol
+ * The layer3 protocol version (passed in host order)
+ *
+ * @retval
+ * Success - Pointer to the start of the Ethernet header i.e. L2.
+ * @retval
+ * Error - NULL
+ */
+ETHHDR* net_create_eth_header (Uint8* ptr_l3_hdr, Uint8* dst_mac, Uint16 protocol)
+{
+ Int32 rsvd_space;
+
+ /* Compute the reserved space. */
+ rsvd_space = (Int32)ptr_l3_hdr - (Int32)&netmcb.tx_packet[0];
+
+ /* Ensure there is sufficient space to add the header. We dont want memory corruption
+ * to occur here. */
+ if ((rsvd_space < 0) || (rsvd_space > NET_MAX_MTU) || (rsvd_space < ETHHDR_SIZE))
+ return NULL;
+
+ /* Convert the protocol to network order. */
+ protocol = ntohs(protocol);
+
+ /* Start adding the Ethernet header.
+ * Move back the data pointer to account for the protocol. */
+ ptr_l3_hdr = ptr_l3_hdr - 2;
+ memcpy ((void *)ptr_l3_hdr, (void *)&protocol, sizeof(Uint16));
+
+ /* Move back the data pointer to account for the source MAC. */
+ ptr_l3_hdr = ptr_l3_hdr - 6;
+ memcpy ((void *)ptr_l3_hdr, (void *)&netmcb.net_device.mac_address[0], 6);
+
+ /* Move back the data pointer to account for the destination MAC. */
+ ptr_l3_hdr = ptr_l3_hdr - 6;
+ memcpy ((void *)ptr_l3_hdr, (void *)dst_mac, 6);
+
+ /* Return the pointer to the start of the Ethernet header. */
+ return (ETHHDR *)ptr_l3_hdr;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is used to send a packet to the driver.
+ *
+ * @param[in] ptr_l2_hdr
+ * This is the pointer to the L2 header of the packet to be transmitted.
+ * All the headers need to be populated by the time comes to this API.
+ * @param[in] length
+ * Length of the packet being transmitted. This include the L2 header
+ * information.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void net_send_packet (ETHHDR* ptr_l2_hdr, Uint16 length)
+{
+ /* Sanity Check: This is called after the LAYER3 and ETHER headers
+ * have been appended to the packet. Here we ensure that the layer3 header
+ * is aligned on the 4 byte boundary. */
+ if ( (((Uint32)ptr_l2_hdr+ETHHDR_SIZE) % 4) != 0)
+ mprintf ("ERROR: Misaligned Layer3 packet transmitted 0x%p.\n", ptr_l2_hdr);
+
+ /* Increment the stats. */
+ net_stats.num_pkt_txed++;
+
+ /* Pass the packet to the platform API for transmission. */
+ netmcb.net_device.send (&netmcb.net_device, (Uint8 *)ptr_l2_hdr, (Int32)length);
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called from any entity inside the NETWORK Boot Module
+ * to indicate that there has been a FATAL error and that the boot module
+ * processing needs to be aborted.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void net_set_error (void)
+{
+ /* Set the Error Flag; */
+ netmcb.error_flag = 1;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function opens the BLF NET Module. The function initializes
+ * the various internal components of the NET module and also
+ * initializes the peripheral driver controller
+ *
+ * @param[in] ptr_driver
+ * This is the pointer to the driver block which was passed to
+ * the BLF through the BOOT Mode descriptor. For the NET boot
+ * module this points to the NET_DRV_DEVICE object.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_open (void* ptr_driver, void (*asyncComplete)(void *))
+{
+ NET_DRV_DEVICE* ptr_net_driver;
+
+ /* Get the pointer to the net driver. */
+ ptr_net_driver = (NET_DRV_DEVICE*)ptr_driver;
+
+ /* Basic Validation: Ensure there is a valid driver block being passed. */
+ if (ptr_net_driver == NULL)
+ return -1;
+
+ /* Basic Validation: Ensure that all the required API have been provided */
+ if ((ptr_net_driver->start == NULL) || (ptr_net_driver->send == NULL) ||
+ (ptr_net_driver->receive == NULL) || (ptr_net_driver->stop == NULL))
+ {
+ /* Error: Required API was not specified. */
+ return -1;
+ }
+
+ /* Initialize the NET MCB. */
+ memset (&netmcb, 0, sizeof(NET_MCB));
+
+ /* Initialize the Network Statistics. */
+ memset (&net_stats, 0, sizeof(NET_STATS));
+
+ /* Copy the driver information into the NET MCB */
+ memcpy ((void *)&netmcb.net_device, (void *)ptr_net_driver, sizeof(NET_DRV_DEVICE));
+
+ /* Initialize the ARP Module. */
+ arp_init ();
+
+ /* Initialize the IP Module. */
+ ip_init ();
+
+ /* Initialize the UDP Module. */
+ udp_init ();
+
+ /* Start the networking device */
+ if (netmcb.net_device.start(&netmcb.net_device) < 0)
+ return -1;
+
+ /* Determine if we need to execute BOOTP or not? */
+ if (netmcb.net_device.ip_address != 0)
+ {
+ /* IP Address was supplied by the device team. There is no need
+ * to execute the BOOTP protocol; manually create the network route also. */
+ ip_add_route (FLG_RT_NETWORK, netmcb.net_device.ip_address, netmcb.net_device.net_mask, 0);
+
+ /* Optional call back with boot server info */
+ if (asyncComplete != NULL)
+ (*asyncComplete)((void *)&netmcb.net_device);
+
+ /* Lets download the file from the TFTP Server. */
+ tftp_get_file (netmcb.net_device.server_ip, netmcb.net_device.file_name);
+ }
+ else
+ {
+ /* No IP Address was supplied we need to execute the BOOTP protocol. */
+ bootp_init (asyncComplete);
+ }
+
+ /* The network module is UP and running.. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function closes the BLF NET Module.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_close (void)
+{
+ return 0;
+}
+
+
+/**
+ * @b Description
+ * @n
+ * If a waiting packet is found it is processed
+ */
+static void proc_packet (void)
+{
+ Uint8* ptr_data_packet;
+ Int32 packet_size;
+ Uint16 protocol;
+ Uint8 dst_mac_address[6];
+
+ /* Initialize the pointer in the received packet is stored.
+ * This is misaligned on the 2 byte boundary as this will ensure that
+ * the layer3 headers i.e. IPv4 and ARP are aligned correctly. */
+ ptr_data_packet = (Uint8 *)&netmcb.rx_packet[2];
+
+ /* Check if a packet has been received? */
+ packet_size = netmcb.net_device.receive(&netmcb.net_device, ptr_data_packet);
+ if (packet_size == 0)
+ return;
+
+ /* Increment the number of packets received. */
+ net_stats.num_pkt_rxed++;
+
+ /* Extract the destination MAC Address from the received packet. */
+ memcpy ((void *)&dst_mac_address[0], (void *)ptr_data_packet, 6);
+
+ /* Extract the protocol from the received packet. This is at offset 12 from the
+ * start of the packet. We need to skip the destination and source mac address. */
+ protocol = *((Uint16 *)(ptr_data_packet + 12));
+ protocol = ntohs(protocol);
+
+ /* Process the received data.
+ * Check the destination mac address to determine if the packet is
+ * meant for us or not? We accept only directed UNICAST & BROADCAST
+ * packets */
+ if(((dst_mac_address[0] != 0xFF) || (dst_mac_address[1] != 0xFF) ||
+ (dst_mac_address[2] != 0xFF) || (dst_mac_address[3] != 0xFF) ||
+ (dst_mac_address[4] != 0xFF) || (dst_mac_address[5] != 0xFF)) &&
+ ((dst_mac_address[0] != netmcb.net_device.mac_address[0]) ||
+ (dst_mac_address[1] != netmcb.net_device.mac_address[1]) ||
+ (dst_mac_address[2] != netmcb.net_device.mac_address[2]) ||
+ (dst_mac_address[3] != netmcb.net_device.mac_address[3]) ||
+ (dst_mac_address[4] != netmcb.net_device.mac_address[4]) ||
+ (dst_mac_address[5] != netmcb.net_device.mac_address[5])))
+ {
+ /* Packet is not meant for us; ignore this packet. */
+ net_stats.rx_l2_dropped++;
+ return;
+ }
+
+ /* Move the pointer to the data packet and skip the ethernet header. */
+ ptr_data_packet = ptr_data_packet + sizeof(ETHHDR);
+
+ /* Deduct the Ethernet header size from the total number of bytes received. */
+ packet_size = packet_size - sizeof(ETHHDR);
+
+ /* Sanity Check: We need to ensure that the Layer3 headers are aligned on the
+ * 4 byte boundary at this stage. */
+ if (((Uint32)ptr_data_packet % 4) != 0)
+ mprintf ("ERROR: Misaligned Layer3 packet received 0x%p.\n", ptr_data_packet);
+
+ /* Demux on the protocol basis and pass it to the upper layer. */
+ switch (protocol)
+ {
+ case ETH_IP:
+ {
+ /* IPv4 Packet. */
+ if (ip_receive ((IPHDR *)ptr_data_packet, packet_size) < 0)
+ net_stats.rx_ip_dropped++;
+ break;
+ }
+ case ETH_ARP:
+ {
+ /* ARP Packet. */
+ if (arp_receive ((ARPHDR *)ptr_data_packet, packet_size) < 0)
+ net_stats.rx_arp_dropped++;
+ break;
+ }
+ default:
+ {
+ /* Unexpected packet. Drop the packet! */
+ net_stats.rx_l2_dropped++;
+ break;
+ }
+ }
+
+}
+
+/**
+ * @b Description
+ * @n
+ * The function reads/peeks data from the BLF net module.
+ *
+ * @param[in] ptr_buf
+ * This points to the data buffer which needs to be populated
+ * with the received data.
+ *
+ * @param[in] num_bytes
+ * This is the number of bytes of data which need to be read.
+ *
+ * @param[in] op
+ * Determines if a read or peek operation is performed
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_read_peek (Uint8* ptr_buf, Uint32 num_bytes, Int32 op)
+{
+ Int32 num_bytes_read = 0;
+ Int32 total_num_bytes_read = 0;
+
+ /* Basic Validations: Ensure that the parameters are valid. */
+ if ((ptr_buf == NULL) || (num_bytes == 0))
+ return -1;
+
+ /* Execute the network scheduler; till there is no error. */
+ while (netmcb.error_flag == 0)
+ {
+
+ /* If the stream is empty and closed return */
+ if (stream_level() < 0) {
+ if (total_num_bytes_read > 0)
+ return (0);
+ else
+ return (-1);
+ }
+
+
+ /* Call the timer scheduler. */
+ timer_run();
+
+ /* Check if there is data in the STREAM? */
+ if (stream_isempty() == FALSE)
+ {
+ /* STREAM indicates there is some data. Lets read it first. */
+ if (op == NET_READ) {
+ num_bytes_read = stream_read (((ptr_buf + total_num_bytes_read)), num_bytes);
+ netmcb.fileOffset = netmcb.fileOffset + num_bytes_read;
+ } else
+ num_bytes_read = stream_peek (((ptr_buf + total_num_bytes_read)), num_bytes);
+
+ /* Keep track of the total amount of data read till now. */
+ total_num_bytes_read = total_num_bytes_read + num_bytes_read;
+
+ /* How much more data do we need to read? */
+ num_bytes = num_bytes - num_bytes_read;
+
+ /* Check if we have read all the data that was requested? */
+ if (num_bytes == 0)
+ break;
+
+ /* Control comes here implies that there was more data to be read into
+ * the buffer. We need it to have it available before we can exit the loop.
+ * So lets fall through! */
+ }
+ else
+ {
+ /* STREAM Module is empty. */
+ }
+
+ /* Check for and process any received packets */
+ proc_packet ();
+
+ }
+
+ /* Did we come out because of error or not? */
+ if (netmcb.error_flag == 0)
+ return 0;
+
+ /* Return error */
+ return -1;
+}
+
+
+/**
+ * @b Description
+ * @n
+ * The function reads data from the BLF net module.
+ *
+ * @param[in] ptr_buf
+ * This points to the data buffer which needs to be populated
+ * with the received data.
+ *
+ * @param[in] num_bytes
+ * This is the number of bytes of data which need to be read.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_read (Uint8* ptr_buf, Uint32 num_bytes)
+{
+ return (net_read_peek (ptr_buf, num_bytes, NET_READ));
+}
+
+
+/**
+ * @b Description
+ * @n
+ * The function peeks data from the BLF net module.
+ *
+ * @param[in] ptr_buf
+ * This points to the data buffer which needs to be populated
+ * with the received data.
+ *
+ * @param[in] num_bytes
+ * This is the number of bytes of data which need to be read.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_peek (Uint8* ptr_buf, Uint32 num_bytes)
+{
+ return (net_read_peek (ptr_buf, num_bytes, NET_PEEK));
+}
+
+/**
+ * @b Description
+ * @n
+ * This function moves the read pointer in the stream.
+ * Because this is a tftp boot, only forward reads
+ * are permitted.
+ *
+ * @param[in] loc
+ * This points to where the stream should be
+ *
+ * @param[in] from
+ * This describes parameter loc.
+ * 0 = from the start of the file
+ * 1 = from the current position
+ * 2 = from the end of the file
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_seek (Int32 loc, Int32 from)
+{
+ Uint32 num_bytes;
+ Int32 num_bytes_read = 0;
+ Int32 total_num_bytes_read = 0;
+ Uint32 desiredPos;
+
+
+ /* This driver can only seek forward, and cannot seek from the end of the file */
+ if (from == 0)
+ desiredPos = loc;
+ else if (from == 1)
+ desiredPos = netmcb.fileOffset + loc;
+ else
+ return (-1);
+
+ /* Check if already in the correct position */
+ if (desiredPos == netmcb.fileOffset)
+ return (0);
+
+ /* Check for an invalid position */
+ if (desiredPos < netmcb.fileOffset)
+ return (-1);
+
+ /* Read data from the file until the file position matches the desired one */
+ num_bytes = desiredPos - netmcb.fileOffset;
+
+
+ /* Execute the network scheduler; till there is no error. */
+ while (netmcb.error_flag == 0)
+ {
+ /* Call the timer scheduler. */
+ timer_run();
+
+ /* Check if there is data in the STREAM? */
+ if (stream_isempty() == FALSE)
+ {
+ /* STREAM indicates there is some data. Lets read it first. */
+ num_bytes_read = stream_read (NULL, num_bytes);
+ netmcb.fileOffset = netmcb.fileOffset + num_bytes_read;
+
+ /* Keep track of the total amount of data read till now. */
+ total_num_bytes_read = total_num_bytes_read + num_bytes_read;
+
+ /* How much more data do we need to read? */
+ num_bytes = num_bytes - num_bytes_read;
+
+ /* Check if we have read all the data that was requested? */
+ if (num_bytes == 0)
+ break;
+
+ /* Control comes here implies that there was more data to be read into
+ * the buffer. We need it to have it available before we can exit the loop.
+ * So lets fall through! */
+ }
+ else
+ {
+ /* STREAM Module is empty. */
+ }
+
+ /* Check for and process any received packets */
+ proc_packet ();
+
+ }
+
+ /* Did we come out because of error or not? */
+ if (netmcb.error_flag == 0)
+ return 0;
+
+ /* Return error */
+ return -1;
+}
+
+/**
+ * @b Description
+ * @n
+ * This function returns how many bytes of data
+ * are currently available for immediate read.
+ *
+ * @retval
+ * The number of bytes available
+ */
+static Int32 net_query (void)
+{
+ return (stream_level());
+}
+
+
diff --git a/src/driver/eth/net.h b/src/driver/eth/net.h
--- /dev/null
+++ b/src/driver/eth/net.h
@@ -0,0 +1,293 @@
+/**
+ * @file net.h
+ *
+ * @brief
+ * The file has data structures and API definitions for the
+ * NET Boot Module
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#ifndef __NET_H__
+#define __NET_H__
+
+/**
+ * @brief This is the MAX MTU of the packet that can be received in
+ * the network module. This is configured to Ethernet standards at 1518
+ */
+#define NET_MAX_MTU 1518
+
+/**
+ * @brief This field indicates that the route is a network route
+ * and any packet destined to the specific network is directly accessible.
+ * Network Routes have the Next Hop address and the IP address to be the
+ * same.
+ *
+ * @sa
+ * ip_add_route
+ * @sa
+ * ip_del_route
+ */
+#define FLG_RT_NETWORK 0x1
+
+/**
+ * @brief This field indicates that the route is a default route.
+ * This is a last entry in the routing table and is an indication that
+ * the IP address to which the packet is destined is not directly accessible
+ * but needs to be sent through a gateway (i.e. Next Hop)
+ *
+ * @sa
+ * ip_add_route
+ * @sa
+ * ip_del_route
+ */
+#define FLG_RT_DEFAULT 0x2
+
+/**
+ * @brief
+ * The structure describes the Network Device Configuration.
+ *
+ * @details
+ * This structures stores configuration data which is used populated
+ * by the Device layer and passed to the network boot module.
+ */
+typedef struct NET_DRV_DEVICE
+{
+ /**
+ * @brief The physical port number to use
+ */
+ Uint32 port_num;
+
+ /**
+ * @brief This is the MAC Address which is populated by the device
+ * team. All packets sent by the NET module will use this MAC Address.
+ */
+ Uint8 mac_address[6];
+
+ /**
+ * @brief This is the IP Address associated with the networking device
+ * Device team can specify an IP address which will be used for all
+ * further communications. If BOOTP is enabled and this is 0; then the
+ * BOOTP protocol kicks in to determine an IP Address to be used.
+ */
+ IPN ip_address;
+
+ /**
+ * @brief This is the network mask. This is only required to be specified
+ * if the device team has specified an IP address. If BOOTP is being used
+ * this should be set to 0.
+ */
+ IPN net_mask;
+
+ /**
+ * @brief This is the TFTP Server IP Address which is to be used to
+ * download the file. This can be retreived from the BOOTP options but if
+ * BOOTP is not being used; the Server IP address can be specified here.
+ * This is ignored by the NET Boot Module if BOOTP is being used.
+ */
+ IPN server_ip;
+
+ /**
+ * @brief Set this to TRUE to override the server IP received from
+ * the bootp server and use the server_ip value above.
+ */
+ Bool use_bootp_server_ip;
+
+ /**
+ * @brief This is the File Name which is to be downloaded from the TFTP
+ * server. This can be retreived by decoding the BOOTP options but if BOOTP
+ * is not being used then the file name can be specified here. This is ignored
+ * by the NET Boot Module if BOOTP is being used.
+ */
+ Int8 file_name[64];
+
+ /**
+ * @brief Set this to TRUE to override the file_name received from the
+ * bootp server and use the file_name value above.
+ */
+ Bool use_bootp_file_name;
+
+ /**
+ * @brief This API is used to start the Ethernet controller. This is a call
+ * back function which is invoked by the NET boot module when it has been opened.
+ */
+ Int32 (*start) (struct NET_DRV_DEVICE* ptr_device);
+
+ /**
+ * @brief This API is used to stop the Ethernet controller. This is a call
+ * back function which is invoked by the NET boot module when it has been closed.
+ */
+ Int32 (*stop) (struct NET_DRV_DEVICE* ptr_device);
+
+ /**
+ * @brief The API is invoked by the NET module to send data to the driver
+ * for transmission.
+ */
+ Int32 (*send) (struct NET_DRV_DEVICE* ptr_device, Uint8* buffer, Int32 buffer_size);
+
+ /**
+ * @brief The API is invoked by the NET module to receive data from the
+ * driver. The driver populates the buffer passed with the received data
+ * and returns the number of bytes received. If there is no data which
+ * has been received then the function returns 0
+ */
+ Int32 (*receive) (struct NET_DRV_DEVICE* ptr_device, Uint8* buffer);
+}NET_DRV_DEVICE;
+
+/**
+ * @brief
+ * The structure describes the SOCKET structure
+ *
+ * @details
+ * This is a very primitive 'SOCKET' layer structure which is populated
+ * by the application layer and registered with the UDP module. This is
+ * the basic interface through which packets are sent/received by the
+ * application layer and NET boot module. The structure is exported as it
+ * allows even device developers to write their own UDP application.
+ */
+typedef struct SOCKET
+{
+ /**
+ * @brief This is the local port on which the application is waiting
+ * for packets to arrive.
+ */
+ Uint16 local_port;
+
+ /**
+ * @brief This is the remote port to which the application will send
+ * data.
+ */
+ Uint16 remote_port;
+
+ /**
+ * @brief The remote IP address to which the application will send data.
+ */
+ IPN remote_address;
+
+ /**
+ * @brief This is the application supplied call back function which is
+ * invoked by the UDP module when a packet is received on the specific
+ * port.
+ */
+ Int32 (*app_fn) (Int32 sock, Uint8* ptr_data, Int32 num_bytes);
+}SOCKET;
+
+/**
+ * @brief
+ * The structure describes the NET Stats
+ *
+ * @details
+ * The structure keeps track of the network boot module statistics. This
+ * is useful for debugging the network boot operations and drivers
+ */
+typedef struct NET_STATS
+{
+ /**
+ * @brief Total number of packets received.
+ */
+ Uint32 num_pkt_rxed;
+
+ /**
+ * @brief Total number of received packets dropped at the the layer2.
+ * The stat is incremented because of the following reasons:-
+ * - Incorrect L2 Protocol received (Only IPv4 and ARP are handled)
+ * - Dst MAC Address is not directed unicast or broadcast.
+ */
+ Uint32 rx_l2_dropped;
+
+ /**
+ * @brief Total number of received packets dropped at the the ARP layer.
+ * The stat is incremented because of the following reasons:-
+ * - Source MAC Address in the ARP packet is not meant for the stack.
+ * - Source IP Address in the ARP packet is not meant for the stack.
+ */
+ Uint32 rx_arp_dropped;
+
+ /**
+ * @brief Total number of received packets dropped at the the IPv4 layer.
+ * The stat is incremented because of the following reasons:-
+ * - Invalid IP Header (Version 4 is only supported)
+ * - Incorrect Destination IP Address
+ * - Invalid IP checksum.
+ */
+ Uint32 rx_ip_dropped;
+
+ /**
+ * @brief Total number of received packets dropped at the the UDP layer.
+ * The stat is incremented because of the following reasons:-
+ * - Invalid UDP checksum.
+ * - Packet length is below min UDP size.
+ * - No application is registered to handle the packet.
+ */
+ Uint32 rx_udp_dropped;
+
+ /**
+ * @brief Total number of packets transmitted.
+ */
+ Uint32 num_pkt_txed;
+}NET_STATS;
+
+#ifdef _BIG_ENDIAN
+ #define ntohs(a) (a)
+ #define htons(a) (a)
+ #define htonl(a) (a)
+ #define ntohl(a) (a)
+ #define READ32(x) (((Uint32)(*(Uint16 *)(x))<<16)|(Uint32)(*(Uint16 *)(((Uint8 *)(x))+2)))
+#else
+ #define htons(a) ( (((a)>>8)&0xff) + (((a)<<8)&0xff00) )
+ #define ntohs(a) htons(a)
+ #define htonl(a) ( (((a)>>24)&0xff) + (((a)>>8)&0xff00) + \
+ (((a)<<8)&0xff0000) + (((a)<<24)&0xff000000) )
+ #define ntohl(a) htonl(a)
+ #define READ32(x) ((Uint32)(*(Uint16 *)(x))|((Uint32)(*(Uint16 *)(((Uint8 *)(x))+2))<<16))
+#endif
+
+/**********************************************************************
+ **************************** Exported Data ***************************
+ **********************************************************************/
+
+/**
+ * @brief This is the NET Boot Module function table which has been
+ * exported. Device developers who wish to use the NET Boot Module are
+ * advised to populate the address of this into the BOOT Mode descriptor.
+ */
+extern BOOT_MODULE_FXN_TABLE net_boot_module;
+
+/**
+ * @brief This is the NET Boot Module statistics.
+ */
+extern NET_STATS net_stats;
+
+/**********************************************************************
+ **************************** Exported Functions **********************
+ **********************************************************************/
+
+/* IPv4 Route Management Functions: Use these API to manually add/delete routes
+ * to the NET Boot Module. If BOOTP is being used the routes are automatically
+ * added; but if BOOTP is not used; the device layer needs to ensure that
+ * routes are correctly configured */
+extern Int32 ip_add_route (Uint32 flag, IPN ip_address, IPN net_mask, IPN next_hop);
+extern void ip_del_route (Uint32 flag);
+
+/* Socket Functions: These are a very primitive stripped down versions of the
+ * BSD socket API which are available to device authors to write their own
+ * UDP application if one is so desired. BOOTP and TFTP are two applications
+ * provided as a part of the NET Boot Module which use these. */
+extern Int32 udp_sock_open (SOCKET* ptr_socket);
+extern Int32 udp_sock_send (Int32 sock, Uint8* ptr_app_data, Int32 num_bytes);
+extern void udp_sock_close(Int32 sock);
+
+/* TFTP Functions: This is a TFTP exported API available to device authors to
+ * be able to retrieve a file from the TFTP Server. */
+extern Int32 tftp_get_file (IPN server_ip, Int8* filename);
+
+/* NET Core Functions: This function is useful if the device authors are writing
+ * their own application; this is an ERROR Signal to the NET Boot Module that something
+ * catastrophic has happened and that the application is not enable to proceed further. */
+extern void net_set_error(void);
+
+
+#endif /* __NET_H__ */
diff --git a/src/driver/eth/net_orig.c b/src/driver/eth/net_orig.c
--- /dev/null
@@ -0,0 +1,471 @@
+/**
+ * @file net.c
+ *
+ * @brief
+ * The file implements the NET Boot Module.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include "timer.h"
+#include "stream.h"
+#include <string.h>
+
+
+/**********************************************************************
+ *************************** Local Functions **************************
+ **********************************************************************/
+static Int32 net_open (void* ptr_net_driver);
+static Int32 net_close(void);
+static Int32 net_read (Uint8* ptr_buf, Uint32 num_bytes);
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @brief This is the NETWORK Master control block which keeps track
+ * of all the Network boot module related information.
+ */
+NET_MCB netmcb;
+
+/**
+ * @brief This keeps track of the network statistics.
+ */
+NET_STATS net_stats;
+
+/**
+ * @brief This is the global Network Boot Module function table which
+ * implements the Boot Module Interface with the kernel.
+ */
+BOOT_MODULE_FXN_TABLE net_boot_module =
+{
+ net_open, /* Open API */
+ net_close, /* Close API */
+ net_read, /* Read API */
+ NULL, /* Write API (NULL: This is not interactive) */
+ net_peek, /* Peek API (TBA) */
+};
+
+/**********************************************************************
+ **************************** NET Functions ***************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * The function is used to allocate a packet for transmission. This
+ * is called by the higher layer protocols when a packet needs to
+ * be transmitted. The function ensures there is sufficient space
+ * allocated at the beginning of the packet for the Ethernet header.
+ * Since the pointer returned by this API is used to store L3/L4 headers
+ * it always returns a 4 byte aligned buffer data pointer.
+ *
+ * @param[in] packet_len
+ * Length of the packet being transmitted.
+ *
+ * @retval
+ * Success - Pointer to the L3 header.
+ * @retval
+ * Error - NULL
+ */
+Uint8* net_alloc_tx_packet(Int32 packet_len)
+{
+ /* Sanity Check: Ensure the packet being allocated does not exceed the
+ * max buffer size that we have. */
+ if (packet_len > NET_MAX_MTU)
+ return NULL;
+
+ /* Sanity Check: Ensure that the packet is available for use. */
+ if (netmcb.txuse == 1)
+ return NULL;
+
+ /* Mark the packet as being in use. */
+ netmcb.txuse = 1;
+
+ /* Reset the contents of the packet */
+ memset ((void *)&netmcb.tx_packet[0], 0, sizeof(netmcb.tx_packet));
+
+ /* Reserve some space at the head of the packet for the Ethernet headers. */
+ return &netmcb.tx_packet[16];
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called to free up a previously allocated transmit
+ * packet.
+ *
+ * @param[in] ptr
+ * Pointer to the packet being cleaned.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void net_free_tx_packet (Uint8* ptr)
+{
+ /* Sanity Checks: Ensure that the packet being cleaned is the same as the one
+ * which was allocated. */
+ if (ptr != &netmcb.tx_packet[16])
+ mprintf ("ERROR: NET Free Transmit packet detected corruption\n");
+
+ /* Sanity Checks: Ensure that there is no double free. */
+ if (netmcb.txuse == 0)
+ mprintf ("ERROR: NET Free Transmit packet detected double free\n");
+
+ /* Mark the transmit packet as free and available. */
+ netmcb.txuse = 0;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is used to append an Ethernet header on the packet.
+ * The source MAC Address in the packet is always the one which was
+ * registered by the driver. Higher layer protocol authors need to
+ * use the 'net_alloc_tx_packet' API to get a transmit buffer.
+ *
+ * @param[in] ptr_l3_hdr
+ * This is the pointer to the layer3 header.
+ * @param[in] dst_mac
+ * The destination MAC address
+ * @param[in] protocol
+ * The layer3 protocol version (passed in host order)
+ *
+ * @retval
+ * Success - Pointer to the start of the Ethernet header i.e. L2.
+ * @retval
+ * Error - NULL
+ */
+ETHHDR* net_create_eth_header (Uint8* ptr_l3_hdr, Uint8* dst_mac, Uint16 protocol)
+{
+ Int32 rsvd_space;
+
+ /* Compute the reserved space. */
+ rsvd_space = (Int32)ptr_l3_hdr - (Int32)&netmcb.tx_packet[0];
+
+ /* Ensure there is sufficient space to add the header. We dont want memory corruption
+ * to occur here. */
+ if ((rsvd_space < 0) || (rsvd_space > NET_MAX_MTU) || (rsvd_space < ETHHDR_SIZE))
+ return NULL;
+
+ /* Convert the protocol to network order. */
+ protocol = ntohs(protocol);
+
+ /* Start adding the Ethernet header.
+ * Move back the data pointer to account for the protocol. */
+ ptr_l3_hdr = ptr_l3_hdr - 2;
+ memcpy ((void *)ptr_l3_hdr, (void *)&protocol, sizeof(Uint16));
+
+ /* Move back the data pointer to account for the source MAC. */
+ ptr_l3_hdr = ptr_l3_hdr - 6;
+ memcpy ((void *)ptr_l3_hdr, (void *)&netmcb.net_device.mac_address[0], 6);
+
+ /* Move back the data pointer to account for the destination MAC. */
+ ptr_l3_hdr = ptr_l3_hdr - 6;
+ memcpy ((void *)ptr_l3_hdr, (void *)dst_mac, 6);
+
+ /* Return the pointer to the start of the Ethernet header. */
+ return (ETHHDR *)ptr_l3_hdr;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is used to send a packet to the driver.
+ *
+ * @param[in] ptr_l2_hdr
+ * This is the pointer to the L2 header of the packet to be transmitted.
+ * All the headers need to be populated by the time comes to this API.
+ * @param[in] length
+ * Length of the packet being transmitted. This include the L2 header
+ * information.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void net_send_packet (ETHHDR* ptr_l2_hdr, Uint16 length)
+{
+ /* Sanity Check: This is called after the LAYER3 and ETHER headers
+ * have been appended to the packet. Here we ensure that the layer3 header
+ * is aligned on the 4 byte boundary. */
+ if ( (((Uint32)ptr_l2_hdr+ETHHDR_SIZE) % 4) != 0)
+ mprintf ("ERROR: Misaligned Layer3 packet transmitted 0x%p.\n", ptr_l2_hdr);
+
+ /* Increment the stats. */
+ net_stats.num_pkt_txed++;
+
+ /* Pass the packet to the platform API for transmission. */
+ netmcb.net_device.send (&netmcb.net_device, (Uint8 *)ptr_l2_hdr, (Int32)length);
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called from any entity inside the NETWORK Boot Module
+ * to indicate that there has been a FATAL error and that the boot module
+ * processing needs to be aborted.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void net_set_error (void)
+{
+ /* Set the Error Flag; */
+ netmcb.error_flag = 1;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function opens the BLF NET Module. The function initializes
+ * the various internal components of the NET module and also
+ * initializes the peripheral driver controller
+ *
+ * @param[in] ptr_driver
+ * This is the pointer to the driver block which was passed to
+ * the BLF through the BOOT Mode descriptor. For the NET boot
+ * module this points to the NET_DRV_DEVICE object.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_open (void* ptr_driver)
+{
+ NET_DRV_DEVICE* ptr_net_driver;
+
+ /* Get the pointer to the net driver. */
+ ptr_net_driver = (NET_DRV_DEVICE*)ptr_driver;
+
+ /* Basic Validation: Ensure there is a valid driver block being passed. */
+ if (ptr_net_driver == NULL)
+ return -1;
+
+ /* Basic Validation: Ensure that all the required API have been provided */
+ if ((ptr_net_driver->start == NULL) || (ptr_net_driver->send == NULL) ||
+ (ptr_net_driver->receive == NULL) || (ptr_net_driver->stop == NULL))
+ {
+ /* Error: Required API was not specified. */
+ return -1;
+ }
+
+ /* Initialize the NET MCB. */
+ memset (&netmcb, 0, sizeof(NET_MCB));
+
+ /* Initialize the Network Statistics. */
+ memset (&net_stats, 0, sizeof(NET_STATS));
+
+ /* Copy the driver information into the NET MCB */
+ memcpy ((void *)&netmcb.net_device, (void *)ptr_net_driver, sizeof(NET_DRV_DEVICE));
+
+ /* Initialize the ARP Module. */
+ arp_init ();
+
+ /* Initialize the IP Module. */
+ ip_init ();
+
+ /* Initialize the UDP Module. */
+ udp_init ();
+
+ /* Start the networking device */
+ if (netmcb.net_device.start(&netmcb.net_device) < 0)
+ return -1;
+
+ /* Determine if we need to execute BOOTP or not? */
+ if (netmcb.net_device.ip_address != 0)
+ {
+ /* IP Address was supplied by the device team. There is no need
+ * to execute the BOOTP protocol; manually create the network route also. */
+ ip_add_route (FLG_RT_NETWORK, netmcb.net_device.ip_address, netmcb.net_device.net_mask, 0);
+
+#ifdef INCLUDE_BLF_NET_TFTP
+ /* Lets download the file from the TFTP Server. */
+ tftp_get_file (netmcb.net_device.server_ip, netmcb.net_device.file_name);
+#endif /* INCLUDE_BLF_NET_TFTP */
+ }
+ else
+ {
+#ifdef INCLUDE_BLF_NET_BOOTP
+ /* No IP Address was supplied we need to execute the BOOTP protocol. */
+ bootp_init ();
+#endif
+ }
+
+ /* The network module is UP and running.. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function closes the BLF NET Module.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_close (void)
+{
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function reads data from the BLF net module.
+ *
+ * @param[in] ptr_buf
+ * This points to the data buffer which needs to be populated
+ * with the received data.
+ *
+ * @param[in] num_bytes
+ * This is the number of bytes of data which need to be read.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 net_read (Uint8* ptr_buf, Uint32 num_bytes)
+{
+ Int32 packet_size;
+ Uint16 protocol;
+ Uint8 dst_mac_address[6];
+ Uint8* ptr_data_packet;
+ Int32 num_bytes_read = 0;
+ Int32 total_num_bytes_read = 0;
+
+ /* Basic Validations: Ensure that the parameters are valid. */
+ if ((ptr_buf == NULL) || (num_bytes == 0))
+ return -1;
+
+ /* Execute the network scheduler; till there is no error. */
+ while (netmcb.error_flag == 0)
+ {
+ /* Call the timer scheduler. */
+ timer_run();
+
+ /* Check if there is data in the STREAM? */
+ if (stream_isempty() == FALSE)
+ {
+ /* STREAM indicates there is some data. Lets read it first. */
+ num_bytes_read = stream_read (((ptr_buf + total_num_bytes_read)), num_bytes);
+
+ /* Keep track of the total amount of data read till now. */
+ total_num_bytes_read = total_num_bytes_read + num_bytes_read;
+
+ /* How much more data do we need to read? */
+ num_bytes = num_bytes - num_bytes_read;
+
+ /* Check if we have read all the data that was requested? */
+ if (num_bytes == 0)
+ break;
+
+ /* Control comes here implies that there was more data to be read into
+ * the buffer. We need it to have it available before we can exit the loop.
+ * So lets fall through! */
+ }
+ else
+ {
+ /* STREAM Module is empty. */
+ }
+
+ /* Initialize the pointer in the received packet is stored.
+ * This is misaligned on the 2 byte boundary as this will ensure that
+ * the layer3 headers i.e. IPv4 and ARP are aligned correctly. */
+ ptr_data_packet = (Uint8 *)&netmcb.rx_packet[2];
+
+ /* Check if a packet has been received? */
+ packet_size = netmcb.net_device.receive(&netmcb.net_device, ptr_data_packet);
+ if (packet_size == 0)
+ continue;
+
+ /* Increment the number of packets received. */
+ net_stats.num_pkt_rxed++;
+
+ /* Extract the destination MAC Address from the received packet. */
+ memcpy ((void *)&dst_mac_address[0], (void *)ptr_data_packet, 6);
+
+ /* Extract the protocol from the received packet. This is at offset 12 from the
+ * start of the packet. We need to skip the destination and source mac address. */
+ protocol = *((Uint16 *)(ptr_data_packet + 12));
+ protocol = ntohs(protocol);
+
+ /* Process the received data.
+ * Check the destination mac address to determine if the packet is
+ * meant for us or not? We accept only directed UNICAST & BROADCAST
+ * packets */
+ if(((dst_mac_address[0] != 0xFF) || (dst_mac_address[1] != 0xFF) ||
+ (dst_mac_address[2] != 0xFF) || (dst_mac_address[3] != 0xFF) ||
+ (dst_mac_address[4] != 0xFF) || (dst_mac_address[5] != 0xFF)) &&
+ ((dst_mac_address[0] != netmcb.net_device.mac_address[0]) ||
+ (dst_mac_address[1] != netmcb.net_device.mac_address[1]) ||
+ (dst_mac_address[2] != netmcb.net_device.mac_address[2]) ||
+ (dst_mac_address[3] != netmcb.net_device.mac_address[3]) ||
+ (dst_mac_address[4] != netmcb.net_device.mac_address[4]) ||
+ (dst_mac_address[5] != netmcb.net_device.mac_address[5])))
+ {
+ /* Packet is not meant for us; ignore this packet. */
+ net_stats.rx_l2_dropped++;
+ continue;
+ }
+
+ /* Move the pointer to the data packet and skip the ethernet header. */
+ ptr_data_packet = ptr_data_packet + sizeof(ETHHDR);
+
+ /* Deduct the Ethernet header size from the total number of bytes received. */
+ packet_size = packet_size - sizeof(ETHHDR);
+
+ /* Sanity Check: We need to ensure that the Layer3 headers are aligned on the
+ * 4 byte boundary at this stage. */
+ if (((Uint32)ptr_data_packet % 4) != 0)
+ mprintf ("ERROR: Misaligned Layer3 packet received 0x%p.\n", ptr_data_packet);
+
+ /* Demux on the protocol basis and pass it to the upper layer. */
+ switch (protocol)
+ {
+ case ETH_IP:
+ {
+ /* IPv4 Packet. */
+ if (ip_receive ((IPHDR *)ptr_data_packet, packet_size) < 0)
+ net_stats.rx_ip_dropped++;
+ break;
+ }
+ case ETH_ARP:
+ {
+ /* ARP Packet. */
+ if (arp_receive ((ARPHDR *)ptr_data_packet, packet_size) < 0)
+ net_stats.rx_arp_dropped++;
+ break;
+ }
+ default:
+ {
+ /* Unexpected packet. Drop the packet! */
+ net_stats.rx_l2_dropped++;
+ break;
+ }
+ }
+ }
+
+ /* Did we come out because of error or not? */
+ if (netmcb.error_flag == 0)
+ return 0;
+
+ /* Return error */
+ return -1;
+}
+
+
diff --git a/src/driver/eth/netif.h b/src/driver/eth/netif.h
--- /dev/null
+++ b/src/driver/eth/netif.h
@@ -0,0 +1,390 @@
+/**
+ * @file netif.h
+ *
+ * @brief
+ * Internal header file used only by the NET Boot Module
+ * This header file is not accessible by the DEVICE layers.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+
+#ifndef __NETIF_H__
+#define __NETIF_H__
+
+/**
+ * @brief This is the protocol identification field in the Ethernet
+ * header which identifies the packet as an IPv4 packet.
+ */
+#define ETH_IP 0x800
+
+/**
+ * @brief This is the protocol identification field in the Ethernet
+ * header which identifies the packet as an IPv4 packet.
+ */
+#define ETH_ARP 0x806
+
+/**
+ * @brief This is the protocol identification field in the IPv4 header
+ * which identifies the packet as an ICMP packet.
+ */
+#define IPPROTO_ICMP 1
+
+/**
+ * @brief This is the protocol identification field in the IPv4 header
+ * which identifies the packet as a UDP packet.
+ */
+#define IPPROTO_UDP 17
+
+/**
+ * @brief This is the ICMP Echo request type field which is present in the
+ * ICMP header. This is the only type handled in the ICMP Network Boot Module.
+ */
+#define ICMP_ECHO_REQUEST_TYPE 8
+
+/**
+ * @brief This is the ICMP Echo reply type field which is present in the
+ * ICMP header. This is the reply packet generated in response to the REQ
+ * packet.
+ */
+#define ICMP_ECHO_REPLY_TYPE 0
+
+/**
+ * @brief This is the BOOTP SERVER port to which BOOTP requests are sent
+ * by the BOOTP client module.
+ */
+#define BOOTP_SERVER_PORT 67
+
+/**
+ * @brief This is the BOOTP Local port using which the BOOTP client will
+ * send requests.
+ */
+#define BOOTP_CLIENT_PORT 68
+
+/**
+ * @brief This is the BOOTP OP definition for a BOOTP request
+ */
+#define BOOTP_OP_REQUEST 1
+
+/**
+ * @brief This is the BOOTP OP definition for a BOOTP reply
+ */
+#define BOOTP_OP_REPLY 2
+
+/**
+ * @brief This is the BOOTP HTYPE definition for Ethernet.
+ */
+#define BOOTP_HTYPE_ETHERNET 1
+
+/**
+ * @brief This is the BOOTP Seed Timeout (in milliseconds) which is being used.
+ */
+#define BOOTP_SEED_TIMEOUT 4000
+
+/**
+ * @brief This is the max. number of retries for which the BOOTP client
+ * will wait.
+ */
+#define BOOTP_MAX_RETRIES 5
+
+/**
+ * @brief This is the default BOOTP subnet mask which is used if there
+ * is none present in the BOOTP options.
+ */
+#define BOOTP_DEFAULT_MASK htonl(0xFFFFFF00)
+
+/**
+ * @brief This is the well defined TFTP Server port.
+ */
+#define TFTP_SERVER_PORT 69
+
+/**
+ * @brief This is the maximum TFTP data size that is sent out.
+ */
+#define TFTP_DATA_SIZE 512
+
+/**
+ * @brief This is the TFTP opcode for READ
+ */
+#define TFTP_OPCODE_RRQ 1
+
+/**
+ * @brief This is the TFTP opcode for DATA
+ */
+#define TFTP_OPCODE_DATA 3
+
+/**
+ * @brief This is the TFTP opcode for ACK
+ */
+#define TFTP_OPCODE_ACK 4
+
+/**
+ * @brief This is the TFTP opcode for ERROR
+ */
+#define TFTP_OPCODE_ERROR 5
+
+/**
+ * @brief This is the TFTP timeout (in milliseconds) used
+ * to send out periodic READ Requests if there is no response
+ * detected.
+ */
+#define TFTP_TIMEOUT 1000
+
+/**
+ * @brief This is the TFTP Server timeout (in milliseconds)
+ * to detect the condition where the TFTP Server goes away in
+ * the middle of the download.
+ */
+#define TFTP_SERVER_TIMEOUT 60000
+
+/**
+ * @brief This is the maximum number of retransmits allowed
+ * in the TFTP Client after which an error is indicated.
+ */
+#define MAX_TFTP_RETRANSMITS 5
+
+/**
+ * @brief This is the the ARP timeout (in milliseconds) used
+ * to resend ARP requests.
+ */
+#define ARP_TIMEOUT 1000
+
+/***********************************************************************
+ ****************** STANDARD NETWORK HEADER DEFINITIONS ****************
+ ***********************************************************************/
+
+#define ETHHDR_SIZE 14
+typedef struct ETHHDR
+{
+ Uint8 DstMac[6];
+ Uint8 SrcMac[6];
+ Uint16 Type;
+} ETHHDR;
+
+#define IPHDR_SIZE 20
+typedef struct IPHDR
+{
+ Uint8 VerLen;
+ Uint8 Tos;
+ Uint16 TotalLen;
+ Uint16 Id;
+ Uint16 FlagOff;
+ Uint8 Ttl;
+ Uint8 Protocol;
+ Uint16 Checksum;
+ Uint32 IPSrc;
+ Uint32 IPDst;
+ Uint8 Options[1];
+} IPHDR;
+
+#define ARPHDR_SIZE 28
+typedef struct ARPHDR
+{
+ Uint16 HardType;
+ Uint16 ProtocolType;
+ Uint8 HardSize;
+ Uint8 ProtocolSize;
+ Uint16 Op;
+ Uint8 SrcAddr[6];
+ Uint8 IPSrc[4];
+ Uint8 DstAddr[6];
+ Uint8 IPDst[4];
+} ARPHDR;
+
+typedef struct PSEUDOHDR
+{
+ IPN IPSrc;
+ IPN IPDst;
+ Uint16 Length;
+ Uint8 Null;
+ Uint8 Protocol;
+} PSEUDOHDR;
+
+#define UDPHDR_SIZE 8
+typedef struct UDPHDR
+{
+ Uint16 SrcPort;
+ Uint16 DstPort;
+ Uint16 Length;
+ Uint16 UDPChecksum;
+}UDPHDR;
+
+#define ICMPHDR_SIZE 4
+typedef struct ICMPHDR
+{
+ Uint8 Type;
+ Uint8 Code;
+ Uint16 Checksum;
+ Uint8 Data[1];
+}ICMPHDR;
+
+typedef struct BOOTPHDR
+{
+ Uint8 op;
+ Uint8 htype;
+ Uint8 hlen;
+ Uint8 hops;
+ Uint32 xid;
+ Uint16 secs;
+ Uint16 unused;
+ Uint32 ciaddr;
+ Uint32 yiaddr;
+ Uint32 siaddr;
+ Uint32 giaddr;
+ Uint8 chaddr[16];
+ Uint8 sname[64];
+ Uint8 file[128];
+ Uint8 options[64];
+} BOOTPHDR;
+
+#define TFTPHEADER_SIZE 4
+typedef struct TFTPHDR
+{
+ Uint16 opcode;
+ Uint16 block;
+ Uint8 data[1];
+}TFTPHDR;
+
+/**
+ * @brief
+ * The structure describes the ROUTE Entry.
+ *
+ * @details
+ * This structures describes the routing entry. This is used by the network
+ * boot module to determine the next hop address. The next hop address might
+ * not be the same as the destination IP address if there exists a default
+ * gateway.
+ */
+typedef struct RT_ENTRY
+{
+ /**
+ * @brief Flags which describe the routing entry.
+ */
+ Uint32 flags;
+
+ /**
+ * @brief IP Address associated with the route
+ */
+ IPN ip_addr;
+
+ /**
+ * @brief Network Mask associated with the route
+ */
+ IPN net_mask;
+
+ /**
+ * @brief Network Address associated with the route
+ */
+ IPN net_addr;
+
+ /**
+ * @brief Next Hop Address associated with the route
+ */
+ IPN next_hop;
+}RT_ENTRY;
+
+/**
+ * @brief
+ * The structure describes the NET Master Control Block.
+ *
+ * @details
+ * This is an *internal* structure used by the NET Core Module for storing
+ * information. This structure should not be used or be accessed by the
+ * platform team.
+ */
+typedef struct NET_MCB
+{
+ /**
+ * @brief This is the network device which is attached to the network
+ * boot module.
+ */
+ NET_DRV_DEVICE net_device;
+
+ /**
+ * @brief This is the receive packet which is passed to the driver
+ * when the Net boot module invokes the receive API. The driver copies
+ * data from its internal buffers to this buffer. The network boot module
+ * only operates on this buffer.
+ */
+ Uint8 rx_packet[NET_MAX_MTU];
+
+ /**
+ * @brief This is the IP ID field which is globally incremented on
+ * every packet transmitted from the Network boot module.
+ */
+ Uint16 ipID;
+
+ /**
+ * @brief This indicates the status of the transmission buffer and whether
+ * it is available to be used or not. This is manipulated by the alloc_tx
+ * and free_tx routines to ensure there is no corruption with respect to the
+ * internal buffers.
+ */
+ Uint32 txuse;
+
+ /**
+ * @brief This flag indicates if there was an Error detected in the
+ * NET Boot Module or not? This is then used to break out of the NET Boot
+ * Module Scheduler. If there is no error detected the flag is set to 0.
+ */
+ Int32 error_flag;
+
+ /**
+ * @brief This is the transmit packet which is used by the network
+ * module to send a packet to the driver.
+ */
+ Uint8 tx_packet[NET_MAX_MTU];
+
+
+ /**
+ * @brief This tracks the current read byte in the file
+ */
+ Uint32 fileOffset;
+
+
+}NET_MCB;
+
+/**********************************************************************
+ **************************** Extern Data *****************************
+ **********************************************************************/
+extern NET_MCB netmcb;
+
+/**********************************************************************
+ **************************** Exported API ****************************
+ **********************************************************************/
+extern void net_init (void);
+extern Uint8* net_alloc_tx_packet(Int32 packet_len);
+extern void net_free_tx_packet (Uint8* ptr);
+extern ETHHDR* net_create_eth_header (Uint8* ptr_l3_hdr, Uint8* dst_mac, Uint16 protocol);
+extern void net_send_packet (ETHHDR* ptr_l2_hdr, Uint16 length);
+
+/* ARP Module exported API. */
+extern void arp_init (void);
+extern Int32 arp_receive (ARPHDR* ptr_arphdr, Int32 num_bytes);
+extern void arp_resolve (IPN dst_ip, IPHDR* ptr_iphdr, Uint16 l3_pkt_size);
+
+/* IPv4 Module exported API. */
+extern void ip_init (void);
+extern Int32 ip_receive (IPHDR* ptr_iphdr, Int32 num_bytes);
+extern void ip_send (IPHDR* ptr_iphdr, Uint16 size);
+extern RT_ENTRY* ip_lookup_route (IPN ip_address);
+
+/* UDP Module exported API. */
+extern void udp_init (void);
+extern Int32 udp_receive (IPHDR* ptr_iphdr);
+
+/* BOOTP Module exported API */
+#ifdef INCLUDE_BLF_NET_BOOTP
+extern void bootp_init (void);
+#endif
+
+#ifdef INCLUDE_BLF_NET_ICMP
+extern void icmp_receive (IPHDR* ptr_iphdr);
+#endif
+
+#endif /* __NETIF_H__ */
+
+
diff --git a/src/driver/eth/tftp.c b/src/driver/eth/tftp.c
--- /dev/null
+++ b/src/driver/eth/tftp.c
@@ -0,0 +1,511 @@
+/**
+ * @file tftp.c
+ *
+ * @brief
+ * The file implements the NET Module TFTP functionality.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include "timer.h"
+#include "stream.h"
+#include <string.h>
+
+
+/**********************************************************************
+ *************************** LOCAL Structures *************************
+ **********************************************************************/
+
+/**
+ * @brief
+ * The structure describes the TFTP State
+ *
+ * @details
+ * The TFTP client can be in one of the following states which are
+ * described in this structure.
+ */
+typedef enum TFTP_STATE
+{
+ /**
+ * @brief This is the initial state of the TFTP client during startup
+ * In this state the TFTP client has sent out the READ Request and has
+ * not yet received a data packet in acknowledgment.
+ */
+ READ_REQUEST = 0x1,
+
+ /**
+ * @brief This is the data receive state of the TFTP client in which
+ * the TFTP client is receiving data packets from the TFTP server.
+ */
+ DATA_RECEIVE
+}TFTP_STATE;
+
+/**
+ * @brief
+ * The structure describes the TFTP Master Control Block.
+ *
+ * @details
+ * The TFTP Master control block stores information used by the
+ * TFTP module.
+ */
+typedef struct TFTP_MCB
+{
+ /**
+ * @brief This describes the state of the TFTP client.
+ */
+ TFTP_STATE state;
+
+ /**
+ * @brief This is the IP Address of the server from where the file
+ * is downloaded.
+ */
+ IPN server_ip;
+
+ /**
+ * @brief This is the TFTP socket which is used to communicate
+ * with the UDP module.
+ */
+ Int32 sock;
+
+ /**
+ * @brief This is the TFTP Timer handle which is used to handle
+ * retransmissions of the READ REQUEST.
+ */
+ Int32 timer;
+
+ /**
+ * @brief This is the name of the file which is being downloaded.
+ * File Names are typically exchanged through the BOOTP protocol
+ * where the max file name length is 64.
+ */
+ Uint8 filename[64];
+
+ /**
+ * @brief This is the block number we expect.
+ */
+ Uint16 block_num;
+
+ /**
+ * @brief This is a generic buffer used by the TFTP module,
+ */
+ Uint8 buffer[TFTP_DATA_SIZE + TFTPHEADER_SIZE];
+
+ /**
+ * @brief Number of retransmission done.
+ */
+ Uint32 num_retransmits;
+}TFTP_MCB;
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @brief This is the global master control block for the TFTP
+ * module and keeps track of all the information regarding TFTP.
+ */
+TFTP_MCB tftpmcb;
+
+/**********************************************************************
+ **************************** TFTP Functions **************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * The function cleans up the TFTP Client. This can be called
+ * on an ERROR or SUCCESSFUL exit.
+ *
+ * @retval
+ * Not Applicable.
+ */
+static void tftp_cleanup (void)
+{
+ /* Close any open timers. */
+ timer_delete (tftpmcb.timer);
+ tftpmcb.timer = -1;
+
+ /* Close the UDP Sockets. */
+ udp_sock_close (tftpmcb.sock);
+
+ /* Close the STREAM module */
+ stream_close ();
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function creates the TFTP read request and populates it
+ * in the internal TFTP buffer.
+ *
+ * @retval
+ * Size of the TFTP Read Request.
+ */
+static Int32 tftp_create_read_req (Uint8* filename)
+{
+ Uint16* ptr_op;
+ Int32 index = 0;
+
+ /* Create the Read Request: Populate the Request op type */
+ ptr_op = (Uint16 *)&tftpmcb.buffer[0];
+ *ptr_op = htons(TFTP_OPCODE_RRQ);
+
+ /* Copy the file name */
+ index = 0;
+ while (filename[index] != 0)
+ {
+ tftpmcb.buffer[index + 2] = filename[index];
+ index++;
+ }
+
+ /* Null Terminate the file name. */
+ tftpmcb.buffer[index + 2] = 0;
+ index = index + 3;
+
+ /* Copy the transfer mode. */
+ tftpmcb.buffer[index++] = (Uint8)'o';
+ tftpmcb.buffer[index++] = (Uint8)'c';
+ tftpmcb.buffer[index++] = (Uint8)'t';
+ tftpmcb.buffer[index++] = (Uint8)'e';
+ tftpmcb.buffer[index++] = (Uint8)'t';
+ tftpmcb.buffer[index++] = (Uint8)0;
+
+ /* Return the size of the read request */
+ return index;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is used to send an ACK back to TFTP Server.
+ *
+ * @retval
+ * Not Applicable
+ */
+static void tftp_send_ack(void)
+{
+ TFTPHDR* ptr_tftphdr;
+
+ /* Initialize the data buffer. */
+ memset ((void *)&tftpmcb.buffer[0], 0, TFTP_DATA_SIZE + TFTPHEADER_SIZE);
+
+ /* Create an ACK packet which is to be sent out. Get the pointer to the
+ * TFTP Header. */
+ ptr_tftphdr = (TFTPHDR *)&tftpmcb.buffer[0];
+ ptr_tftphdr->opcode = htons (TFTP_OPCODE_ACK);
+ ptr_tftphdr->block = htons (tftpmcb.block_num);
+
+ /* The packet has been populated; send it to the server; this transfer is now done
+ * over the data socket. */
+ udp_sock_send (tftpmcb.sock, (Uint8 *)ptr_tftphdr, TFTPHEADER_SIZE);
+
+ /* Increment the block number. */
+ tftpmcb.block_num++;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is the timer expiration for TFTP.
+ *
+ * @retval
+ * Not Applicable
+ */
+static void tftp_timer_expiry (void)
+{
+ Int32 len;
+
+ /* Determine the state of the TFTP. */
+ if (tftpmcb.state == READ_REQUEST)
+ {
+ /* We were sending out READ Request and have not received a response
+ * Increment the number of retransmissions which have been done. */
+ tftpmcb.num_retransmits++;
+
+ /* Check if we have exceeded the max allowed? */
+ if (tftpmcb.num_retransmits > MAX_TFTP_RETRANSMITS)
+ {
+ /* FATAL Error: We need to close the TFTP Client and signal Error to the NET Boot Module. */
+ mprintf ("Error: TFTP READ REQ Retransmissions have exceeded\n");
+ tftp_cleanup ();
+ net_set_error();
+ return;
+ }
+
+ /* Create the TFTP Read Request */
+ len = tftp_create_read_req (&tftpmcb.filename[0]);
+
+ /* Send out the READ Request again. */
+ udp_sock_send (tftpmcb.sock, (Uint8 *)&tftpmcb.buffer[0], len);
+ }
+ else
+ {
+ /* We were receiving data from the TFTP Server and there was a timeout. This can
+ * happen only if we have not received any data from the TFTP server. */
+ mprintf ("Error: TFTP server is down; no packet received.\n");
+ tftp_cleanup();
+ net_set_error();
+ return;
+ }
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * This is a call back function registered with the UDP module to
+ * be invoked when a TFTP packet is received.
+ *
+ * @param[in] sock
+ * This is the socket handle on which packet was received.
+ * @param[in] ptr_data
+ * This is the pointer to the TFTP data payload.
+ * @param[in] num_bytes
+ * This is the number of bytes of TFTP data received.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+static Int32 tftp_receive (Int32 sock, Uint8* ptr_data, Int32 num_bytes)
+{
+ TFTPHDR* ptr_tftphdr;
+ UDPHDR* ptr_udphdr;
+ Uint16 src_port;
+ SOCKET socket;
+
+ /* Get the pointer to the TFTP Header. */
+ ptr_tftphdr = (TFTPHDR *)ptr_data;
+
+ /* Process the received packet depending on the type of packet received */
+ switch (ntohs(ptr_tftphdr->opcode))
+ {
+ case TFTP_OPCODE_DATA:
+ {
+ /* Is this the first data packet we have received? */
+ if (tftpmcb.state == READ_REQUEST)
+ {
+ /* YES. In this case the socket on which the request was sent has completed
+ * its job. Lets shut it down and open another one for the data transfers. */
+ udp_sock_close (sock);
+
+ /* We need to get the source port from where the data was received.
+ * This information is present in the UDP layer. This is required to
+ * open the data socket. */
+ ptr_udphdr = (UDPHDR *)(ptr_data - sizeof(UDPHDR));
+ src_port = ntohs(ptr_udphdr->SrcPort);
+
+ /* Populate the socket structure and register this with the UDP module. */
+ socket.local_port = 1234;
+ socket.remote_port = src_port;
+ socket.remote_address = tftpmcb.server_ip;
+ socket.app_fn = tftp_receive;
+
+ /* Move to the DATA State. */
+ tftpmcb.state = DATA_RECEIVE;
+ tftpmcb.num_retransmits = 0;
+
+ /* Close the timer. */
+ timer_delete (tftpmcb.timer);
+ tftpmcb.timer = -1;
+
+ /* Open the TFTP data socket. */
+ tftpmcb.sock = udp_sock_open (&socket);
+ if (tftpmcb.sock < 0)
+ {
+ /* Error: Data Socket open failed. */
+ mprintf ("Error: TFTP Data Socket Open Failed\n");
+ tftp_cleanup();
+ net_set_error();
+ return -1;
+ }
+ }
+
+ /* We are in the DATA State: Start the TFTP Server Keep Alive Timer. This timer
+ * keeps track of the TFTP Server and ensures it does not die behind us. This will
+ * help detect that error. */
+ timer_delete (tftpmcb.timer);
+ tftpmcb.timer = timer_add (TFTP_SERVER_TIMEOUT, tftp_timer_expiry);
+ if (tftpmcb.timer < 0)
+ {
+ /* Timer creation failed. */
+ mprintf ("Error: TFTP Timer creation failed\n");
+ tftp_cleanup();
+ net_set_error();
+ return -1;
+ }
+
+ /* Received a data block. Ensure that the block number matches what we expect! */
+ if (ntohs(ptr_tftphdr->block) != tftpmcb.block_num)
+ {
+ /* There is a block number mismatch. This could occur if the ACK we sent was lost.
+ * Increment the number of retransmissions. */
+ tftpmcb.num_retransmits++;
+ if (tftpmcb.num_retransmits > MAX_TFTP_RETRANSMITS)
+ {
+ /* OK; we resent the ACK multiple times & the server still kept sending the
+ * same packet back. We just give up now. */
+ mprintf ("Error: TFTP ACK Retransmits Exceeded\n");
+ tftp_cleanup();
+ net_set_error();
+ return -1;
+ }
+
+ /* We need to send out the ACK for the previous 'block' */
+ tftpmcb.block_num = tftpmcb.block_num - 1;
+
+ /* Send the ACK out again. */
+ tftp_send_ack ();
+
+ /* We dont need to process this packet since we had already picked it up. */
+ return 0;
+ }
+
+ /* The packet looks good. Reset the number of retransmissions. */
+ tftpmcb.num_retransmits = 0;
+
+ /* Pass the received data packet to the STREAM Module.
+ * We need to skip the TFTP Header. */
+ if (stream_write ((ptr_data + TFTPHEADER_SIZE), (num_bytes - TFTPHEADER_SIZE)) == 0)
+ {
+ /* Packet has been copied successfully into the STREAM Buffer. */
+ tftp_send_ack();
+ }
+ else
+ {
+ /* Packet could not be copied; let the server retransmit the packet
+ * because we did not send the ACK. */
+ }
+
+ /* Determine if the TFTP file transfer is complete or not?
+ * If the received number of bytes is less than the TFTP Data Size this
+ * indicates that the transfer is successfully completed. */
+ if (num_bytes < (TFTP_DATA_SIZE + TFTPHEADER_SIZE))
+ {
+ /* Successfully downloaded the file */
+ tftp_cleanup();
+ }
+ break;
+ }
+ default:
+ {
+ /* Control comes here for ERROR, ACK and WRQ which are all indicate
+ * failure. ERROR packet is the only expected failure which is mentioned
+ * in the RFC. All other packets are violation of the RFC. Both these
+ * cases are handled similarly. */
+ mprintf ("Error: TFTP Error Packet Received\n");
+ tftp_cleanup();
+ net_set_error();
+
+ /* Return Error. */
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function gets a file from the TFTP Server. The function
+ * simply initiates the transfer. Successful completion of this
+ * API does not gurantee that the file was downloaded.
+ *
+ * @param[in] server_ip
+ * TFTP Server IP address from where the file is downloaded.
+ * @param[in] filename
+ * Name of the file to be downloaded.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 tftp_get_file (IPN server_ip, Int8* filename)
+{
+ SOCKET socket;
+ Int32 index = 0;
+
+ /* Basic Validations: Ensure the parameters passed are correct. */
+ if ((server_ip == 0) || (filename == NULL))
+ {
+ /* Error: Invalid parameters passed. Stop the network boot module. */
+ net_set_error();
+ return -1;
+ }
+
+ /* Open the stream module. */
+ if (stream_open (TFTP_DATA_SIZE) < 0)
+ {
+ /* Error: Unable to open the stream device. */
+ net_set_error();
+ return -1;
+ }
+
+ /* Initialize the TFTP MCB at this stage... */
+ memset ((void *)&tftpmcb, 0, sizeof(TFTP_MCB));
+
+ /* Populate the socket structure and register this with the UDP module. */
+ socket.local_port = 1234;
+ socket.remote_port = TFTP_SERVER_PORT;
+ socket.remote_address = server_ip;
+ socket.app_fn = tftp_receive;
+
+ /* Open the TFTP Control socket. */
+ tftpmcb.sock = udp_sock_open (&socket);
+ if (tftpmcb.sock < 0)
+ {
+ /* ERROR: UDP Socket could not be opened. */
+ stream_close();
+ net_set_error();
+ return -1;
+ }
+
+ /* Remember the parameters passed to the TFTP. */
+ tftpmcb.server_ip = server_ip;
+
+ /* Copy the file name over... */
+ while (filename[index] != 0)
+ {
+ tftpmcb.filename[index] = filename[index];
+ index++;
+ }
+
+ /* Initialize the block number expected. */
+ tftpmcb.block_num = 1;
+
+ /* Create the TFTP Read Request. */
+ index = tftp_create_read_req ((Uint8 *)filename);
+
+ /* Initialize the TFTP Client state */
+ tftpmcb.state = READ_REQUEST;
+
+ /* Initialize the TFTP Timer. */
+ tftpmcb.timer = timer_add (TFTP_TIMEOUT, tftp_timer_expiry);
+ if (tftpmcb.timer < 0)
+ {
+ /* Error: TFTP Timer Creation Failed. TFTP is not operational. */
+ mprintf ("Error: TFTP Timer Creation Failed\n");
+ tftp_cleanup ();
+ net_set_error();
+ return -1;
+ }
+
+ /* The packet has been populated; send it to the server. */
+ udp_sock_send (tftpmcb.sock, (Uint8 *)&tftpmcb.buffer[0], index);
+
+ /* Send out the TFTP Read request. */
+ return 0;
+}
+
+
diff --git a/src/driver/eth/udp.c b/src/driver/eth/udp.c
--- /dev/null
+++ b/src/driver/eth/udp.c
@@ -0,0 +1,322 @@
+/**
+ * @file udp.c
+ *
+ * @brief
+ * The file implements the NET Module UDP functionality.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "net.h"
+#include "netif.h"
+#include "iblcfg.h"
+#include <string.h>
+
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @brief This is the global master control block for the UDP
+ * Socket Module and contains information about all the UDP sockets
+ * which are open.
+ */
+SOCKET udp_socket[MAX_UDP_SOCKET];
+
+/**********************************************************************
+ **************************** UDP Functions ***************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * The function computes the UDP checksum and populates the UDP
+ * Checksum field.
+ *
+ * @param[in] ptr_udphdr
+ * This is the pointer to the UDP header.
+ * @param[in] ptr_pseudo
+ * This is the UDP Pseudo header used for checksum calculations.
+ *
+ * @retval
+ * Not Applicable.
+ */
+static void udp_checksum (UDPHDR *ptr_udphdr, PSEUDOHDR* ptr_pseudo)
+{
+ Int32 tmp1;
+ Uint16* pw;
+ Uint32 TSum;
+
+ /* Get header size in bytes */
+ tmp1 = ntohs(ptr_pseudo->Length);
+
+ /* Checksum field is NULL in checksum calculations */
+ ptr_udphdr->UDPChecksum = 0;
+
+ /* Checksum the header */
+ pw = (Uint16 *)ptr_udphdr;
+ TSum = 0;
+ for( ; tmp1 > 1; tmp1 -= 2 )
+ TSum += (Uint32)*pw++;
+#ifdef BIGENDIAN
+ if( tmp1 )
+ TSum += (Uint32)(*pw & 0xFF00);
+#else
+ if( tmp1 )
+ TSum += (Uint32)(*pw & 0x00FF);
+#endif
+
+ /* Checksum the pseudo header */
+ pw = (Uint16 *)ptr_pseudo;
+ for( tmp1=0; tmp1 < 6; tmp1++ )
+ TSum += (Uint32)*pw++;
+
+ TSum = (TSum&0xFFFF) + (TSum>>16);
+ TSum = (TSum&0xFFFF) + (TSum>>16);
+
+ /* Special case the 0xFFFF checksum - don't use a checksum
+ * value of 0x0000 */
+ if( TSum != 0xFFFF )
+ TSum = ~TSum;
+
+ /* Note checksum is Net/Host byte order independent */
+ ptr_udphdr->UDPChecksum = (Uint16)TSum;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function handles the processing of UDP packets.
+ *
+ * @param[in] ptr_iphdr
+ * This is the pointer to the IP header.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 udp_receive (IPHDR* ptr_iphdr)
+{
+ UDPHDR* ptr_udphdr;
+ Uint16 l4_pkt_size;
+ PSEUDOHDR pseudo;
+ Uint16 checksum;
+ Int32 index;
+
+ /* Get the pointer to the ICMP header. */
+ ptr_udphdr = (UDPHDR *) ((Uint8 *)ptr_iphdr + IPHDR_SIZE);
+
+ /* Compute the l4 packet size. */
+ l4_pkt_size = ntohs(ptr_iphdr->TotalLen) - IPHDR_SIZE;
+
+ /* Make sure we have minimum size to proceed. */
+ if (l4_pkt_size < UDPHDR_SIZE)
+ return -1;
+
+ /* Validate the UDP Checksum if one has been provided. */
+ if (ptr_udphdr->UDPChecksum)
+ {
+ /* Create the Pseudo header. */
+ pseudo.IPSrc = ptr_iphdr->IPSrc;
+ pseudo.IPDst = ptr_iphdr->IPDst;
+ pseudo.Null = 0;
+ pseudo.Protocol = 17;
+ pseudo.Length = ptr_udphdr->Length;
+
+ /* Compute the checksum and compare with the one received. */
+ checksum = ptr_udphdr->UDPChecksum;
+ udp_checksum (ptr_udphdr, &pseudo);
+ if (checksum != ptr_udphdr->UDPChecksum)
+ return -1;
+ }
+
+ /* Cycle through the UDP sockets and pass it to the application. */
+ for (index = 0; index < MAX_UDP_SOCKET; index++)
+ {
+ /* Check if there is a match of the destination port of the received
+ * packet with a local port on the socket. */
+ if (udp_socket[index].local_port == ntohs(ptr_udphdr->DstPort))
+ {
+ /* Found the socket! Pass the packet to the application receive handler. */
+ udp_socket[index].app_fn (index, (Uint8 *)((Uint8*)ptr_udphdr + sizeof(UDPHDR)),
+ (ntohs(ptr_udphdr->Length) - sizeof(UDPHDR)));
+
+ /* Packet has been successfully passed to the application. */
+ return 0;
+ }
+ }
+
+ /* Control comes here implies that there was no application waiting for the UDP data. */
+ return -1;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is available to the application layer to register themselves
+ * with the UDP layer.
+ *
+ * @param[in] ptr_socket
+ * This is the pointer to the socket structure which is populated by the
+ * application layer and registered with the UDP module.
+ *
+ * @retval
+ * Success - Socket handle
+ * @retval
+ * Error - <0
+ */
+Int32 udp_sock_open (SOCKET* ptr_socket)
+{
+ Int32 index = 0;
+
+ /* Basic Validations: The structure should be populated completely. */
+ if ((ptr_socket->remote_address == 0) || (ptr_socket->remote_port == 0) ||
+ (ptr_socket->local_port == 0) || (ptr_socket->app_fn == NULL))
+ return -1;
+
+ /* Cycle through all the UDP socket and create an entry. */
+ for (index= 0; index < MAX_UDP_SOCKET; index++)
+ {
+ /* Check if the socket is free or occupied?
+ * This can simply be done by verifying that the local port is not 0 */
+ if (udp_socket[index].local_port == 0)
+ {
+ /* Got a free slot. Copy the socket data over and return the index as the handle. */
+ memcpy ((void *)&udp_socket[index], (void *)ptr_socket, sizeof(SOCKET));
+ return index;
+ }
+ }
+ /* Control comes here indicates that there were no free sockets available. */
+ return -1;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called from the application layer to send out a packet
+ * to the UDP layer.
+ *
+ * @param[in] sock
+ * This is the socket handle which was returned in the call to udp_sock_open.
+ * @param[in] ptr_app_data
+ * This is the pointer to the application data payload.
+ * @param[in] num_bytes
+ * This is the length of the application data payload
+ *
+ * @retval
+ * Success - Number of bytes transmitted
+ * @retval
+ * Error - < 0
+ */
+Int32 udp_sock_send (Int32 sock, Uint8* ptr_app_data, Int32 num_bytes)
+{
+ SOCKET* ptr_socket;
+ IPHDR* ptr_iphdr;
+ UDPHDR* ptr_udphdr;
+ Uint8* ptr_data;
+ PSEUDOHDR pseudo;
+
+ /* Get the pointer to the socket handle. */
+ ptr_socket = &udp_socket[sock];
+
+ /* Sanity Check: Make sure that the UDP socket is valid */
+ if (ptr_socket->local_port == 0)
+ return -1;
+
+ /* Allocate memory for the packet. */
+ ptr_iphdr = (IPHDR *)net_alloc_tx_packet (num_bytes + IPHDR_SIZE + UDPHDR_SIZE);
+ if (ptr_iphdr == NULL)
+ return -1;
+
+ /* Get the pointer to the UDP header. */
+ ptr_udphdr = (UDPHDR *)((Uint8 *)ptr_iphdr + IPHDR_SIZE);
+
+ /* Get the pointer to the data payload in the newly allocated packet. */
+ ptr_data = (Uint8 *)ptr_udphdr + UDPHDR_SIZE;
+
+ /*******************************************************************************
+ ********************************* APP Data ************************************
+ *******************************************************************************/
+ memcpy ((void *)ptr_data, (void *)ptr_app_data, num_bytes);
+
+ /*******************************************************************************
+ ********************************* UDP Header **********************************
+ *******************************************************************************/
+ ptr_udphdr->SrcPort = htons(ptr_socket->local_port);
+ ptr_udphdr->DstPort = htons(ptr_socket->remote_port);
+ ptr_udphdr->Length = htons(UDPHDR_SIZE + num_bytes);
+
+ /* Create the Pseudo header. */
+ pseudo.IPSrc = netmcb.net_device.ip_address;
+ pseudo.IPDst = ptr_socket->remote_address;
+ pseudo.Null = 0;
+ pseudo.Protocol = 17;
+ pseudo.Length = ptr_udphdr->Length;
+ udp_checksum (ptr_udphdr, &pseudo);
+
+ /*******************************************************************************
+ ********************************* IPv4 Header *********************************
+ *******************************************************************************/
+ ptr_iphdr->IPDst = ptr_socket->remote_address;
+ ptr_iphdr->Protocol = IPPROTO_UDP;
+
+ /* Send the IP packet. */
+ ip_send (ptr_iphdr, UDPHDR_SIZE + IPHDR_SIZE + num_bytes);
+
+ /* Packet has been sent out. */
+ return num_bytes;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is available to the application layer to deregister themselves
+ * with the UDP layer.
+ *
+ * @param[in] sock
+ * This is the socket handle which is to be closed.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void udp_sock_close (Int32 sock)
+{
+ SOCKET* ptr_socket;
+
+ /* Basic Validation: Ensure the sock is in the valid range. */
+ if ((sock < 0) || (sock > MAX_UDP_SOCKET))
+ return;
+
+ /* Get the pointer to the socket handle. */
+ ptr_socket = &udp_socket[sock];
+
+ /* Reset the memory block */
+ memset ((void *)ptr_socket, 0, sizeof(SOCKET));
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function initializes the UDP Module in the NET Boot module.
+ *
+ * @retval
+ * Not Applicable
+ */
+void udp_init (void)
+{
+ /* Initialize the socket table */
+ memset (&udp_socket, 0, sizeof(udp_socket));
+ return;
+}
+
+
+
diff --git a/src/driver/nand/nand.c b/src/driver/nand/nand.c
--- /dev/null
+++ b/src/driver/nand/nand.c
@@ -0,0 +1,342 @@
+/************************************************************************************************
+ * FILE PURPOSE: The top level NAND driver
+ ************************************************************************************************
+ * FILE NAME: nand.c
+ *
+ * DESCRIPTION: Provides the required driver functions which populate the BOOT_MODULE_FXN_TABLE
+ *
+ * @file nand.c
+ *
+ * @brief
+ * The top level nand driver
+ *
+ *************************************************************************************************/
+#include "types.h"
+#include "ibl.h"
+#include "iblloc.h"
+#include "nand.h"
+#include "nandhwapi.h"
+#include <string.h>
+#include <stdlib.h>
+
+
+/**
+ * @brief The nand master control block which tracks the current nand boot information
+ */
+typedef struct nandmcb_s
+{
+ nandDevInfo_t devInfo; /**< Device information */
+
+ Int32 fpos; /**< The current logical file position */
+ Uint32 currentLogicalBlock; /**< The logical block number of the page currently stored */
+ Uint32 currentPage; /**< The page number currently stored */
+
+ Uint8 *page; /**< The current page */
+ Uint16 *logicalToPhysMap; /**< Maps local block to physical block */
+ Uint16 *physToLogicalMap; /**< Maps a physical block number to a logical block number */
+
+ Uint32 numBadBlocks; /**< Total number of bad blocks */
+ Uint8 *blocks; /**< There is one byte per block. A non-zero value indicates
+ that the block is bad */
+
+} nandmcb_t;
+
+nandmcb_t nandmcb;
+
+
+/**
+ * @b Description
+ * @n
+ *
+ * This function sets the current file position, and loads the page corresponding
+ * to that position into the pre-allocated page memory
+ */
+Int32 nand_seek (Int32 loc, Int32 from)
+{
+ Int32 desiredPos;
+ Uint32 desiredBlock;
+ Uint32 desiredPage;
+
+ /* Can't seek from the end of the file, since the end is not known */
+ if (from == 0)
+ desiredPos = loc;
+ else if (from == 1)
+ desiredPos = nandmcb.fpos + loc;
+ else
+ return (-1);
+
+ if (desiredPos < 0)
+ return (-1);
+
+
+ /* Convert the file position (relative to the file start) into a page number */
+ desiredPage = desiredPos / nandmcb.devInfo.pageSizeBytes;
+
+ /* Convert the logical page to logical block/page */
+ desiredBlock = desiredPage / nandmcb.devInfo.pagesPerBlock;
+ desiredPage = desiredPage % nandmcb.devInfo.pagesPerBlock;
+
+ /* Nothing to do if the current block/page is already loaded */
+ if ((desiredBlock == nandmcb.currentLogicalBlock) && (desiredPage == nandmcb.currentPage))
+ return (0);
+
+ /* Otherwise load the desired page */
+ if (nandHwDriverReadPage((Uint32)(nandmcb.logicalToPhysMap[desiredBlock]), desiredPage, nandmcb.page) < 0)
+ return (-2);
+
+ /* Update the currently loaded block/page info */
+ nandmcb.currentLogicalBlock = desiredBlock;
+ nandmcb.currentPage = desiredPage;
+ nandmcb.fpos = desiredPos;
+
+ return (0);
+
+}
+
+
+/**
+ * @b Description
+ * @n
+ * Free any memory allocated by the driver
+ */
+Int32 nand_free_return (Int32 retcode)
+{
+ if (nandmcb.page != NULL)
+ free (nandmcb.page);
+
+ if (nandmcb.logicalToPhysMap != NULL)
+ free (nandmcb.logicalToPhysMap);
+
+ if (nandmcb.physToLogicalMap != NULL)
+ free (nandmcb.physToLogicalMap);
+
+ if (nandmcb.blocks != NULL)
+ free (nandmcb.blocks);
+
+ return (retcode);
+
+}
+
+
+
+/**
+ * @b Description
+ * @n
+ *
+ * This function initializes the nand control structure and reads the bad block info
+ * from the nand.
+ */
+Int32 nand_open (void *ptr_driver, void (*asyncComplete)(void *))
+{
+ iblNand_t *ibln = (iblNand_t *)ptr_driver;
+
+ Int32 size;
+ Int32 ret;
+ Int32 i, j;
+
+ /* Initialize the control info */
+ memset (&nandmcb, 0, sizeof(nandmcb));
+ memcpy (&nandmcb.devInfo, &ibln->nandInfo, sizeof(iblNand_t));
+
+ nandmcb.page = NULL;
+ nandmcb.logicalToPhysMap = NULL;
+ nandmcb.physToLogicalMap = NULL;
+ nandmcb.blocks = NULL;
+
+ ret = nandHwDriverInit (&nandmcb.devInfo);
+ if (ret < 0)
+ nand_free_return (ret);
+
+ /* allocate memory for the page data and the logical to physical block map */
+ size = nandmcb.devInfo.pageSizeBytes + nandmcb.devInfo.pageEccBytes;
+ nandmcb.page = malloc (size * sizeof(Uint8));
+ if (nandmcb.page == NULL)
+ nand_free_return (NAND_MALLOC_PAGE_FAIL);
+
+
+ /* Logical to physical map data */
+ nandmcb.logicalToPhysMap = malloc (nandmcb.devInfo.totalBlocks * sizeof(Uint16));
+ if (nandmcb.logicalToPhysMap == NULL)
+ nand_free_return (NAND_MALLOC_MAP_LTOP_FAIL);
+
+
+ /* Physical to logical map data */
+ nandmcb.physToLogicalMap = malloc (nandmcb.devInfo.totalBlocks * sizeof(Uint16));
+ if (nandmcb.physToLogicalMap == NULL)
+ nand_free_return (NAND_MALLOC_MAP_PTOL_FAIL);
+
+ /* Block info */
+ size = nandmcb.devInfo.totalBlocks * sizeof(Uint8);
+ nandmcb.blocks = malloc (size);
+ if (nandmcb.blocks == NULL)
+ nand_free_return (NAND_MALLOC_BLOCK_INFO_FAIL);
+
+
+ /* mdebug - read page 0 */
+ nandHwDriverReadPage(0, 0, nandmcb.page);
+
+
+ /* Bad blocks are identified by reading page 0 and page 1. If the first two
+ * bytes in these pages is not 0xffff then the block is bad */
+ nandmcb.numBadBlocks = 0;
+ for (i = 0; i < nandmcb.devInfo.totalBlocks; i++) {
+
+ ret = nandHwDriverReadBytes (i, 0, nandmcb.devInfo.pageSizeBytes, 1, &nandmcb.page[0]);
+ if (ret < 0)
+ nand_free_return (ret);
+
+ ret = nandHwDriverReadBytes (i, 0, nandmcb.devInfo.pageSizeBytes, 1, &nandmcb.page[1]);
+ if (ret < 0)
+ nand_free_return (ret);
+
+ if ((nandmcb.page[0] != 0xff) || (nandmcb.page[1] != 0xff)) {
+ nandmcb.blocks[i] = 0xff;
+ nandmcb.numBadBlocks += 1;
+ } else
+ nandmcb.blocks[i] = 0;
+
+ }
+
+
+ /* Construct the logical to physical block array */
+ for (i = j = 0; i < nandmcb.devInfo.totalBlocks; i++) {
+ if (nandmcb.blocks[i] != 0xff)
+ nandmcb.logicalToPhysMap[j++] = i;
+ }
+
+ /* Construct the physical to logical block array */
+ for (i = j = 0; i < nandmcb.devInfo.totalBlocks; i++) {
+ if (nandmcb.blocks[i] == 0xff)
+ nandmcb.physToLogicalMap[i] = 0xff;
+ else
+ nandmcb.physToLogicalMap[i] = j++;
+ }
+
+
+ /* Seek to the first byte of the file */
+ nandmcb.fpos = -1; /* Force a read on the first seek */
+ nandmcb.currentLogicalBlock = 0xffffffff;
+ nandmcb.currentPage = 0xffffffff;
+ nand_seek (0, 0);
+
+
+ return (0);
+
+}
+
+
+/**
+ * @b Description
+ * @n
+ * This function performs a reads from the current read point
+ *
+ */
+Int32 nand_read (Uint8 *ptr_buf, Uint32 num_bytes)
+{
+ Int32 i;
+ Int32 pIdx;
+
+ /* Convert the global file position to an offset in the currently cached page */
+ pIdx = nandmcb.fpos % nandmcb.devInfo.pageSizeBytes;
+
+
+ for (i = 0; i < num_bytes; i++) {
+
+ ptr_buf[i] = nandmcb.page[pIdx++];
+
+ if (pIdx >= nandmcb.devInfo.pageSizeBytes) {
+
+ pIdx = 0;
+ nandmcb.currentPage += 1;
+
+ if (nandmcb.currentPage >= nandmcb.devInfo.pagesPerBlock) {
+ nandmcb.currentPage = 0;
+ nandmcb.currentLogicalBlock += 1;
+ }
+
+
+ /* Load the new block */
+ if (nandHwDriverReadPage((Uint32)(nandmcb.logicalToPhysMap[nandmcb.currentLogicalBlock]), nandmcb.currentPage, nandmcb.page) < 0)
+ return (-2);
+
+ }
+ }
+
+ return (0);
+
+}
+
+/**
+ * @b Description
+ * @n
+ * This function performs a peek from the current read point.
+ */
+Int32 nand_peek (Uint8 *ptr_buf, Uint32 num_bytes)
+{
+ Int32 ret;
+ Int32 origPos;
+ Uint32 origLogicalBlock;
+ Uint32 origPage;
+
+ origPos = nandmcb.fpos;
+ origLogicalBlock = nandmcb.currentLogicalBlock;
+ origPage = nandmcb.currentPage;
+
+ ret = nand_read (ptr_buf, num_bytes);
+
+ if ( (origLogicalBlock != nandmcb.currentLogicalBlock) ||
+ (origPage != nandmcb.currentPage) ) {
+
+ if (nandHwDriverReadPage((Uint32)(nandmcb.logicalToPhysMap[origLogicalBlock]), origPage, nandmcb.page) < 0)
+ return (-2);
+ }
+
+ nandmcb.fpos = origPos;
+ nandmcb.currentLogicalBlock = origLogicalBlock;
+ nandmcb.currentPage = origPage;
+
+ return (ret);
+
+}
+
+/**
+ * @b Description
+ * @n
+ * This function returns how much data is available for immediate read.
+ * On nand this always returns -1.
+ */
+Int32 nand_query (void)
+{
+ return (-1);
+}
+
+
+/**
+ * @b Description
+ * @n
+ * This function closes the nand driver
+ */
+Int32 nand_close (void)
+{
+ nandHwDriverClose ();
+ return (nand_free_return (0));
+
+}
+
+
+
+/**
+ * @brief The global nand module function table
+ */
+BOOT_MODULE_FXN_TABLE nand_boot_module =
+{
+ nand_open, /* Open API */
+ nand_close, /* Close API */
+ nand_read, /* Read API */
+ NULL, /* Write API */
+ nand_peek, /* Peek API */
+ nand_seek, /* Seek API */
+ nand_query /* Query API */
+
+};
+
diff --git a/src/driver/nand/nand.h b/src/driver/nand/nand.h
--- /dev/null
+++ b/src/driver/nand/nand.h
@@ -0,0 +1,31 @@
+#ifndef _NAND_H
+#define _NAND_H
+/************************************************************************************************
+ * FILE PURPOSE: NAND API definitions
+ ************************************************************************************************
+ * FILE NAME: nand.h
+ *
+ * DESCRIPTION: Defines the nand api
+ *
+ * @file nand.h
+ *
+ * @brief
+ * Defines the nand api.
+ *
+ **************************************************************************************************/
+#include "iblloc.h"
+
+/* All error codes must be negative */
+#define NAND_MALLOC_PAGE_FAIL -400
+#define NAND_MALLOC_MAP_LTOP_FAIL -401
+#define NAND_MALLOC_MAP_PTOL_FAIL -402
+#define NAND_MALLOC_BLOCK_INFO_FAIL -403
+#define NAND_BAD_BAD_BLOCK_MAGIC -404
+#define NAND_BAD_APP_MAGIC -405
+
+extern BOOT_MODULE_FXN_TABLE nand_boot_module;
+
+
+#endif /* _NAND_H */
+
+
diff --git a/src/driver/nand/nflashlay.h.old b/src/driver/nand/nflashlay.h.old
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _NAND_FLASH_LAYOUT_H
+#define _NAND_FLASH_LAYOUT_H
+/*******************************************************************************************
+ * FILE PURPOSE: Define values associated with the nand flash layout
+ *******************************************************************************************
+ * FILE NAME: nflashlay.h
+ *
+ * DESCRIPTION: The nand flash layout is defined
+ *
+ * @file nflashlay.h
+ *
+ * @brief
+ * The nand flash layout is defined
+ *
+ ********************************************************************************************/
+
+#define APP_MAGIC_NUM 0xa1aced11
+#define BAD_BLOCK_MAGIC_NUM 0xa1aced00
+
+
+
+#endif /* _NAND_FLASH_LAYOUT_H */
+
+
+
+
+
diff --git a/src/driver/stream/stream.c b/src/driver/stream/stream.c
--- /dev/null
@@ -0,0 +1,344 @@
+/**
+ * @file stream.c
+ *
+ * @brief
+ * The file implements the STREAM module.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+
+
+/**********************************************************************
+ ************************** Local Structures **************************
+ **********************************************************************/
+#include "types.h"
+#include "iblcfg.h"
+#include <string.h>
+
+/**
+ * @defgroup stream_op
+ *
+ * @ingroup stream_op
+ * @{
+ *
+ * @brief
+ * Internal defintion to distinguish between read and peek
+ */
+/**
+ * @def STREAM_READ
+ */
+#define STREAM_READ 200 /**< Read from a stream */
+
+/**
+ * @def STREAM_PEEK
+ */
+#define STREAM_PEEK 210 /**< Peek from a stream */
+
+/* @} */
+
+
+
+/**
+ * @brief
+ * The structure describes the Stream Master Control block.
+ *
+ * @details
+ * The structure stores information about the stream module
+ * internal buffers and state information.
+ */
+typedef struct STREAM_MCB
+{
+ /**
+ * @brief Flag which indicates if the stream buffer is open or not?
+ */
+ Bool is_open;
+
+ /**
+ * @brief This is the *internal* stream buffer.
+ */
+ Uint8 buffer[MAX_SIZE_STREAM_BUFFER];
+
+ /**
+ * @brief This is the read index from where data is read.
+ */
+ Int32 read_idx;
+
+ /**
+ * @brief This is the write index to which data is written.
+ */
+ Int32 write_idx;
+
+ /**
+ * @brief This is the free size available in the internal buffer.
+ */
+ Int32 free_size;
+}STREAM_MCB;
+
+/**********************************************************************
+ ************************** Global Variables **************************
+ **********************************************************************/
+
+/**
+ * @brief This is the STREAM Master control block which keeps track
+ * of all the stream module information.
+ */
+STREAM_MCB stream_mcb;
+
+/**********************************************************************
+ ************************** Stream Functions **************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * The function is called to open the stream module
+ *
+ * @param[in] chunk_size
+ * Maximum amount of data that can be received at any
+ * instant by the boot module.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 stream_open (Uint32 chunk_size)
+{
+ /* Basic Validations: Ensure that the chunk size is not greater
+ * than the internal buffer size. */
+ if (chunk_size > MAX_SIZE_STREAM_BUFFER)
+ return -1;
+
+ /* Initialize the Master control block. */
+ stream_mcb.is_open = TRUE;
+ stream_mcb.read_idx = 0;
+ stream_mcb.write_idx = 0;
+ stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
+
+ /* Module has been initialized. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called to read/peek data from the stream module.
+ *
+ * @param[in] ptr_data
+ * Pointer to the data buffer where the data will be copied to.
+ * @param[in] num_bytes
+ * Number of bytes to be read.
+ * @param[in] op
+ * Distinguishes a read from a peek @ref stream_op
+ *
+ * @retval
+ * Success - Number of bytes actually read
+ * @retval
+ * Error - <0
+ */
+Int32 stream_read_peek (Uint8* ptr_data, Int32 num_bytes, Int32 op)
+{
+ Int32 index;
+ Int32 num_bytes_to_read;
+
+ /* Determine the number of bytes which can be read. */
+ if (num_bytes > (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size))
+ {
+ /* User has requested more data than what is available. In this case we
+ * can return only what we have. */
+ num_bytes_to_read = (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size);
+ }
+ else
+ {
+ /* User has requested less data than what is available. In this case we
+ * return only what the user wants. */
+ num_bytes_to_read = num_bytes;
+ }
+
+ /* There is data available copy it from the internal to the user supplied buffer. */
+ for (index = 0; index < num_bytes_to_read; index++)
+ {
+ /* Copy the data to the "write" index. */
+ if (ptr_data != NULL)
+ *(ptr_data + index) = *(stream_mcb.buffer + stream_mcb.read_idx + index);
+
+ }
+
+ /* Increment the read index.
+ * Once data has been copied; increment the free size accordingly */
+ if (op == STREAM_READ) {
+ stream_mcb.read_idx = (stream_mcb.read_idx + num_bytes_to_read) % MAX_SIZE_STREAM_BUFFER;
+ stream_mcb.free_size = stream_mcb.free_size + num_bytes_to_read;
+ }
+
+
+ /* Return the number of bytes read. */
+ return num_bytes_to_read;
+}
+
+
+/**
+ * @b Description
+ * @n
+ * The function is called to read data from the stream module.
+ *
+ * @param[in] ptr_data
+ * Pointer to the data buffer where the data will be copied to.
+ * @param[in] num_bytes
+ * Number of bytes to be read.
+ *
+ * @retval
+ * Success - Number of bytes actually read
+ * @retval
+ * Error - <0
+ */
+Int32 stream_read (Uint8* ptr_data, Int32 num_bytes)
+{
+ return (stream_read_peek (ptr_data, num_bytes, STREAM_READ));
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called to peek data from the stream module.
+ *
+ * @param[in] ptr_data
+ * Pointer to the data buffer where the data will be copied to.
+ * @param[in] num_bytes
+ * Number of bytes to be read.
+ *
+ * @retval
+ * Success - Number of bytes actually read
+ * @retval
+ * Error - <0
+ */
+Int32 stream_peek (Uint8* ptr_data, Int32 num_bytes)
+{
+ return (stream_read_peek (ptr_data, num_bytes, STREAM_PEEK));
+}
+
+
+/**
+ * @b Description
+ * @n
+ * The function is called to write data to the stream
+ * module.
+ *
+ * @param[in] ptr_data
+ * Pointer to the data buffer which contains the data to be copied.
+ * @param[in] num_bytes
+ * Number of bytes being written
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 stream_write (Uint8* ptr_data, Int32 num_bytes)
+{
+ Int32 index;
+
+ /* Basic Validations: Ensure there is sufficient space to copy the data. */
+ if (num_bytes > stream_mcb.free_size)
+ return -1;
+
+ /* Basic Validations: Make sure the pointers are valid. */
+ if (ptr_data == NULL)
+ return -1;
+
+ /* There was sufficient space to copy the data lets do so but we copy byte by byte
+ * since the internal buffer is circular and we can wrap around... */
+ for (index = 0; index < num_bytes; index++)
+ {
+ /* Copy the data to the "write" index. */
+ *(stream_mcb.buffer + stream_mcb.write_idx) = *(ptr_data + index);
+
+ /* Increment the write index. */
+ stream_mcb.write_idx = (stream_mcb.write_idx + 1) % MAX_SIZE_STREAM_BUFFER;
+ }
+
+ /* Once data has been copied; decrement the free size accordingly */
+ stream_mcb.free_size = stream_mcb.free_size - num_bytes;
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is used to check if the stream buffers are empty or
+ * not?
+ *
+ * @retval
+ * Empty - TRUE
+ * @retval
+ * Not Empty - FALSE
+ */
+Bool stream_isempty (void)
+{
+ /* Check the number of free bytes available? */
+ if (stream_mcb.free_size == MAX_SIZE_STREAM_BUFFER)
+ return TRUE;
+
+ /* There is data in the stream buffer; so its not empty. */
+ return FALSE;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function closes the stream module.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void stream_close (void)
+{
+ /* The stream module is no longer open... */
+ stream_mcb.is_open = FALSE;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function initializes the stream module.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void stream_init (void)
+{
+ /* Reset the memory contents. */
+ memset ((void *)&stream_mcb, 0, sizeof(STREAM_MCB));
+
+ /* Make sure we initialize the free size correctly. */
+ stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
+ return;
+}
+
+
+/**
+ * @b Description
+ * @n
+ * Returns the number of bytes currently available in the stream
+ *
+ * @retval
+ * The number of bytes in the stream buffer
+ * -1 if the stream is closed AND empty
+ */
+Int32 stream_level (void)
+{
+ Int32 remain;
+
+ remain = MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size;
+
+ if ((stream_mcb.is_open != TRUE) && (remain == 0))
+ return (-1);
+
+ return (remain);
+
+}
diff --git a/src/driver/stream/stream.h b/src/driver/stream/stream.h
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * @file stream.h
+ *
+ * @brief
+ * The file has data structures and API definitions for the
+ * STREAM Module
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#ifndef __STREAM_H__
+#define __STREAM_H__
+
+/**********************************************************************
+ **************************** Exported Functions **********************
+ **********************************************************************/
+
+extern void stream_init (void);
+extern Int32 stream_open (Uint32 chunk_size);
+extern void stream_close (void);
+extern Int32 stream_read (Uint8* ptr_data, Int32 num_bytes);
+extern Int32 stream_peek (Uint8* ptr_data, Int32 num_bytes);
+extern Int32 stream_write (Uint8* ptr_data, Int32 num_bytes);
+extern Bool stream_isempty(void);
+extern Int32 stream_level (void);
+
+#endif /* __STREAM_H__ */
diff --git a/src/driver/stream/stream_orig.c b/src/driver/stream/stream_orig.c
--- /dev/null
@@ -0,0 +1,251 @@
+/**
+ * @file stream.c
+ *
+ * @brief
+ * The file implements the STREAM module.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+
+
+/**********************************************************************
+ ************************** Local Structures **************************
+ **********************************************************************/
+#include "types.h"
+#include "iblcfg.h"
+#include <string.h>
+
+/**
+ * @brief
+ * The structure describes the Stream Master Control block.
+ *
+ * @details
+ * The structure stores information about the stream module
+ * internal buffers and state information.
+ */
+typedef struct STREAM_MCB
+{
+ /**
+ * @brief Flag which indicates if the stream buffer is open or not?
+ */
+ Bool is_open;
+
+ /**
+ * @brief This is the *internal* stream buffer.
+ */
+ Uint8 buffer[MAX_SIZE_STREAM_BUFFER];
+
+ /**
+ * @brief This is the read index from where data is read.
+ */
+ Int32 read_idx;
+
+ /**
+ * @brief This is the write index to which data is written.
+ */
+ Int32 write_idx;
+
+ /**
+ * @brief This is the free size available in the internal buffer.
+ */
+ Int32 free_size;
+}STREAM_MCB;
+
+/**********************************************************************
+ ************************** Global Variables **************************
+ **********************************************************************/
+
+/**
+ * @brief This is the STREAM Master control block which keeps track
+ * of all the stream module information.
+ */
+STREAM_MCB stream_mcb;
+
+/**********************************************************************
+ ************************** Stream Functions **************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * The function is called to open the stream module
+ *
+ * @param[in] chunk_size
+ * Maximum amount of data that can be received at any
+ * instant by the boot module.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 stream_open (Uint32 chunk_size)
+{
+ /* Basic Validations: Ensure that the chunk size is not greater
+ * than the internal buffer size. */
+ if (chunk_size > MAX_SIZE_STREAM_BUFFER)
+ return -1;
+
+ /* Initialize the Master control block. */
+ stream_mcb.is_open = TRUE;
+ stream_mcb.read_idx = 0;
+ stream_mcb.write_idx = 0;
+ stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
+
+ /* Module has been initialized. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called to read data from the stream module.
+ *
+ * @param[in] ptr_data
+ * Pointer to the data buffer where the data will be copied to.
+ * @param[in] num_bytes
+ * Number of bytes to be read.
+ *
+ * @retval
+ * Success - Number of bytes actually read
+ * @retval
+ * Error - <0
+ */
+Int32 stream_read (Uint8* ptr_data, Int32 num_bytes)
+{
+ Int32 index;
+ Int32 num_bytes_to_read;
+
+ /* Determine the number of bytes which can be read. */
+ if (num_bytes > (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size))
+ {
+ /* User has requested more data than what is available. In this case we
+ * can return only what we have. */
+ num_bytes_to_read = (MAX_SIZE_STREAM_BUFFER - stream_mcb.free_size);
+ }
+ else
+ {
+ /* User has requested less data than what is available. In this case we
+ * return only what the user wants. */
+ num_bytes_to_read = num_bytes;
+ }
+
+ /* There is data available copy it from the internal to the user supplied buffer. */
+ for (index = 0; index < num_bytes_to_read; index++)
+ {
+ /* Copy the data to the "write" index. */
+ *(ptr_data + index) = *(stream_mcb.buffer + stream_mcb.read_idx);
+
+ /* Increment the read index. */
+ stream_mcb.read_idx = (stream_mcb.read_idx + 1) % MAX_SIZE_STREAM_BUFFER;
+ }
+
+ /* Once data has been copied; increment the free size accordingly */
+ stream_mcb.free_size = stream_mcb.free_size + num_bytes_to_read;
+
+ /* Return the number of bytes read. */
+ return num_bytes_to_read;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is called to write data to the stream
+ * module.
+ *
+ * @param[in] ptr_data
+ * Pointer to the data buffer which contains the data to be copied.
+ * @param[in] num_bytes
+ * Number of bytes being written
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 stream_write (Uint8* ptr_data, Int32 num_bytes)
+{
+ Int32 index;
+
+ /* Basic Validations: Ensure there is sufficient space to copy the data. */
+ if (num_bytes > stream_mcb.free_size)
+ return -1;
+
+ /* Basic Validations: Make sure the pointers are valid. */
+ if (ptr_data == NULL)
+ return -1;
+
+ /* There was sufficient space to copy the data lets do so but we copy byte by byte
+ * since the internal buffer is circular and we can wrap around... */
+ for (index = 0; index < num_bytes; index++)
+ {
+ /* Copy the data to the "write" index. */
+ *(stream_mcb.buffer + stream_mcb.write_idx) = *(ptr_data + index);
+
+ /* Increment the write index. */
+ stream_mcb.write_idx = (stream_mcb.write_idx + 1) % MAX_SIZE_STREAM_BUFFER;
+ }
+
+ /* Once data has been copied; decrement the free size accordingly */
+ stream_mcb.free_size = stream_mcb.free_size - num_bytes;
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function is used to check if the stream buffers are empty or
+ * not?
+ *
+ * @retval
+ * Empty - TRUE
+ * @retval
+ * Not Empty - FALSE
+ */
+Bool stream_isempty (void)
+{
+ /* Check the number of free bytes available? */
+ if (stream_mcb.free_size == MAX_SIZE_STREAM_BUFFER)
+ return TRUE;
+
+ /* There is data in the stream buffer; so its not empty. */
+ return FALSE;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function closes the stream module.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void stream_close (void)
+{
+ /* The stream module is no longer open... */
+ stream_mcb.is_open = FALSE;
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function initializes the stream module.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void stream_init (void)
+{
+ /* Reset the memory contents. */
+ memset ((void *)&stream_mcb, 0, sizeof(STREAM_MCB));
+
+ /* Make sure we initialize the free size correctly. */
+ stream_mcb.free_size = MAX_SIZE_STREAM_BUFFER;
+ return;
+}
+
diff --git a/src/driver/timer/timer.c b/src/driver/timer/timer.c
--- /dev/null
+++ b/src/driver/timer/timer.c
@@ -0,0 +1,252 @@
+/**
+ * @file timer.c
+ *
+ * @brief
+ * The file implements the TIMER module.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+ #include "types.h"
+ #include "iblloc.h"
+ #include "timer.h"
+ #include "devtimer.h"
+ #include "iblcfg.h"
+ #include <string.h>
+
+
+/**********************************************************************
+ *************************** LOCAL Structures *************************
+ **********************************************************************/
+
+/**
+ * @brief
+ * The structure describes the Timer blocks.
+ *
+ * @details
+ * Each timer in the system is associated with a timer
+ * block.
+ */
+typedef struct TIMER_BLOCK
+{
+ /**
+ * @brief Expiration Routine which is called once the timer
+ * expires.
+ */
+ void (*expiry)(void);
+
+ /**
+ * @brief This is the original expiration time in milli-seconds.
+ */
+ Uint32 org_timeout;
+
+ /**
+ * @brief This is the expiration time in milli-seconds. This is
+ * decremented by the timer module.
+ */
+ Uint32 timeout;
+}TIMER_BLOCK;
+
+/**
+ * @brief
+ * The structure describes the Timer Master Control Block.
+ *
+ * @details
+ * The structure contains information about the Timer Master Control
+ * block which stores information about the Timer Module.
+ */
+typedef struct TIMER_MCB
+{
+ /**
+ * @brief This keeps track of all timers which can exist in the
+ * System.
+ */
+ TIMER_BLOCK timer[MAX_TIMER_BLOCKS];
+
+ /**
+ * @brief This is the number of active timers in the system.
+ */
+ Uint32 num_active_timers;
+}TIMER_MCB;
+
+/**********************************************************************
+ *************************** GLOBAL Variables *************************
+ **********************************************************************/
+
+/**
+ * @brief This global variable keeps track of all the timer which are
+ * currently active in the system.
+ */
+TIMER_MCB timermcb;
+
+/**********************************************************************
+ *************************** TIMER Functions **************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * The function initializes the Timer module.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void timer_init (void)
+{
+ /* Initialize the Timer Master Control Block. */
+ memset (&timermcb, 0, sizeof(TIMER_MCB));
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function creates a timer.
+ *
+ * @param[in] timeout
+ * This is the timeout specified in milli-seconds after which the timer
+ * will expire.
+ * @param[in] expiry
+ * Expiration routine which is called to indicate that the timer block
+ * has expired.
+ *
+ * @retval
+ * Success - Handle to the timer block
+ * @retval
+ * Error - <0
+ */
+Int32 timer_add (Uint32 timeout, void (*expiry)(void))
+{
+ Uint16 index;
+
+ /* Basic Validations: Ensure parameters passed are valid. */
+ if ((timeout == 0) || (expiry == NULL))
+ return -1;
+
+ /* Cycle through and find a free timer block. */
+ for (index = 0; index < MAX_TIMER_BLOCKS; index++)
+ {
+ /* Free timers can be identified using the expiry routine. NULL indicates
+ * that the timer block is free. */
+ if (timermcb.timer[index].expiry == NULL)
+ {
+ /* Found a free slot. Is this the first timer being created? */
+ if (timermcb.num_active_timers == 0)
+ {
+ /* YES. We need to start the device timer. */
+ if (dev_create_timer() < 0)
+ {
+ /* Device layer timer creation failed. We will not be able
+ * to get the timers operational without this API. So we
+ * might as well fail also. */
+ return -1;
+ }
+ }
+
+ /* Populate the timer block structure. */
+ timermcb.timer[index].expiry = expiry;
+ timermcb.timer[index].timeout = timeout;
+ timermcb.timer[index].org_timeout = timeout;
+
+ /* Increment the number of timers in the system */
+ timermcb.num_active_timers++;
+
+ /* Return the handle to the timer block. */
+ return index;
+ }
+ }
+
+ /* Control comes here indicating that there were no free timer slots. */
+ return -1;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function deletes a timer which was previously created.
+ *
+ * @param[in] handle
+ * This is the handle to the timer block to be deleted.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void timer_delete (Int32 handle)
+{
+ /* Basic Validations: Ensure paramter is valid. */
+ if ((handle < 0) || (handle > MAX_TIMER_BLOCKS))
+ return;
+
+ /* Make sure there is at least one timer which is active; */
+ if (timermcb.num_active_timers > 0)
+ {
+ /* Simply reset the memory contents */
+ memset ((void *)&timermcb.timer[handle], 0, sizeof(TIMER_BLOCK));
+
+ /* Decrement the number of active timers in the system */
+ timermcb.num_active_timers--;
+
+ /* Check if there are any active timers in the system? */
+ if (timermcb.num_active_timers == 0)
+ {
+ /* No more active timers; we can delete the timer in the device layer. */
+ dev_delete_timer ();
+ }
+ }
+ return;
+}
+
+/**
+ * @b Description
+ * @n
+ * The function runs the timer scheduler. This API is required to be
+ * called by the boot modules and this in turn will decrement the various
+ * timer registered in the system and will call the appropriate
+ * expiration routines. If the boot modules fail to call this API then
+ * the timers will never expire.
+ *
+ * @retval
+ * Not Applicable.
+ */
+void timer_run (void)
+{
+ Uint16 index;
+
+ /* Check if there are any active timers in the System or not?
+ * If none are present; then we dont need to run the scheduler. */
+ if (timermcb.num_active_timers == 0)
+ return;
+
+ /* Check if the device timer has expired or not?
+ * If the timer has not expired there is no management to be done. */
+ if (dev_check_timer() == FALSE)
+ return;
+
+ /* Cycle through all the timer blocks and update them. */
+ for (index = 0; index < MAX_TIMER_BLOCKS; index++)
+ {
+ /* Is this an active timer? */
+ if (timermcb.timer[index].expiry != NULL)
+ {
+ /* YES. Decrement the timeout. */
+ timermcb.timer[index].timeout = timermcb.timer[index].timeout - 100;
+
+ /* Has the timer expired? */
+ if (timermcb.timer[index].timeout == 0)
+ {
+ /* Reset the timeouts */
+ timermcb.timer[index].timeout = timermcb.timer[index].org_timeout;
+
+ /* Call the expiration routine. */
+ timermcb.timer[index].expiry();
+ }
+
+ }
+ }
+ return;
+}
+
+
diff --git a/src/driver/timer/timer.h b/src/driver/timer/timer.h
--- /dev/null
+++ b/src/driver/timer/timer.h
@@ -0,0 +1,28 @@
+/**
+ * @file timer.h
+ *
+ * @brief
+ * The file has data structures and API definitions for the
+ * TIMER Module
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+
+/**********************************************************************
+ **************************** Exported Functions **********************
+ **********************************************************************/
+
+extern void timer_init(void);
+extern Int32 timer_add (Uint32 timeout, void (*expiry)(void));
+extern void timer_delete(Int32 handle);
+extern void timer_run (void);
+
+#endif /* __TIMER_H__ */
+
diff --git a/src/ecc/3byte/3byte_ecc.c b/src/ecc/3byte/3byte_ecc.c
--- /dev/null
@@ -0,0 +1,262 @@
+/******************************************************************************
+ * Copyright (c) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * File Name: ecc.c
+ *
+ * Description: This file implements ECC algorithm used on micron NAND flash
+ *
+ * History:
+ * SEP/4/2009, Amit Solanki, Created the file
+ *
+ *****************************************************************************/
+/****************
+ * Include Files
+ ****************/
+#include "types.h"
+#include "ecc.h"
+
+/*********************************
+ * Defines and Macros and globals
+ *********************************/
+// Pre-calculated 256-way 1 byte column parity
+static const Uint8 nand_ecc_precalc_table[] = {
+ 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+ 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+ 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+ 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+ 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+ 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+ 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+ 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+ 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+ 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+ 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+ 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+ 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+ 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+ 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+ 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
+};
+
+/******************************************************************************
+ *
+ * Function: nandTransResult
+ *
+ * Description: Creates non-inverted ECC code from line parity
+ *
+ * Parameters: Uint8 uchReg2 - line parity reg 2
+ * Uint8 uchReg3 - line parity reg 3
+ * Uint8 *puchEccCode - ecc
+ *
+ * Return Value: void
+ ******************************************************************************/
+static void nandTransResult(Uint8 uchReg2, Uint8 uchReg3, Uint8 *puchEccCode)
+{
+ Uint8 a, b, i, tmp1, tmp2;
+
+ /* Initialize variables */
+ a = b = 0x80;
+ tmp1 = tmp2 = 0;
+
+ /* Calculate first ECC byte */
+ for (i = 0; i < 4; i++) {
+ if (uchReg3 & a) /* LP15,13,11,9 --> ecc_code[0] */
+ tmp1 |= b;
+ b >>= 1;
+ if (uchReg2 & a) /* LP14,12,10,8 --> ecc_code[0] */
+ tmp1 |= b;
+ b >>= 1;
+ a >>= 1;
+ }
+
+ /* Calculate second ECC byte */
+ b = 0x80;
+ for (i = 0; i < 4; i++) {
+ if (uchReg3 & a) /* LP7,5,3,1 --> ecc_code[1] */
+ tmp2 |= b;
+ b >>= 1;
+ if (uchReg2 & a) /* LP6,4,2,0 --> ecc_code[1] */
+ tmp2 |= b;
+ b >>= 1;
+ a >>= 1;
+ }
+
+ /* Store two of the ECC bytes */
+ puchEccCode[0] = tmp1;
+ puchEccCode[1] = tmp2;
+}
+/******************************************************************************
+ *
+ * Function: eccComputeECC
+ *
+ * Description: Compute 3 byte ECC code for 256 byte block
+ *
+ * Parameters: Uint8* puchData - pointer to raw data
+ * Uint8 *puchEccCode - pointer to ECC buffer
+ *
+ * Return Value: status
+ ******************************************************************************/
+Int32 eccComputeECC(const Uint8 *puchData, Uint8 *puchEccCode)
+{
+ Uint8 uchIndex, uchReg1, uchReg2, uchReg3;
+ int j;
+ if(puchData == NULL || puchEccCode == NULL)
+ return ECC_FAIL;
+
+ /* Initialize variables */
+ uchReg1 = uchReg2 = uchReg3 = 0;
+ puchEccCode[0] = puchEccCode[1] = puchEccCode[2] = 0;
+
+ /* Build up column parity */
+ for(j = 0; j < 256; j++) {
+
+ /* Get CP0 - CP5 from table */
+ uchIndex = nand_ecc_precalc_table[puchData[j]];
+ uchReg1 ^= (uchIndex & 0x3f);
+
+ /* All bit XOR = 1 ? */
+ if (uchIndex & 0x40) {
+ uchReg3 ^= (Uint8) j;
+ uchReg2 ^= ~((Uint8) j);
+ }
+ }
+
+ /* Create non-inverted ECC code from line parity */
+ nandTransResult(uchReg2, uchReg3, puchEccCode);
+
+ /* Calculate final ECC code */
+ puchEccCode[0] = ~puchEccCode[0];
+ puchEccCode[1] = ~puchEccCode[1];
+ puchEccCode[2] = ((~uchReg1) << 2) | 0x03;
+ return ECC_SUCCESS;
+}
+
+
+/******************************************************************************
+ *
+ * Function: eccCorrectData
+ *
+ * Description: Detect and correct a 1 bit error for 256 byte block
+ *
+ * Parameters: Uint8* puchData - Raw data read from the chip
+ * Uint8 *puchEccRead - ECC from the chip
+ * Uint8 *puchEccCalc - ECC calculated from raw data
+ *
+ * Return Value: status
+ ******************************************************************************/
+Int32 eccCorrectData(Uint8 *puchData, Uint8 *puchEccRead, Uint8 *puchEccCalc)
+{
+ Uint8 a, b, c, d1, d2, d3, add, bit, i;
+
+ if(puchData == NULL || puchEccRead == NULL || puchEccCalc == NULL)
+ return ECC_FAIL;
+
+ /* Do error detection */
+ d1 = puchEccCalc[0] ^ puchEccRead[0];
+ d2 = puchEccCalc[1] ^ puchEccRead[1];
+ d3 = puchEccCalc[2] ^ puchEccRead[2];
+
+ if ((d1 | d2 | d3) == 0) {
+ /* No errors */
+ return ECC_SUCCESS;
+ }
+ else {
+ a = (d1 ^ (d1 >> 1)) & 0x55;
+ b = (d2 ^ (d2 >> 1)) & 0x55;
+ c = (d3 ^ (d3 >> 1)) & 0x54;
+
+ /* Found and will correct single bit error in the data */
+ if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
+ c = 0x80;
+ add = 0;
+ a = 0x80;
+ for (i=0; i<4; i++) {
+ if (d1 & c)
+ add |= a;
+ c >>= 2;
+ a >>= 1;
+ }
+ c = 0x80;
+ for (i=0; i<4; i++) {
+ if (d2 & c)
+ add |= a;
+ c >>= 2;
+ a >>= 1;
+ }
+ bit = 0;
+ b = 0x04;
+ c = 0x80;
+ for (i=0; i<3; i++) {
+ if (d3 & c)
+ bit |= b;
+ c >>= 2;
+ b >>= 1;
+ }
+ b = 0x01;
+ a = puchData[add];
+ a ^= (b << bit);
+ puchData[add] = a;
+ return ECC_SUCCESS;
+ } else {
+ i = 0;
+ while (d1) {
+ if (d1 & 0x01)
+ ++i;
+ d1 >>= 1;
+ }
+ while (d2) {
+ if (d2 & 0x01)
+ ++i;
+ d2 >>= 1;
+ }
+ while (d3) {
+ if (d3 & 0x01)
+ ++i;
+ d3 >>= 1;
+ }
+ if (i == 1) {
+ /* ECC Code Error Correction */
+ puchEccRead[0] = puchEccCalc[0];
+ puchEccRead[1] = puchEccCalc[1];
+ puchEccRead[2] = puchEccCalc[2];
+ return ECC_SUCCESS;
+ }
+ else {
+ /* Uncorrectable Error */
+ return ECC_FAIL;
+ }
+ }
+ }
+}
diff --git a/src/ecc/c64x/make/makefile b/src/ecc/c64x/make/makefile
--- /dev/null
@@ -0,0 +1,42 @@
+#*************************************************************************************
+#* FILE NAME: makefile
+#*
+#* DESCRIPTION: Makes the ECC module for the IBL
+#*
+#*************************************************************************************/
+
+ifndef IBL_ROOT
+ export IBL_ROOT= ../../..
+endif
+
+ECODIR= $(IBL_ROOT)/ecc
+
+CSRC= 3byte_ecc.c
+
+.PHONY: ecc
+
+
+include $(IBL_ROOT)/make/$(ARCH)/makeeco.mk
+
+
+
+C6X_C_DIR= $(IBL_ROOT)
+C6X_C_DIR+= ;$(IBL_ROOT)/arch/$(ARCH)
+C6X_C_DIR+= ;$(ECODIR)
+C6X_C_DIR+= ;$(STDINC)
+export C6X_C_DIR
+
+vpath % $(ECODIR)/3byte
+
+
+ecc: gen_cdefdep makefile $(OBJS)
+
+
+$(OBJS): cdefdep
+
+gen_cdefdep:
+ @echo Checking command line dependencies
+ @echo $(ENDIAN) $(TARGET) > cdefdep.tmp
+ @sh -c 'if diff -q cdefdep.tmp cdefdep ; then echo same ; else $(CP) cdefdep.tmp cdefdep ; fi '
+
+
diff --git a/src/ecc/ecc.h b/src/ecc/ecc.h
--- /dev/null
+++ b/src/ecc/ecc.h
@@ -0,0 +1,21 @@
+/*******************************************************************************************
+ * FILE PURPOSE: Define the ECC api used by all ECC algorithms
+ *******************************************************************************************
+ * FILE NAME: ecc.h
+ *
+ * DESCRIPTION: The API used by all software CRCs is defined
+ *
+ * @file ecc.h
+ *
+ * @brief
+ * The API used by all software CRCs is defined
+ *
+ *******************************************************************************************/
+#include "types.h"
+
+
+#define ECC_SUCCESS 0
+#define ECC_FAIL -1
+
+Int32 eccCorrectData(Uint8 *puchData, Uint8 *puchEccRead, Uint8 *puchEccCalc);
+Int32 eccComputeECC(const Uint8 *puchData, Uint8 *puchEccCode);
diff --git a/src/ethboot/c64x/make/makefile b/src/ethboot/c64x/make/makefile
--- /dev/null
@@ -0,0 +1,46 @@
+#*************************************************************************************
+#* FILE NAME: makefile
+#*
+#* DESCRIPTION: Makes the ethernet module for the IBL
+#*
+#*************************************************************************************/
+
+ifndef IBL_ROOT
+ export IBL_ROOT= ../../..
+endif
+
+ECODIR= $(IBL_ROOT)/ethboot
+
+CSRC= ethboot.c
+
+.PHONY: ethboot
+
+
+include $(IBL_ROOT)/make/$(ARCH)/makeeco.mk
+
+
+
+C6X_C_DIR+= $(IBL_ROOT)
+C6X_C_DIR+= ;$(IBL_ROOT)/arch/$(ARCH)
+C6X_C_DIR+= ;$(IBL_ROOT)/device
+C6X_C_DIR+= ;$(IBL_ROOT)/device/$(TARGET)
+C6X_C_DIR+= ;$(IBL_ROOT)/ethboot
+C6X_C_DIR+= ;$(IBL_ROOT)/driver/eth
+C6X_C_DIR+= ;$(STDINC)
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/macs
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/mdio
+export C6X_C_DIR
+
+
+
+ethboot: gen_cdefdep makefile $(OBJS)
+
+
+$(OBJS): cdefdep
+
+gen_cdefdep:
+ @echo Checking command line dependencies
+ @echo $(ENDIAN) $(TARGET) > cdefdep.tmp
+ @sh -c 'if diff -q cdefdep.tmp cdefdep ; then echo same ; else $(CP) cdefdep.tmp cdefdep ; fi '
+
+
diff --git a/src/ethboot/ethboot.c b/src/ethboot/ethboot.c
--- /dev/null
+++ b/src/ethboot/ethboot.c
@@ -0,0 +1,233 @@
+/*********************************************************************************
+ * FILE PURPOSE: The Ethernet boot wrapper
+ *********************************************************************************
+ * FILE NAME: ethboot.c
+ *
+ * DESCRIPTION: This file provides the ethernet boot wrapper used by IBL modules
+ *
+ * @file ethboot.c
+ *
+ * @brief
+ * The ethernet boot wrapper
+ *
+ ***********************************************************************************/
+#include "types.h"
+#include "ibl.h"
+#include "iblloc.h"
+#include "ethboot.h"
+#include "net.h"
+#include "cpmacdrv.h"
+#include "device.h"
+#include "mdioapi.h"
+#include <string.h>
+
+
+/* Convert an IP address from unsigned char to IPN (uint32) */
+#define FORM_IPN(x) ( (x[0] << 24) | \
+ (x[1] << 16) | \
+ (x[2] << 8) | \
+ (x[3] << 0) )
+
+#define UNFORM_IPN(x,y) (x)[0] = (y) >> 24; \
+ (x)[1] = (y) >> 16; \
+ (x)[2] = (y) >> 8; \
+ (x)[3] = (y) >> 0
+
+#define MIN(a,b) ((a) < (b)) ? (a) : (b)
+
+static bool have_params;
+
+/* Receive a call back when the boot file name is known */
+void ibl_rec_params (void *params)
+{
+ NET_DRV_DEVICE *netdev = (NET_DRV_DEVICE *)params;
+
+ have_params = TRUE;
+
+ /* Copy the information to the status fields */
+ UNFORM_IPN(iblStatus.ethParams.ipAddr, netdev->ip_address);
+ UNFORM_IPN(iblStatus.ethParams.serverIp, netdev->server_ip);
+
+ memcpy (iblStatus.ethParams.hwAddress, netdev->mac_address, sizeof(iblStatus.ethParams.hwAddress));
+ strncpy (iblStatus.ethParams.fileName, netdev->file_name, sizeof(iblStatus.ethParams.fileName));
+
+}
+
+
+void iblEthBoot (Int32 eIdx)
+{
+ NET_DRV_DEVICE nDevice;
+ Uint32 nl;
+ Uint32 entry;
+ Int32 n;
+ Int32 dataSize;
+ Int32 format;
+ void (*exit)();
+ uint8 buf[16];
+ char *ext;
+
+
+
+ /* Power up the device. No action is taken if the device is already powered up */
+ if (devicePowerPeriph (TARGET_PWR_ETH(ibl.ethConfig[eIdx].port)) < 0)
+ return;
+
+ /* Do any mdio configuration */
+ if (ibl.mdioConfig.nMdioOps > 0)
+ hwMdio (ibl.mdioConfig.nMdioOps, ibl.mdioConfig.mdio,
+ ibl.mdioConfig.mdioClkDiv, ibl.mdioConfig.interDelay);
+
+
+ nDevice.port_num = ibl.ethConfig[eIdx].port;
+
+ /* Simple transation to initialize the driver */
+ memcpy (nDevice.mac_address, ibl.ethConfig[eIdx].ethInfo.hwAddress, sizeof(nDevice.mac_address));
+
+ nl = FORM_IPN(ibl.ethConfig[eIdx].ethInfo.ipAddr);
+ if (ibl.ethConfig[eIdx].doBootp == TRUE)
+ nDevice.ip_address = 0;
+ else
+ nDevice.ip_address = htonl(nl);
+
+ nl = FORM_IPN(ibl.ethConfig[eIdx].ethInfo.netmask);
+ nDevice.net_mask = htonl(nl);
+
+ nl = FORM_IPN(ibl.ethConfig[eIdx].ethInfo.serverIp);
+ nDevice.server_ip = htonl(nl);
+ nDevice.use_bootp_server_ip = ibl.ethConfig[eIdx].useBootpServerIp;
+
+ /* Note - the file name structure in nDevice is only 64 bytes, but 128 in ethInfo */
+ memcpy (nDevice.file_name, ibl.ethConfig[eIdx].ethInfo.fileName, sizeof(nDevice.file_name));
+ nDevice.use_bootp_file_name = ibl.ethConfig[eIdx].useBootpFileName;
+
+
+ nDevice.start = cpmac_drv_start;
+ nDevice.stop = cpmac_drv_stop;
+ nDevice.send = cpmac_drv_send;
+ nDevice.receive = cpmac_drv_receive;
+
+
+ /* have_params will be set to true in the tftp call back. It must be
+ * set to false before opening the module, since the call back will
+ * be from the open call if bootp is not used */
+ have_params = FALSE;
+
+ /* Open the network device */
+ if ((*net_boot_module.open) ((void *)&nDevice, ibl_rec_params) != 0)
+ return;
+
+ /* Wait for the callback with the requested filename */
+ while (have_params == FALSE) {
+
+ if ((*net_boot_module.peek) ((uint8 *)&nl, sizeof(nl)) < 0) {
+
+ (*net_boot_module.close)();
+ return;
+ }
+ }
+
+ format = ibl.ethConfig[eIdx].bootFormat;
+
+ /* If the data format was based on the name extension, determine
+ * the boot data format */
+ if (format == ibl_BOOT_FORMAT_NAME) {
+
+ ext = strrchr (iblStatus.ethParams.fileName, '.');
+
+ if (ext != NULL) {
+
+ if (!strcmp (ext, ".bis"))
+ format = ibl_BOOT_FORMAT_BIS;
+
+ else if (!strcmp (ext, ".ais"))
+ format = ibl_BOOT_FORMAT_BIS;
+
+ else if (!strcmp (ext, ".out"))
+ format = ibl_BOOT_FORMAT_COFF;
+
+ else if (!strcmp (ext, ".coff"))
+ format = ibl_BOOT_FORMAT_COFF;
+
+ else if (!strcmp (ext, ".btbl"))
+ format = ibl_BOOT_FORMAT_BTBL;
+
+ else if (!strcmp (ext, ".bin"))
+ format = ibl_BOOT_FORMAT_BBLOB;
+
+ else if (!strcmp (ext, ".blob"))
+ format = ibl_BOOT_FORMAT_BBLOB;
+
+ }
+
+ /* Name match failed it didn't change */
+ if (format == ibl_BOOT_FORMAT_NAME) {
+
+ iblStatus.nameDetectFailCnt += 1;
+
+ /* Close up the peripheral */
+ (*net_boot_module.close)();
+
+ return;
+ }
+
+ }
+
+ entry = iblBoot (&net_boot_module, format, &ibl.ethConfig[eIdx].blob);
+
+
+ /* Before closing the module read any remaining data. In the coff boot mode the boot may
+ * detect an exit before the entire file has been read. Read the rest of the file
+ * to make the server happy */
+
+ do {
+
+ dataSize = (*net_boot_module.query)(); /* Will return -1 when the data is done */
+
+ if (dataSize > 0) {
+
+ while (dataSize > 0) {
+
+ n = MIN(dataSize, sizeof(buf));
+ (*net_boot_module.read)(buf, n);
+ dataSize = dataSize - n;
+ }
+
+ /* Do not peek if the data size returned in the query was > 0 */
+ } else if (dataSize == 0) {
+
+ (*net_boot_module.peek)(buf, 1);
+ }
+
+ } while (dataSize >= 0);
+
+
+
+ /* Close up the peripheral */
+ (*net_boot_module.close)();
+
+ if (entry != 0) {
+
+ iblStatus.exitAddress = entry;
+ exit = (void (*)())entry;
+ (*exit)();
+
+ }
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ethboot/ethboot.h b/src/ethboot/ethboot.h
--- /dev/null
+++ b/src/ethboot/ethboot.h
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * FILE PURPOSE: Define the Ethernet boot wrapper
+ *****************************************************************************
+ * FILE NAME: ethboot.h
+ *
+ * DESCRIPTION: This file defines the ethernet wrapper used by IBL modules
+ *
+ * @file ethboot.h
+ *
+ * @brief
+ * The ethernet boot wrapper API is defined
+ *
+ *****************************************************************************/
+
+#ifndef ETHBOOT_H
+#define ETHBOOT_H
+
+#include "types.h"
+
+/**
+ * @brief
+ * Attempt an enternet boot
+ *
+ * @details
+ * The IBL will attempt to boot over the ethernet device
+ */
+void iblEthBoot (int32 eIdx);
+
+
+
+#endif /* ETHBOOT_H */
+
+
+
+
diff --git a/src/hw/c64x/make/makefile b/src/hw/c64x/make/makefile
--- /dev/null
@@ -0,0 +1,75 @@
+#**************************************************************************
+#* FILE NAME: makefile
+#*
+#* DESCRIPTION: Makes the low level drivers for the hardware modules
+#*
+#**************************************************************************
+
+ifndef IBL_ROOT
+ export IBL_ROOT=../../..
+endif
+
+ECODIR= $(IBL_ROOT)/hw
+
+ifeq ($(TARGET),c6472)
+ CSRC= t64.c cpmacdrv.c pll.c psc.c emif31.c mdio.c gpio.c nandgpio.c i2c.c
+endif
+
+.PHONY: hw
+
+
+include $(IBL_ROOT)/make/$(ARCH)/makeeco.mk
+
+
+C6X_C_DIR= $(IBL_ROOT)
+C6X_C_DIR+= ;$(IBL_ROOT)/arch/$(ARCH)
+C6X_C_DIR+= ;$(ECODIR)
+C6X_C_DIR+= ;$(STDINC)
+C6X_C_DIR+= ;$(IBL_ROOT)/cfg/$(TARGET)
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/timer
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/macs/cpmac
+C6X_C_DIR+= ;$(IBL_ROOT)/driver/eth
+C6X_C_DIR+= ;$(IBL_ROOT)/device
+C6X_C_DIR+= ;$(IBL_ROOT)/device/$(TARGET)
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/plls
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/pscs
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/mdio
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/gpio
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands/gpio
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/i2c
+C6X_C_DIR+= ;$(IBL_ROOT)/ecc
+export C6X_C_DIR
+
+
+vpath % $(ECODIR)/timer/timer64
+
+ifeq ($(TARGET),c6472)
+ vpath % $(ECODIR)/macs/cpmac
+ vpath % $(ECODIR)/plls/pllxx1p8
+ vpath % $(ECODIR)/pscs/psc2
+ vpath % $(ECODIR)/ddrs/emif31
+ vpath % $(ECODIR)/mdio
+ vpath % $(ECODIR)/gpio
+ vpath % $(ECODIR)/nands/gpio
+ vpath % $(ECODIR)/i2c
+endif
+
+
+hw: gen_cdefdep makefile $(OBJS)
+
+$(OBJS): cdefdep
+
+
+gen_cdefdep:
+ @echo Checking command line dependencies
+ @echo $(ENDIAN) $(TARGET) $(ARCH) > cdefdep.tmp
+ @sh -c 'if diff -q cdefdep.tmp cdefdep ; then echo same ; else $(CP) cdefdep.tmp cdefdep ; fi '
+
+
+
+
+
+
+
+
diff --git a/src/hw/ddrs/emif31/emif31.c b/src/hw/ddrs/emif31/emif31.c
--- /dev/null
@@ -0,0 +1,44 @@
+/************************************************************************************
+ * FILE PURPOSE: The emif 3.1 driver
+ ************************************************************************************
+ * FILE NAME: emif31.c
+ *
+ * DESCRIPTION: The emif controller is setup
+ *
+ * @file emif31.c
+ *
+ * @brief
+ * The emif controller is setup
+ *
+ **************************************************************************************/
+#include "types.h"
+#include "ibl.h"
+#include "emif31api.h"
+#include "emif31loc.h"
+#include "target.h"
+
+#define DEVICE_REG32_W(x,y) *(volatile unsigned int *)(x)=(y)
+#define DEVICE_REG32_R(x) (*(volatile unsigned int *)(x))
+
+void hwEmif3p1Enable (iblEmif3p1_t *cfg)
+{
+ uint32 v;
+
+ v = cfg->sdcfg | (1 << 15); /* Unlock */
+ DEVICE_REG32_W (DEVICE_DDR_BASE + DDR_REG_SDCFG, v);
+
+ DEVICE_REG32_W (DEVICE_DDR_BASE + DDR_REG_SDRFC, cfg->sdrfc);
+ DEVICE_REG32_W (DEVICE_DDR_BASE + DDR_REG_SDTIM1, cfg->sdtim1);
+ DEVICE_REG32_W (DEVICE_DDR_BASE + DDR_REG_SDTIM2, cfg->sdtim2);
+ DEVICE_REG32_W (DEVICE_DDR_BASE + DDR_REG_DMCCTL, cfg->dmcctl);
+
+ v = cfg->sdcfg & (~(1 << 15)); /* lock */
+ DEVICE_REG32_W (DEVICE_DDR_BASE + DDR_REG_SDCFG, v);
+
+}
+
+
+
+
+
+
diff --git a/src/hw/ddrs/emif31/emif31api.h b/src/hw/ddrs/emif31/emif31api.h
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef EMIF31API_H
+#define EMIF31API_H
+/********************************************************************************
+ * FILE PURPOSE: Define the emif 3.1 API to the applicaiton
+ ********************************************************************************
+ * FILE NAME: emif31api.h
+ *
+ * DESCRIPTION: Defines the user API to the emif 3.1 driver
+ *
+ * @file emif31api.h
+ *
+ * @brief
+ * The Driver API is defined
+ *
+ ********************************************************************************/
+#include "types.h"
+#include "ibl.h"
+
+
+void hwEmif3p1Enable (iblEmif3p1_t *cfg);
+
+
+
+#endif /* EMIF31API_H */
+
diff --git a/src/hw/ddrs/emif31/emif31loc.h b/src/hw/ddrs/emif31/emif31loc.h
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef EMIF31LOC_H
+#define EMIF31LOC_H
+/***********************************************************************************
+ * FILE PURPOSE: Provide EMIF controller definitions
+ ***********************************************************************************
+ * FILE NAME: emif31loc.h
+ *
+ * DESCRIPTION: The EMIF controller is defined
+ *
+ * @file emif31loc.h
+ *
+ * @brief
+ * The EMIF controller is defined
+ *
+ **********************************************************************************/
+
+/* Offsets from the peripheral base */
+#define DDR_REG_SDCFG 0x08
+#define DDR_REG_SDRFC 0x0c
+#define DDR_REG_SDTIM1 0x10
+#define DDR_REG_SDTIM2 0x14
+#define DDR_REG_DMCCTL 0xe4
+
+
+
+
+
+#endif /* EMIF31LOC_H */
diff --git a/src/hw/gpio/gpio.c b/src/hw/gpio/gpio.c
--- /dev/null
+++ b/src/hw/gpio/gpio.c
@@ -0,0 +1,351 @@
+/******************************************************************************
+ * Copyright (c) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * File Name: gpio.c
+ *
+ * Description: This file contains the lower level function to access GPIO
+ *
+ * History:
+ * JUL/22/2009, Amit Solanki, Created the file
+ * SEP/01/2009, Amit Solanki, Updated the documentation
+ *
+ *****************************************************************************/
+/****************
+ * Include Files
+ ****************/
+#include "types.h"
+#include "gpio.h"
+#include "target.h"
+
+/******************************************************************************
+ *
+ * Function: hwGpioSetDirection
+ *
+ * Description: This function configures the specified GPIO's direction
+ *
+ * Parameters: uiNumber - GPIO number to configure
+ * direction - GPIO_OUT or GPIO_IN
+ *
+ * Return Value: void
+ *
+ *****************************************************************************/
+void hwGpioSetDirection( Uint32 uiNumber, GpioDirection direction )
+{
+ Uint32* puiGpioDir = ( Uint32*)GPIO_DIR_REG;
+
+ if ( direction == GPIO_OUT )
+ *puiGpioDir = *puiGpioDir & ~(1 << uiNumber); // Set to OUTPUT
+ else
+ *puiGpioDir = *puiGpioDir | (1 << uiNumber); // Set to INTPUT
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioSetDataBusDirection
+ *
+ * Description: This function configures the GPIO[7:0]'s direction
+ *
+ * Parameters: direction - GPIO_OUT or GPIO_IN
+ *
+ * Return Value: void
+ *
+ *****************************************************************************/
+void hwGpioSetDataBusDirection( GpioDirection direction )
+{
+ Uint32* puiGpioDir = ( Uint32*)GPIO_DIR_REG;
+
+ if ( direction == GPIO_OUT )
+ *puiGpioDir = *puiGpioDir & 0xffffff00; // Set to OUTPUT
+ else
+ *puiGpioDir = *puiGpioDir | 0x000000ff; // Set to INTPUT
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioSetOutput
+ *
+ * Description: This function sets the specified GPIO's pin state to 1
+ *
+ * Parameters: uiNumber - GPIO number to configure
+ *
+ * Return Value: void
+ *
+ * Pre-Condition: The specified GPIO should be configured as output
+ *
+ *****************************************************************************/
+void hwGpioSetOutput( Uint32 uiNumber)
+{
+ Uint32* puiGpioSet = (Uint32*) GPIO_SET_DATA_REG;
+ *puiGpioSet = ( 1 << (uiNumber % 32) ); // Set to 1
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioClearOutput
+ *
+ * Description: This function Clears the specified GPIO's pin state to 0
+ *
+ * Parameters: uiNumber - GPIO number to configure
+ *
+ * Return Value: void
+ *
+ * Pre-Condition: The specified GPIO should be configured as output
+ *
+ *****************************************************************************/
+void hwGpioClearOutput( Uint32 uiNumber)
+{
+ Uint32* puiGpioClear = (Uint32*) GPIO_CLEAR_DATA_REG;
+ *puiGpioClear = ( 1 << (uiNumber % 32) ); // Clear to 0
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioReadInput
+ *
+ * Description: This function gets the specified GPIO's pin state
+ *
+ * Parameters: uiNumber - GPIO number to configure
+ *
+ * Return Value: Uint32 - Input state of GPIO if success
+ * - else GPIO status
+ *
+ * Pre-Condition: The specified GPIO should be configured as input
+ *
+ *****************************************************************************/
+Uint32 hwGpioReadInput( Uint32 uiNumber )
+{
+ Uint32* puiGpioInput = (Uint32*)GPIO_IN_DATA_REG;
+ if(uiNumber > GPIO_MAX_NUMBER)
+ return INVALID_GPIO_NUMBER;
+
+ if( ( (*puiGpioInput >> uiNumber) & GPIO_HIGH) == GPIO_HIGH)
+ return GPIO_HIGH;
+ else
+ return GPIO_LOW;
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioWriteDataBus
+ *
+ * Description: This function sets the GPIO[7:0] pins state
+ *
+ * Parameters: uchValue - Value to set as output
+ *
+ * Return Value: void
+ *
+ * Pre-Condition: The GPIO[7:0] should be configured as output
+ *
+ *****************************************************************************/
+void hwGpioWriteDataBus ( Uint8 uchValue )
+{
+ Uint32* puiGpioOutput = (Uint32*) GPIO_OUT_DATA_REG;
+ *puiGpioOutput = ( (*puiGpioOutput & 0xffffff00) | uchValue );
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioClearDataBus
+ *
+ * Description: This function sets the value to the Clear data register
+ *
+ * Parameters: uchValue - Value to set as output
+ *
+ * Return Value: void
+ *
+ * Pre-Condition: None
+ *
+ *****************************************************************************/
+void hwGpioClearDataBus(Uint8 uchValue)
+{
+ Uint32* puiGpioOutput = (Uint32*) GPIO_CLEAR_DATA_REG;
+ *puiGpioOutput = uchValue;
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioSetDataBus
+ *
+ * Description: This function sets the value to the Set data register
+ *
+ * Parameters: uchValue - Value to set as output
+ *
+ * Return Value: void
+ *
+ * Pre-Condition: None
+ *
+ *****************************************************************************/
+void hwGpioSetDataBus(Uint8 uchValue)
+{
+ Uint32* puiGpioOutput = (Uint32*) GPIO_SET_DATA_REG;
+ *puiGpioOutput = uchValue;
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioReadDataBus
+ *
+ * Description: This function gets the GPIO[7:0] pins state
+ *
+ * Parameters: void
+ *
+ * Return Value: Uint8 - Input state of GPIO[7:0]
+ *
+ * Pre-Condition: The GPIO[7:0] should be configured as input
+ *
+ *****************************************************************************/
+Uint8 hwGpioReadDataBus( void )
+{
+ Uint8* puchGpioInput = (Uint8*)GPIO_IN_DATA_REG;
+ return *puchGpioInput;
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioEnableGlobalInterrupt
+ *
+ * Description: This function Enables GPIO interrupts to CPU
+ *
+ * Parameters: void
+ *
+ * Return Value: void
+ *
+ *****************************************************************************/
+void hwGpioEnableGlobalInterrupt( void )
+{
+ Uint32* puiGpioInterrupt = (Uint32*)GPIO_BINTEN_REG;
+ *puiGpioInterrupt = 0x01;
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioDisableGlobalInterrupt
+ *
+ * Description: This function Disables GPIO interrupts to CPU
+ *
+ * Parameters: void
+ *
+ * Return Value: void
+ *
+ *****************************************************************************/
+void hwGpioDisableGlobalInterrupt( void )
+{
+ Uint32* puiGpioInterrupt = (Uint32*)GPIO_BINTEN_REG;
+ *puiGpioInterrupt = 0x00;
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioSetRisingEdgeInterrupt
+ *
+ * Description: This function sets specified GPIO's rising edge interrupt
+ *
+ * Parameters: uiNumber - GPIO number to configure
+ *
+ * Return Value: void
+ *
+ *****************************************************************************/
+void hwGpioSetRisingEdgeInterrupt( Uint32 uiNumber )
+{
+ Uint32* puiGpioSetRisingEdge = (Uint32*)GPIO_SET_RIS_TRIG_REG;
+ *puiGpioSetRisingEdge = (1 << uiNumber);
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioClearRisingEdgeInterrupt
+ *
+ * Description: This function clears specified GPIO's rising edge interrupt
+ *
+ * Parameters: uiNumber - GPIO number to configure
+ *
+ * Return Value: void
+ *
+ *****************************************************************************/
+void hwGpioClearRisingEdgeInterrupt( Uint32 uiNumber )
+{
+ Uint32* puiGpioClearRisingEdge = (Uint32*)GPIO_CLR_RIS_TRIG_REG;
+ *puiGpioClearRisingEdge = (1 << uiNumber);
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioSetFallingEdgeInterrupt
+ *
+ * Description: This function sets specified GPIO's falling edge interrupt
+ *
+ * Parameters: uiNumber - GPIO number to configure
+ *
+ * Return Value: void
+ *
+ *****************************************************************************/
+void hwGpioSetFallingEdgeInterrupt( Uint32 uiNumber )
+{
+ Uint32* puiGpioSetFallingEdge = (Uint32*)GPIO_SET_FAL_TRIG_REG;
+ *puiGpioSetFallingEdge = (1 << uiNumber);
+}
+
+/******************************************************************************
+ *
+ * Function: hwGpioClearFallingEdgeInterrupt
+ *
+ * Description: This function clears specified GPIO's falling edge interrupt
+ *
+ * Parameters: uiNumber - GPIO number to configure
+ *
+ * Return Value: void
+ *
+ *****************************************************************************/
+void hwGpioClearFallingEdgeInterrupt( Uint32 uiNumber )
+{
+ Uint32* puiGpioClearFallingEdge = (Uint32*)GPIO_CLR_FAL_TRIG_REG;
+ *puiGpioClearFallingEdge = (1 << uiNumber);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/hw/gpio/gpio.h b/src/hw/gpio/gpio.h
--- /dev/null
+++ b/src/hw/gpio/gpio.h
@@ -0,0 +1,139 @@
+/******************************************************************************
+ * Copyright (c) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * File Name: gpio.h
+ *
+ * Description: This file is the header file for GPIO module
+ *
+ * History:
+ * JUL/22/2009, Amit Solanki, Created the file
+ *
+ ******************************************************************************/
+#ifndef GPIO_H_
+#define GPIO_H_
+/****************
+ * Include Files
+ ****************/
+#include "types.h"
+
+/*********************************
+ * Defines and Macros and globals
+ *********************************/
+
+#define GPIO_0 0
+#define GPIO_1 1
+#define GPIO_2 2
+#define GPIO_3 3
+#define GPIO_4 4
+#define GPIO_5 5
+#define GPIO_6 6
+#define GPIO_7 7
+#define GPIO_8 8
+#define GPIO_9 9
+#define GPIO_10 10
+#define GPIO_11 11
+#define GPIO_12 12
+#define GPIO_13 13
+#define GPIO_14 14
+#define GPIO_15 15
+
+#define GPIO_DATAMASK 0x000000FF
+
+#define GPIO_MAX_NUMBER 15
+
+#define SUCCESS 0
+#define GPIO_LOW 0
+#define GPIO_HIGH 1
+#define INVALID_GPIO_NUMBER 2
+#define INVALID_GPIO_DIRECTION 3
+#define INVALID_GPIO_STATE 4
+
+// GPIO pins and the Nand flash controller signal mapping
+
+// GPIO[7:0] are used as bi-directional data-bus
+// between DSP and FPGA
+
+// Command pins
+#define DSP_FPGA_CMD0 GPIO_8
+#define DSP_FPGA_CMD1 GPIO_9
+
+// DSP to FPGA strobe for synchronization
+#define DSP_FPGA_STROBE GPIO_10
+
+// FPGA to DSP ready signal
+#define FPGA_DSP_READY GPIO_11
+
+// LED signals
+#define DSP_FPGA_LED_0 GPIO_12
+#define DSP_FPGA_LED_1 GPIO_13
+
+// NAND or non-UART FPGA interrupt
+#define FPGA_DSP_NFC_INTR GPIO_14
+
+// Nand mode selection GPIO
+#define NAND_MODE_GPIO GPIO_14
+
+// UART interrupt
+#define FPGA_DSP_UART_INTR GPIO_15
+
+/*********************
+ * Typedefs and Enums
+ *********************/
+typedef enum _GpioDirection
+{
+ GPIO_OUT = 0,
+ GPIO_IN
+}GpioDirection;
+
+/************************
+ * Function declarations
+ ************************/
+void hwGpioSetDirection( Uint32 uiNumber, GpioDirection direction );
+void hwGpioSetDataBusDirection( GpioDirection direction );
+void hwGpioSetOutput( Uint32 uiNumber);
+void hwGpioClearOutput( Uint32 uiNumber);
+Uint32 hwGpioReadInput( Uint32 uiNumber );
+void hwGpioWriteDataBus ( Uint8 uchValue );
+Uint8 hwGpioReadDataBus( void );
+void hwGpioEnableGlobalInterrupt( void );
+void hwGpioSetDataBus(Uint8 uchValue);
+void hwGpioClearDataBus(Uint8 uchValue);
+void hwGpioDisableGlobalInterrupt( void );
+void hwGpioSetRisingEdgeInterrupt( Uint32 uiNumber );
+void hwGpioClearRisingEdgeInterrupt( Uint32 uiNumber );
+void hwGpioSetFallingEdgeInterrupt( Uint32 uiNumber );
+void hwGpioClearFallingEdgeInterrupt( Uint32 uiNumber );
+
+#endif // GPIO_H_
+
diff --git a/src/hw/i2c/i2c.c b/src/hw/i2c/i2c.c
--- /dev/null
+++ b/src/hw/i2c/i2c.c
@@ -0,0 +1,368 @@
+/****************************************************************************
+ * FILE PURPOSE: An i2c driver for the rom boot loader
+ ****************************************************************************
+ * FILE NAME: i2c.c
+ *
+ * DESCRIPTION: Provides an i2c driver for the rom boot loader. The driver
+ * is adapted from the csl polling driver in the 64x csl.
+ *
+ ****************************************************************************/
+#include "types.h"
+#include "i2c.h"
+#include "i2cloc.h"
+#include "target.h"
+
+#define DEVICE_REG32_W(x,y) *(volatile unsigned int *)(x)=(y)
+#define DEVICE_REG32_R(x) (*(volatile unsigned int *)(x))
+
+ /**************************************************************************
+ * Global variables
+ *************************************************************************/
+ UINT32 i2cCoreFreqMhz;
+ UINT32 i2cBitPeriodCycles;
+
+
+/***********************************************************************************
+ * FUNCTION PURPOSE: Provide an approximate delay
+ ***********************************************************************************
+ * DESCRIPTION: A delay in units of CPU cycles is executed
+ ***********************************************************************************/
+static void chipDelay32 (uint32 del)
+{
+ volatile unsigned int i;
+
+ for (i = 0; i < del/8; i++);
+
+}
+
+
+/***************************************************************************
+ * FUNCTION PURPOSE: Generate a delay
+ ***************************************************************************
+ * DESCRIPTION: Creates a delay specified in usec
+ ***************************************************************************/
+void hw_i2c_delay_usec (UINT32 usec)
+{
+ UINT32 delayCycles;
+
+ delayCycles = usec * i2cCoreFreqMhz;
+
+ chipDelay32 (delayCycles);
+
+} /* hw_i2c_delay_usec */
+
+
+ /***************************************************************************
+ * FUNCTION PURPOSE: Initialize the I2C.
+ ***************************************************************************
+ * DESCRIPTION: Puts the I2C into reset, sets up the device and takes
+ * the device out of reset in slave receiver mode.
+ **************************************************************************/
+void hwI2Cinit (UINT16 coreFreqMhz, UINT16 moduleDivisor, UINT16 clkFreqKhz, UINT16 ownAddr)
+ {
+ UINT32 psc;
+ UINT32 clkx;
+ UINT32 tmp;
+ UINT32 moduleFreqMhzQ1;
+ UINT32 trueModFreqHz;
+ UINT32 trueModFreqkHz;
+
+ /* Put the i2c peripheral into reset */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_RESET);
+
+ /* To determine the module prescaler Q31.1 format will be used. This is just
+ * handled simply since the input module frequency is an integer it will just
+ * be multiplied by two. Dividing two Q31.1 result in a Q30.0, or the divider *
+ * Calculate module prescalars to get as close to target frequencies as possible */
+ moduleFreqMhzQ1 = (coreFreqMhz << 1) / moduleDivisor;
+ psc = moduleFreqMhzQ1 / I2C_TARGET_MODULE_FREQ_MHZ_Q1;
+ if (psc > 0)
+ psc = psc - 1;
+ trueModFreqHz = ((UINT32)coreFreqMhz * (UINT32)1000000) / (moduleDivisor * (psc+1));
+
+ tmp = trueModFreqHz / (clkFreqKhz * 1000);
+ if (tmp > 12)
+ clkx = (tmp - 12) >> 1;
+ else
+ clkx = 0;
+
+ /* Store the core frequency for use in generating delay */
+ i2cCoreFreqMhz = coreFreqMhz;
+
+ /* Calculate the number of micro seconds for each bit. */
+ trueModFreqkHz = trueModFreqHz / 1000; /* Prevent 32 bit integer overlflow */
+ i2cBitPeriodCycles = (UINT32)coreFreqMhz * 1000 * (2 * clkx + 12) / trueModFreqkHz;
+
+ /* Initialize the registers */
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_PSC, (UINT32)psc);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_OAR, (UINT32)ownAddr);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_IER, (UINT32)0);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_STR, I2C_VAL_REG_STR_RESET);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_CLKL, clkx);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_CLKH, clkx);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_CNT, (UINT32)0);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_SAR, (UINT32)0x3ff);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_DXR, (UINT32)0);
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_PFUNC, (UINT32)0);
+
+ /* Take the I2C out of reset in the slave receiver mode */
+ DEVICE_REG32_W(DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_SLVRCV);
+
+ /* Read the receive register to clear it */
+ tmp = DEVICE_REG32_R(DEVICE_I2C_BASE + I2C_REG_DRR);
+
+
+} /* hwI2Cinit */
+
+
+/****************************************************************************
+ * FUNCTION PURPOSE: Perform a master write
+ ****************************************************************************
+ * DESCRIPTION: Enters master transmitter mode, writes a specified number
+ * of bytes. The byte stream arrives packed in the 16 bit
+ * data stream, and are sent most significant byte first.
+ ****************************************************************************/
+I2C_RET hwI2cMasterWrite (UINT16 eeprom_i2c_id, UINT8 *eData, UINT16 nbytes, UINT16 endBusState, BOOL busIsMine)
+{
+ UINT32 timeoutCount;
+ UINT32 polling;
+ UINT32 value;
+ UINT32 str;
+ UINT16 i;
+
+ /* If the byte length is 0 there is nothing to do */
+ if (nbytes == 0)
+ return (I2C_RET_OK);
+
+ /* Check for the bus busy signal */
+ if (busIsMine == FALSE) {
+ timeoutCount = 0;
+ do {
+ polling = I2C_REG_STR_FIELD_BB(DEVICE_REG32_R (DEVICE_I2C_BASE + I2C_REG_STR));
+
+ if (polling != 0) {
+ hw_i2c_delay_usec (I2C_MASTER_TRANSMITTER_BUS_ACCESS_DELAY_US);
+
+ timeoutCount += 1;
+ if (timeoutCount >= I2C_MAX_MASTER_TRANSMITTER_BUS_ACCESS_TIMEOUT) {
+
+ /* Return to slave receiver, clear nack and bus busy */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_SLVRCV);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_STR, I2C_VAL_REG_STR_ON_FAIL);
+ return (I2C_RET_IDLE_TIMEOUT);
+ }
+ } else { /* The bus is free */
+ timeoutCount = 0;
+ }
+ }
+ while (timeoutCount != 0);
+
+ }
+
+ /* Enter master transmitter mode, set the slave address register */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_MSTXMT);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_SAR, (UINT32)eeprom_i2c_id);
+
+ /* Put the first byte into the transmit register, set the start bit */
+ value = *eData & 0x00ff;
+ eData = eData + 1;
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_DXR, value);
+
+
+ /* Some delay required */
+ chipDelay32 (i2cBitPeriodCycles);
+
+ /* Set the start bit */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_MSTXMTSTRT);
+
+ for (i = 1; i < nbytes; i++) {
+ timeoutCount = 0;
+
+ do {
+ /* Read status */
+ str = DEVICE_REG32_R (DEVICE_I2C_BASE + I2C_REG_STR);
+
+ /* On Nack return failure */
+ if (I2C_REG_STR_FIELD_NACK(str) != 0) {
+
+ /* Return to slave receiver, clear nack and bus busy */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_SLVRCV);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_STR, I2C_VAL_REG_STR_ON_FAIL);
+ return (I2C_RET_NO_ACK);
+ }
+
+ /* Check for transmit ready */
+ if (I2C_REG_STR_FIELD_XRDY(str) != 0) {
+ timeoutCount = 0;
+
+ value = *eData & 0x00ff;
+ eData = eData + 1;
+
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_DXR, value);
+
+
+ } else { /* XRDY bit not set */
+ chipDelay32 (i2cBitPeriodCycles);
+ timeoutCount += 1;
+ if (timeoutCount >= I2C_MAX_MASTER_TRANSMITTER_TIMEOUT) {
+ /* Return to slave receiver, clear nack and bus busy */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_SLVRCV);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_STR, I2C_VAL_REG_STR_ON_FAIL);
+ return (I2C_RET_IDLE_TIMEOUT);
+ }
+ }
+
+ } while (timeoutCount != 0);
+
+ } /* end for loop */
+
+
+ /* If releasing the bus, send a stop bit */
+ if (endBusState == I2C_RELEASE_BUS) {
+
+ /* Wait for the ardy bit to go high */
+ timeoutCount = 0;
+ do {
+ str = DEVICE_REG32_R (DEVICE_I2C_BASE + I2C_REG_STR);
+ if (I2C_REG_STR_FIELD_ARDY(str) != 0) {
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_MSTXMTSTOP);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_STR, I2C_VAL_REG_STR_CLR_BUSY);
+ hw_i2c_delay_usec (10000);
+ timeoutCount = 0;
+
+ } else { /* Registers not ready for access */
+ timeoutCount += 1;
+
+ if (timeoutCount >= I2C_MAX_MASTER_TRANSMITTER_ARDY_TIMEOUT) {
+ /* On timeout put the peripheral into reset, wait, then
+ * take it out of reset */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_RESET);
+ hw_i2c_delay_usec (10000);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_SLVRCV);
+ return (I2C_RET_IDLE_TIMEOUT);
+ }
+ chipDelay32 (i2cBitPeriodCycles);
+ }
+ } while (timeoutCount != 0);
+
+ } /* end bus release */
+
+ return (I2C_RET_OK);
+
+} /* hwI2cMasterWrite */
+
+
+
+/**************************************************************************
+ * FUNCTION PURPOSE: Perform a master read from an I2C prom
+ **************************************************************************
+ * DESCRIPTION: Reads a fixed number of bytes from an I2C prom. The read
+ * consists of a master write of 2 bytes (forming a 16 bit address,
+ * msb transmitted first), followed by a master read of the
+ * input number of bytes. The bytes that are read are placed
+ * in p_packed_bytes in big endian format.
+ **************************************************************************/
+I2C_RET hwI2cMasterRead (
+ UINT32 byte_addr,
+ UINT32 byte_len,
+ UINT8 *p_packed_bytes,
+ UINT16 eeprom_i2c_id,
+ UINT16 address_delay)
+{
+
+ UINT32 str;
+ UINT32 timeoutCount;
+ UINT32 i;
+ UINT8 eAddr[2];
+ I2C_RET ret;
+
+ /* If the byte length is 0, there is nothing to do */
+ if (byte_len == 0)
+ return (I2C_RET_OK);
+
+ /* Write the byte address to the eeprom. Do not send a stop */
+ eAddr[0] = (byte_addr >> 8) & 0xff;
+ eAddr[1] = byte_addr & 0xff;
+
+ ret = hwI2cMasterWrite (eeprom_i2c_id, eAddr, 2, I2C_DO_NOT_RELEASE_BUS, FALSE);
+ if (ret != I2C_RET_OK)
+ return (ret);
+
+ /* Give the I2C prom some time to process the read command */
+ chipDelay32 (((UINT32)address_delay)<<8);
+
+ /* Set the start bit, begin the master read */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_MSTRCV);
+
+ /* Read the requested number of bytes */
+ for (i = 0; i < byte_len; i++) {
+ timeoutCount = 0;
+
+ do {
+ /* Read status */
+ str = DEVICE_REG32_R (DEVICE_I2C_BASE + I2C_REG_STR);
+
+ /* On Nack return failure */
+ if (I2C_REG_STR_FIELD_NACK(str) != 0) {
+
+ /* Return to slave receiver, clear nack and bus busy */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_SLVRCV);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_STR, I2C_VAL_REG_STR_ON_FAIL);
+ return (I2C_RET_NO_ACK);
+ }
+
+ /* Check for receive byte ready */
+ if (I2C_REG_STR_FIELD_RRDY(str) != 0) {
+ *p_packed_bytes = (UINT16) (DEVICE_REG32_R (DEVICE_I2C_BASE + I2C_REG_DRR) & 0x00ff);
+ timeoutCount = 0;
+ p_packed_bytes = p_packed_bytes + 1;
+
+
+ } else { /* RRDY bit not set */
+ chipDelay32 (i2cBitPeriodCycles);
+ timeoutCount += 1;
+ if (timeoutCount >= I2C_MAX_MASTER_RECEIVE_TIMEOUT) {
+ /* Return to slave receiver, clear nack and bus busy */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_SLVRCV);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_STR, I2C_VAL_REG_STR_ON_FAIL);
+ return (I2C_RET_IDLE_TIMEOUT);
+ }
+ }
+
+ } while (timeoutCount != 0);
+
+ } /* end for loop */
+
+ /* The data block has been read. Send the stop bit */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_MSTRCVSTOP);
+
+
+ /* Wait for the rrdy and read the dummy byte */
+ timeoutCount = 0;
+ do {
+
+ str = DEVICE_REG32_R (DEVICE_I2C_BASE + I2C_REG_STR);
+
+ /* Check for receive byte ready */
+ if (I2C_REG_STR_FIELD_RRDY(str) != 0) {
+ eAddr[0] = (UINT16) (DEVICE_REG32_R (DEVICE_I2C_BASE + I2C_REG_DRR) & 0x00ff);
+ timeoutCount = 0;
+
+ } else { /* rrdy not set */
+
+ chipDelay32 (i2cBitPeriodCycles);
+ timeoutCount += 1;
+ if (timeoutCount >= I2C_MAX_MASTER_RECEIVE_TIMEOUT) {
+ /* Return to slave receiver, clear nack and bus busy */
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, I2C_VAL_REG_MDR_SLVRCV);
+ DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_STR, I2C_VAL_REG_STR_ON_FAIL);
+ return (I2C_RET_IDLE_TIMEOUT);
+ }
+ }
+
+ } while (timeoutCount != 0);
+
+ return (I2C_RET_OK);
+
+} /* hwI2cMasterRead */
+
diff --git a/src/hw/i2c/i2c.h b/src/hw/i2c/i2c.h
--- /dev/null
+++ b/src/hw/i2c/i2c.h
@@ -0,0 +1,39 @@
+/*********************************************************************
+ * FILE PURPOSE: I2C API definition
+ *********************************************************************
+ * FILE NAME: i2c.h
+ *
+ * DESCRIPTION: Defines the i2c API
+ *
+ * @file i2c.h
+ *
+ * @brief
+ * Defines the i2c API
+ *
+ *********************************************************************/
+#include "types.h"
+
+typedef UINT16 I2C_RET;
+
+
+#define I2C_RET_OK 0
+#define I2C_RET_LOST_ARB 1
+#define I2C_RET_NO_ACK 2
+#define I2C_RET_IDLE_TIMEOUT 3
+#define I2C_RET_BAD_REQUEST 4
+#define I2C_RET_CLOCK_STUCK_LOW 5
+#define I2C_RET_GEN_ERROR 99
+
+
+enum {
+ I2C_RELEASE_BUS,
+ I2C_DO_NOT_RELEASE_BUS
+};
+
+
+void hwI2Cinit (UINT16 coreFreqMhz, UINT16 moduleDivisor, UINT16 clkFreqKhz, UINT16 ownAddr);
+I2C_RET hwI2cMasterWrite (UINT16 eeprom_i2c_id, UINT8 *eData, UINT16 nbytes, UINT16 endBusState, BOOL busIsMine);
+I2C_RET hwI2cMasterRead (UINT32 byte_addr, UINT32 byte_len, UINT8 *p_packed_bytes, UINT16 eeprom_i2c_id, UINT16 address_delay);
+
+
+
diff --git a/src/hw/i2c/i2cloc.h b/src/hw/i2c/i2cloc.h
--- /dev/null
+++ b/src/hw/i2c/i2cloc.h
@@ -0,0 +1,109 @@
+#ifndef _I2CLOC_H
+#define _I2CLOC_H
+/***********************************************************************
+ * FILE PURPOSE: Local definitions used to run the I2C peripheral
+ ***********************************************************************
+ * FILE NAME: i2cloc.h
+ *
+ * DESCRIPTION: Provides defintions and prototypes local to the i2c module
+ *
+ ************************************************************************/
+#include "types.h"
+
+#define BOOTBITMASK(x,y) ( ( ( ((UINT32)1 << (((UINT32)x)-((UINT32)y)+(UINT32)1) ) - (UINT32)1 ) ) << ((UINT32)y) )
+#define BOOT_READ_BITFIELD(z,x,y) (((UINT32)z) & BOOTBITMASK(x,y)) >> (y)
+#define BOOT_SET_BITFIELD(z,f,x,y) (((UINT32)z) & ~BOOTBITMASK(x,y)) | ( (((UINT32)f) << (y)) & BOOTBITMASK(x,y) )
+
+/* Register addresses relative to a base address */
+#define I2C_REG_OAR 0x00
+#define I2C_REG_IER 0x04
+#define I2C_REG_STR 0x08
+#define I2C_REG_CLKL 0x0c
+#define I2C_REG_CLKH 0x10
+#define I2C_REG_CNT 0x14
+#define I2C_REG_DRR 0x18
+#define I2C_REG_SAR 0x1c
+#define I2C_REG_DXR 0x20
+#define I2C_REG_MDR 0x24
+#define I2C_REG_ISR 0x28
+#define I2C_REG_EXMODE 0x2c
+#define I2C_REG_PSC 0x30
+#define I2C_REG_PID1 0x34
+#define I2C_REG_PID2 0x38
+#define I2C_REG_PFUNC 0x48
+
+/* Individual register definitions */
+#define I2C_VAL_REG_MDR_RESET 0x4000
+#define I2C_VAL_REG_MDR_SLVRCV 0x40A0
+#define I2C_VAL_REG_MDR_MSTRCV 0x64A0
+#define I2C_VAL_REG_MDR_MSTRCVSTOP 0x4CA0
+#define I2C_VAL_REG_MDR_MSTXMT 0x46A0
+#define I2C_VAL_REG_MDR_MSTXMTSTRT 0x66A0
+#define I2C_VAL_REG_MDR_MSTXMTSTOP 0x4CA0
+
+#define I2C_VAL_REG_STR_RESET 0x0410
+#define I2C_VAL_REG_STR_ON_FAIL 0x1002 /* Clear bus busy, clear nack */
+#define I2C_VAL_REG_STR_CLR_BUSY 0x1000 /* Clear busy */
+#define I2C_VAL_REG_STR_CLR_RRDY 0x003F
+
+/* Bit field definitions */
+#define I2C_REG_STR_FIELD_BB(x) BOOT_READ_BITFIELD((x), 12, 12)
+#define I2C_REG_STR_FIELD_NACK(x) BOOT_READ_BITFIELD((x), 1, 1)
+#define I2C_REG_STR_FIELD_ARDY(x) BOOT_READ_BITFIELD((x), 2, 2)
+#define I2C_REG_STR_FIELD_XRDY(x) BOOT_READ_BITFIELD((x), 4, 4)
+#define I2C_REG_STR_FIELD_RRDY(x) BOOT_READ_BITFIELD((x), 3, 3)
+
+
+
+/* Byte ordering */
+enum {
+ I2C_BYTE_LSB,
+ I2C_BYTE_MSB
+};
+
+/************************************************************************
+ * Definition: Desired frequency for module operation in Qx.1 format
+ ************************************************************************/
+#define I2C_TARGET_MODULE_FREQ_MHZ_Q1 27 /* 13.5 MHz */
+
+
+/************************************************************************
+ * Definition: Timeout limit for master receiver. The units are
+ * in number of bits, so provide some overhead
+ ************************************************************************/
+#define I2C_MAX_MASTER_RECEIVE_TIMEOUT 240 /* 30 bytes */
+
+/************************************************************************
+ * Definition: Timeout limit for master transmitter. The units are
+ * in number of bits, so provide some overhead
+ ************************************************************************/
+#define I2C_MAX_MASTER_TRANSMITTER_TIMEOUT 240 /* 30 bytes */
+
+/************************************************************************
+ * Definition: Timeout limit for the master transmitter to get access
+ * to the bus. In 10ms units.
+ ************************************************************************/
+#define I2C_MAX_MASTER_TRANSMITTER_BUS_ACCESS_TIMEOUT 100
+#define I2C_MASTER_TRANSMITTER_BUS_ACCESS_DELAY_US 10000
+
+/*************************************************************************
+ * Definition: Timeout limit after a master transmitter operation is
+ * complete, and waiting for access to the MMRs. This should
+ * be on the order of two bytes, for the last two that are
+ * being sent (one in the shift register, one in the dxr. The
+ * units are in bits.
+ *************************************************************************/
+#define I2C_MAX_MASTER_TRANSMITTER_ARDY_TIMEOUT 32 /* 4 bytes */
+
+
+/*************************************************************************
+ * Definition: Timeout limit in slave receiver mode. The unit is in
+ * expected bit periods, but is long since the master
+ * may have a long delay before beginning transmission.
+ *************************************************************************/
+#define I2C_MAX_SLAVE_RECEIVE_TIMEOUT 5000000
+
+
+
+
+#endif /* _I2CLOC_H */
diff --git a/src/hw/macs/cpmac/cpmac_regs.h b/src/hw/macs/cpmac/cpmac_regs.h
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * @file cpmac_regs.h
+ *
+ * @brief
+ * This file contains the Register Desciptions for EMAC
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ *
+ * \par
+ */
+
+#ifndef __CPMAC_REGS_H__
+#define __CPMAC_REGS_H__
+
+/**
+ * @brief
+ * The structure describes the CPMAC Register Overlay.
+ *
+ * @details
+ * This is the CPMAC Register overlay data structure which is used
+ * by the CPMAC Driver.
+ */
+typedef struct CPMAC_REGS
+{
+ volatile Uint32 TXIDVER;
+ volatile Uint32 TXCONTROL;
+ volatile Uint32 TXTEARDOWN;
+ volatile Uint8 RSVD0[4];
+ volatile Uint32 RXIDVER;
+ volatile Uint32 RXCONTROL;
+ volatile Uint32 RXTEARDOWN;
+ volatile Uint8 RSVD1[100];
+ volatile Uint32 TXINTSTATRAW;
+ volatile Uint32 TXINTSTATMASKED;
+ volatile Uint32 TXINTMASKSET;
+ volatile Uint32 TXINTMASKCLEAR;
+ volatile Uint32 MACINVECTOR;
+ volatile Uint8 RSVD2[12];
+ volatile Uint32 RXINTSTATRAW;
+ volatile Uint32 RXINTSTATMASKED;
+ volatile Uint32 RXINTMASKSET;
+ volatile Uint32 RXINTMASKCLEAR;
+ volatile Uint32 MACINTSTATRAW;
+ volatile Uint32 MACINTSTATMASKED;
+ volatile Uint32 MACINTMASKSET;
+ volatile Uint32 MACINTMASKCLEAR;
+ volatile Uint8 RSVD3[64];
+ volatile Uint32 RXMBPENABLE;
+ volatile Uint32 RXUNICASTSET;
+ volatile Uint32 RXUNICASTCLEAR;
+ volatile Uint32 RXMAXLEN;
+ volatile Uint32 RXBUFFEROFFSET;
+ volatile Uint32 RXFILTERLOWTHRESH;
+ volatile Uint8 RSVD4[8];
+ volatile Uint32 RX0FLOWTHRESH;
+ volatile Uint32 RX1FLOWTHRESH;
+ volatile Uint32 RX2FLOWTHRESH;
+ volatile Uint32 RX3FLOWTHRESH;
+ volatile Uint32 RX4FLOWTHRESH;
+ volatile Uint32 RX5FLOWTHRESH;
+ volatile Uint32 RX6FLOWTHRESH;
+ volatile Uint32 RX7FLOWTHRESH;
+ volatile Uint32 RX0FREEBUFFER;
+ volatile Uint32 RX1FREEBUFFER;
+ volatile Uint32 RX2FREEBUFFER;
+ volatile Uint32 RX3FREEBUFFER;
+ volatile Uint32 RX4FREEBUFFER;
+ volatile Uint32 RX5FREEBUFFER;
+ volatile Uint32 RX6FREEBUFFER;
+ volatile Uint32 RX7FREEBUFFER;
+ volatile Uint32 MACCONTROL;
+ volatile Uint32 MACSTATUS;
+ volatile Uint32 EMCONTROL;
+ volatile Uint32 FIFOCONTROL;
+ volatile Uint32 MACCONFIG;
+ volatile Uint32 SOFTRESET;
+ volatile Uint8 RSVD5[88];
+ volatile Uint32 MACSRCADDRLO;
+ volatile Uint32 MACSRCADDRHI;
+ volatile Uint32 MACHASH1;
+ volatile Uint32 MACHASH2;
+ volatile Uint32 BOFFTEST;
+ volatile Uint32 TPACETEST;
+ volatile Uint32 RXPAUSE;
+ volatile Uint32 TXPAUSE;
+ volatile Uint8 RSVD6[16];
+ volatile Uint32 RXGOODFRAMES;
+ volatile Uint32 RXBCASTFRAMES;
+ volatile Uint32 RXMCASTFRAMES;
+ volatile Uint32 RXPAUSEFRAMES;
+ volatile Uint32 RXCRCERRORS;
+ volatile Uint32 RXALIGNCODEERRORS;
+ volatile Uint32 RXOVERSIZED;
+ volatile Uint32 RXJABBER;
+ volatile Uint32 RXUNDERSIZED;
+ volatile Uint32 RXFRAGMENTS;
+ volatile Uint32 RXFILTERED;
+ volatile Uint32 RXQOSFILTERED;
+ volatile Uint32 RXOCTETS;
+ volatile Uint32 TXGOODFRAMES;
+ volatile Uint32 TXBCASTFRAMES;
+ volatile Uint32 TXMCASTFRAMES;
+ volatile Uint32 TXPAUSEFRAMES;
+ volatile Uint32 TXDEFERRED;
+ volatile Uint32 TXCOLLISION;
+ volatile Uint32 TXSINGLECOLL;
+ volatile Uint32 TXMULTICOLL;
+ volatile Uint32 TXEXCESSIVECOLL;
+ volatile Uint32 TXLATECOLL;
+ volatile Uint32 TXUNDERRUN;
+ volatile Uint32 TXCARRIERSENSE;
+ volatile Uint32 TXOCTETS;
+ volatile Uint32 FRAME64;
+ volatile Uint32 FRAME65T127;
+ volatile Uint32 FRAME128T255;
+ volatile Uint32 FRAME256T511;
+ volatile Uint32 FRAME512T1023;
+ volatile Uint32 FRAME1024TUP;
+ volatile Uint32 NETOCTETS;
+ volatile Uint32 RXSOFOVERRUNS;
+ volatile Uint32 RXMOFOVERRUNS;
+ volatile Uint32 RXDMAOVERRUNS;
+ volatile Uint8 RSVD7[624];
+ volatile Uint32 MACADDRLO;
+ volatile Uint32 MACADDRHI;
+ volatile Uint32 MACINDEX;
+ volatile Uint8 RSVD8[244];
+ volatile Uint32 TX0HDP;
+ volatile Uint32 TX1HDP;
+ volatile Uint32 TX2HDP;
+ volatile Uint32 TX3HDP;
+ volatile Uint32 TX4HDP;
+ volatile Uint32 TX5HDP;
+ volatile Uint32 TX6HDP;
+ volatile Uint32 TX7HDP;
+ volatile Uint32 RX0HDP;
+ volatile Uint32 RX1HDP;
+ volatile Uint32 RX2HDP;
+ volatile Uint32 RX3HDP;
+ volatile Uint32 RX4HDP;
+ volatile Uint32 RX5HDP;
+ volatile Uint32 RX6HDP;
+ volatile Uint32 RX7HDP;
+ volatile Uint32 TX0CP;
+ volatile Uint32 TX1CP;
+ volatile Uint32 TX2CP;
+ volatile Uint32 TX3CP;
+ volatile Uint32 TX4CP;
+ volatile Uint32 TX5CP;
+ volatile Uint32 TX6CP;
+ volatile Uint32 TX7CP;
+ volatile Uint32 RX0CP;
+ volatile Uint32 RX1CP;
+ volatile Uint32 RX2CP;
+ volatile Uint32 RX3CP;
+ volatile Uint32 RX4CP;
+ volatile Uint32 RX5CP;
+ volatile Uint32 RX6CP;
+ volatile Uint32 RX7CP;
+}CPMAC_REGS;
+
+/* MACADDRLO: Bit Mask Definitions. */
+#define CPMAC_MACADDRLO_VALID (0x00100000u)
+#define CPMAC_MACADDRLO_MATCHFILT (0x00080000u)
+
+/* MACCONTROL: Bit Mask Definitions. */
+#define CPMAC_MACCONTROL_RXOWNERSHIP (0x00002000u)
+#define CPMAC_MACCONTROL_RXOFFLENBLOCK (0x00004000u)
+#define CPMAC_MACCONTROL_MIIEN (0x00000020u)
+
+/* RXMBP Enable: Bit Mask Definitions. */
+#define CPMAC_RXMBPENABLE_RXBROADEN (0x00002000u)
+
+#endif /* __CPMAC_REGS_H__ */
diff --git a/src/hw/macs/cpmac/cpmacdrv.c b/src/hw/macs/cpmac/cpmacdrv.c
--- /dev/null
@@ -0,0 +1,444 @@
+/**
+ * @file cpmacdrv.c
+ *
+ * @brief
+ * The driver is written for the CPMAC Ethernet controller. It follows
+ * the Network Boot Module Ethernet Driver Specifications.
+ *
+ * If there are modifications to this driver required for it to work
+ * on the specific device then device authors are recommended to
+ * create a copy of this file in the RBL directory and do the
+ * necessary modifications. Please pass on the appropriate information
+ * to the ROM Boot Loader Framework Development Team.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ * \par
+ */
+
+#include "types.h"
+#include "iblloc.h"
+#include "device.h"
+#include "net.h"
+#include "cpmac_regs.h"
+#include <string.h>
+
+#ifdef TARGET_DEVICE_CPMAC
+
+/**********************************************************************
+ ************************** Local Definitions *************************
+ **********************************************************************/
+
+// Packet Flags for TX and RX
+#define EMAC_DSC_FLAG_SOP 0x80000000u
+#define EMAC_DSC_FLAG_EOP 0x40000000u
+#define EMAC_DSC_FLAG_OWNER 0x20000000u
+#define EMAC_DSC_FLAG_EOQ 0x10000000u
+#define EMAC_DSC_FLAG_TDOWNCMPLT 0x08000000u
+#define EMAC_DSC_FLAG_PASSCRC 0x04000000u
+
+// The following flags are RX only
+#define EMAC_DSC_FLAG_JABBER 0x02000000u
+#define EMAC_DSC_FLAG_OVERSIZE 0x01000000u
+#define EMAC_DSC_FLAG_FRAGMENT 0x00800000u
+#define EMAC_DSC_FLAG_UNDERSIZED 0x00400000u
+#define EMAC_DSC_FLAG_CONTROL 0x00200000u
+#define EMAC_DSC_FLAG_OVERRUN 0x00100000u
+#define EMAC_DSC_FLAG_CODEERROR 0x00080000u
+#define EMAC_DSC_FLAG_ALIGNERROR 0x00040000u
+#define EMAC_DSC_FLAG_CRCERROR 0x00020000u
+#define EMAC_DSC_FLAG_NOMATCH 0x00010000u
+
+/**********************************************************************
+ ************************** Local Structures **************************
+ **********************************************************************/
+
+/**
+ * @brief
+ * The structure describes the EMAC Descriptor.
+ *
+ * @details
+ * Ethernet drivers receives and transmits data through the descriptor
+ * object described here.
+ */
+typedef struct _EMAC_Desc
+{
+ /**
+ * @brief Pointer to next descriptor in chain
+ */
+ struct _EMAC_Desc* pNext;
+
+ /**
+ * @brief Pointer to the data buffer.
+ */
+ Uint8* pBuffer;
+
+ /**
+ * @brief Buffer Offset(MSW) and Length(LSW)
+ */
+ Uint32 BufOffLen;
+
+ /**
+ * @brief Packet Flags(MSW) and Length(LSW)
+ */
+ volatile Uint32 PktFlgLen;
+
+}EMAC_Desc;
+
+/**
+ * @brief
+ * The structure describes the EMAC Master Control Block.
+ *
+ * @details
+ * The structure stores information required by the EMAC Driver;
+ * which includes the Receive and Transmit Buffer Descriptors.
+ */
+typedef struct EMAC_MCB
+{
+ /**
+ * @brief Pointer to the Receive Buffer Descriptor
+ */
+ EMAC_Desc* rx_bd;
+
+ /**
+ * @brief Pointer to the Transmit Buffer Descriptor
+ */
+ EMAC_Desc* tx_bd;
+
+ /**
+ * @brief Buffer for receiving data linked with the receive
+ * buffer descriptor.
+ */
+ Uint8 rx_buffer[NET_MAX_MTU];
+
+ /**
+ * @brief Tracks the last value placed into the rx hdp
+ */
+ Uint32 lastRxHdp;
+
+}EMAC_MCB;
+
+/**********************************************************************
+ ************************** Global Variables **************************
+ **********************************************************************/
+
+/**
+ * @brief Global Driver structure which keeps track of all the Ethernet
+ * Driver related information.
+ */
+EMAC_MCB emacMCB;
+
+/**
+ * @brief EMAC Registers.
+ */
+Uint32 aptr_EMACRegs[] = TARGET_EMAC_BASE_ADDRESSES;
+Uint32 aptr_EmacDesc[] = TARGET_EMAC_DSC_BASE_ADDR;
+
+
+/**********************************************************************
+ ************************** ETHDRV Functions **************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * This is the Network Open API which is registered with the
+ * NET Boot module to initialize the Ethernet device.
+ *
+ * @param[in] ptr_device
+ * Pointer to the NET Device structure which is being opened.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 cpmac_drv_start (NET_DRV_DEVICE* ptr_device)
+{
+ Uint32 tmpval;
+ volatile Uint32* pRegAddr;
+ Int32 index;
+ CPMAC_REGS* ptr_EMACRegs;
+ EMAC_Desc* pDesc;
+
+ if (ptr_device->port_num >= TARGET_EMAC_N_PORTS)
+ return (-1);
+
+ ptr_EMACRegs = (CPMAC_REGS *)(aptr_EMACRegs[ptr_device->port_num]);
+ pDesc = (EMAC_Desc *)(aptr_EmacDesc[ptr_device->port_num]);
+
+
+ /* Reset EMAC */
+ ptr_EMACRegs->SOFTRESET = 0x1;
+ while (ptr_EMACRegs->SOFTRESET != 0x0);
+
+ /* Reset MAC Control */
+ ptr_EMACRegs->MACCONTROL = 0;
+
+ /* Must manually init HDPs to NULL */
+ pRegAddr = &ptr_EMACRegs->TX0HDP;
+ for( index=0; index<8; index++ )
+ *pRegAddr++ = 0;
+
+ pRegAddr = &ptr_EMACRegs->RX0HDP;
+ for( index=0; index<8; index++ )
+ *pRegAddr++ = 0;
+
+ pRegAddr = &ptr_EMACRegs->TX0CP;
+ for( index=0; index<8; index++ ) {
+ tmpval = *pRegAddr;
+ *pRegAddr++ = tmpval;
+ }
+
+ pRegAddr = &ptr_EMACRegs->RX0CP;
+ for( index=0; index<8; index++ ) {
+ tmpval = *pRegAddr;
+ *pRegAddr++ = tmpval;
+ }
+
+
+ /* Initialize the RAM locations */
+ for (index = 0; index < 32; index++)
+ {
+ ptr_EMACRegs->MACINDEX = index;
+ ptr_EMACRegs->MACADDRHI = 0;
+ ptr_EMACRegs->MACADDRLO = 0;
+ }
+
+ /* Setup device MAC address */
+ ptr_EMACRegs->MACINDEX = 0x0;
+
+ /* Configure the MAC Address into the EMAC Controller. */
+ tmpval = 0;
+ for( index=3; index>=0; index-- )
+ tmpval = (tmpval<<8) | *(ptr_device->mac_address+index);
+ ptr_EMACRegs->MACADDRHI = tmpval;
+ tmpval = *(ptr_device->mac_address+5);
+ ptr_EMACRegs->MACADDRLO = CPMAC_MACADDRLO_VALID | CPMAC_MACADDRLO_MATCHFILT |
+ (tmpval<<8) | *(ptr_device->mac_address+4);
+
+ /* For us buffer offset will always be zero */
+ ptr_EMACRegs->RXBUFFEROFFSET = 0;
+
+ /* Reset RX (M)ulticast (B)roadcast (P)romiscuous Enable register */
+ ptr_EMACRegs->RXMBPENABLE = 0;
+ ptr_EMACRegs->MACHASH1 = 0;
+ ptr_EMACRegs->MACHASH2 = 0;
+
+ /* Clear Unicast RX on channel 0-7 */
+ ptr_EMACRegs->RXUNICASTCLEAR = 0xFF;
+
+ /* Make sure there are none of the interrupts are enabled. */
+ ptr_EMACRegs->RXINTMASKCLEAR = 0xFF;
+ ptr_EMACRegs->TXINTMASKCLEAR = 0xFF;
+ ptr_EMACRegs->MACINTMASKCLEAR = 0x0;
+
+ /* Initialize the receive buffer descriptor. */
+ pDesc->pNext = 0;
+ pDesc->pBuffer = (Uint8 *)deviceLocalAddrToGlobal((Uint32)&emacMCB.rx_buffer[0]);
+ pDesc->BufOffLen = NET_MAX_MTU;
+ pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
+
+ /* Store this buffer descriptor in the global EMAC MCB */
+ emacMCB.rx_bd = pDesc;
+
+ /* Get the transmit buffer descriptor; it comes right after the receive BD. */
+ pDesc = pDesc + 1;
+
+ /* Initialize the transmit buffer descriptor. */
+ pDesc->pNext = 0;
+ pDesc->pBuffer = 0;
+ pDesc->BufOffLen = 0;
+ pDesc->PktFlgLen = 0;
+
+ /* Store this buffer descriptor in the global EMAC MCB */
+ emacMCB.tx_bd = pDesc;
+
+#ifdef EMAC_CACHE_SUPPORT
+ /* Writeback the EMAC MCB Information to the PHYSICAL Memory.
+ * This is required because the buffer in the cache will always be
+ * invalidated on the RECEIVE; if the buffer is not aligned on the
+ * CACHE Line then it will result in the RX & TX BD in the structure
+ * to also get invalidated to what resides in the PHYSICAL memory.
+ * But if we have written back the structure here then the PHYSICAL
+ * and CACHE are one and the same as far as the BD's are concerned. */
+ Cache_wbL2((void *)&emacMCB, sizeof(emacMCB));
+#endif
+
+ /* Enable the receive and transmit. */
+ ptr_EMACRegs->TXCONTROL = 0x1;
+ ptr_EMACRegs->RXCONTROL = 0x1;
+
+ /* Initialize the MAC Control: We set the Receive Ownership Bit and the Receive
+ * Offset Length Word and enable the MII. */
+ ptr_EMACRegs->MACCONTROL = CPMAC_MACCONTROL_RXOWNERSHIP |
+ CPMAC_MACCONTROL_RXOFFLENBLOCK |
+ CPMAC_MACCONTROL_MIIEN;
+
+ /* Startup RX */
+ ptr_EMACRegs->RX0HDP = (Uint32)emacMCB.rx_bd;
+ emacMCB.lastRxHdp = (Uint32)emacMCB.rx_bd;
+
+ /* Enable receive filters for channel 1 and all broadcast packets. */
+ ptr_EMACRegs->RXUNICASTSET = 1;
+ ptr_EMACRegs->RXMBPENABLE = CPMAC_RXMBPENABLE_RXBROADEN;
+
+ /* Initialize the Device MDIO layer: The function returns only when
+ * the LINK is UP and RUNNING. */
+ if (dev_mdio_open () < 0)
+ return -1;
+
+ /* Debug Message: */
+ mprintf ("DEBUG: Ethernet Link is UP \n");
+
+ /* Hardware is up and running. */
+ return 0;
+}
+
+/**
+ * @b Description
+ * @n
+ * This is the Network Send API which is registered with the NET boot module
+ * to send out packets.
+ *
+ * @param[in] ptr_device
+ * Pointer to the network interface descriptor object.
+ * @param[in] buffer
+ * Pointer to the packet which is to be transmitted.
+ * @param[in] num_bytes
+ * Length of the packet which is transmitted.
+ *
+ * @retval
+ * Success - Number of bytes transmitted.
+ * @retval
+ * Error - <0
+ */
+Int32 cpmac_drv_send (NET_DRV_DEVICE* ptr_device, Uint8* buffer, int num_bytes)
+{
+ volatile EMAC_Desc* pDesc;
+ CPMAC_REGS* ptr_EMACRegs;
+
+ if (ptr_device->port_num >= TARGET_EMAC_N_PORTS)
+ return (-1);
+
+ ptr_EMACRegs = (CPMAC_REGS *)(aptr_EMACRegs[ptr_device->port_num]);
+
+ /* Ensure the minimum ethernet size is sent out. */
+ if (num_bytes < 64)
+ num_bytes = 64;
+
+#ifdef EMAC_CACHE_SUPPORT
+ /* Clean the cache for external addesses */
+ Cache_wbL2((void *)buffer, num_bytes);
+#endif
+
+ /* Get the pointer to the transmit buffer descriptor. */
+ pDesc = emacMCB.tx_bd;
+
+ /* Fill out the transmit buffer descriptor */
+ pDesc->pNext = 0;
+ pDesc->pBuffer = (Uint8 *)deviceLocalAddrToGlobal((Uint32)buffer);
+ pDesc->BufOffLen = num_bytes;
+ pDesc->PktFlgLen = EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_EOP | num_bytes | EMAC_DSC_FLAG_OWNER;
+
+ /* Send the packet out. */
+ ptr_EMACRegs->TX0HDP = (Uint32)pDesc;
+
+ /* Loop around till the transmission is complete. */
+ do {
+ pDesc = (EMAC_Desc *)ptr_EMACRegs->TX0CP;
+ } while (pDesc->PktFlgLen & EMAC_DSC_FLAG_OWNER);
+
+ /* The packet has been successfully transmitted. */
+ return num_bytes;
+}
+
+/**
+ * @b Description
+ * @n
+ * This is the Network Receive API which is registered with the NET boot module
+ * to receive packets.
+ *
+ * @param[in] ptr_device
+ * Pointer to the network interface descriptor object.
+ * @param[out] buffer
+ * Pointer to the packet which is populated with the received data
+ *
+ * @retval
+ * Success - Number of bytes received.
+ * @retval
+ * Error - <0
+ */
+Int32 cpmac_drv_receive (NET_DRV_DEVICE* ptr_device, Uint8* buffer)
+{
+ Int32 bytes_received = 0;
+ Uint32 rxhdp;
+ EMAC_Desc* pDesc;
+ CPMAC_REGS* ptr_EMACRegs;
+
+ if (ptr_device->port_num >= TARGET_EMAC_N_PORTS)
+ return (-1);
+
+ ptr_EMACRegs = (CPMAC_REGS *)(aptr_EMACRegs[ptr_device->port_num]);
+
+ /* Initialize the number of bytes received. */
+ bytes_received = 0;
+
+
+ /* Make sure the header pointer has advanced. */
+ rxhdp = (Uint32)ptr_EMACRegs->RX0HDP;
+ if (rxhdp == emacMCB.lastRxHdp)
+ return (0);
+
+ /* Read the completion register. We know for sure if the SOP flag is set then
+ * a packet has been received and needs to be picked up from the controller. */
+ pDesc = (EMAC_Desc *)ptr_EMACRegs->RX0CP;
+ if (pDesc->PktFlgLen & EMAC_DSC_FLAG_SOP)
+ {
+ /* Acknowledge that the descriptor has been processed. */
+ ptr_EMACRegs->RX0CP = (Uint32)pDesc;
+
+#ifdef EMAC_CACHE_SUPPORT
+ /* External Memory Support: Invalidate the cache. */
+ Cache_invL2((void *)(pDesc->pBuffer), NET_MAX_MTU);
+#endif
+ /* Remember the number of bytes received. */
+ bytes_received = (pDesc->PktFlgLen & 0xFFFF);
+
+ /* The descriptor is now free to receive more data. Set the status accordingly. */
+ pDesc->BufOffLen = NET_MAX_MTU;
+ pDesc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
+
+ /* Copy the data from the descriptor buffer to the supplied buffer. */
+ memcpy((void *)buffer, (void *)pDesc->pBuffer, bytes_received);
+
+ /* Put this descriptor back to the HDP. */
+ ptr_EMACRegs->RX0HDP = (Uint32)pDesc;
+ }
+
+ /* Return the number of bytes received. */
+ return bytes_received;
+}
+
+/**
+ * @b Description
+ * @n
+ * This is the Network Close API which is registered with the NET boot module
+ * to close and shutdown the Ethernet controller.
+ *
+ * @param[in] ptr_device
+ * Pointer to the network interface descriptor object.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 cpmac_drv_stop (NET_DRV_DEVICE* ptr_device)
+{
+ return 0;
+}
+
+
+#endif /* TARGET_DEVICE_CPMAC */
diff --git a/src/hw/macs/cpmac/cpmacdrv.orig.c b/src/hw/macs/cpmac/cpmacdrv.orig.c
--- /dev/null
@@ -0,0 +1,392 @@
+/**
+ * @file cpmacdrv.c
+ *
+ * @brief
+ * The driver is written for the CPMAC Ethernet controller. It follows
+ * the Network Boot Module Ethernet Driver Specifications.
+ *
+ * If there are modifications to this driver required for it to work
+ * on the specific device then device authors are recommended to
+ * create a copy of this file in the RBL directory and do the
+ * necessary modifications. Please pass on the appropriate information
+ * to the ROM Boot Loader Framework Development Team.
+ *
+ * \par
+ * NOTE:
+ * (C) Copyright 2008, Texas Instruments, Inc.
+ * \par
+ */
+#include "types.h"
+#include "iblloc.h"
+#include "device.h"
+#include "net.h"
+#include "cpmac_regs.h"
+#include <string.h>
+
+
+/**********************************************************************
+ ************************** Local Definitions *************************
+ **********************************************************************/
+
+// Packet Flags for TX and RX
+#define EMAC_DSC_FLAG_SOP 0x80000000u
+#define EMAC_DSC_FLAG_EOP 0x40000000u
+#define EMAC_DSC_FLAG_OWNER 0x20000000u
+#define EMAC_DSC_FLAG_EOQ 0x10000000u
+#define EMAC_DSC_FLAG_TDOWNCMPLT 0x08000000u
+#define EMAC_DSC_FLAG_PASSCRC 0x04000000u
+
+// The following flags are RX only
+#define EMAC_DSC_FLAG_JABBER 0x02000000u
+#define EMAC_DSC_FLAG_OVERSIZE 0x01000000u
+#define EMAC_DSC_FLAG_FRAGMENT 0x00800000u
+#define EMAC_DSC_FLAG_UNDERSIZED 0x00400000u
+#define EMAC_DSC_FLAG_CONTROL 0x00200000u
+#define EMAC_DSC_FLAG_OVERRUN 0x00100000u
+#define EMAC_DSC_FLAG_CODEERROR 0x00080000u
+#define EMAC_DSC_FLAG_ALIGNERROR 0x00040000u
+#define EMAC_DSC_FLAG_CRCERROR 0x00020000u
+#define EMAC_DSC_FLAG_NOMATCH 0x00010000u
+
+/**********************************************************************
+ ************************** Local Structures **************************
+ **********************************************************************/
+
+/**
+ * @brief
+ * The structure describes the EMAC Descriptor.
+ *
+ * @details
+ * Ethernet drivers receives and transmits data through the descriptor
+ * object described here.
+ */
+typedef struct _EMAC_Desc
+{
+ /**
+ * @brief Pointer to next descriptor in chain
+ */
+ struct _EMAC_Desc* pNext;
+
+ /**
+ * @brief Pointer to the data buffer.
+ */
+ Uint8* pBuffer;
+
+ /**
+ * @brief Buffer Offset(MSW) and Length(LSW)
+ */
+ Uint32 BufOffLen;
+
+ /**
+ * @brief Packet Flags(MSW) and Length(LSW)
+ */
+ volatile Uint32 PktFlgLen;
+}EMAC_Desc;
+
+/**
+ * @brief
+ * The structure describes the EMAC Master Control Block.
+ *
+ * @details
+ * The structure stores information required by the EMAC Driver;
+ * which includes the Receive and Transmit Buffer Descriptors.
+ */
+typedef struct EMAC_MCB
+{
+ /**
+ * @brief Pointer to the Receive Buffer Descriptor
+ */
+ EMAC_Desc* rx_bd;
+
+ /**
+ * @brief Pointer to the Transmit Buffer Descriptor
+ */
+ EMAC_Desc* tx_bd;
+
+ /**
+ * @brief Buffer for receiving data linked with the receive
+ * buffer descriptor.
+ */
+ Uint8 rx_buffer[NET_MAX_MTU];
+}EMAC_MCB;
+
+/**********************************************************************
+ ************************** Global Variables **************************
+ **********************************************************************/
+
+/**
+ * @brief Global Driver structure which keeps track of all the Ethernet
+ * Driver related information.
+ */
+EMAC_MCB emacMCB;
+
+/**
+ * @brief EMAC Registers.
+ */
+CPMAC_REGS* ptr_EMACRegs = (CPMAC_REGS *)EMAC_BASE_ADDRESS;
+
+/**********************************************************************
+ ************************** ETHDRV Functions **************************
+ **********************************************************************/
+
+/**
+ * @b Description
+ * @n
+ * This is the Network Open API which is registered with the
+ * NET Boot module to initialize the Ethernet device.
+ *
+ * @param[in] ptr_device
+ * Pointer to the NET Device structure which is being opened.
+ *
+ * @retval
+ * Success - 0
+ * @retval
+ * Error - <0
+ */
+Int32 cpmac_drv_start (NET_DRV_DEVICE* ptr_device)
+{
+ Uint32 tmpval;
+ volatile Uint32* pRegAddr;
+ Int32 index;
+ EMAC_Desc* pDesc;
+
+ /* Reset EMAC */
+ ptr_EMACRegs->SOFTRESET = 0x1;
+ while (ptr_EMACRegs->SOFTRESET != 0x0);
+
+ /* Reset MAC Control */
+ ptr_EMACRegs->MACCONTROL = 0;
+
+ /* Must manually init HDPs to NULL */
+ pRegAddr = &ptr_EMACRegs->TX0HDP;
+ for( index=0; index<8; index++ )
+ *pRegAddr++ = 0;
+ pRegAddr = &ptr_EMACRegs->RX0HDP;
+ for( index=0; index<8; index++ )
+ *pRegAddr++ = 0;
+
+ /* Initialize the RAM locations */
+ for (index = 0; index < 32; index++)
+ {
+ ptr_EMACRegs->MACINDEX = index;
+ ptr_EMACRegs->MACADDRHI = 0;
+ ptr_EMACRegs->MACADDRLO = 0;
+ }
+
+ /* Setup device MAC address */
+ ptr_EMACRegs->MACINDEX = 0x0;
+
+ /* Configure the MAC Address into the EMAC Controller. */
+ tmpval = 0;
+ for( index=3; index>=0; index-- )
+ tmpval = (tmpval<<8) | *(ptr_device->mac_address+index);
+ ptr_EMACRegs->MACADDRHI = tmpval;