diff options
| -rw-r--r-- | CHANGELOG | 8 | ||||
| -rw-r--r-- | cpu/mpc5xxx/fec.c | 108 | ||||
| -rw-r--r-- | doc/README.standalone | 198 | ||||
| -rw-r--r-- | examples/stubs.c | 4 | ||||
| -rw-r--r-- | examples/x86-testapp.c | 87 | ||||
| -rw-r--r-- | include/configs/IceCube.h | 5 | ||||
| -rw-r--r-- | include/exports.h | 4 | ||||
| -rw-r--r-- | include/net.h | 8 | ||||
| -rw-r--r-- | lib_arm/armlinux.c | 2 | ||||
| -rw-r--r-- | lib_generic/crc32.c | 1 | 
10 files changed, 237 insertions, 188 deletions
| @@ -2,6 +2,14 @@  Changes for U-Boot 0.4.5:  ====================================================================== +* Allow crc32 to be used at address 0x000 + +* Provide consistent interface to standalone applications to access +  the 'global_data' structure +  Provide a doc/README.standalone more useful to users/developers. + +* Make IceCube MGT5100 FEC driver work +  * Implement new mechanism to export U-Boot's functions to standalone    applications: instead of using (PPC-specific) system calls we now    use a jump table; please see doc/README.standalone for details diff --git a/cpu/mpc5xxx/fec.c b/cpu/mpc5xxx/fec.c index b8e2560cf..16ca0a9d2 100644 --- a/cpu/mpc5xxx/fec.c +++ b/cpu/mpc5xxx/fec.c @@ -14,7 +14,7 @@  #include "sdma.h"  #include "fec.h" -#define DEBUG	0x8 +/* #define DEBUG	0x28 */  #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \  	defined(CONFIG_MPC5XXX_FEC) @@ -28,25 +28,33 @@ static void rfifo_print(mpc5xxx_fec_priv *fec);  static uint32 local_crc32(char *string, unsigned int crc_value, int len);  #endif +typedef struct { +    uint8 data[1500];           /* actual data */ +    int length;                 /* actual length */ +    int used;                   /* buffer in use or not */ +    uint8 head[16];             /* MAC header(6 + 6 + 2) + 2(aligned) */ +} NBUF; +  /********************************************************************/  static int mpc5xxx_fec_rbd_init(mpc5xxx_fec_priv *fec)  {  	int ix;  	char *data; +	static int once = 0; -	/* -	 * the receive ring is located right after the transmit one -	 */  	for (ix = 0; ix < FEC_RBD_NUM; ix++) { -		data = (char *)malloc(FEC_MAX_PKT_SIZE); -		if (data == NULL) { -			printf ("RBD INIT FAILED\n"); -			return -1; +		if (!once) { +			data = (char *)malloc(FEC_MAX_PKT_SIZE); +			if (data == NULL) { +				printf ("RBD INIT FAILED\n"); +				return -1; +			} +			fec->rbdBase[ix].dataPointer = (uint32)data;  		}  		fec->rbdBase[ix].status = FEC_RBD_EMPTY;  		fec->rbdBase[ix].dataLength = 0; -		fec->rbdBase[ix].dataPointer = (uint32)data;  	} +	once ++;  	/*  	 * have the last RBD to close the ring @@ -336,11 +344,6 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)  	SDMA_CLEAR_IEVENT(FEC_RECV_TASK_NO);  	/* -	 * Set SmartDMA intMask register to enable SmartDMA task interrupts -	 */ -	SDMA_INT_ENABLE(FEC_RECV_TASK_NO); - -	/*  	 * Initialize SmartDMA parameters stored in SRAM  	 */  	*(int *)FEC_TBD_BASE = (int)fec->tbdBase; @@ -494,8 +497,10 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)  /********************************************************************/  static void mpc5xxx_fec_halt(struct eth_device *dev)  { -	mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv; +#if defined(CONFIG_MPC5200)  	struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA; +#endif +	mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;  	int counter = 0xffff;  #if (DEBUG & 0x2) @@ -530,8 +535,6 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)  	 */  	while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ; -	SDMA_INT_DISABLE (FEC_RECV_TASK_NO); -  	/*  	 * Disable SmartDMA tasks  	 */ @@ -671,7 +674,7 @@ static int mpc5xxx_fec_send(struct eth_device *dev, volatile void *eth_data,  	pTbd = &fec->tbdBase[fec->tbdIndex];  	pTbd->dataLength = data_length;  	pTbd->dataPointer = (uint32)eth_data; -	pTbd->status |= FEC_TBD_READY; +	pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;  	fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;  #if (DEBUG & 0x100) @@ -729,8 +732,9 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)  	mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;  	FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];  	unsigned long ievent; -	int frame_length; -	char *frame; +	int frame_length, len = 0; +	NBUF *frame; +	char buff[FEC_MAX_PKT_SIZE];  #if (DEBUG & 0x1)  	printf ("mpc5xxx_fec_recv %d Start...\n", fec->rbdIndex); @@ -763,41 +767,40 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)  		}  	} -	/* -	 * Do we have data in Rx FIFO? -	 */ -	if ((pRbd->status & FEC_RBD_EMPTY) || !(pRbd->status & FEC_RBD_LAST)){ -		return 0; -	} +	if (!(pRbd->status & FEC_RBD_EMPTY)) { +		if ((pRbd->status & FEC_RBD_LAST) && !(pRbd->status & FEC_RBD_ERR) && +			((pRbd->dataLength - 4) > 14)) { -	/* -	 * Pass the packet up only if reception was Ok -	 */ -	if ((pRbd->dataLength <= 14) || (pRbd->status & FEC_RBD_ERR)) { -		mpc5xxx_fec_rbd_clean(fec, pRbd); -#if (DEBUG & 0x8) -		printf( "X0" ); +			/* +			 * Get buffer address and size +			 */ +			frame = (NBUF *)pRbd->dataPointer; +			frame_length = pRbd->dataLength - 4; + +#if (DEBUG & 0x20) +			{ +				int i; +				printf("recv data hdr:"); +				for (i = 0; i < 14; i++) +					printf("%x ", *(frame->head + i)); +				printf("\n"); +			}  #endif -		return 0; +			/* +			 *  Fill the buffer and pass it to upper layers +			 */ +			memcpy(buff, frame->head, 14); +			memcpy(buff + 14, frame->data, frame_length); +			NetReceive(buff, frame_length); +			len = frame_length; +		} +		/* +		 * Reset buffer descriptor as empty +		 */ +		mpc5xxx_fec_rbd_clean(fec, pRbd);  	} - -	/* -	 * Get buffer address and size -	 */ -	frame = (char *)pRbd->dataPointer; -	frame_length = pRbd->dataLength; - -	/* -	 * Pass the buffer to upper layers -	 */ -	NetReceive(frame, frame_length); - -	/* -	 * Reset buffer descriptor as empty -	 */ -	mpc5xxx_fec_rbd_clean(fec, pRbd); - -	return frame_length; +	SDMA_CLEAR_IEVENT (FEC_RECV_TASK_NO); +	return len;  } @@ -824,6 +827,7 @@ int mpc5xxx_fec_initialize(bd_t * bis)  	dev->send = mpc5xxx_fec_send;  	dev->recv = mpc5xxx_fec_recv; +	sprintf(dev->name, "FEC ETHERNET");  	eth_register(dev);  	return 1; diff --git a/doc/README.standalone b/doc/README.standalone index a5992ab87..39988317e 100644 --- a/doc/README.standalone +++ b/doc/README.standalone @@ -1,156 +1,96 @@  Design Notes on Exporting U-Boot Functions to Standalone Applications:  ====================================================================== -1. Add a field to the global_data structure, the pointer to a jump -   table. +1. The functions are exported by U-Boot via a jump table. The jump +   table is allocated and initialized in the jumptable_init() routine +   (common/exports.c). Other routines may also modify the jump table, +   however. The jump table can be accessed as the 'jt' field of the +   'global_data' structure. The slot numbers for the jump table are +   defined in the <include/exports.h> header. E.g., to substitute the +   malloc() and free() functions that will be available to standalone +   applications, one should do the following: -2. Jump table itself is allocated and filled in the same way as the -   syscall table is (allocated with malloc() after the code has been -   relocated to RAM); a special function, fixed to the table element -   number 0, will be added which returns the ABI version so -   applications can check for compatibility issues. +	DECLARE_GLOBAL_DATA_PTR; -3. It is application's responsibility to check the ABI version and -   act accordingly. +	gd->jt[XF_malloc]	= my_malloc; +	gd->jt[XF_free]		= my_free; -4. Pointer to the global_data is passed to the application in the -   dedicated register that is used in the U-Boot to hold this -   pointer. This assumes that the application is built with the same -   register- allocation flags as the U-Boot itself. (Actually, this -   is a requirement even now, as the 'go' command does not perform -   any actions to protect this register against being clobbered by -   the application). +   Note that the pointers to the functions all have 'void *' type and +   thus the compiler cannot perform type checks on these assignments. -   This approach won't work on the x86 architecture. See below. +2. The pointer to the jump table is passed to the application in a +   machine-dependent way. PowerPC, ARM and MIPS architectures use a +   dedicated register to hold the pointer to the 'global_data' +   structure: r29 on PowerPC, r8 on ARM and k0 on MIPS. The x86 +   architecture does not use such a register; instead, the pointer to +   the 'global_data' structure is passed as 'argv[-1]' pointer. -5. Application now calls standard library functions like printf() -   instead of specially prefixed names like mon_printf() as it did -   before. Present implementation of these functions (using the -   system calls mechanism) will be replaced with jump stubs. +   The application can access the 'global_data' structure in the same +   way as U-Boot does: -6. To export additional functions, the following steps will have to be  -   taken: +	DECLARE_GLOBAL_DATA_PTR; -   - Add the xxx() U-Boot function to the EXPORT_FUNC list -   - Add initialization of the appropriate slot in the jump table +	printf("U-Boot relocation offset: %x\n", gd->reloc_off); -7. To port to a new architecture, the appropriate stub code should be -   provided. No other machine-dependent code is used. Once the stub -   template is available, no additional coding is needed when -   exporting new U-Boot functions. A pre-processor macro will be used -   to automatically instantiate the stub definition for each exported -   function. +3. The application should call the app_startup() function before any +   call to the exported functions. Also, implementor of the +   application may want to check the version of the ABI provided by +   U-Boot. To facilitate this, a get_version() function is exported +   that returns the ABI version of the running U-Boot. I.e., a +   typical application startup may look like this: -Note the following: +	int my_app (int argc, char *argv[]) +	{ +		app_startup (argv); +		if (get_version () != XF_VERSION) +			return 1; +	} -- This approach uses a jump table with fixed slot allocation. That -  said, to retain the ABI compatibility, no table reordering, -  inserting new functions in the middle of the list or deleting -  functions from the list is allowed. Any such action will break the -  ABI compatibility. +4. The default load and start addresses of the applications are as +   follows: -- The x86 architecture does not use a dedicated register to store the -  pointer to the global_data structure. There are the following -  approaches available: +		Load address	Start address +	x86	0x00040000	0x00040000 +	PowerPC	0x00040000	0x00040004 +	ARM	0x0c100000	0x0c100000 +	MIPS	0x80200000	0x80200000 -  * Pass the global_data pointer to the application in a register or -    as an additional argument. This requires special machine- -    dependent startup code to be compiled into the application. +   For example, the "hello world" application may be loaded and +   executed on a PowerPC board with the following commands: -  * Make the x86 consistent with the rest of architectures and use a -    dedicated register. This renders one register unusable in the -    rest of the U-Boot code and thus increases the size of the U-Boot -    binary and decreases it performance. - -The following changes will be made: - -- The syscall handling code will be removed. - -- The include/_exports.h file will be introduced, containing the list -  of the exported functions in the following form: - -  EXPORT_FUNC(getc) -  EXPORT_FUNC(tstc) -  ... - -  This list will be used to assign the slot numbers in the jump -  table, to determine the size of the jump table and to generate the -  code for the stub functions. - -- The include/exports.h file will be introduced, containing the -  prototypes of the exported functions and the assigned slot numbers. - -- The examples/stubs.c file will be introduced, containing the code -  for the jump stubs for each of the exported functions. - -Implementation Notes on Exporting U-Boot Functions: -=================================================== - -1. The patch was applied against TOT as of 7/24 12:50 MEST; the -   resulting images were tested on the following boards: - -   * lwmon (PowerPC) -   * trab  (ARM) -   * inca  (MIPS) - -   The hello_world application was loaded and executed then: - -   [lwmon] -   => tftp 0x40000 /tftpboot/LWMON/hello_world.bin-avn +   => tftp 0x40000 hello_world.bin     => go 0x40004 -   [trab] -   TRAB # tftp 0xc100000 /tftpboot/TRAB/hello_world.bin-avn -   TRAB # go 0xc100000 - -   [inca] -   INCA-IP # tftp 0x80200000 /tftpboot/INCA/hello_world.bin-avn -   INCA-IP # go 0x80200000 - -2. As neither of supported x86 boards can be built from the TOT -   sources currently, the patch build was verified by manually -   running the following command in the U-Boot top directory: +5. To export some additional function foobar(), the following steps +   should be undertaken: -   > make -C examples TOPDIR=`pwd` ARCH=i386 CROSS_COMPILE= +   - Append the following line at the end of the include/_exports.h +     file: -   The rest of the code is mostly machine-independent and was not -   verified. +	EXPORT_FUNC(foobar) -3. To test the x86 assembly code, a small standalone application was -   written. It was built and run on the RedHat Linux 8.0 (x86). The -   application performs a jump using a pointer to jump table and a -   function's index in it. +   - Add the prototype for this function to the include/exports.h +     file: -4. For the MIPS architecture, the linker script is also provided for -   linking applications. The default linker script places the .text -   and .data sections too far from each other so that the resulting -   .bin files span about 256Mb in size. +	void foobar(void); -5. Several example applications required updating for the new API. -   These applications relied upon the bd_t pointer being passed as -   the 1st argument to the main function; this had changed when the -   system calls were introduced, but apparently, these applications -   weren't fixed at that moment. This is fixed now. +   - Add the initialization of the jump table slot wherever +     appropriate (most likely, to the jumptable_init() function): -6. GCC issues warnings for the 'sched' application. Since now the -   mon_printf() function is renamed to printf(), GCC applies its -   knowledge of the format specifiers to check the arguments, -   complaining about ints passed as longs and vice versa. This is not -   fixed yet. +	gd->jt[XF_foobar] = foobar; -7. Only the hello_world example application was modified to make use -   of the newly supplied get_version() function. The application now -   prints two ABI versions, the one that the application was compiled -   for and the other, actual ABI version. +   - Increase the XF_VERSION value by one in the include/exports.h +     file -8. The following new files were added: -   common/exports.c -   examples/mips.lds -   examples/stubs.c -   include/_exports.h -   include/exports.h -   doc/README.standalone +6. The code for exporting the U-Boot functions to applications is +   mostly machine-independent. The only places written in assembly +   language are stub functions that perform the jump through the jump +   table. That said, to port this code to a new architecture, the +   only thing to be provided is the code in the examples/stubs.c +   file. If this architecture, however, uses some uncommon method of +   passing the 'global_data' pointer (like x86 does), one should add +   the respective code to the app_startup() function in that file. -   The following files are no longer used and will be removed: -   examples/syscall.S -   include/syscall.h +   Note that these functions may only use call-clobbered registers; +   those registers that are used to pass the function's arguments, +   the stack contents and the return address should be left intact. diff --git a/examples/stubs.c b/examples/stubs.c index c0ef65048..9c4c51b0e 100644 --- a/examples/stubs.c +++ b/examples/stubs.c @@ -9,6 +9,7 @@   * to the application program.   */  static void **jt; +gd_t *global_data;  #define EXPORT_FUNC(x) \  	asm volatile (			\ @@ -80,7 +81,8 @@ void app_startup(char **argv)  {  #if defined(CONFIG_I386)  	/* x86 does not have a dedicated register for passing global_data */ -	jt = ((gd_t *)argv[-1])->jt; +	global_data = (gd_t *)argv[-1]; +	jt = global_data->jt;  #endif  } diff --git a/examples/x86-testapp.c b/examples/x86-testapp.c new file mode 100644 index 000000000..a1ab319ae --- /dev/null +++ b/examples/x86-testapp.c @@ -0,0 +1,87 @@ +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +void *func[8], **pfunc; + +typedef struct xxx xxx_t; +struct xxx { +	int dummy; +	void **pfunc; +} q; + +#define XF_strcpy 3 +#define XF_printf 4 + +#define LABEL(x)					\ +asm volatile (						\ + +#if defined(__i386__) +#define EXPORT_FUNC(x)					\ +asm volatile (						\ +"	.globl mon_" #x "\n"				\ +"mon_" #x ":\n"						\ +"	movl	%0, %%eax\n"				\ +"	movl	pfunc, %%ecx\n"				\ +"	jmp	*(%%ecx,%%eax)\n"			\ +	: : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx"); +#elif defined(__powerpc__) +#define EXPORT_FUNC(x)					\ +asm volatile (						\ +"	.globl mon_" #x "\n"				\ +"mon_" #x ":\n"						\ +"	lwz	%%r11, %0(%%r29)\n"			\ +"	lwz	%%r11, %1(%%r11)\n"			\ +"	mtctr	%%r11\n"				\ +"	bctr\n"					\ +	: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "r11", "r29"); +#elif defined(__arm__) +#define EXPORT_FUNC(x)					\ +asm volatile (						\ +"	.globl mon_" #x "\n"				\ +"mon_" #x ":\n"						\ +"	ldr	ip, [r8, %0]\n"				\ +"	ldr	pc, [ip, %1]\n"				\ +	: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "ip"); +#elif defined(__mips__) +#define EXPORT_FUNC(x)					\ +asm volatile (						\ +"	.globl mon_" #x "\n"				\ +"mon_" #x ":\n"						\ +"	lw	$25, %0($26)\n"				\ +"	lw	$25, %1($25)\n"				\ +"	jr	$25\n"					\ +	: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "t9"); +#else +#error [No stub code for this arch] +#endif + +void dummy(void) +{ +EXPORT_FUNC(printf) +EXPORT_FUNC(strcpy) +} + +int main(void) +{ +#if defined(__i386__) +	xxx_t *pq; +#elif defined(__powerpc__) +	register volatile xxx_t *pq asm("r29"); +#elif defined(__arm__) +	register volatile xxx_t *pq asm("r8"); +#elif defined(__mips__) +	register volatile xxx_t *pq asm("k0"); +#endif +	char buf[32]; + +	func[XF_strcpy] = strcpy; +	func[XF_printf] = printf; +	pq = &q; +	pq->pfunc = pfunc = func; + +	mon_strcpy(buf, "test"); +	mon_printf("hi %s %d z\n", buf, 444); + +	return 0; +} diff --git a/include/configs/IceCube.h b/include/configs/IceCube.h index e6d735a22..2a455f892 100644 --- a/include/configs/IceCube.h +++ b/include/configs/IceCube.h @@ -52,7 +52,7 @@  /*   * Supported commands   */ -#define CONFIG_COMMANDS		(CONFIG_CMD_DFL & ~(CFG_CMD_NET)) +#define CONFIG_COMMANDS		CONFIG_CMD_DFL  /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */  #include <cmd_confdefs.h> @@ -122,10 +122,7 @@  /*   * Ethernet configuration   */ -#if 0 -#define CONFIG_NET_MULTI	1  #define CONFIG_MPC5XXX_FEC	1 -#endif  /*   * GPIO configuration diff --git a/include/exports.h b/include/exports.h index b45a46691..f812f1607 100644 --- a/include/exports.h +++ b/include/exports.h @@ -33,4 +33,8 @@ enum {  #define XF_VERSION	1 +#if defined(CONFIG_I386) +extern gd_t *global_data; +#endif +  #endif diff --git a/include/net.h b/include/net.h index b9bf133d9..dd8d37804 100644 --- a/include/net.h +++ b/include/net.h @@ -21,6 +21,14 @@  # endif  #endif	/* CONFIG_8xx */ +#if defined(CONFIG_MPC5XXX) +# if !defined(CONFIG_NET_MULTI) +#  if defined(CONFIG_MPC5XXX_FEC) +#   define CONFIG_NET_MULTI +#  endif +# endif +#endif	/* CONFIG_MPC5XXX */ +  #if !defined(CONFIG_NET_MULTI) && defined(CONFIG_8260)  #include <config.h>  #if defined(CONFIG_ETHER_ON_FCC) diff --git a/lib_arm/armlinux.c b/lib_arm/armlinux.c index 8e06bd642..68e12d330 100644 --- a/lib_arm/armlinux.c +++ b/lib_arm/armlinux.c @@ -231,7 +231,7 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],      setup_ramdisk_tag(bd);  #endif  #if defined (CONFIG_VFD) -    setup_videolfb_tag(gd); +    setup_videolfb_tag((gd_t *)gd);  #endif      setup_end_tag(bd);  #endif diff --git a/lib_generic/crc32.c b/lib_generic/crc32.c index 2de39c7db..ce18fc225 100644 --- a/lib_generic/crc32.c +++ b/lib_generic/crc32.c @@ -155,7 +155,6 @@ uLong ZEXPORT crc32(crc, buf, len)      const Bytef *buf;      uInt len;  { -    if (buf == Z_NULL) return 0L;  #ifdef DYNAMIC_CRC_TABLE      if (crc_table_empty)        make_crc_table(); |