Commit 7784674852c66b0924bdc79062bd208aa51fd0a9

Authored by wdenk
1 parent 27b207fd0a

* 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

Showing 10 changed files with 251 additions and 202 deletions Side-by-side Diff

... ... @@ -2,6 +2,14 @@
2 2 Changes for U-Boot 0.4.5:
3 3 ======================================================================
4 4  
  5 +* Allow crc32 to be used at address 0x000
  6 +
  7 +* Provide consistent interface to standalone applications to access
  8 + the 'global_data' structure
  9 + Provide a doc/README.standalone more useful to users/developers.
  10 +
  11 +* Make IceCube MGT5100 FEC driver work
  12 +
5 13 * Implement new mechanism to export U-Boot's functions to standalone
6 14 applications: instead of using (PPC-specific) system calls we now
7 15 use a jump table; please see doc/README.standalone for details
... ... @@ -14,7 +14,7 @@
14 14 #include "sdma.h"
15 15 #include "fec.h"
16 16  
17   -#define DEBUG 0x8
  17 +/* #define DEBUG 0x28 */
18 18  
19 19 #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
20 20 defined(CONFIG_MPC5XXX_FEC)
21 21  
22 22  
23 23  
24 24  
25 25  
... ... @@ -28,25 +28,33 @@
28 28 static uint32 local_crc32(char *string, unsigned int crc_value, int len);
29 29 #endif
30 30  
  31 +typedef struct {
  32 + uint8 data[1500]; /* actual data */
  33 + int length; /* actual length */
  34 + int used; /* buffer in use or not */
  35 + uint8 head[16]; /* MAC header(6 + 6 + 2) + 2(aligned) */
  36 +} NBUF;
  37 +
31 38 /********************************************************************/
32 39 static int mpc5xxx_fec_rbd_init(mpc5xxx_fec_priv *fec)
33 40 {
34 41 int ix;
35 42 char *data;
  43 + static int once = 0;
36 44  
37   - /*
38   - * the receive ring is located right after the transmit one
39   - */
40 45 for (ix = 0; ix < FEC_RBD_NUM; ix++) {
41   - data = (char *)malloc(FEC_MAX_PKT_SIZE);
42   - if (data == NULL) {
43   - printf ("RBD INIT FAILED\n");
44   - return -1;
  46 + if (!once) {
  47 + data = (char *)malloc(FEC_MAX_PKT_SIZE);
  48 + if (data == NULL) {
  49 + printf ("RBD INIT FAILED\n");
  50 + return -1;
  51 + }
  52 + fec->rbdBase[ix].dataPointer = (uint32)data;
45 53 }
46 54 fec->rbdBase[ix].status = FEC_RBD_EMPTY;
47 55 fec->rbdBase[ix].dataLength = 0;
48   - fec->rbdBase[ix].dataPointer = (uint32)data;
49 56 }
  57 + once ++;
50 58  
51 59 /*
52 60 * have the last RBD to close the ring
... ... @@ -336,11 +344,6 @@
336 344 SDMA_CLEAR_IEVENT(FEC_RECV_TASK_NO);
337 345  
338 346 /*
339   - * Set SmartDMA intMask register to enable SmartDMA task interrupts
340   - */
341   - SDMA_INT_ENABLE(FEC_RECV_TASK_NO);
342   -
343   - /*
344 347 * Initialize SmartDMA parameters stored in SRAM
345 348 */
346 349 *(int *)FEC_TBD_BASE = (int)fec->tbdBase;
347 350  
... ... @@ -494,8 +497,10 @@
494 497 /********************************************************************/
495 498 static void mpc5xxx_fec_halt(struct eth_device *dev)
496 499 {
497   - mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
  500 +#if defined(CONFIG_MPC5200)
498 501 struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
  502 +#endif
  503 + mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
499 504 int counter = 0xffff;
500 505  
501 506 #if (DEBUG & 0x2)
... ... @@ -530,8 +535,6 @@
530 535 */
531 536 while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ;
532 537  
533   - SDMA_INT_DISABLE (FEC_RECV_TASK_NO);
534   -
535 538 /*
536 539 * Disable SmartDMA tasks
537 540 */
... ... @@ -671,7 +674,7 @@
671 674 pTbd = &fec->tbdBase[fec->tbdIndex];
672 675 pTbd->dataLength = data_length;
673 676 pTbd->dataPointer = (uint32)eth_data;
674   - pTbd->status |= FEC_TBD_READY;
  677 + pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
675 678 fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
676 679  
677 680 #if (DEBUG & 0x100)
... ... @@ -729,8 +732,9 @@
729 732 mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
730 733 FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
731 734 unsigned long ievent;
732   - int frame_length;
733   - char *frame;
  735 + int frame_length, len = 0;
  736 + NBUF *frame;
  737 + char buff[FEC_MAX_PKT_SIZE];
734 738  
735 739 #if (DEBUG & 0x1)
736 740 printf ("mpc5xxx_fec_recv %d Start...\n", fec->rbdIndex);
737 741  
738 742  
739 743  
... ... @@ -763,41 +767,40 @@
763 767 }
764 768 }
765 769  
766   - /*
767   - * Do we have data in Rx FIFO?
768   - */
769   - if ((pRbd->status & FEC_RBD_EMPTY) || !(pRbd->status & FEC_RBD_LAST)){
770   - return 0;
771   - }
  770 + if (!(pRbd->status & FEC_RBD_EMPTY)) {
  771 + if ((pRbd->status & FEC_RBD_LAST) && !(pRbd->status & FEC_RBD_ERR) &&
  772 + ((pRbd->dataLength - 4) > 14)) {
772 773  
773   - /*
774   - * Pass the packet up only if reception was Ok
775   - */
776   - if ((pRbd->dataLength <= 14) || (pRbd->status & FEC_RBD_ERR)) {
777   - mpc5xxx_fec_rbd_clean(fec, pRbd);
778   -#if (DEBUG & 0x8)
779   - printf( "X0" );
  774 + /*
  775 + * Get buffer address and size
  776 + */
  777 + frame = (NBUF *)pRbd->dataPointer;
  778 + frame_length = pRbd->dataLength - 4;
  779 +
  780 +#if (DEBUG & 0x20)
  781 + {
  782 + int i;
  783 + printf("recv data hdr:");
  784 + for (i = 0; i < 14; i++)
  785 + printf("%x ", *(frame->head + i));
  786 + printf("\n");
  787 + }
780 788 #endif
781   - return 0;
  789 + /*
  790 + * Fill the buffer and pass it to upper layers
  791 + */
  792 + memcpy(buff, frame->head, 14);
  793 + memcpy(buff + 14, frame->data, frame_length);
  794 + NetReceive(buff, frame_length);
  795 + len = frame_length;
  796 + }
  797 + /*
  798 + * Reset buffer descriptor as empty
  799 + */
  800 + mpc5xxx_fec_rbd_clean(fec, pRbd);
782 801 }
783   -
784   - /*
785   - * Get buffer address and size
786   - */
787   - frame = (char *)pRbd->dataPointer;
788   - frame_length = pRbd->dataLength;
789   -
790   - /*
791   - * Pass the buffer to upper layers
792   - */
793   - NetReceive(frame, frame_length);
794   -
795   - /*
796   - * Reset buffer descriptor as empty
797   - */
798   - mpc5xxx_fec_rbd_clean(fec, pRbd);
799   -
800   - return frame_length;
  802 + SDMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
  803 + return len;
801 804 }
802 805  
803 806  
... ... @@ -824,6 +827,7 @@
824 827 dev->send = mpc5xxx_fec_send;
825 828 dev->recv = mpc5xxx_fec_recv;
826 829  
  830 + sprintf(dev->name, "FEC ETHERNET");
827 831 eth_register(dev);
828 832  
829 833 return 1;
doc/README.standalone
1 1 Design Notes on Exporting U-Boot Functions to Standalone Applications:
2 2 ======================================================================
3 3  
4   -1. Add a field to the global_data structure, the pointer to a jump
5   - table.
  4 +1. The functions are exported by U-Boot via a jump table. The jump
  5 + table is allocated and initialized in the jumptable_init() routine
  6 + (common/exports.c). Other routines may also modify the jump table,
  7 + however. The jump table can be accessed as the 'jt' field of the
  8 + 'global_data' structure. The slot numbers for the jump table are
  9 + defined in the <include/exports.h> header. E.g., to substitute the
  10 + malloc() and free() functions that will be available to standalone
  11 + applications, one should do the following:
6 12  
7   -2. Jump table itself is allocated and filled in the same way as the
8   - syscall table is (allocated with malloc() after the code has been
9   - relocated to RAM); a special function, fixed to the table element
10   - number 0, will be added which returns the ABI version so
11   - applications can check for compatibility issues.
  13 + DECLARE_GLOBAL_DATA_PTR;
12 14  
13   -3. It is application's responsibility to check the ABI version and
14   - act accordingly.
  15 + gd->jt[XF_malloc] = my_malloc;
  16 + gd->jt[XF_free] = my_free;
15 17  
16   -4. Pointer to the global_data is passed to the application in the
17   - dedicated register that is used in the U-Boot to hold this
18   - pointer. This assumes that the application is built with the same
19   - register- allocation flags as the U-Boot itself. (Actually, this
20   - is a requirement even now, as the 'go' command does not perform
21   - any actions to protect this register against being clobbered by
22   - the application).
  18 + Note that the pointers to the functions all have 'void *' type and
  19 + thus the compiler cannot perform type checks on these assignments.
23 20  
24   - This approach won't work on the x86 architecture. See below.
  21 +2. The pointer to the jump table is passed to the application in a
  22 + machine-dependent way. PowerPC, ARM and MIPS architectures use a
  23 + dedicated register to hold the pointer to the 'global_data'
  24 + structure: r29 on PowerPC, r8 on ARM and k0 on MIPS. The x86
  25 + architecture does not use such a register; instead, the pointer to
  26 + the 'global_data' structure is passed as 'argv[-1]' pointer.
25 27  
26   -5. Application now calls standard library functions like printf()
27   - instead of specially prefixed names like mon_printf() as it did
28   - before. Present implementation of these functions (using the
29   - system calls mechanism) will be replaced with jump stubs.
  28 + The application can access the 'global_data' structure in the same
  29 + way as U-Boot does:
30 30  
31   -6. To export additional functions, the following steps will have to be
32   - taken:
  31 + DECLARE_GLOBAL_DATA_PTR;
33 32  
34   - - Add the xxx() U-Boot function to the EXPORT_FUNC list
35   - - Add initialization of the appropriate slot in the jump table
  33 + printf("U-Boot relocation offset: %x\n", gd->reloc_off);
36 34  
37   -7. To port to a new architecture, the appropriate stub code should be
38   - provided. No other machine-dependent code is used. Once the stub
39   - template is available, no additional coding is needed when
40   - exporting new U-Boot functions. A pre-processor macro will be used
41   - to automatically instantiate the stub definition for each exported
42   - function.
  35 +3. The application should call the app_startup() function before any
  36 + call to the exported functions. Also, implementor of the
  37 + application may want to check the version of the ABI provided by
  38 + U-Boot. To facilitate this, a get_version() function is exported
  39 + that returns the ABI version of the running U-Boot. I.e., a
  40 + typical application startup may look like this:
43 41  
44   -Note the following:
  42 + int my_app (int argc, char *argv[])
  43 + {
  44 + app_startup (argv);
  45 + if (get_version () != XF_VERSION)
  46 + return 1;
  47 + }
45 48  
46   -- This approach uses a jump table with fixed slot allocation. That
47   - said, to retain the ABI compatibility, no table reordering,
48   - inserting new functions in the middle of the list or deleting
49   - functions from the list is allowed. Any such action will break the
50   - ABI compatibility.
  49 +4. The default load and start addresses of the applications are as
  50 + follows:
51 51  
52   -- The x86 architecture does not use a dedicated register to store the
53   - pointer to the global_data structure. There are the following
54   - approaches available:
  52 + Load address Start address
  53 + x86 0x00040000 0x00040000
  54 + PowerPC 0x00040000 0x00040004
  55 + ARM 0x0c100000 0x0c100000
  56 + MIPS 0x80200000 0x80200000
55 57  
56   - * Pass the global_data pointer to the application in a register or
57   - as an additional argument. This requires special machine-
58   - dependent startup code to be compiled into the application.
  58 + For example, the "hello world" application may be loaded and
  59 + executed on a PowerPC board with the following commands:
59 60  
60   - * Make the x86 consistent with the rest of architectures and use a
61   - dedicated register. This renders one register unusable in the
62   - rest of the U-Boot code and thus increases the size of the U-Boot
63   - binary and decreases it performance.
64   -
65   -The following changes will be made:
66   -
67   -- The syscall handling code will be removed.
68   -
69   -- The include/_exports.h file will be introduced, containing the list
70   - of the exported functions in the following form:
71   -
72   - EXPORT_FUNC(getc)
73   - EXPORT_FUNC(tstc)
74   - ...
75   -
76   - This list will be used to assign the slot numbers in the jump
77   - table, to determine the size of the jump table and to generate the
78   - code for the stub functions.
79   -
80   -- The include/exports.h file will be introduced, containing the
81   - prototypes of the exported functions and the assigned slot numbers.
82   -
83   -- The examples/stubs.c file will be introduced, containing the code
84   - for the jump stubs for each of the exported functions.
85   -
86   -Implementation Notes on Exporting U-Boot Functions:
87   -===================================================
88   -
89   -1. The patch was applied against TOT as of 7/24 12:50 MEST; the
90   - resulting images were tested on the following boards:
91   -
92   - * lwmon (PowerPC)
93   - * trab (ARM)
94   - * inca (MIPS)
95   -
96   - The hello_world application was loaded and executed then:
97   -
98   - [lwmon]
99   - => tftp 0x40000 /tftpboot/LWMON/hello_world.bin-avn
  61 + => tftp 0x40000 hello_world.bin
100 62 => go 0x40004
101 63  
102   - [trab]
103   - TRAB # tftp 0xc100000 /tftpboot/TRAB/hello_world.bin-avn
104   - TRAB # go 0xc100000
  64 +5. To export some additional function foobar(), the following steps
  65 + should be undertaken:
105 66  
106   - [inca]
107   - INCA-IP # tftp 0x80200000 /tftpboot/INCA/hello_world.bin-avn
108   - INCA-IP # go 0x80200000
  67 + - Append the following line at the end of the include/_exports.h
  68 + file:
109 69  
110   -2. As neither of supported x86 boards can be built from the TOT
111   - sources currently, the patch build was verified by manually
112   - running the following command in the U-Boot top directory:
  70 + EXPORT_FUNC(foobar)
113 71  
114   - > make -C examples TOPDIR=`pwd` ARCH=i386 CROSS_COMPILE=
  72 + - Add the prototype for this function to the include/exports.h
  73 + file:
115 74  
116   - The rest of the code is mostly machine-independent and was not
117   - verified.
  75 + void foobar(void);
118 76  
119   -3. To test the x86 assembly code, a small standalone application was
120   - written. It was built and run on the RedHat Linux 8.0 (x86). The
121   - application performs a jump using a pointer to jump table and a
122   - function's index in it.
  77 + - Add the initialization of the jump table slot wherever
  78 + appropriate (most likely, to the jumptable_init() function):
123 79  
124   -4. For the MIPS architecture, the linker script is also provided for
125   - linking applications. The default linker script places the .text
126   - and .data sections too far from each other so that the resulting
127   - .bin files span about 256Mb in size.
  80 + gd->jt[XF_foobar] = foobar;
128 81  
129   -5. Several example applications required updating for the new API.
130   - These applications relied upon the bd_t pointer being passed as
131   - the 1st argument to the main function; this had changed when the
132   - system calls were introduced, but apparently, these applications
133   - weren't fixed at that moment. This is fixed now.
  82 + - Increase the XF_VERSION value by one in the include/exports.h
  83 + file
134 84  
135   -6. GCC issues warnings for the 'sched' application. Since now the
136   - mon_printf() function is renamed to printf(), GCC applies its
137   - knowledge of the format specifiers to check the arguments,
138   - complaining about ints passed as longs and vice versa. This is not
139   - fixed yet.
  85 +6. The code for exporting the U-Boot functions to applications is
  86 + mostly machine-independent. The only places written in assembly
  87 + language are stub functions that perform the jump through the jump
  88 + table. That said, to port this code to a new architecture, the
  89 + only thing to be provided is the code in the examples/stubs.c
  90 + file. If this architecture, however, uses some uncommon method of
  91 + passing the 'global_data' pointer (like x86 does), one should add
  92 + the respective code to the app_startup() function in that file.
140 93  
141   -7. Only the hello_world example application was modified to make use
142   - of the newly supplied get_version() function. The application now
143   - prints two ABI versions, the one that the application was compiled
144   - for and the other, actual ABI version.
145   -
146   -8. The following new files were added:
147   - common/exports.c
148   - examples/mips.lds
149   - examples/stubs.c
150   - include/_exports.h
151   - include/exports.h
152   - doc/README.standalone
153   -
154   - The following files are no longer used and will be removed:
155   - examples/syscall.S
156   - include/syscall.h
  94 + Note that these functions may only use call-clobbered registers;
  95 + those registers that are used to pass the function's arguments,
  96 + the stack contents and the return address should be left intact.
... ... @@ -9,6 +9,7 @@
9 9 * to the application program.
10 10 */
11 11 static void **jt;
  12 +gd_t *global_data;
12 13  
13 14 #define EXPORT_FUNC(x) \
14 15 asm volatile ( \
... ... @@ -80,7 +81,8 @@
80 81 {
81 82 #if defined(CONFIG_I386)
82 83 /* x86 does not have a dedicated register for passing global_data */
83   - jt = ((gd_t *)argv[-1])->jt;
  84 + global_data = (gd_t *)argv[-1];
  85 + jt = global_data->jt;
84 86 #endif
85 87 }
86 88  
examples/x86-testapp.c
  1 +#include <stddef.h>
  2 +#include <stdio.h>
  3 +#include <string.h>
  4 +
  5 +void *func[8], **pfunc;
  6 +
  7 +typedef struct xxx xxx_t;
  8 +struct xxx {
  9 + int dummy;
  10 + void **pfunc;
  11 +} q;
  12 +
  13 +#define XF_strcpy 3
  14 +#define XF_printf 4
  15 +
  16 +#define LABEL(x) \
  17 +asm volatile ( \
  18 +
  19 +#if defined(__i386__)
  20 +#define EXPORT_FUNC(x) \
  21 +asm volatile ( \
  22 +" .globl mon_" #x "\n" \
  23 +"mon_" #x ":\n" \
  24 +" movl %0, %%eax\n" \
  25 +" movl pfunc, %%ecx\n" \
  26 +" jmp *(%%ecx,%%eax)\n" \
  27 + : : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx");
  28 +#elif defined(__powerpc__)
  29 +#define EXPORT_FUNC(x) \
  30 +asm volatile ( \
  31 +" .globl mon_" #x "\n" \
  32 +"mon_" #x ":\n" \
  33 +" lwz %%r11, %0(%%r29)\n" \
  34 +" lwz %%r11, %1(%%r11)\n" \
  35 +" mtctr %%r11\n" \
  36 +" bctr\n" \
  37 + : : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "r11", "r29");
  38 +#elif defined(__arm__)
  39 +#define EXPORT_FUNC(x) \
  40 +asm volatile ( \
  41 +" .globl mon_" #x "\n" \
  42 +"mon_" #x ":\n" \
  43 +" ldr ip, [r8, %0]\n" \
  44 +" ldr pc, [ip, %1]\n" \
  45 + : : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "ip");
  46 +#elif defined(__mips__)
  47 +#define EXPORT_FUNC(x) \
  48 +asm volatile ( \
  49 +" .globl mon_" #x "\n" \
  50 +"mon_" #x ":\n" \
  51 +" lw $25, %0($26)\n" \
  52 +" lw $25, %1($25)\n" \
  53 +" jr $25\n" \
  54 + : : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "t9");
  55 +#else
  56 +#error [No stub code for this arch]
  57 +#endif
  58 +
  59 +void dummy(void)
  60 +{
  61 +EXPORT_FUNC(printf)
  62 +EXPORT_FUNC(strcpy)
  63 +}
  64 +
  65 +int main(void)
  66 +{
  67 +#if defined(__i386__)
  68 + xxx_t *pq;
  69 +#elif defined(__powerpc__)
  70 + register volatile xxx_t *pq asm("r29");
  71 +#elif defined(__arm__)
  72 + register volatile xxx_t *pq asm("r8");
  73 +#elif defined(__mips__)
  74 + register volatile xxx_t *pq asm("k0");
  75 +#endif
  76 + char buf[32];
  77 +
  78 + func[XF_strcpy] = strcpy;
  79 + func[XF_printf] = printf;
  80 + pq = &q;
  81 + pq->pfunc = pfunc = func;
  82 +
  83 + mon_strcpy(buf, "test");
  84 + mon_printf("hi %s %d z\n", buf, 444);
  85 +
  86 + return 0;
  87 +}
include/configs/IceCube.h
... ... @@ -52,7 +52,7 @@
52 52 /*
53 53 * Supported commands
54 54 */
55   -#define CONFIG_COMMANDS (CONFIG_CMD_DFL & ~(CFG_CMD_NET))
  55 +#define CONFIG_COMMANDS CONFIG_CMD_DFL
56 56  
57 57 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
58 58 #include <cmd_confdefs.h>
59 59  
... ... @@ -122,10 +122,7 @@
122 122 /*
123 123 * Ethernet configuration
124 124 */
125   -#if 0
126   -#define CONFIG_NET_MULTI 1
127 125 #define CONFIG_MPC5XXX_FEC 1
128   -#endif
129 126  
130 127 /*
131 128 * GPIO configuration
... ... @@ -33,5 +33,9 @@
33 33  
34 34 #define XF_VERSION 1
35 35  
  36 +#if defined(CONFIG_I386)
  37 +extern gd_t *global_data;
  38 +#endif
  39 +
36 40 #endif
... ... @@ -21,6 +21,14 @@
21 21 # endif
22 22 #endif /* CONFIG_8xx */
23 23  
  24 +#if defined(CONFIG_MPC5XXX)
  25 +# if !defined(CONFIG_NET_MULTI)
  26 +# if defined(CONFIG_MPC5XXX_FEC)
  27 +# define CONFIG_NET_MULTI
  28 +# endif
  29 +# endif
  30 +#endif /* CONFIG_MPC5XXX */
  31 +
24 32 #if !defined(CONFIG_NET_MULTI) && defined(CONFIG_8260)
25 33 #include <config.h>
26 34 #if defined(CONFIG_ETHER_ON_FCC)
... ... @@ -231,7 +231,7 @@
231 231 setup_ramdisk_tag(bd);
232 232 #endif
233 233 #if defined (CONFIG_VFD)
234   - setup_videolfb_tag(gd);
  234 + setup_videolfb_tag((gd_t *)gd);
235 235 #endif
236 236 setup_end_tag(bd);
237 237 #endif
... ... @@ -155,7 +155,6 @@
155 155 const Bytef *buf;
156 156 uInt len;
157 157 {
158   - if (buf == Z_NULL) return 0L;
159 158 #ifdef DYNAMIC_CRC_TABLE
160 159 if (crc_table_empty)
161 160 make_crc_table();