From 7784674852c66b0924bdc79062bd208aa51fd0a9 Mon Sep 17 00:00:00 2001 From: wdenk Date: Sat, 26 Jul 2003 08:08:08 +0000 Subject: [PATCH] * 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 --- CHANGELOG | 8 ++ cpu/mpc5xxx/fec.c | 108 +++++++++--------- doc/README.standalone | 226 ++++++++++++++------------------------ examples/stubs.c | 4 +- examples/x86-testapp.c | 87 +++++++++++++++ include/configs/IceCube.h | 5 +- include/exports.h | 4 + include/net.h | 8 ++ lib_arm/armlinux.c | 2 +- lib_generic/crc32.c | 1 - 10 files changed, 251 insertions(+), 202 deletions(-) create mode 100644 examples/x86-testapp.c diff --git a/CHANGELOG b/CHANGELOG index 53fb5bbbcf..886373ef85 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 b8e2560cf7..16ca0a9d20 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 @@ -335,11 +343,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 */ @@ -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 a5992ab876..39988317ee 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. - -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. - -3. It is application's responsibility to check the ABI version and - act accordingly. - -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). - - This approach won't work on the x86 architecture. See below. - -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. - -6. To export additional functions, the following steps will have to be - taken: - - - Add the xxx() U-Boot function to the EXPORT_FUNC list - - Add initialization of the appropriate slot in the jump table - -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. - -Note the following: - -- 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. - -- The x86 architecture does not use a dedicated register to store the - pointer to the global_data structure. There are the following - approaches available: - - * 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. - - * 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: +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 header. E.g., to substitute the + malloc() and free() functions that will be available to standalone + applications, one should do the following: + + DECLARE_GLOBAL_DATA_PTR; + + gd->jt[XF_malloc] = my_malloc; + gd->jt[XF_free] = my_free; + + Note that the pointers to the functions all have 'void *' type and + thus the compiler cannot perform type checks on these assignments. + +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. + + The application can access the 'global_data' structure in the same + way as U-Boot does: + + DECLARE_GLOBAL_DATA_PTR; + + printf("U-Boot relocation offset: %x\n", gd->reloc_off); + +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: + + int my_app (int argc, char *argv[]) + { + app_startup (argv); + if (get_version () != XF_VERSION) + return 1; + } + +4. The default load and start addresses of the applications are as + follows: + + Load address Start address + x86 0x00040000 0x00040000 + PowerPC 0x00040000 0x00040004 + ARM 0x0c100000 0x0c100000 + MIPS 0x80200000 0x80200000 + + For example, the "hello world" application may be loaded and + executed on a PowerPC board with the following commands: + + => tftp 0x40000 hello_world.bin + => go 0x40004 - EXPORT_FUNC(getc) - EXPORT_FUNC(tstc) - ... +5. To export some additional function foobar(), the following steps + should be undertaken: - 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. + - Append the following line at the end of the include/_exports.h + file: -- The include/exports.h file will be introduced, containing the - prototypes of the exported functions and the assigned slot numbers. + EXPORT_FUNC(foobar) -- The examples/stubs.c file will be introduced, containing the code - for the jump stubs for each of the exported functions. + - Add the prototype for this function to the include/exports.h + file: -Implementation Notes on Exporting U-Boot Functions: -=================================================== + void foobar(void); -1. The patch was applied against TOT as of 7/24 12:50 MEST; the - resulting images were tested on the following boards: + - Add the initialization of the jump table slot wherever + appropriate (most likely, to the jumptable_init() function): - * lwmon (PowerPC) - * trab (ARM) - * inca (MIPS) + gd->jt[XF_foobar] = foobar; - The hello_world application was loaded and executed then: + - Increase the XF_VERSION value by one in the include/exports.h + file - [lwmon] - => tftp 0x40000 /tftpboot/LWMON/hello_world.bin-avn - => go 0x40004 +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. - [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: - - > make -C examples TOPDIR=`pwd` ARCH=i386 CROSS_COMPILE= - - The rest of the code is mostly machine-independent and was not - verified. - -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. - -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. - -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. - -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. - -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. - -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 - - 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 c0ef65048e..9c4c51b0e4 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 0000000000..a1ab319ae8 --- /dev/null +++ b/examples/x86-testapp.c @@ -0,0 +1,87 @@ +#include +#include +#include + +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 e6d735a229..2a455f8922 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 @@ -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 b45a466914..f812f16072 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 b9bf133d9f..dd8d378045 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 #if defined(CONFIG_ETHER_ON_FCC) diff --git a/lib_arm/armlinux.c b/lib_arm/armlinux.c index 8e06bd6427..68e12d330d 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 2de39c7db7..ce18fc2252 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(); -- 2.39.5