summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorwdenk <wdenk>2003-07-24 23:38:38 +0000
committerwdenk <wdenk>2003-07-24 23:38:38 +0000
commit27b207fd0a0941b03f27e2a82c0468b1a090c745 (patch)
tree4d339d7a2a00889f09a876425ce430be57de56e9 /examples
parent2535d60277cc295adf75cd5721dcecd840c69a63 (diff)
downloadtalos-obmc-uboot-27b207fd0a0941b03f27e2a82c0468b1a090c745.tar.gz
talos-obmc-uboot-27b207fd0a0941b03f27e2a82c0468b1a090c745.zip
* 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 * Patch by Dave Westwood, 24 Jul 2003: added support for Unity OS (a proprietary OS)
Diffstat (limited to 'examples')
-rw-r--r--examples/82559_eeprom.c31
-rw-r--r--examples/Makefile25
-rw-r--r--examples/eepro100_eeprom.c20
-rw-r--r--examples/hello_world.c21
-rw-r--r--examples/mem_to_mem_idma2intr.c20
-rw-r--r--examples/mips.lds56
-rw-r--r--examples/sched.c64
-rw-r--r--examples/stubs.c87
-rw-r--r--examples/syscall.S114
-rw-r--r--examples/timer.c48
10 files changed, 266 insertions, 220 deletions
diff --git a/examples/82559_eeprom.c b/examples/82559_eeprom.c
index d66b3dd8e2..1a121d4287 100644
--- a/examples/82559_eeprom.c
+++ b/examples/82559_eeprom.c
@@ -22,7 +22,7 @@
#define _LINUX_STRING_H_ /* avoid unnecessary str/mem functions */
#include <common.h>
-#include <syscall.h>
+#include <exports.h>
#include <asm/io.h>
@@ -96,7 +96,7 @@ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
long ee_addr = ioaddr + EE_OFFSET;
if (debug > 1)
- mon_printf(" EEPROM op 0x%x: ", cmd);
+ printf(" EEPROM op 0x%x: ", cmd);
outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
@@ -106,7 +106,7 @@ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
outw(dataval, ee_addr);
eeprom_delay(ee_addr);
if (debug > 2)
- mon_printf("%X", inw(ee_addr) & 15);
+ printf("%X", inw(ee_addr) & 15);
outw(dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay(ee_addr);
retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
@@ -117,7 +117,7 @@ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
/* Terminate the EEPROM access. */
outw(EE_ENB & ~EE_CS, ee_addr);
if (debug > 1)
- mon_printf(" EEPROM result is 0x%5.5x.\n", retval);
+ printf(" EEPROM result is 0x%5.5x.\n", retval);
return retval;
}
@@ -143,7 +143,7 @@ static void write_eeprom(long ioaddr, int index, int value, int addr_len)
/* Poll for write finished. */
i = eeprom_busy_poll(ee_ioaddr); /* Typical 2000 ticks */
if (debug)
- mon_printf(" Write finished after %d ticks.\n", i);
+ printf(" Write finished after %d ticks.\n", i);
/* Disable programming. This command is not instantaneous, so we check
for busy before the next op. */
do_eeprom_cmd(ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
@@ -156,7 +156,7 @@ static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr)
int size_test;
int i;
- mon_printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr);
+ printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr);
size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27);
eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6;
@@ -177,11 +177,11 @@ static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr)
for (i = 0; i < eeprom_size; i++)
if (read_eeprom(ioaddr, i, eeprom_addr_size) != eeprom[i]) {
- mon_printf("failed\n");
+ printf("failed\n");
return 1;
}
- mon_printf("done\n");
+ printf("done\n");
return 0;
}
@@ -308,19 +308,20 @@ int main (int argc, char *argv[])
char buf[6];
int instance;
+ app_startup(argv);
if (argc != 2) {
- mon_printf ("call with base Ethernet address\n");
+ printf ("call with base Ethernet address\n");
return 1;
}
eth_addr = gethwaddr(argv[1], buf);
if (NULL == eth_addr) {
- mon_printf ("Can not parse ethernet address\n");
+ printf ("Can not parse ethernet address\n");
return 1;
}
if (eth_addr[5] & 0x01) {
- mon_printf("Base Ethernet address must be even\n");
+ printf("Base Ethernet address must be even\n");
}
@@ -329,22 +330,22 @@ int main (int argc, char *argv[])
unsigned char mac[6];
int bar1 = read_config_dword(0, 6+instance, 0, 0x14);
if (! (bar1 & 1)) {
- mon_printf("ETH%d is disabled %x\n", instance, bar1);
+ printf("ETH%d is disabled %x\n", instance, bar1);
} else {
- mon_printf("ETH%d IO=0x%04x\n", instance, bar1 & ~3);
+ printf("ETH%d IO=0x%04x\n", instance, bar1 & ~3);
}
io_addr = (bar1 & (~3L));
write_config_word(0, 6+instance, 0, 4,
read_config_word(0, 6+instance, 0, 4) | 1);
- mon_printf("ETH%d CMD %04x\n", instance,
+ printf("ETH%d CMD %04x\n", instance,
read_config_word(0, 6+instance, 0, 4));
memcpy(mac, eth_addr, 6);
mac[5] += instance;
- mon_printf("got io=%04x, ha=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ printf("got io=%04x, ha=%02x:%02x:%02x:%02x:%02x:%02x\n",
io_addr, mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
reset_eeprom(io_addr, mac);
diff --git a/examples/Makefile b/examples/Makefile
index 9abff63f1a..7975df55ca 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -21,7 +21,21 @@
# MA 02111-1307 USA
#
+ifeq ($(ARCH),ppc)
LOAD_ADDR = 0x40000
+endif
+
+ifeq ($(ARCH),i386)
+LOAD_ADDR = 0x40000
+endif
+
+ifeq ($(ARCH),arm)
+LOAD_ADDR = 0xc100000
+endif
+
+ifeq ($(ARCH),mips)
+LOAD_ADDR = 0x80200000 -T mips.lds
+endif
include $(TOPDIR)/config.mk
@@ -38,11 +52,6 @@ SREC += sched.srec
BIN += sched.bin
endif
-ifeq ($(ARCH),mips)
-SREC =
-BIN =
-endif
-
# The following example is pretty 8xx specific...
ifeq ($(CPU),mpc8xx)
SREC += timer.srec
@@ -62,12 +71,12 @@ endif
OBJS = $(SREC:.srec=.o)
-LIB = libsyscall.a
-LIBAOBJS= syscall.o
+LIB = libstubs.a
+LIBAOBJS=
ifeq ($(ARCH),ppc)
LIBAOBJS+= $(ARCH)_longjmp.o $(ARCH)_setjmp.o
endif
-LIBCOBJS=
+LIBCOBJS= stubs.o
LIBOBJS = $(LIBAOBJS) $(LIBCOBJS)
CPPFLAGS += -I..
diff --git a/examples/eepro100_eeprom.c b/examples/eepro100_eeprom.c
index 23020037d3..60b937ef8d 100644
--- a/examples/eepro100_eeprom.c
+++ b/examples/eepro100_eeprom.c
@@ -21,17 +21,19 @@
#define _LINUX_STRING_H_ /* avoid unnecessary str/mem functions */
#include <common.h>
-#include <syscall.h>
+#include <exports.h>
static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr);
-int eepro100_eeprom(void)
+int eepro100_eeprom(int argc, char *argv[])
{
int ret = 0;
unsigned char hwaddr1[6] = { 0x00, 0x00, 0x02, 0x03, 0x04, 0x05 };
unsigned char hwaddr2[6] = { 0x00, 0x00, 0x02, 0x03, 0x04, 0x06 };
+ app_startup(argv);
+
#if defined(CONFIG_OXC)
ret |= reset_eeprom(0x80000000, hwaddr1);
ret |= reset_eeprom(0x81000000, hwaddr2);
@@ -119,7 +121,7 @@ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
long ee_addr = ioaddr + EE_OFFSET;
if (debug > 1)
- mon_printf(" EEPROM op 0x%x: ", cmd);
+ printf(" EEPROM op 0x%x: ", cmd);
outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
@@ -129,7 +131,7 @@ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
outw(dataval, ee_addr);
eeprom_delay(ee_addr);
if (debug > 2)
- mon_printf("%X", inw(ee_addr) & 15);
+ printf("%X", inw(ee_addr) & 15);
outw(dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay(ee_addr);
retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
@@ -140,7 +142,7 @@ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
/* Terminate the EEPROM access. */
outw(EE_ENB & ~EE_CS, ee_addr);
if (debug > 1)
- mon_printf(" EEPROM result is 0x%5.5x.\n", retval);
+ printf(" EEPROM result is 0x%5.5x.\n", retval);
return retval;
}
@@ -166,7 +168,7 @@ static void write_eeprom(long ioaddr, int index, int value, int addr_len)
/* Poll for write finished. */
i = eeprom_busy_poll(ee_ioaddr); /* Typical 2000 ticks */
if (debug)
- mon_printf(" Write finished after %d ticks.\n", i);
+ printf(" Write finished after %d ticks.\n", i);
/* Disable programming. This command is not instantaneous, so we check
for busy before the next op. */
do_eeprom_cmd(ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
@@ -179,7 +181,7 @@ static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr)
int size_test;
int i;
- mon_printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr);
+ printf("Resetting i82559 EEPROM @ 0x%08lX ... ", ioaddr);
size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27);
eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6;
@@ -200,10 +202,10 @@ static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr)
for (i = 0; i < eeprom_size; i++)
if (read_eeprom(ioaddr, i, eeprom_addr_size) != eeprom[i]) {
- mon_printf("failed\n");
+ printf("failed\n");
return 1;
}
- mon_printf("done\n");
+ printf("done\n");
return 0;
}
diff --git a/examples/hello_world.c b/examples/hello_world.c
index 96204c4507..9317f6d8c0 100644
--- a/examples/hello_world.c
+++ b/examples/hello_world.c
@@ -22,28 +22,33 @@
*/
#include <common.h>
-#include <syscall.h>
+#include <exports.h>
int hello_world (int argc, char *argv[])
{
int i;
- mon_printf ("Hello World\n");
+ /* Print the ABI version */
+ app_startup(argv);
+ printf ("Example expects ABI version %d\n", XF_VERSION);
+ printf ("Actual U-Boot ABI version %d\n", (int)get_version());
- mon_printf ("argc = %d\n", argc);
+ printf ("Hello World\n");
+
+ printf ("argc = %d\n", argc);
for (i=0; i<=argc; ++i) {
- mon_printf ("argv[%d] = \"%s\"\n",
+ printf ("argv[%d] = \"%s\"\n",
i,
argv[i] ? argv[i] : "<NULL>");
}
- mon_printf ("Hit any key to exit ... ");
- while (!mon_tstc())
+ printf ("Hit any key to exit ... ");
+ while (!tstc())
;
/* consume input */
- (void) mon_getc();
+ (void) getc();
- mon_printf ("\n\n");
+ printf ("\n\n");
return (0);
}
diff --git a/examples/mem_to_mem_idma2intr.c b/examples/mem_to_mem_idma2intr.c
index 3f0fd372b0..3a269c9082 100644
--- a/examples/mem_to_mem_idma2intr.c
+++ b/examples/mem_to_mem_idma2intr.c
@@ -28,7 +28,7 @@
#include <common.h>
-#include <syscall.h>
+#include <exports.h>
#define STANDALONE
@@ -36,13 +36,6 @@
#include <command.h>
#include <watchdog.h>
#else /* Standalone app of PPCBoot */
-#include <syscall.h>
-#define printf mon_printf
-#define tstc mon_tstc
-#define getc mon_getc
-#define putc mon_putc
-#define udelay mon_udelay
-#define malloc mon_malloc
#define WATCHDOG_RESET() { \
*(ushort *)(CFG_IMMR + 0x1000E) = 0x556c; \
*(ushort *)(CFG_IMMR + 0x1000E) = 0xaa39; \
@@ -180,8 +173,8 @@ uint dpinit_done = 0;
#ifdef STANDALONE
int ctrlc (void)
{
- if (mon_tstc()) {
- switch (mon_getc ()) {
+ if (tstc()) {
+ switch (getc ()) {
case 0x03: /* ^C - Control C */
return 1;
default:
@@ -209,19 +202,20 @@ int memcmp(const void * cs,const void * ct,size_t count)
#endif /* STANDALONE */
#ifdef STANDALONE
-int mem_to_mem_idma2intr (bd_t * bd, int argc, char *argv[])
+int mem_to_mem_idma2intr (int argc, char *argv[])
#else
int do_idma (bd_t * bd, int argc, char *argv[])
#endif /* STANDALONE */
{
int i;
+ app_startup(argv);
dpinit_done = 0;
idma_init ();
DEBUG ("Installing dma handler\n");
- mon_install_hdlr (7, dmadone_handler, (void *) bdf);
+ install_hdlr (7, dmadone_handler, (void *) bdf);
memset ((void *) 0x100000, 'a', 512);
memset ((void *) 0x200000, 'b', 512);
@@ -232,7 +226,7 @@ int do_idma (bd_t * bd, int argc, char *argv[])
}
DEBUG ("Uninstalling dma handler\n");
- mon_free_hdlr (7);
+ free_hdlr (7);
return 0;
}
diff --git a/examples/mips.lds b/examples/mips.lds
new file mode 100644
index 0000000000..8ed01c4458
--- /dev/null
+++ b/examples/mips.lds
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk Engineering, <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+}
diff --git a/examples/sched.c b/examples/sched.c
index ceb5c1f08e..6b78f69985 100644
--- a/examples/sched.c
+++ b/examples/sched.c
@@ -16,7 +16,7 @@
*/
#include <common.h>
-#include <syscall.h>
+#include <exports.h>
/*
* Author: Arun Dharankar <ADharankar@ATTBI.Com>
@@ -76,9 +76,9 @@ static uchar dbg = 0;
#define PDEBUG(fmt, args...) { \
if(dbg != 0) { \
- mon_printf("[%s %d %s]: ",__FILE__,__LINE__,__FUNCTION__);\
- mon_printf(fmt, ##args); \
- mon_printf("\n"); \
+ printf("[%s %d %s]: ",__FILE__,__LINE__,__FUNCTION__);\
+ printf(fmt, ##args); \
+ printf("\n"); \
} \
}
@@ -97,41 +97,43 @@ static int thread_stop (int id);
/* An example of schedular test */
#define NUMTHREADS 7
-int sched (bd_t * bd, int ac, char *av[])
+int sched (int ac, char *av[])
{
int i, j;
int tid[NUMTHREADS];
int names[NUMTHREADS];
+ app_startup(av);
+
sched_init ();
for (i = 0; i < NUMTHREADS; i++) {
names[i] = i;
j = thread_create (testthread, (void *) &names[i]);
if (j == RC_FAILURE)
- mon_printf ("schedtest: Failed to create thread %d\n", i);
+ printf ("schedtest: Failed to create thread %d\n", i);
if (j > 0) {
- mon_printf ("schedtest: Created thread with id %d, name %d\n",
+ printf ("schedtest: Created thread with id %d, name %d\n",
j, i);
tid[i] = j;
}
}
- mon_printf ("schedtest: Threads created\n");
+ printf ("schedtest: Threads created\n");
- mon_printf ("sched_test: function=0x%08x\n", testthread);
+ printf ("sched_test: function=0x%08x\n", (unsigned)testthread);
for (i = 0; i < NUMTHREADS; i++) {
- mon_printf ("schedtest: Setting thread %d runnable\n", tid[i]);
+ printf ("schedtest: Setting thread %d runnable\n", tid[i]);
thread_start (tid[i]);
thread_yield ();
}
- mon_printf ("schedtest: Started %d threads\n", NUMTHREADS);
+ printf ("schedtest: Started %d threads\n", NUMTHREADS);
while (1) {
- mon_printf ("schedtest: Waiting for threads to complete\n");
- if (mon_tstc () && mon_getc () == 0x3) {
- mon_printf ("schedtest: Aborting threads...\n");
+ printf ("schedtest: Waiting for threads to complete\n");
+ if (tstc () && getc () == 0x3) {
+ printf ("schedtest: Aborting threads...\n");
for (i = 0; i < NUMTHREADS; i++) {
- mon_printf ("schedtest: Deleting thread %d\n", tid[i]);
+ printf ("schedtest: Deleting thread %d\n", tid[i]);
thread_delete (tid[i]);
}
return RC_SUCCESS;
@@ -139,11 +141,11 @@ int sched (bd_t * bd, int ac, char *av[])
j = -1;
i = thread_join (&j);
if (i == RC_FAILURE) {
- mon_printf ("schedtest: No threads pending, "
+ printf ("schedtest: No threads pending, "
"exiting schedular test\n");
return RC_SUCCESS;
}
- mon_printf ("schedtest: thread is %d returned %d\n", i, j);
+ printf ("schedtest: thread is %d returned %d\n", i, j);
thread_yield ();
}
@@ -154,14 +156,14 @@ static int testthread (void *name)
{
int i;
- mon_printf ("testthread: Begin executing thread, myname %d, &i=0x%08x\n",
- *(int *) name, &i);
+ printf ("testthread: Begin executing thread, myname %d, &i=0x%08x\n",
+ *(int *) name, (unsigned)&i);
- mon_printf ("Thread %02d, i=%d\n", *(int *) name);
+ printf ("Thread %02d, i=%d\n", *(int *) name, i);
for (i = 0; i < 0xffff * (*(int *) name + 1); i++) {
- if (mon_tstc () && mon_getc () == 0x3) {
- mon_printf ("testthread: myname %d terminating.\n",
+ if (tstc () && getc () == 0x3) {
+ printf ("testthread: myname %d terminating.\n",
*(int *) name);
return *(int *) name + 1;
}
@@ -170,7 +172,7 @@ static int testthread (void *name)
thread_yield ();
}
- mon_printf ("testthread: returning %d, i=0x%x\n",
+ printf ("testthread: returning %d, i=0x%x\n",
*(int *) name + 1, i);
return *(int *) name + 1;
@@ -187,7 +189,7 @@ static void sched_init (void)
current_tid = MASTER_THREAD;
lthreads[current_tid].state = STATE_RUNNABLE;
PDEBUG ("sched_init: master context = 0x%08x",
- lthreads[current_tid].context);
+ (unsigned)lthreads[current_tid].context);
return;
}
@@ -200,7 +202,8 @@ static void thread_yield (void)
#define SWITCH(new) \
if(lthreads[new].state == STATE_RUNNABLE) { \
PDEBUG("thread_yield: %d match, ctx=0x%08x", \
- new, lthreads[current_tid].context); \
+ new, \
+ (unsigned)lthreads[current_tid].context); \
if(setjmp(lthreads[current_tid].context) == 0) { \
current_tid = new; \
PDEBUG("thread_yield: tid %d returns 0", \
@@ -260,7 +263,7 @@ static int thread_delete (int id)
static void thread_launcher (void)
{
PDEBUG ("thread_launcher: invoking func=0x%08x",
- lthreads[current_tid].func);
+ (unsigned)lthreads[current_tid].func);
lthreads[current_tid].retval =
lthreads[current_tid].func (lthreads[current_tid].arg);
@@ -269,7 +272,7 @@ static void thread_launcher (void)
lthreads[current_tid].state = STATE_TERMINATED;
thread_yield ();
- mon_printf ("thread_launcher: should NEVER get here!\n");
+ printf ("thread_launcher: should NEVER get here!\n");
return;
}
@@ -287,7 +290,8 @@ static int thread_start (int id)
if (setjmp (lthreads[current_tid].context) == 0) {
lthreads[id].state = STATE_RUNNABLE;
current_tid = id;
- PDEBUG ("thread_start: to be stack=0%08x", lthreads[id].stack);
+ PDEBUG ("thread_start: to be stack=0%08x",
+ (unsigned)lthreads[id].stack);
setctxsp (&lthreads[id].stack[STK_SIZE]);
thread_launcher ();
}
@@ -297,7 +301,7 @@ static int thread_start (int id)
return RC_SUCCESS;
}
-#if 0 /* not used so far */
+#if 0 /* not used so far */
static int thread_stop (int id)
{
if (id <= MASTER_THREAD || id >= MAX_THREADS)
@@ -309,7 +313,7 @@ static int thread_stop (int id)
lthreads[id].state = STATE_STOPPED;
return RC_SUCCESS;
}
-#endif /* not used so far */
+#endif /* not used so far */
static int thread_join (int *ret)
{
diff --git a/examples/stubs.c b/examples/stubs.c
new file mode 100644
index 0000000000..c0ef65048e
--- /dev/null
+++ b/examples/stubs.c
@@ -0,0 +1,87 @@
+#include <exports.h>
+
+#if defined(CONFIG_I386)
+/*
+ * x86 does not have a dedicated register to store the pointer to
+ * the global_data. Thus the jump table address is stored in a
+ * global variable, but such approach does not allow for execution
+ * from flash memory. The global_data address is passed as argv[-1]
+ * to the application program.
+ */
+static void **jt;
+
+#define EXPORT_FUNC(x) \
+ asm volatile ( \
+" .globl " #x "\n" \
+#x ":\n" \
+" movl %0, %%eax\n" \
+" movl jt, %%ecx\n" \
+" jmp *(%%ecx, %%eax)\n" \
+ : : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx");
+#elif defined(CONFIG_PPC)
+/*
+ * r29 holds the pointer to the global_data, r11 is a call-clobbered
+ * register
+ */
+#define EXPORT_FUNC(x) \
+ asm volatile ( \
+" .globl " #x "\n" \
+#x ":\n" \
+" lwz %%r11, %0(%%r29)\n" \
+" lwz %%r11, %1(%%r11)\n" \
+" mtctr %%r11\n" \
+" bctr\n" \
+ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11");
+#elif defined(CONFIG_ARM)
+/*
+ * r8 holds the pointer to the global_data, ip is a call-clobbered
+ * register
+ */
+#define EXPORT_FUNC(x) \
+ asm volatile ( \
+" .globl " #x "\n" \
+#x ":\n" \
+" ldr ip, [r8, %0]\n" \
+" ldr pc, [ip, %1]\n" \
+ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip");
+#elif defined(CONFIG_MIPS)
+/*
+ * k0 ($26) holds the pointer to the global_data; t9 ($25) is a call-
+ * clobbered register that is also used to set gp ($26). Note that the
+ * jr instruction also executes the instruction immediately following
+ * it; however, GCC/mips generates an additional `nop' after each asm
+ * statement
+ */
+#define EXPORT_FUNC(x) \
+ asm volatile ( \
+" .globl " #x "\n" \
+#x ":\n" \
+" lw $25, %0($26)\n" \
+" lw $25, %1($25)\n" \
+" jr $25\n" \
+ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "t9");
+#else
+#error stubs definition missing for this architecture
+#endif
+
+/* This function is necessary to prevent the compiler from
+ * generating prologue/epilogue, preparing stack frame etc.
+ * The stub functions are special, they do not use the stack
+ * frame passed to them, but pass it intact to the actual
+ * implementation. On the other hand, asm() statements with
+ * arguments can be used only inside the functions (gcc limitation)
+ */
+static void __attribute__((unused)) dummy(void)
+{
+#include <_exports.h>
+}
+
+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;
+#endif
+}
+
+#undef EXPORT_FUNC
diff --git a/examples/syscall.S b/examples/syscall.S
deleted file mode 100644
index f319409ee6..0000000000
--- a/examples/syscall.S
+++ /dev/null
@@ -1,114 +0,0 @@
-#include <ppc_asm.tmpl>
-#include <ppc_defs.h>
-#include <syscall.h>
-
-#ifdef CONFIG_ARM /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-#warning ARM version not implemented yet /* XXXXXXXXXXXXXXXXXXXXXXXXXXXX */
- .global mon_getc
- .type mon_getc,function
-mon_getc:
- .global mon_tstc
- .type mon_tstc,function
-mon_tstc:
- .global mon_putc
- .type mon_putc,function
-mon_putc:
- .global mon_puts
- .type mon_puts,function
-mon_puts:
- .global mon_printf
- .type mon_printf,function
-mon_printf:
- .global mon_install_hdlr
- .type mon_install_hdlr,function
-mon_install_hdlr:
- .global mon_free_hdlr
- .type mon_free_hdlr,function
-mon_free_hdlr:
- .global mon_malloc
- .type mon_malloc,function
-mon_malloc:
- .global mon_free
- .type mon_free,function
-mon_free:
- @ args = 0, pretend = 0, frame = 0
- @ frame_needed = 1, current_function_anonymous_args = 0
- mov ip, sp
- stmfd sp!, {fp, ip, lr, pc}
- sub fp, ip, #4
- ldmea fp, {fp, sp, pc}
-#elif defined(CONFIG_MIPS)/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-#warning MIPS version not implemented yet
- .global mon_getc
- .type mon_getc,function
-mon_getc:
- .global mon_tstc
- .type mon_tstc,function
-mon_tstc:
- .global mon_putc
- .type mon_putc,function
-mon_putc:
- .global mon_puts
- .type mon_puts,function
-mon_puts:
- .global mon_printf
- .type mon_printf,function
-mon_printf:
- .global mon_install_hdlr
- .type mon_install_hdlr,function
-mon_install_hdlr:
- .global mon_free_hdlr
- .type mon_free_hdlr,function
-mon_free_hdlr:
- .global mon_malloc
- .type mon_malloc,function
-mon_malloc:
- .global mon_free
- .type mon_free,function
-mon_free:
-
-#else
-
-#ifdef CONFIG_I386 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-#define SYMBOL_NAME(X) X
-#define SYMBOL_NAME_LABEL(X) X##:
-
-#define SYSCALL(name,n) \
- .globl SYMBOL_NAME(name) ; \
-SYMBOL_NAME_LABEL(name) ; \
- movl $n, %eax ;\
- pushl %ebx; \
- pushl %ecx; \
- int $0x40 ;\
-
-
-#endif /* CONFIG_I386 */
-
-#ifdef CONFIG_PPC
-#define SYSCALL(name,n) \
- .globl name ; \
-name: ; \
- li r0,n ; \
- sc ; \
- blr
-#endif /* CONFIG_PPC */
-
- .text
-
- /*
- * Make sure these functions are in the same order as they
- * appear in the "include/syscall.h" header file !!!
- */
-
- SYSCALL(mon_getc,SYSCALL_GETC)
- SYSCALL(mon_tstc,SYSCALL_TSTC)
- SYSCALL(mon_putc,SYSCALL_PUTC)
- SYSCALL(mon_puts,SYSCALL_PUTS)
- SYSCALL(mon_printf,SYSCALL_PRINTF)
- SYSCALL(mon_install_hdlr,SYSCALL_INSTALL_HDLR)
- SYSCALL(mon_free_hdlr,SYSCALL_FREE_HDLR)
- SYSCALL(mon_malloc,SYSCALL_MALLOC)
- SYSCALL(mon_free,SYSCALL_FREE)
- SYSCALL(mon_udelay,SYSCALL_UDELAY)
- SYSCALL(mon_get_timer,SYSCALL_GET_TIMER)
-#endif /* CONFIG_ARM XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
diff --git a/examples/timer.c b/examples/timer.c
index bfe3d668d8..037fdfdb3a 100644
--- a/examples/timer.c
+++ b/examples/timer.c
@@ -24,7 +24,7 @@
#include <common.h>
#include <commproc.h>
#include <mpc8xx_irq.h>
-#include <syscall.h>
+#include <exports.h>
#undef DEBUG
@@ -123,10 +123,12 @@ int timer (int argc, char *argv[])
int c;
int running;
+ app_startup(argv);
+
/* Pointer to CPM Timer structure */
cpmtimerp = &((immap_t *) gd->bd->bi_immr_base)->im_cpmtimer;
- mon_printf ("TIMERS=0x%x\n", (unsigned) cpmtimerp);
+ printf ("TIMERS=0x%x\n", (unsigned) cpmtimerp);
/* Initialize pointers depending on which timer we use */
switch (TID_TIMER_ID) {
@@ -166,7 +168,7 @@ int timer (int argc, char *argv[])
hwp->tgcrp = &cpmtimerp->cpmt_tgcr;
- mon_printf ("Using timer %d\n"
+ printf ("Using timer %d\n"
"tgcr @ 0x%x, tmr @ 0x%x, trr @ 0x%x,"
" tcr @ 0x%x, tcn @ 0x%x, ter @ 0x%x\n",
TID_TIMER_ID + 1,
@@ -184,24 +186,24 @@ int timer (int argc, char *argv[])
/* clear all events */
*hwp->terp = (CPMT_EVENT_CAP | CPMT_EVENT_REF);
- mon_printf (usage);
+ printf (usage);
running = 0;
- while ((c = mon_getc()) != 'q') {
+ while ((c = getc()) != 'q') {
if (c == 'b') {
setPeriod (hwp, TIMER_PERIOD); /* Set period and start ticking */
/* Install interrupt handler (enable timer in CIMR) */
- mon_install_hdlr (hwp->cpm_vec, timer_handler, hwp);
+ install_hdlr (hwp->cpm_vec, timer_handler, hwp);
- mon_printf ("Enabling timer\n");
+ printf ("Enabling timer\n");
/* enable timer */
*hwp->tgcrp |= (CPMT_GCR_RST << TID_TIMER_ID);
running = 1;
#ifdef DEBUG
- mon_printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
+ printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
*hwp->tcrp, *hwp->tcnp, *hwp->terp
@@ -209,20 +211,20 @@ int timer (int argc, char *argv[])
#endif
} else if (c == 'e') {
- mon_printf ("Stopping timer\n");
+ printf ("Stopping timer\n");
*hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);
running = 0;
#ifdef DEBUG
- mon_printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
+ printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
*hwp->tcrp, *hwp->tcnp, *hwp->terp
);
#endif
/* Uninstall interrupt handler */
- mon_free_hdlr (hwp->cpm_vec);
+ free_hdlr (hwp->cpm_vec);
} else if (c == '?') {
#ifdef DEBUG
@@ -230,13 +232,13 @@ int timer (int argc, char *argv[])
sysconf8xx_t *siup = &((immap_t *) gd->bd->bi_immr_base)->im_siu_conf;
#endif
- mon_printf ("\ntgcr=0x%x, tmr=0x%x, trr=0x%x,"
+ printf ("\ntgcr=0x%x, tmr=0x%x, trr=0x%x,"
" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
*hwp->tcrp, *hwp->tcnp, *hwp->terp
);
#ifdef DEBUG
- mon_printf ("SIUMCR=0x%08lx, SYPCR=0x%08lx,"
+ printf ("SIUMCR=0x%08lx, SYPCR=0x%08lx,"
" SIMASK=0x%08lx, SIPEND=0x%08lx\n",
siup->sc_siumcr,
siup->sc_sypcr,
@@ -244,21 +246,21 @@ int timer (int argc, char *argv[])
siup->sc_sipend
);
- mon_printf ("CIMR=0x%08lx, CICR=0x%08lx, CIPR=0x%08lx\n",
+ printf ("CIMR=0x%08lx, CICR=0x%08lx, CIPR=0x%08lx\n",
cpm_icp->cpic_cimr,
cpm_icp->cpic_cicr,
cpm_icp->cpic_cipr
);
#endif
} else {
- mon_printf ("\nEnter: q - quit, b - start timer, e - stop timer, ? - get status\n");
+ printf ("\nEnter: q - quit, b - start timer, e - stop timer, ? - get status\n");
}
- mon_printf (usage);
+ printf (usage);
}
if (running) {
- mon_printf ("Stopping timer\n");
+ printf ("Stopping timer\n");
*hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);
- mon_free_hdlr (hwp->cpm_vec);
+ free_hdlr (hwp->cpm_vec);
}
return (0);
@@ -274,11 +276,11 @@ void setPeriod (tid_8xx_cpmtimer_t *hwp, ulong interval)
unsigned short prescaler;
unsigned long ticks;
- mon_printf ("Set interval %ld us\n", interval);
+ printf ("Set interval %ld us\n", interval);
/* Warn if requesting longer period than possible */
if (interval > CPMT_MAX_INTERVAL) {
- mon_printf ("Truncate interval %ld to maximum (%d)\n",
+ printf ("Truncate interval %ld to maximum (%d)\n",
interval, CPMT_MAX_INTERVAL);
interval = CPMT_MAX_INTERVAL;
}
@@ -303,7 +305,7 @@ void setPeriod (tid_8xx_cpmtimer_t *hwp, ulong interval)
}
#ifdef DEBUG
- mon_printf ("clock/%d, prescale factor %d, reference %ld, ticks %ld\n",
+ printf ("clock/%d, prescale factor %d, reference %ld, ticks %ld\n",
(ticks > CPMT_MAX_TICKS) ? CPMT_CLOCK_DIV : 1,
CPMT_PRESCALER,
(ticks / CPMT_PRESCALER),
@@ -321,7 +323,7 @@ void setPeriod (tid_8xx_cpmtimer_t *hwp, ulong interval)
*hwp->trrp = (unsigned short) (ticks / CPMT_PRESCALER);
#ifdef DEBUG
- mon_printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
+ printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
*hwp->tcrp, *hwp->tcnp, *hwp->terp
@@ -340,7 +342,7 @@ void timer_handler (void *arg)
/* printf ("** TER1=%04x ** ", *hwp->terp); */
/* just for demonstration */
- mon_printf (".");
+ printf (".");
/* clear all possible events: Ref. and Cap. */
*hwp->terp = (CPMT_EVENT_CAP | CPMT_EVENT_REF);
OpenPOWER on IntegriCloud