Version 0.4 from Mike Line
authorBill Mills <wmills@ti.com>
Tue, 14 Sep 2010 22:02:49 +0000 (18:02 -0400)
committerBill 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:
.gitignore
src/arch/c64x/types.h [new file with mode: 0644]
src/cfg/c6455/iblcfg.h [new file with mode: 0644]
src/cfg/c6472/iblcfg.h [new file with mode: 0644]
src/device/c6455/c6455.c [new file with mode: 0644]
src/device/c6455/target.h [new file with mode: 0644]
src/device/c6472/c6472.c [new file with mode: 0644]
src/device/c6472/target.h [new file with mode: 0644]
src/device/c64x/make/makefile [new file with mode: 0644]
src/device/device.h [new file with mode: 0644]
src/driver/c64x/make/makefile [new file with mode: 0644]
src/driver/eth/arp.c [new file with mode: 0644]
src/driver/eth/arp.pretimer.c [new file with mode: 0644]
src/driver/eth/arp.timer.c [new file with mode: 0644]
src/driver/eth/bootp.c [new file with mode: 0644]
src/driver/eth/icmp.c [new file with mode: 0644]
src/driver/eth/ip.c [new file with mode: 0644]
src/driver/eth/net.c [new file with mode: 0644]
src/driver/eth/net.h [new file with mode: 0644]
src/driver/eth/net_orig.c [new file with mode: 0644]
src/driver/eth/netif.h [new file with mode: 0644]
src/driver/eth/tftp.c [new file with mode: 0644]
src/driver/eth/udp.c [new file with mode: 0644]
src/driver/nand/nand.c [new file with mode: 0644]
src/driver/nand/nand.h [new file with mode: 0644]
src/driver/nand/nflashlay.h.old [new file with mode: 0644]
src/driver/stream/stream.c [new file with mode: 0644]
src/driver/stream/stream.h [new file with mode: 0644]
src/driver/stream/stream_orig.c [new file with mode: 0644]
src/driver/timer/timer.c [new file with mode: 0644]
src/driver/timer/timer.h [new file with mode: 0644]
src/ecc/3byte/3byte_ecc.c [new file with mode: 0644]
src/ecc/c64x/make/makefile [new file with mode: 0644]
src/ecc/ecc.h [new file with mode: 0644]
src/ethboot/c64x/make/makefile [new file with mode: 0644]
src/ethboot/ethboot.c [new file with mode: 0644]
src/ethboot/ethboot.h [new file with mode: 0644]
src/hw/c64x/make/makefile [new file with mode: 0644]
src/hw/ddrs/emif31/emif31.c [new file with mode: 0644]
src/hw/ddrs/emif31/emif31api.h [new file with mode: 0644]
src/hw/ddrs/emif31/emif31loc.h [new file with mode: 0644]
src/hw/gpio/gpio.c [new file with mode: 0644]
src/hw/gpio/gpio.h [new file with mode: 0644]
src/hw/i2c/i2c.c [new file with mode: 0644]
src/hw/i2c/i2c.h [new file with mode: 0644]
src/hw/i2c/i2cloc.h [new file with mode: 0644]
src/hw/macs/cpmac/cpmac_regs.h [new file with mode: 0644]
src/hw/macs/cpmac/cpmacdrv.c [new file with mode: 0644]
src/hw/macs/cpmac/cpmacdrv.orig.c [new file with mode: 0644]
src/hw/macs/cpmacdrv.h [new file with mode: 0644]
src/hw/mdio/mdio.c [new file with mode: 0644]
src/hw/mdio/mdio.h [new file with mode: 0644]
src/hw/mdio/mdioapi.h [new file with mode: 0644]
src/hw/nands/gpio/nandgpio.c [new file with mode: 0644]
src/hw/nands/nandhwapi.h [new file with mode: 0644]
src/hw/plls/pllapi.h [new file with mode: 0644]
src/hw/plls/pllxx1p8/pll.c [new file with mode: 0644]
src/hw/plls/pllxx1p8/pllloc.h [new file with mode: 0644]
src/hw/pscs/psc2/psc.c [new file with mode: 0644]
src/hw/pscs/psc2/pscloc.h [new file with mode: 0644]
src/hw/pscs/pscapi.h [new file with mode: 0644]
src/hw/timer/devtimer.h [new file with mode: 0644]
src/hw/timer/timer64/t64.c [new file with mode: 0644]
src/hw/timer/timer64/t64hw.h [new file with mode: 0644]
src/ibl.h [new file with mode: 0644]
src/iblloc.h [new file with mode: 0644]
src/interp/bis/bis.c [new file with mode: 0644]
src/interp/bis/bis.h [new file with mode: 0644]
src/interp/blob/blob.c [new file with mode: 0644]
src/interp/blob/iblblob.h [new file with mode: 0644]
src/interp/btbl/btbl.h [new file with mode: 0644]
src/interp/btbl/btblloc.h [new file with mode: 0644]
src/interp/btbl/btblpr.c [new file with mode: 0644]
src/interp/btbl/btblwrap.c [new file with mode: 0644]
src/interp/btbl/btblwrap.h [new file with mode: 0644]
src/interp/btbl/gem.c [new file with mode: 0644]
src/interp/btbl/iblbtbl.h [new file with mode: 0644]
src/interp/c64x/make/makefile [new file with mode: 0644]
src/interp/coff/cload.c [new file with mode: 0644]
src/interp/coff/cload.h [new file with mode: 0644]
src/interp/coff/cload.mike.c [new file with mode: 0644]
src/interp/coff/cload.mike.h [new file with mode: 0644]
src/interp/coff/cload_main.c [new file with mode: 0644]
src/interp/coff/coff.h [new file with mode: 0644]
src/interp/coff/coff.mike.h [new file with mode: 0644]
src/interp/coff/coff_trg.h [new file with mode: 0644]
src/interp/coff/coff_trg.mike.h [new file with mode: 0644]
src/interp/coff/coffdefs.h [new file with mode: 0644]
src/interp/coff/coffdefs.mike.h [new file with mode: 0644]
src/interp/coff/coffwrap.h [new file with mode: 0644]
src/interp/coff/header.h [new file with mode: 0644]
src/interp/coff/osal.c [new file with mode: 0644]
src/interp/coff/osal.h [new file with mode: 0644]
src/interp/coff/params.h [new file with mode: 0644]
src/interp/coff/proto.h [new file with mode: 0644]
src/interp/coff/version.h [new file with mode: 0644]
src/main/c64x/make/makefile [new file with mode: 0644]
src/main/iblmain.c [new file with mode: 0644]
src/make/Makefile [new file with mode: 0644]
src/make/c64x/bootinc.mk [new file with mode: 0644]
src/make/c64x/makedefs.mk [new file with mode: 0644]
src/make/c64x/makeeco.mk [new file with mode: 0644]
src/make/cpytools/cpytools.pl [new file with mode: 0644]
src/make/ibl_c6455/ibl.cmd [new file with mode: 0644]
src/make/ibl_c6455/ibl_c6455.out.ept [new file with mode: 0644]
src/make/ibl_c6472/i2crom.dat [new file with mode: 0644]
src/make/ibl_c6472/ibl.cmd [new file with mode: 0644]
src/make/ibl_c6472/ibl.rmd [new file with mode: 0644]
src/make/makedep/makedep.awk [new file with mode: 0644]
src/make/makestg2 [new file with mode: 0644]
src/mkdeppath.bat [new file with mode: 0644]
src/nandboot/c64x/make/makefile [new file with mode: 0644]
src/nandboot/nandboot.c [new file with mode: 0644]
src/setupenv.bat [new file with mode: 0644]
src/test/test1/makefile [new file with mode: 0644]
src/test/test1/test1.btbl [new file with mode: 0644]
src/test/test1/test1.btbl.bin [new file with mode: 0644]
src/test/test1/test1.c [new file with mode: 0644]
src/test/test1/test1.cmd [new file with mode: 0644]
src/test/test2/c0.c [new file with mode: 0644]
src/test/test2/makefile [new file with mode: 0644]
src/test/test2/makestage2 [new file with mode: 0644]
src/test/test2/test.blob [new file with mode: 0644]
src/test/test2/test2.c [new file with mode: 0644]
src/test/test2/test2.cmd [new file with mode: 0644]
src/test/test2/test2.rmd [new file with mode: 0644]
src/test/test2/test2_little.bccs [new file with mode: 0644]
src/test/test2/test2_little.blob [new file with mode: 0644]
src/test/test2/test2im.hex [new file with mode: 0644]
src/test/test2/test2ini.s [new file with mode: 0644]
src/util/btoccs/Makefile [new file with mode: 0644]
src/util/btoccs/b2ccs.c [new file with mode: 0644]
src/util/btoccs/b2ccs_nb.c [new file with mode: 0644]
src/util/btoccs/b2i2c.c [new file with mode: 0644]
src/util/btoccs/bfaddsect.c [new file with mode: 0644]
src/util/btoccs/bfmerge.c [new file with mode: 0644]
src/util/btoccs/ccs2b.c [new file with mode: 0644]
src/util/i2cConfig/Makefile [new file with mode: 0644]
src/util/i2cConfig/i2cparam.c [new file with mode: 0644]
src/util/i2cConfig/i2cparam_c6472.cmd [new file with mode: 0644]
src/util/i2cConfig/makestg2 [new file with mode: 0644]
src/util/nandwriter/nandwriter.c [new file with mode: 0644]
src/util/romparse_c6472/Makefile [new file with mode: 0644]
src/util/romparse_c6472/bison.simple [new file with mode: 0644]
src/util/romparse_c6472/romparse.c [new file with mode: 0644]
src/util/romparse_c6472/romparse.h [new file with mode: 0644]
src/util/romparse_c6472/rparse.flex [new file with mode: 0644]
src/util/romparse_c6472/rparse.tab.c [new file with mode: 0644]
src/util/romparse_c6472/rparse.tab.h [new file with mode: 0644]
src/util/romparse_c6472/rparse.y [new file with mode: 0644]
src/util/romparse_c6472/tiboot.h [new file with mode: 0644]
src/util/romparse_c6472/types.h [new file with mode: 0644]

index 7d18c5e5a219cd60c72af2176818a214ba9bcd03..4d3f8bd8e5a228732c24ae8d9fcde67268e908a8 100644 (file)
@@ -19,5 +19,3 @@ cdefdep
 junk/
 logs/
 hacky-stuff/cgtools
-
-
diff --git a/src/arch/c64x/types.h b/src/arch/c64x/types.h
new file mode 100644 (file)
index 0000000..f9215f2
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..d1ffa60
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..7580315
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..c178869
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..f9174c1
--- /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
new file mode 100644 (file)
index 0000000..2b44a7e
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..bf00acf
--- /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
new file mode 100644 (file)
index 0000000..cc437e8
--- /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
new file mode 100644 (file)
index 0000000..a58a472
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..b2f6d40
--- /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
new file mode 100644 (file)
index 0000000..e299440
--- /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.pretimer.c b/src/driver/eth/arp.pretimer.c
new file mode 100644 (file)
index 0000000..e299440
--- /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
new file mode 100644 (file)
index 0000000..e8e3169
--- /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
new file mode 100644 (file)
index 0000000..6a360f0
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..f3144ec
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..86c2519
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..858713b
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..28e1e12
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..2efcbea
--- /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
new file mode 100644 (file)
index 0000000..8ba0cc5
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..2d7c526
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..7283d2c
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..5a119b6
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..16ccdc1
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..66cb208
--- /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
new file mode 100644 (file)
index 0000000..26a1c27
--- /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
new file mode 100644 (file)
index 0000000..4cdc8ca
--- /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
new file mode 100644 (file)
index 0000000..0d847ef
--- /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
new file mode 100644 (file)
index 0000000..51b3e4b
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..0c3bf03
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..011c08a
--- /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
new file mode 100644 (file)
index 0000000..8d63671
--- /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
new file mode 100644 (file)
index 0000000..063d3e0
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..1f6e964
--- /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
new file mode 100644 (file)
index 0000000..07b8c3c
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..5236736
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..67ff7f8
--- /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
new file mode 100644 (file)
index 0000000..d21ed88
--- /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
new file mode 100644 (file)
index 0000000..c2e2223
--- /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
new file mode 100644 (file)
index 0000000..12b8cc2
--- /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
new file mode 100644 (file)
index 0000000..3f5be16
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..34f473c
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..319bd02
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..69c0008
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..89a6559
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..fe31b0f
--- /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
new file mode 100644 (file)
index 0000000..939d9cb
--- /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
new file mode 100644 (file)
index 0000000..00d15eb
--- /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;