summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libmisc')
-rw-r--r--cpukit/libmisc/.cvsignore2
-rw-r--r--cpukit/libmisc/Makefile.am331
-rw-r--r--cpukit/libmisc/README23
-rw-r--r--cpukit/libmisc/capture/README255
-rw-r--r--cpukit/libmisc/capture/capture-cli.c1470
-rw-r--r--cpukit/libmisc/capture/capture-cli.h52
-rw-r--r--cpukit/libmisc/capture/capture.c1569
-rw-r--r--cpukit/libmisc/capture/capture.h869
-rw-r--r--cpukit/libmisc/cpuuse/README41
-rw-r--r--cpukit/libmisc/cpuuse/cpuuse.c148
-rw-r--r--cpukit/libmisc/cpuuse/cpuuse.h40
-rw-r--r--cpukit/libmisc/devnull/devnull.c184
-rw-r--r--cpukit/libmisc/devnull/devnull.h71
-rw-r--r--cpukit/libmisc/dummy/README23
-rw-r--r--cpukit/libmisc/dummy/dummy.c45
-rw-r--r--cpukit/libmisc/dumpbuf/dumpbuf.c79
-rw-r--r--cpukit/libmisc/dumpbuf/dumpbuf.h21
-rw-r--r--cpukit/libmisc/fsmount/README24
-rw-r--r--cpukit/libmisc/fsmount/fsmount.c195
-rw-r--r--cpukit/libmisc/fsmount/fsmount.h71
-rw-r--r--cpukit/libmisc/monitor/README97
-rw-r--r--cpukit/libmisc/monitor/mon-command.c745
-rw-r--r--cpukit/libmisc/monitor/mon-config.c134
-rw-r--r--cpukit/libmisc/monitor/mon-dname.c116
-rw-r--r--cpukit/libmisc/monitor/mon-driver.c140
-rw-r--r--cpukit/libmisc/monitor/mon-extension.c102
-rw-r--r--cpukit/libmisc/monitor/mon-itask.c119
-rw-r--r--cpukit/libmisc/monitor/mon-manager.c54
-rw-r--r--cpukit/libmisc/monitor/mon-monitor.c591
-rw-r--r--cpukit/libmisc/monitor/mon-mpci.c162
-rw-r--r--cpukit/libmisc/monitor/mon-object.c387
-rw-r--r--cpukit/libmisc/monitor/mon-prmisc.c268
-rw-r--r--cpukit/libmisc/monitor/mon-queue.c68
-rw-r--r--cpukit/libmisc/monitor/mon-server.c307
-rw-r--r--cpukit/libmisc/monitor/mon-symbols.c486
-rw-r--r--cpukit/libmisc/monitor/mon-task.c96
-rw-r--r--cpukit/libmisc/monitor/monitor.h459
-rw-r--r--cpukit/libmisc/monitor/symbols.h64
-rw-r--r--cpukit/libmisc/mw-fb/mw_fb.c194
-rw-r--r--cpukit/libmisc/mw-fb/mw_fb.h170
-rw-r--r--cpukit/libmisc/mw-fb/mw_uid.c248
-rw-r--r--cpukit/libmisc/mw-fb/mw_uid.h160
-rw-r--r--cpukit/libmisc/rtmonuse/rtmonuse.c208
-rw-r--r--cpukit/libmisc/rtmonuse/rtmonuse.h18
-rw-r--r--cpukit/libmisc/serdbg/README138
-rw-r--r--cpukit/libmisc/serdbg/serdbg.c94
-rw-r--r--cpukit/libmisc/serdbg/serdbg.h174
-rw-r--r--cpukit/libmisc/serdbg/serdbgcnf.h81
-rw-r--r--cpukit/libmisc/serdbg/serdbgio.c256
-rw-r--r--cpukit/libmisc/serdbg/termios_printk.c237
-rw-r--r--cpukit/libmisc/serdbg/termios_printk.h95
-rw-r--r--cpukit/libmisc/serdbg/termios_printk_cnf.h70
-rw-r--r--cpukit/libmisc/shell/README27
-rw-r--r--cpukit/libmisc/shell/cmds.c526
-rw-r--r--cpukit/libmisc/shell/shell.c682
-rw-r--r--cpukit/libmisc/shell/shell.h88
-rw-r--r--cpukit/libmisc/stackchk/README56
-rw-r--r--cpukit/libmisc/stackchk/check.c553
-rw-r--r--cpukit/libmisc/stackchk/internal.h95
-rw-r--r--cpukit/libmisc/stackchk/stackchk.h82
-rw-r--r--cpukit/libmisc/untar/README26
-rw-r--r--cpukit/libmisc/untar/untar.c385
-rw-r--r--cpukit/libmisc/untar/untar.h25
63 files changed, 14596 insertions, 0 deletions
diff --git a/cpukit/libmisc/.cvsignore b/cpukit/libmisc/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/libmisc/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
new file mode 100644
index 0000000000..1d1cd18209
--- /dev/null
+++ b/cpukit/libmisc/Makefile.am
@@ -0,0 +1,331 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_DIST = README
+
+AM_CPPFLAGS += -I$(top_builddir)
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS =
+EXTRA_LIBRARIES =
+TMP_LIBS =
+CLEANFILES =
+
+## capture
+EXTRA_DIST += capture/README
+include_rtems_HEADERS += capture/capture.h capture/capture-cli.h
+
+EXTRA_LIBRARIES += libcapture.a
+CLEANFILES += libcapture.a
+libcapture_a_SOURCES = capture/capture.c capture/capture-cli.c
+libcapture_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libcapture_g.a
+CLEANFILES += libcapture_g.a
+libcapture_g_a_SOURCES = $(libcapture_a_SOURCES)
+libcapture_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libcapture$(LIB_VARIANT).a
+
+## cpuuse
+EXTRA_DIST += cpuuse/README
+include_rtems_HEADERS += cpuuse/cpuuse.h
+
+EXTRA_LIBRARIES += libcpuuse.a
+CLEANFILES += libcpuuse.a
+libcpuuse_a_SOURCES = cpuuse/cpuuse.c
+libcpuuse_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libcpuuse_g.a
+CLEANFILES += libcpuuse_g.a
+libcpuuse_g_a_SOURCES = $(libcpuuse_a_SOURCES)
+libcpuuse_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libcpuuse$(LIB_VARIANT).a
+
+## devnull
+include_rtems_HEADERS += devnull/devnull.h
+
+EXTRA_LIBRARIES += libdevnull.a
+CLEANFILES += libdevnull.a
+libdevnull_a_SOURCES = devnull/devnull.c
+libdevnull_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libdevnull_g.a
+CLEANFILES += libdevnull_g.a
+libdevnull_g_a_SOURCES = $(libdevnull_a_SOURCES)
+libdevnull_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libdevnull$(LIB_VARIANT).a
+
+## dummy
+EXTRA_DIST += dummy/README
+
+EXTRA_LIBRARIES += libdummy.a
+CLEANFILES += libdummy.a
+libdummy_a_SOURCES = dummy/dummy.c
+libdummy_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libdummy_g.a
+CLEANFILES += libdummy_g.a
+libdummy_g_a_SOURCES = $(libdummy_a_SOURCES)
+libdummy_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libdummy$(LIB_VARIANT).a
+
+## dumpbuf
+include_rtems_HEADERS += dumpbuf/dumpbuf.h
+
+EXTRA_LIBRARIES += libdumpbuf.a
+CLEANFILES += libdumpbuf.a
+libdumpbuf_a_SOURCES = dumpbuf/dumpbuf.c
+libdumpbuf_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libdumpbuf_g.a
+CLEANFILES += libdumpbuf_g.a
+libdumpbuf_g_a_SOURCES = $(libdumpbuf_a_SOURCES)
+libdumpbuf_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libdumpbuf$(LIB_VARIANT).a
+
+## monitor
+
+include_rtems_HEADERS += monitor/monitor.h
+libmonitor_a_SOURCES = monitor/mon-command.c monitor/mon-symbols.c \
+ monitor/mon-prmisc.c monitor/mon-monitor.c monitor/mon-object.c \
+ monitor/mon-server.c monitor/mon-task.c monitor/mon-queue.c \
+ monitor/mon-driver.c monitor/mon-dname.c monitor/mon-itask.c \
+ monitor/mon-extension.c monitor/mon-manager.c monitor/mon-config.c \
+ monitor/symbols.h
+if HAS_MP
+libmonitor_a_SOURCES += monitor/mon-mpci.c
+endif
+
+EXTRA_LIBRARIES += libmonitor.a
+CLEANFILES += libmonitor.a
+libmonitor_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libmonitor_g.a
+CLEANFILES += libmonitor_g.a
+libmonitor_g_a_SOURCES = $(libmonitor_a_SOURCES)
+libmonitor_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+EXTRA_DIST += monitor/README
+
+TMP_LIBS += libmonitor$(LIB_VARIANT).a
+
+## mw-fb
+include_rtems_HEADERS += mw-fb/mw_fb.h mw-fb/mw_uid.h
+
+EXTRA_LIBRARIES += libmw-fb.a
+CLEANFILES += libmw-fb.a
+libmw_fb_a_SOURCES = mw-fb/mw_fb.c mw-fb/mw_uid.c
+libmw_fb_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libmw-fb_g.a
+CLEANFILES += libmw-fb_g.a
+libmw_fb_g_a_SOURCES = $(libmw_fb_a_SOURCES)
+libmw_fb_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libmw-fb$(LIB_VARIANT).a
+
+## shell
+
+if LIBSHELL
+include_rtems_HEADERS += shell/shell.h
+
+EXTRA_LIBRARIES += libshell.a
+CLEANFILES += libshell.a
+libshell_a_SOURCES = shell/cmds.c shell/shell.c
+libshell_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libshell_g.a
+CLEANFILES += libshell_g.a
+libshell_g_a_SOURCES = $(libshell_a_SOURCES)
+libshell_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libshell$(LIB_VARIANT).a
+endif
+
+EXTRA_DIST += shell/README
+
+## rtmonuse
+include_rtems_HEADERS += rtmonuse/rtmonuse.h
+
+EXTRA_LIBRARIES += librtmonuse.a
+CLEANFILES += librtmonuse.a
+librtmonuse_a_SOURCES = rtmonuse/rtmonuse.c
+librtmonuse_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += librtmonuse_g.a
+CLEANFILES += librtmonuse_g.a
+librtmonuse_g_a_SOURCES = $(librtmonuse_a_SOURCES)
+librtmonuse_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += librtmonuse$(LIB_VARIANT).a
+
+## serdbg
+
+if LIBSERDBG
+include_rtems_HEADERS += serdbg/serdbgcnf.h serdbg/serdbg.h \
+ serdbg/termios_printk_cnf.h serdbg/termios_printk.h
+
+EXTRA_LIBRARIES += libserdbg.a
+CLEANFILES += libserdbg.a
+libserdbg_a_SOURCES = serdbg/serdbg.c serdbg/serdbgio.c \
+ serdbg/termios_printk.c
+libserdbg_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libserdbg_g.a
+CLEANFILES += libserdbg_g.a
+libserdbg_g_a_SOURCES = $(libserdbg_a_SOURCES)
+libserdbg_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libserdbg$(LIB_VARIANT).a
+endif
+
+EXTRA_DIST += serdbg/README
+
+## stackchk
+
+include_rtems_HEADERS += stackchk/stackchk.h
+
+EXTRA_LIBRARIES += libstackchk.a
+CLEANFILES += libstackchk.a
+libstackchk_a_SOURCES = stackchk/check.c stackchk/internal.h
+libstackchk_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libstackchk_g.a
+CLEANFILES += libstackchk_g.a
+libstackchk_g_a_SOURCES = $(libstackchk_a_SOURCES)
+libstackchk_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libstackchk$(LIB_VARIANT).a
+EXTRA_DIST += stackchk/README
+
+## libuntar
+
+include_rtems_HEADERS += untar/untar.h
+
+EXTRA_LIBRARIES += libuntar.a
+CLEANFILES += libuntar.a
+libuntar_a_SOURCES = untar/untar.c
+libuntar_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libuntar_g.a
+CLEANFILES += libuntar_g.a
+libuntar_g_a_SOURCES = $(libuntar_a_SOURCES)
+libuntar_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libuntar$(LIB_VARIANT).a
+
+EXTRA_DIST += untar/README
+
+## fsmount
+include_rtems_HEADERS += fsmount/fsmount.h
+
+EXTRA_LIBRARIES += libfsmount.a
+CLEANFILES += libfsmount.a
+libfsmount_a_SOURCES = fsmount/fsmount.c
+libfsmount_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libfsmount_g.a
+CLEANFILES += libfsmount_g.a
+libfsmount_g_a_SOURCES = $(libfsmount_a_SOURCES)
+libfsmount_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libfsmount$(LIB_VARIANT).a
+
+EXTRA_DIST += fsmount/README
+
+## ---
+
+all-local: $(PREINSTALL_FILES) $(TMP_LIBS)
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/capture.h: capture/capture.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/capture.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/capture.h
+
+$(PROJECT_INCLUDE)/rtems/capture-cli.h: capture/capture-cli.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/capture-cli.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/capture-cli.h
+
+$(PROJECT_INCLUDE)/rtems/cpuuse.h: cpuuse/cpuuse.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/cpuuse.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/cpuuse.h
+
+$(PROJECT_INCLUDE)/rtems/devnull.h: devnull/devnull.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/devnull.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/devnull.h
+
+$(PROJECT_INCLUDE)/rtems/dumpbuf.h: dumpbuf/dumpbuf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/dumpbuf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/dumpbuf.h
+
+$(PROJECT_INCLUDE)/rtems/monitor.h: monitor/monitor.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/monitor.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/monitor.h
+
+$(PROJECT_INCLUDE)/rtems/mw_fb.h: mw-fb/mw_fb.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mw_fb.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mw_fb.h
+
+$(PROJECT_INCLUDE)/rtems/mw_uid.h: mw-fb/mw_uid.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mw_uid.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mw_uid.h
+
+if LIBSHELL
+$(PROJECT_INCLUDE)/rtems/shell.h: shell/shell.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/shell.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/shell.h
+endif
+
+$(PROJECT_INCLUDE)/rtems/rtmonuse.h: rtmonuse/rtmonuse.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtmonuse.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtmonuse.h
+
+if LIBSERDBG
+$(PROJECT_INCLUDE)/rtems/serdbgcnf.h: serdbg/serdbgcnf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/serdbgcnf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/serdbgcnf.h
+
+$(PROJECT_INCLUDE)/rtems/serdbg.h: serdbg/serdbg.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/serdbg.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/serdbg.h
+
+$(PROJECT_INCLUDE)/rtems/termios_printk_cnf.h: serdbg/termios_printk_cnf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/termios_printk_cnf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/termios_printk_cnf.h
+
+$(PROJECT_INCLUDE)/rtems/termios_printk.h: serdbg/termios_printk.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/termios_printk.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/termios_printk.h
+endif
+
+$(PROJECT_INCLUDE)/rtems/stackchk.h: stackchk/stackchk.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/stackchk.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/stackchk.h
+
+$(PROJECT_INCLUDE)/rtems/untar.h: untar/untar.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/untar.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/untar.h
+
+$(PROJECT_INCLUDE)/rtems/fsmount.h: fsmount/fsmount.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/fsmount.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/fsmount.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libmisc/README b/cpukit/libmisc/README
new file mode 100644
index 0000000000..bbde4feeae
--- /dev/null
+++ b/cpukit/libmisc/README
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This directory contains for the "miscellaneous" library. Currently
+this library contains a number of useful support libraries:
+
+ + Task Stack Overflow Checker
+ + Workspace Consistency Checker
+ + Task Execution Time Monitor
+ + Period Statistics Monitor
+ + Debug Monitor
+
+The following ideas have been mentioned for items which could go
+in this library, but this list is not all inclusive:
+
+ + there are no outstanding suggestions.
+
+The intent of this library is to provide a home for useful utility routines
+which are dependent upon RTEMS.
+
+--joel
+16 Sept 97
diff --git a/cpukit/libmisc/capture/README b/cpukit/libmisc/capture/README
new file mode 100644
index 0000000000..2ea76a4cfe
--- /dev/null
+++ b/cpukit/libmisc/capture/README
@@ -0,0 +1,255 @@
+#
+# $Id$
+#
+
+ RTEMS Performance Monitoring and Measurement Framework
+
+ Copyright 2002 Chris Johns (ccj@acm.org)
+ 23 April 2002
+
+This directory contains the source code for the performance monitoring and
+measurement framework. It is more commonly know as the capture engine.
+
+The capture engine is in an early phase of development. Please review the Status
+section of this document for the current status.
+
+Performance.
+
+The capture engine is designed to not effect the system it is
+monitoring. Resources such as memory are used as well as a small performance
+hit in task creation, deletion and context switch. The overhead is small and
+will not be noticed unless the system is operating close to the performance
+limit of the target.
+
+Structure.
+
+The capture engine is implemented in a couple of layers. This lowest layer is
+the capture engine. Its interface is in the file 'capture.h'. Typically this
+interface is directly used unless you are implementing a target interface. The
+user interface is via a target interface.
+
+Command Line Interface (CLI).
+
+This is a target interface that provides a number of user commands via the
+RTEMS monitor. To use you need to provide the following in your
+application initialisation:
+
+ #include <rtems/monitor.h>
+ #include <rtems/capture-cli.h>
+
+ rtems_monitor_init (0);
+ rtems_capture_cli_init (0);
+
+Check the file capture-cli.h for documentation of the interface. The parameter
+is a pointer to your board support package's time stamp handler. The time stamp
+handler is yet to be tested so it is recommended this is left as 0, unless you
+wish to test this part of the engine.
+
+The commands are:
+
+ copen - Open the capture engine.
+ cclose - Close the capture engine.
+ cenable - Enable the capture engine.
+ cdisable - Disable the capture engine.
+ ctlist - List the tasks known to the capture engine.
+ ctload - Display the current load (sort of top).
+ cwlist - List the watch and trigger controls.
+ cwadd - Add a watch.
+ cwdel - Delete a watch.
+ cwctl - Enable or disable a watch.
+ cwglob - Enable or disable the global watch.
+ cwceil - Set the watch ceiling.
+ cwfloor - Set the watch floor.
+ ctrace - Dump the trace records.
+ ctrig - Define a trigger.
+
+Open
+
+ usage: copen [-i] size
+
+Open the capture engine. The size parameter is the size of the capture engine
+trace buffer. A single record hold a single event, for example a task create or
+a context in or out. The option '-i' will enable the capture engine after it is
+opened.
+
+Close
+
+ usage: cclose
+
+Close the capture engine and release all resources held by the capture engine.
+
+Enable
+
+ usage: cenable
+
+Enable the capture engine if it has been opened.
+
+Disable
+
+ usage: cdisable
+
+Disable the capture engine. The enable and disable commands provide a means of
+removing the overhead of the capture engine from the context switch. This may
+be needed when testing if it is felt the capture engines overhead is effecting
+the system.
+
+Task List
+
+ usage: ctlist
+
+List the tasks the capture engine knows about. This may contain tasks that have
+been deleted.
+
+Task Load
+
+ usage: ctload
+
+List the tasks in the order of load in a similar way top does on Unix. The
+command sends ANSI terminal codes. You press enter to stop the update. The
+update period is fixed at 5 seconds. The output looks like:
+
+ Press ENTER to exit.
+
+ PID NAME RPRI CPRI STATE %CPU %STK FLGS EXEC TIME
+04010001 IDLE 255 255 READY 96.012% 0% a-----g 1
+08010009 CPlt 1 1 READY 3.815% 15% a------ 0
+08010003 ntwk 20 20 Wevnt 0.072% 0% at----g 0
+08010004 CSr0 20 20 Wevnt 0.041% 0% at----g 0
+08010001 main 250 250 DELAY 0.041% 0% a-----g 0
+08010008 test 100 100 Wevnt 0.000% 20% at-T-+g 0
+08010007 test 100 100 Wevnt 0.000% 0% at-T-+g 0
+08010005 CSt0 20 20 Wevnt 0.000% 0% at----g 0
+08010006 RMON 1 1 Wsem 0.000% 0% a------ 0
+
+There are 7 flags and from left to right are:
+
+1) 'a' the task is active, and 'd' the task has been deleted.
+2) 't' the task has been traced.
+3) 'F' the task has a from (TO_ANY) trigger.
+4) 'T' the task has a to (FROM_ANY) trigger.
+5) 'E' the task has an edge (FROM_TO) trigger.
+6) '+' the task as a watch control attached, 'w' a watch is enabled.
+7) 'g' the task is part of a global trigger.
+
+The %STK is the percentage of stack used by a task. Currently only tasks
+created while the capture engine is enabled can be monitored.
+
+The RPRI is the real priority. This is the priority set for the task. The
+current priority is the executing priority that may reflect a level set as a
+result of priority inversion.
+
+Watch List
+
+ usage: cwlist
+
+This command lists the watch and trigger controls the capture engine has. A
+control is a structure used by the capture engine to determine if a task is
+watched or triggers capturing.
+
+Watch Add
+
+ usage: cwadd [task name] [id]
+
+Add a watch for a task. You can provide a name or id or both. A name will cause
+all tasks with that name to have the watch added. An id results in a watch
+being for a specific task.
+
+Using a name is useful when the task is not yet created.
+
+Watch Delete
+
+ usage: cwdel [task name] [id]
+
+Delete a watch that has been added.
+
+Watch Control
+
+ usage: cwctl [task name] [id] on/off
+
+Enable or disable a watch. The name and id parameters are the same as the watch
+add command.
+
+Global Watch
+
+ usage: cwglob on/off
+
+Enable or disable the global watch. A global watch is an easy way to enable
+watches for all tasks with real priorities between the watch ceiling and floor
+priorities.
+
+Watch Priority Ceiling
+
+ usage: cwceil priority
+
+Set the watch priority ceiling. All tasks with a priority less than the ceiling
+priority are not watched. This allow you to ignore high priority system and
+driver tasks.
+
+Watch Priority Floor
+
+ usage: cwfloor priority
+
+Set the watch priority floor. All tasks with a priority greater than the floor
+priority level are not watched. This allows you to remove tasks such as IDLE
+from being monitored.
+
+Trace
+
+ usage: ctrace [-c] [-r records]
+
+Dump the trace record. The option '-c' will output the records in comma
+separated variables (CSV). The '-r' option controls the number of records
+dumped. This can help stop the command looping for-ever.
+
+Trigger
+
+ usage: ctrig type [from name] [from id] [to name] [to id]
+
+Set a trigger. The types of triggers are :
+
+ from : trigger on a context switch from a task
+ to : trigger on a context switch to a task
+ edge : trigger on a context switch from a task to a task
+
+The from and to trigger types requires a task name or task id or both be
+provided. The edge requires a from name and/or id and a to name and/or id be
+provided.
+
+Flush
+
+ usage: cflush [-n]
+
+Flush the trace record. The option '-n' stops the capture engine be
+primed. This means an exising trigger state will not be cleared and tracing
+will continue.
+
+Status.
+
+The following is a list of outstanding issues or bugs.
+
+1) The capture engine does not scan the existing list of tasks in the kernel
+ when initialised. This means tasks that exist but are not active are not
+ seen. Not sure how to implement this one.
+
+2) The blocking read of trace records has not been completely implemented or
+ tested. This will wait until I complete the csv support for the cli for a
+ serial UI or the tcp server is implemented.
+
+3) Task control block clean up is not implemented. The control block should be
+ dumped to the trace buffer. This requires extended record formats. This can
+ be implemented using an event flag to indicate an extended record follows
+ the trace record. This would allow a task delete record to be directly
+ followed by the task information.
+
+4) Complete csv (comma separated variable) support for the CLI.
+
+5) Implement a tcp server interface.
+
+6) Complete the capture engine API documentation.
+
+7) Test the user supplied time stamp handler.
+
+8) Task name support is only for the rtems_name type. This means the only the
+ classic API tasks are currently supported. Partial support for the different
+ task names is provided how-ever this is not clean and does not support the
+ variable length task name such as found in the POSIX tasks.
diff --git a/cpukit/libmisc/capture/capture-cli.c b/cpukit/libmisc/capture/capture-cli.c
new file mode 100644
index 0000000000..ca5041d768
--- /dev/null
+++ b/cpukit/libmisc/capture/capture-cli.c
@@ -0,0 +1,1470 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Target Interface Command Line Interface. You need
+ start the RTEMS monitor.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/capture-cli.h>
+#include <rtems/monitor.h>
+
+#define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS (32)
+
+/*
+ * The user capture timestamper.
+ */
+static rtems_capture_timestamp capture_timestamp;
+
+/*
+ * Common variable to sync the load monitor task.
+ */
+static volatile int cli_load_thread_active;
+
+/*
+ * rtems_capture_cli_open
+ *
+ * DESCRIPTION:
+ *
+ * This function opens the capture engine. We need the size of the
+ * capture buffer.
+ *
+ */
+
+static const char* open_usage = "usage: copen [-i] size\n";
+
+static void
+rtems_capture_cli_open (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ uint32_t size = 0;
+ rtems_boolean enable = 0;
+ rtems_status_code sc;
+ int arg;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,open_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'i')
+ enable = 1;
+ else
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ size = strtoul (argv[arg], 0, 0);
+
+ if (size < 100)
+ {
+ fprintf(stdout,"error: size must be greater than or equal to 100\n");
+ return;
+ }
+ }
+ }
+
+ sc = rtems_capture_open (size, capture_timestamp);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: open failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine opened.\n");
+
+ if (!enable)
+ return;
+
+ sc = rtems_capture_control (enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: open enable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine enabled.\n");
+}
+
+/*
+ * rtems_capture_cli_close
+ *
+ * DESCRIPTION:
+ *
+ * This function closes the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_close (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_close ();
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: close failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine closed.\n");
+}
+
+/*
+ * rtems_capture_cli_enable
+ *
+ * DESCRIPTION:
+ *
+ * This function enables the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_enable (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_control (1);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: enable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine enabled.\n");
+}
+
+/*
+ * rtems_capture_cli_disable
+ *
+ * DESCRIPTION:
+ *
+ * This function disables the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_disable (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_control (0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: disable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine disabled.\n");
+}
+
+/*
+ * rtems_capture_cli_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function lists the tasks the capture engine knows about.
+ *
+ */
+
+static void
+rtems_capture_cli_task_list (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+ rtems_capture_task_t* task = rtems_capture_get_task_list ();
+ uint32_t ticks;
+ uint32_t tick_offset;
+ unsigned long long total_time;
+ int count = rtems_capture_task_count ();
+
+ if (capture_timestamp)
+ capture_timestamp (&ticks, &tick_offset);
+ else
+ {
+ ticks = _Watchdog_Ticks_since_boot;
+ tick_offset = 0;
+ }
+
+ total_time = (ticks * rtems_capture_task_time (task)) + tick_offset;
+
+ fprintf(stdout,"total %i\n", count);
+
+ while (task)
+ {
+ rtems_task_priority priority;
+ int stack_used;
+ int time_used;
+
+ stack_used = rtems_capture_task_stack_usage (task) * 100;
+ stack_used /= rtems_capture_task_stack_size (task);
+
+ if (stack_used > 100)
+ stack_used = 100;
+
+ time_used = (rtems_capture_task_time (task) * 100) / total_time;
+
+ if (time_used > 100)
+ time_used = 100;
+
+ priority = rtems_capture_task_real_priority (task);
+
+ fprintf(stdout," ");
+ rtems_monitor_dump_id (rtems_capture_task_id (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_name (rtems_capture_task_name (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (rtems_capture_task_start_priority (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (rtems_capture_task_real_priority (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (rtems_capture_task_curr_priority (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_state (rtems_capture_task_state (task));
+ fprintf(stdout," %c%c%c%c%c",
+ rtems_capture_task_valid (task) ? 'a' : 'd',
+ rtems_capture_task_flags (task) & RTEMS_CAPTURE_TRACED ? 't' : '-',
+ rtems_capture_task_control_flags (task) & RTEMS_CAPTURE_TO_ANY ? 'F' : '-',
+ rtems_capture_task_control_flags (task) & RTEMS_CAPTURE_FROM_ANY ? 'T' : '-',
+ rtems_capture_task_control_flags (task) & RTEMS_CAPTURE_FROM_TO ? 'E' : '-');
+ if ((floor > ceiling) && (ceiling > priority))
+ fprintf(stdout,"--");
+ else
+ fprintf(stdout,"%c%c",
+ rtems_capture_task_control (task) ?
+ (rtems_capture_task_control_flags (task) & RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
+ rtems_capture_watch_global_on () ? 'g' : '-');
+ fprintf(stdout," %3i%% %3i%% (%i)\n",
+ stack_used, time_used, rtems_capture_task_ticks (task));
+
+ task = rtems_capture_next_task (task);
+ }
+}
+
+/*
+ * rtems_capture_cli_task_load_thread
+ *
+ * DESCRIPTION:
+ *
+ * This function displays the load of the tasks on an ANSI terminal.
+ *
+ */
+
+static void
+rtems_capture_cli_task_load_thread (rtems_task_argument arg)
+{
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+ int last_count = 0;
+
+ fprintf(stdout,"\x1b[2J Press ENTER to exit.\n\n");
+ fprintf(stdout," PID NAME RPRI CPRI STATE %%CPU %%STK FLGS EXEC TIME\n");
+
+ for (;;)
+ {
+ rtems_capture_task_t* tasks[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1];
+ unsigned long long load[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1];
+ rtems_capture_task_t* task;
+ unsigned long long total_time;
+ int count = 0;
+ int i;
+ int j;
+
+ cli_load_thread_active = 1;
+
+ /*
+ * Iterate over the tasks and sort the highest load tasks
+ * into our local arrays. We only handle a limited number of
+ * tasks.
+ */
+
+ memset (tasks, 0, sizeof (tasks));
+ memset (load, 0, sizeof (load));
+
+ task = rtems_capture_get_task_list ();
+
+ while (task)
+ {
+ if (rtems_capture_task_valid (task))
+ {
+ unsigned long long l = rtems_capture_task_delta_time (task);
+
+ count++;
+
+ for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++)
+ {
+ if (tasks[i])
+ {
+ if ((l == 0) || (l < load[i]))
+ continue;
+
+ for (j = (RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - 1); j >= i; j--)
+ {
+ tasks[j + 1] = tasks[j];
+ load[j + 1] = load[j];
+ }
+ }
+
+ tasks[i] = task;
+ load[i] = l;
+ break;
+ }
+ }
+ task = rtems_capture_next_task (task);
+ }
+
+ fprintf(stdout,"\x1b[4;0H");
+
+ total_time = 0;
+
+ for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++)
+ total_time += load[i];
+
+ if (count > last_count)
+ j = count;
+ else
+ j = last_count;
+
+ for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++)
+ {
+ rtems_task_priority priority;
+ int stack_used;
+ int task_load;
+ int k;
+
+ if (!tasks[i])
+ break;
+
+ j--;
+
+ stack_used = rtems_capture_task_stack_usage (tasks[i]) * 100;
+ stack_used /= rtems_capture_task_stack_size (tasks[i]);
+
+ if (stack_used > 100)
+ stack_used = 100;
+
+ task_load = (int) ((load[i] * 100000) / total_time);
+
+ priority = rtems_capture_task_real_priority (tasks[i]);
+
+ fprintf(stdout,"\x1b[K");
+ rtems_monitor_dump_id (rtems_capture_task_id (tasks[i]));
+ fprintf(stdout," ");
+ rtems_monitor_dump_name (rtems_capture_task_name (tasks[i]));
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (priority);
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tasks[i]));
+ fprintf(stdout," ");
+ k = rtems_monitor_dump_state (rtems_capture_task_state (tasks[i]));
+ fprintf(stdout,"%*c %3i.%03i%% ", 6 - k, ' ', task_load / 1000, task_load % 1000);
+ fprintf(stdout,"%3i%% %c%c%c%c%c", stack_used,
+ rtems_capture_task_valid (tasks[i]) ? 'a' : 'd',
+ rtems_capture_task_flags (tasks[i]) & RTEMS_CAPTURE_TRACED ? 't' : '-',
+ rtems_capture_task_control_flags (tasks[i]) & RTEMS_CAPTURE_TO_ANY ? 'F' : '-',
+ rtems_capture_task_control_flags (tasks[i]) & RTEMS_CAPTURE_FROM_ANY ? 'T' : '-',
+ rtems_capture_task_control_flags (tasks[i]) & RTEMS_CAPTURE_FROM_TO ? 'E' : '-');
+ if ((floor > ceiling) && (ceiling > priority))
+ fprintf(stdout,"--");
+ else
+ fprintf(stdout,"%c%c",
+ rtems_capture_task_control (tasks[i]) ?
+ (rtems_capture_task_control_flags (tasks[i]) &
+ RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
+ rtems_capture_watch_global_on () ? 'g' : '-');
+
+ fprintf(stdout," %qi\n", rtems_capture_task_time (tasks[i]));
+ }
+
+ while (j)
+ {
+ fprintf(stdout,"\x1b[K\n");
+ j--;
+ }
+
+ last_count = count;
+
+ cli_load_thread_active = 0;
+
+ rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (5000000));
+ }
+}
+
+/*
+ * rtems_capture_cli_task_load
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command.
+ *
+ */
+
+static void
+rtems_capture_cli_task_load (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ rtems_task_priority priority;
+ rtems_name name;
+ rtems_id id;
+
+ sc = rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: cannot obtain the current priority: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ memcpy (&name, "CPlt", 4);
+
+ sc = rtems_task_create (name, priority, 1024,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
+ &id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: cannot create helper thread: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ sc = rtems_task_start (id, rtems_capture_cli_task_load_thread, 0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: cannot start helper thread: %s\n", rtems_status_text (sc));
+ rtems_task_delete (id);
+ return;
+ }
+
+ for (;;)
+ {
+ int c = getchar ();
+
+ if ((c == '\r') || (c == '\n'))
+ {
+ int loops = 20;
+
+ while (loops && cli_load_thread_active)
+ rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (100000));
+
+ rtems_task_delete (id);
+
+ fprintf(stdout,"load monitoring stopped.\n");
+
+ return;
+ }
+ }
+}
+
+/*
+ * rtems_capture_cli_watch_list
+ *
+ * DESCRIPTION:
+ *
+ * This function lists the controls in the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_watch_list (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_capture_control_t* control = rtems_capture_get_control_list ();
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+
+ fprintf(stdout,"watch priority ceiling is %i\n", ceiling);
+ fprintf(stdout,"watch priority floor is %i\n", floor);
+ fprintf(stdout,"global watch is %s\n",
+ rtems_capture_watch_global_on () ? "enabled" : "disabled");
+ fprintf(stdout,"total %d\n", rtems_capture_control_count ());
+
+ while (control)
+ {
+ int f;
+ int fshowed;
+ int lf;
+
+ fprintf(stdout," ");
+ rtems_monitor_dump_id (rtems_capture_control_id (control));
+ fprintf(stdout," ");
+ rtems_monitor_dump_name (rtems_capture_control_name (control));
+ fprintf(stdout," %c%c%c%c%c",
+ rtems_capture_control_flags (control) & RTEMS_CAPTURE_WATCH ? 'w' : '-',
+ rtems_capture_watch_global_on () ? 'g' : '-',
+ rtems_capture_control_flags (control) & RTEMS_CAPTURE_TO_ANY ? 'F' : '-',
+ rtems_capture_control_flags (control) & RTEMS_CAPTURE_FROM_ANY ? 'T' : '-',
+ rtems_capture_control_flags (control) & RTEMS_CAPTURE_FROM_TO ? 'E' : '-');
+
+ for (f = 0, fshowed = 0, lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS; f++)
+ {
+ if (lf && ((fshowed % 16) == 0))
+ {
+ fprintf(stdout,"\n");
+ lf = 0;
+ }
+
+ /*
+ * FIXME: name test.
+ */
+ if (rtems_capture_control_from_name (control, f))
+ {
+ fprintf(stdout," %2i:", f);
+ rtems_monitor_dump_name (rtems_capture_control_from_name (control, f));
+ fprintf(stdout,"/");
+ rtems_monitor_dump_id (rtems_capture_control_from_id (control, f));
+ fshowed++;
+ lf = 1;
+ }
+ }
+
+ if (lf)
+ fprintf(stdout,"\n");
+
+ control = rtems_capture_next_control (control);
+ }
+}
+
+/*
+ * rtems_capture_cli_get_name_id
+ *
+ * DESCRIPTION:
+ *
+ * This function checks arguments for a name or an id.
+ *
+ */
+
+static rtems_boolean
+rtems_capture_cli_get_name_id (char* arg,
+ rtems_boolean* valid_name,
+ rtems_boolean* valid_id,
+ rtems_name* name,
+ rtems_id* id)
+{
+ uint32_t objclass;
+ int l;
+ int i;
+
+ if (*valid_name && *valid_id)
+ {
+ fprintf(stdout,"error: too many arguments\n");
+ return 0;
+ }
+
+ /*
+ * See if the arg is all hex digits.
+ */
+
+ l = strlen (arg);
+
+ for (i = 0; i < l; i++)
+ if (!isxdigit (arg[i]))
+ break;
+
+ *id = strtoul (arg, 0, 16);
+
+ objclass = _Objects_Get_class (*id);
+
+ if ((i == l))
+ *valid_id = 1;
+ else
+ {
+ memcpy (name, arg, sizeof (rtems_name));
+ *valid_name = 1;
+ }
+
+ return 1;
+}
+
+/*
+ * rtems_capture_cli_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that add a watch to the capture
+ * engine.
+ *
+ */
+
+static char const * watch_add_usage = "usage: cwadd [task name] [id]\n";
+
+static void
+rtems_capture_cli_watch_add (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ rtems_boolean valid_name = 0;
+ rtems_boolean valid_id = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_add_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf(stdout,"error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_add (name, id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch add failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch added.\n");
+}
+
+/*
+ * rtems_capture_cli_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that deletes a watch from the capture
+ * engine.
+ *
+ */
+
+static char const * watch_del_usage = "usage: cwdel [task name] [id]\n";
+
+static void
+rtems_capture_cli_watch_del (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ rtems_boolean valid_name = 0;
+ rtems_boolean valid_id = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_del_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf(stdout,"error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_del (name, id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch delete failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch delete.\n");
+}
+
+/*
+ * rtems_capture_cli_watch_control
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that controls a watch.
+ *
+ */
+
+static char const * watch_control_usage = "usage: cwctl [task name] [id] on/off\n";
+
+static void
+rtems_capture_cli_watch_control (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ rtems_boolean valid_name = 0;
+ rtems_boolean valid_id = 0;
+ rtems_boolean enable = 0;
+
+ if (argc <= 2)
+ {
+ fprintf(stdout,watch_control_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (strcmp (argv[arg], "on") == 0)
+ enable = 1;
+ else if (strcmp (argv[arg], "off") == 0)
+ enable = 0;
+ else if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf(stdout,"error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_ctrl (name, id, enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch control failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch %s.\n", enable ? "enabled" : "disabled");
+}
+
+/*
+ * rtems_capture_cli_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets a global watch.
+ *
+ */
+
+static char const * watch_global_usage = "usage: cwglob on/off\n";
+
+static void
+rtems_capture_cli_watch_global (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_boolean enable = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_global_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (strcmp (argv[arg], "on") == 0)
+ enable = 1;
+ else if (strcmp (argv[arg], "off") == 0)
+ enable = 0;
+ }
+ }
+
+ sc = rtems_capture_watch_global (enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: global watch failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"global watch %s.\n", enable ? "enabled" : "disabled");
+}
+
+/*
+ * rtems_capture_cli_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets watch ceiling.
+ *
+ */
+
+static char const * watch_ceiling_usage = "usage: cwceil priority\n";
+
+static void
+rtems_capture_cli_watch_ceiling (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_task_priority priority = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_ceiling_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ priority = strtoul (argv[arg], 0, 0);
+ }
+ }
+
+ sc = rtems_capture_watch_ceiling (priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch ceiling failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch ceiling is %i.\n", priority);
+}
+
+/*
+ * rtems_capture_cli_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets watch floor.
+ *
+ */
+
+static char const * watch_floor_usage = "usage: cwfloor priority\n";
+
+static void
+rtems_capture_cli_watch_floor (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_task_priority priority = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_floor_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ priority = strtoul (argv[arg], 0, 0);
+ }
+ }
+
+ sc = rtems_capture_watch_floor (priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch floor failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch floor is %i.\n", priority);
+}
+
+/*
+ * rtems_capture_cli_trigger_set
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets a trigger.
+ *
+ */
+
+static char const *trigger_set_usage = "usage: ctrig type [from] [fromid] [to] [to id]\n";
+
+static void
+rtems_capture_cli_trigger_set (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_capture_trigger_t trigger = rtems_capture_from_to;
+ rtems_boolean trigger_set = 0;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ rtems_boolean valid_name = 0;
+ rtems_boolean valid_id = 0;
+ rtems_name from_name = 0;
+ rtems_id from_id = 0;
+ rtems_boolean from_valid_name = 0;
+ rtems_boolean from_valid_id = 0;
+ rtems_name to_name = 0;
+ rtems_id to_id = 0;
+ rtems_boolean to_valid_name = 0;
+ rtems_boolean to_valid_id = 0;
+
+ if (argc <= 2)
+ {
+ fprintf(stdout,trigger_set_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (!trigger_set)
+ {
+ if (strcmp (argv[arg], "from") == 0)
+ trigger = rtems_capture_to_any;
+ else if (strcmp (argv[arg], "to") == 0)
+ trigger = rtems_capture_from_any;
+ else if (strcmp (argv[arg], "edge") == 0)
+ trigger = rtems_capture_from_any;
+ else
+ {
+ fprintf(stdout,"error: the first argument is the trigger type (from/to/edge)\n");
+ return;
+ }
+ trigger_set = 1;
+ }
+ else
+ {
+ if (trigger == rtems_capture_to_any)
+ {
+ if (from_valid_name && from_valid_id)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else if (!rtems_capture_cli_get_name_id (argv[arg], &from_valid_name, &from_valid_id,
+ &from_name, &from_id))
+ return;
+ }
+ else if (trigger == rtems_capture_from_any)
+ {
+ if (to_valid_name && to_valid_id)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else if (!rtems_capture_cli_get_name_id (argv[arg], &to_valid_name, &to_valid_id,
+ &to_name, &to_id))
+ return;
+ }
+ else if (trigger == rtems_capture_from_to)
+ {
+ if (from_valid_name && from_valid_id && to_valid_name && to_valid_id)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else
+ {
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id,
+ &name, &id))
+ return;
+
+ if (valid_name)
+ {
+ if (!from_valid_name && !from_valid_id)
+ {
+ from_valid_name = 1;
+ from_name = name;
+ }
+ else if (to_valid_name)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else
+ {
+ to_valid_name = 1;
+ to_name = name;
+ }
+ }
+ if (valid_id)
+ {
+ if (!from_valid_id && !to_valid_name)
+ {
+ from_valid_id = 1;
+ from_id = id;
+ }
+ else if (to_valid_id)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else
+ {
+ to_valid_id = 1;
+ to_id = id;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ((trigger == rtems_capture_to_any) && !from_valid_name && !from_valid_id)
+ {
+ fprintf(stdout,"error: a from trigger need a to name or id\n");
+ return;
+ }
+
+ if ((trigger == rtems_capture_from_any) && !to_valid_name && !to_valid_id)
+ {
+ fprintf(stdout,"error: a to trigger need a from name or id\n");
+ return;
+ }
+
+ if ((trigger == rtems_capture_from_to) &&
+ ((!from_valid_name && !from_valid_id) || (!to_valid_name && !to_valid_id)))
+ {
+ fprintf(stdout,"error: an edge trigger need a from and to name or id\n");
+ return;
+ }
+
+ sc = rtems_capture_set_trigger (from_name, from_id, to_name, to_id, trigger);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: setting the trigger failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"trigger set.\n");
+}
+
+/*
+ * rtems_capture_cli_trace_records
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that dumps trace records.
+ *
+ */
+
+static void
+rtems_capture_cli_trace_records (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ rtems_boolean csv = 0;
+ static int dump_total = 32;
+ int total;
+ int count;
+ uint32_t read;
+ rtems_capture_record_t* rec;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'c')
+ csv = 1;
+ else if (argv[arg][1] == 'r')
+ {
+ int i;
+ int l;
+
+ arg++;
+ if (arg == argc)
+ {
+ fprintf(stdout,"error: option -r requires number\n");
+ return;
+ }
+
+ l = strlen (argv[arg]);
+
+ for (i = 0; i < l; i++)
+ if (!isdigit (argv[arg][i]))
+ {
+ fprintf(stdout,"error: option -r requires number and currently it is not\n");
+ return;
+ }
+
+ dump_total = strtoul (argv[arg], 0, 0);
+ }
+ else
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ }
+
+ total = dump_total;
+
+ while (total)
+ {
+ sc = rtems_capture_read (0, 0, &read, &rec);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: trace read failed: %s\n", rtems_status_text (sc));
+ rtems_capture_flush (0);
+ return;
+ }
+
+ if (read == 0)
+ break;
+
+ for (count = 0; count < read; count++, rec++)
+ {
+ if (csv)
+ fprintf(stdout,"%08x,%03d,%03d,%04x,%d,%d\n",
+ (uint32_t ) rec->task,
+ (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_EVENT_START),
+ rec->ticks, rec->tick_offset);
+ else
+ {
+ unsigned long long t;
+ uint32_t event;
+ int e;
+
+ event = rec->events >> RTEMS_CAPTURE_EVENT_START;
+
+ t = rec->ticks;
+ t *= rtems_capture_tick_time ();
+ t += rec->tick_offset;
+
+ for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++)
+ {
+ if (event & 1)
+ {
+ fprintf(stdout,"%9li.%06li ", (unsigned long) (t / 1000000),
+ (unsigned long) (t % 1000000));
+ rtems_monitor_dump_id (rtems_capture_task_id (rec->task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_name (rtems_capture_task_name (rec->task));
+ fprintf(stdout," %3i %3i %s\n",
+ (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
+ rtems_capture_event_text (e));
+ }
+ event >>= 1;
+ }
+ }
+ }
+
+ if (read < total)
+ total -= read;
+ else
+ total = 0;
+
+ rtems_capture_release (read);
+ }
+}
+
+/*
+ * rtems_capture_cli_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that flushes and primes the capture
+ * engine.
+ *
+ */
+
+static void
+rtems_capture_cli_flush (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ rtems_boolean prime = 1;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'n')
+ prime = 0;
+ else
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ }
+
+ sc = rtems_capture_flush (prime);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: flush failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"trace buffer flushed and %s.\n", prime ? "primed" : "not primed");
+}
+
+static rtems_monitor_command_entry_t rtems_capture_cli_cmds[] =
+{
+ {
+ "copen",
+ "usage: copen [-i] size\n",
+ 0,
+ rtems_capture_cli_open,
+ { 0 },
+ 0
+ },
+ {
+ "cclose",
+ "usage: cclose\n",
+ 0,
+ rtems_capture_cli_close,
+ { 0 },
+ 0
+ },
+ {
+ "cenable",
+ "usage: cenable\n",
+ 0,
+ rtems_capture_cli_enable,
+ { 0 },
+ 0
+ },
+ {
+ "cdisable",
+ "usage: cdisable\n",
+ 0,
+ rtems_capture_cli_disable,
+ { 0 },
+ 0
+ },
+ {
+ "ctlist",
+ "usage: ctlist \n",
+ 0,
+ rtems_capture_cli_task_list,
+ { 0 },
+ 0
+ },
+ {
+ "ctload",
+ "usage: ctload \n",
+ 0,
+ rtems_capture_cli_task_load,
+ { 0 },
+ 0
+ },
+ {
+ "cwlist",
+ "usage: cwlist\n",
+ 0,
+ rtems_capture_cli_watch_list,
+ { 0 },
+ 0
+ },
+ {
+ "cwadd",
+ "usage: cwadd [task name] [id]\n",
+ 0,
+ rtems_capture_cli_watch_add,
+ { 0 },
+ 0
+ },
+ {
+ "cwdel",
+ "usage: cwdel [task name] [id]\n",
+ 0,
+ rtems_capture_cli_watch_del,
+ { 0 },
+ 0
+ },
+ {
+ "cwctl",
+ "usage: cwctl [task name] [id] on/off\n",
+ 0,
+ rtems_capture_cli_watch_control,
+ { 0 },
+ 0
+ },
+ {
+ "cwglob",
+ "usage: cwglob on/off\n",
+ 0,
+ rtems_capture_cli_watch_global,
+ { 0 },
+ 0
+ },
+ {
+ "cwceil",
+ "usage: cwceil priority\n",
+ 0,
+ rtems_capture_cli_watch_ceiling,
+ { 0 },
+ 0
+ },
+ {
+ "cwfloor",
+ "usage: cwfloor priority\n",
+ 0,
+ rtems_capture_cli_watch_floor,
+ { 0 },
+ 0
+ },
+ {
+ "ctrace",
+ "usage: ctrace [-c] [-r records]\n",
+ 0,
+ rtems_capture_cli_trace_records,
+ { 0 },
+ 0
+ },
+ {
+ "ctrig",
+ "usage: ctrig type [from name] [from id] [to name] [to id]\n",
+ 0,
+ rtems_capture_cli_trigger_set,
+ { 0 },
+ 0
+ },
+ {
+ "cflush",
+ "usage: cflush [-n]\n",
+ 0,
+ rtems_capture_cli_flush,
+ { 0 },
+ 0
+ }
+};
+
+/*
+ * rtems_capture_cli_init
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the command line interface to the capture
+ * engine.
+ *
+ */
+
+rtems_status_code
+rtems_capture_cli_init (rtems_capture_timestamp timestamp)
+{
+ int cmd;
+
+ capture_timestamp = timestamp;
+
+ for (cmd = 0;
+ cmd < sizeof (rtems_capture_cli_cmds) / sizeof (rtems_monitor_command_entry_t);
+ cmd++)
+ rtems_monitor_insert_cmd (&rtems_capture_cli_cmds[cmd]);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/capture/capture-cli.h b/cpukit/libmisc/capture/capture-cli.h
new file mode 100644
index 0000000000..519cad0d56
--- /dev/null
+++ b/cpukit/libmisc/capture/capture-cli.h
@@ -0,0 +1,52 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Target Interface Command Line Interface. You need
+ start the RTEMS monitor.
+
+*/
+
+#ifndef __CAPTURE_CLI_H_
+#define __CAPTURE_CLI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/capture.h>
+
+/*
+ * rtems_capture_cli_init
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the command line interface to the capture
+ * engine.
+ *
+ */
+rtems_status_code
+rtems_capture_cli_init (rtems_capture_timestamp timestamp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/capture/capture.c b/cpukit/libmisc/capture/capture.c
new file mode 100644
index 0000000000..c8fd751918
--- /dev/null
+++ b/cpukit/libmisc/capture/capture.c
@@ -0,0 +1,1569 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Capture Engine component.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "capture.h"
+#include <rtems/score/states.inl>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/wkspace.inl>
+
+/*
+ * These events are always recorded and are not part of the
+ * watch filters.
+ */
+#define RTEMS_CAPTURE_RECORD_EVENTS (RTEMS_CAPTURE_CREATED_BY_EVENT | \
+ RTEMS_CAPTURE_CREATED_EVENT | \
+ RTEMS_CAPTURE_STARTED_BY_EVENT | \
+ RTEMS_CAPTURE_STARTED_EVENT | \
+ RTEMS_CAPTURE_RESTARTED_BY_EVENT | \
+ RTEMS_CAPTURE_RESTARTED_EVENT | \
+ RTEMS_CAPTURE_DELETED_BY_EVENT | \
+ RTEMS_CAPTURE_DELETED_EVENT | \
+ RTEMS_CAPTURE_BEGIN_EVENT | \
+ RTEMS_CAPTURE_EXITTED_EVENT)
+
+/*
+ * Global capture flags.
+ */
+#define RTEMS_CAPTURE_ON (1 << 0)
+#define RTEMS_CAPTURE_NO_MEMORY (1 << 1)
+#define RTEMS_CAPTURE_OVERFLOW (1 << 2)
+#define RTEMS_CAPTURE_TRIGGERED (1 << 3)
+#define RTEMS_CAPTURE_READER_ACTIVE (1 << 4)
+#define RTEMS_CAPTURE_READER_WAITING (1 << 5)
+#define RTEMS_CAPTURE_GLOBAL_WATCH (1 << 6)
+
+/*
+ * RTEMS Capture Data.
+ */
+static rtems_capture_record_t* capture_records;
+static uint32_t capture_size;
+static uint32_t capture_count;
+static rtems_capture_record_t* capture_in;
+static uint32_t capture_out;
+static uint32_t capture_flags;
+static rtems_capture_task_t* capture_tasks;
+static rtems_capture_control_t* capture_controls;
+static int capture_extension_index;
+static rtems_id capture_id;
+static rtems_capture_timestamp capture_timestamp;
+static rtems_task_priority capture_ceiling;
+static rtems_task_priority capture_floor;
+static uint32_t capture_tick_period;
+static rtems_id capture_reader;
+
+/*
+ * RTEMS Event text.
+ */
+static const char* capture_event_text[] =
+{
+ "CREATED_BY",
+ "CREATED",
+ "STARTED_BY",
+ "STARTED",
+ "RESTARTED_BY",
+ "RESTARTED",
+ "DELETED_BY",
+ "DELETED",
+ "BEGIN",
+ "EXITTED",
+ "SWITCHED_OUT",
+ "SWITCHED_IN",
+ "TIMESTAMP"
+};
+
+/*
+ * rtems_capture_get_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current time. If a handler is provided
+ * by the user get the time from that.
+ */
+static inline void rtems_capture_get_time (uint32_t * ticks,
+ uint32_t * tick_offset)
+{
+ if (capture_timestamp)
+ capture_timestamp (ticks, tick_offset);
+ else
+ {
+ *ticks = _Watchdog_Ticks_since_boot;
+ *tick_offset = 0;
+ }
+}
+
+/*
+ * rtems_capture_match_names
+ *
+ * DESCRIPTION:
+ *
+ * This function compares rtems_names. It protects the
+ * capture engine from a change to the way names are supported
+ * in RTEMS.
+ *
+ */
+static inline rtems_boolean
+rtems_capture_match_names (rtems_name lhs, rtems_name rhs)
+{
+ return lhs == rhs;
+}
+
+/*
+ * rtems_capture_dup_name
+ *
+ * DESCRIPTION:
+ *
+ * This function duplicates an rtems_names. It protects the
+ * cpature engine from a change to the way names are supported
+ * in RTEMS.
+ *
+ */
+static inline void
+rtems_capture_dup_name (rtems_name* dst, rtems_name src)
+{
+ *dst = src;
+}
+
+/*
+ * rtems_capture_name_in_group
+ *
+ * DESCRIPTION:
+ *
+ * This function sees if a name is in a group of names.
+ *
+ */
+static inline rtems_boolean
+rtems_capture_name_in_group (rtems_name task, rtems_name* tasks)
+{
+ if (tasks)
+ {
+ int i;
+ for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
+ if (rtems_capture_match_names (task, *tasks++))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * rtems_capture_match_name_id
+ *
+ * DESCRIPTION:
+ *
+ * This function matches a name and/or id.
+ */
+static inline rtems_boolean
+rtems_capture_match_name_id (rtems_name lhs_name,
+ rtems_id lhs_id,
+ rtems_name rhs_name,
+ rtems_id rhs_id)
+{
+ /*
+ * The left hand side name or id could be 0 which means a wildcard.
+ */
+ if ((lhs_name == 0) && (lhs_id == rhs_id))
+ return 1;
+ else if ((lhs_id == 0) || (lhs_id == rhs_id))
+ {
+ if (rtems_capture_match_names (lhs_name, rhs_name))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * rtems_capture_init_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function setups a stack so its usage can be monitored.
+ */
+static inline void
+rtems_capture_init_stack_usage (rtems_capture_task_t* task)
+{
+ if (task->tcb)
+ {
+ uint32_t * s;
+ uint32_t i;
+
+ task->stack_size = task->tcb->Start.Initial_stack.size;
+ task->stack_clean = task->stack_size;
+
+ s = task->tcb->Start.Initial_stack.area;
+
+ for (i = 0; i < (task->stack_size - 128); i += 4)
+ *(s++) = 0xdeaddead;
+ }
+}
+
+/*
+ * rtems_capture_find_control
+ *
+ * DESCRIPTION:
+ *
+ * This function searches for a trigger given a name.
+ *
+ */
+static inline rtems_capture_control_t*
+rtems_capture_find_control (rtems_name name, rtems_id id)
+{
+ rtems_capture_control_t* control;
+
+ for (control = capture_controls; control != NULL; control = control->next)
+ if (rtems_capture_match_name_id (name, id, control->name, control->id))
+ break;
+ return control;
+}
+
+/*
+ * rtems_capture_create_control
+ *
+ * DESCRIPTION:
+ *
+ * This function creates a capture control for the capture engine.
+ *
+ */
+static inline rtems_capture_control_t*
+rtems_capture_create_control (rtems_name name, rtems_id id)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ rtems_capture_task_t* task;
+
+ if ((name == 0) && (id == 0))
+ return NULL;
+
+ control = rtems_capture_find_control (name, id);
+
+ if (control == NULL)
+ {
+ control = _Workspace_Allocate (sizeof (rtems_capture_control_t));
+
+ if (control == NULL)
+ {
+ capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
+ return NULL;
+ }
+
+ control->name = name;
+ control->id = id;
+ control->flags = 0;
+
+ memset (control->from, 0, sizeof (control->from));
+ memset (control->from_id, 0, sizeof (control->from_id));
+
+ rtems_interrupt_disable (level);
+
+ control->next = capture_controls;
+ capture_controls = control;
+
+ /*
+ * We need to scan the task list as set the control to the
+ * tasks.
+ */
+ for (task = capture_tasks; task != NULL; task = task->next)
+ if (rtems_capture_match_name_id (name, id, task->name, task->id))
+ task->control = control;
+
+ rtems_interrupt_enable (level);
+ }
+
+ return control;
+}
+
+/*
+ * rtems_capture_create_capture_task
+ *
+ * DESCRIPTION:
+ *
+ * This function create the task control.
+ *
+ */
+static inline rtems_capture_task_t*
+rtems_capture_create_capture_task (rtems_tcb* new_task)
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+ rtems_capture_control_t* control;
+
+ task = _Workspace_Allocate (sizeof (rtems_capture_task_t));
+
+ if (task == NULL)
+ {
+ capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
+ return NULL;
+ }
+
+ rtems_capture_dup_name (&task->name, ((rtems_name) new_task->Object.name));
+
+ task->id = new_task->Object.id;
+ task->flags = 0;
+ task->in = 0;
+ task->out = 0;
+ task->tcb = new_task;
+ task->ticks = 0;
+ task->tick_offset = 0;
+ task->ticks_in = 0;
+ task->tick_offset_in = 0;
+ task->control = 0;
+ task->last_ticks = 0;
+ task->last_tick_offset = 0;
+
+ task->tcb->extensions[capture_extension_index] = task;
+
+ task->start_priority = new_task->Start.initial_priority;
+ task->stack_size = new_task->Start.Initial_stack.size;
+ task->stack_clean = task->stack_size;
+
+ rtems_interrupt_disable (level);
+
+ task->next = capture_tasks;
+ capture_tasks = task;
+
+ rtems_interrupt_enable (level);
+
+ /*
+ * We need to scan the default control list to initialise
+ * this control.
+ */
+
+ for (control = capture_controls; control != NULL; control = control->next)
+ if (rtems_capture_match_name_id (control->name, control->id,
+ task->name, task->id))
+ task->control = control;
+
+ return task;
+}
+
+/*
+ * rtems_capture_record
+ *
+ * DESCRIPTION:
+ *
+ * This function records a capture record into the capture buffer.
+ *
+ */
+static inline void
+rtems_capture_record (rtems_capture_task_t* task,
+ uint32_t events)
+{
+ /*
+ * Check the watch state if we have a task control, and
+ * the task's real priority is lower or equal to the ceiling.
+ */
+ if (task)
+ {
+ rtems_capture_control_t* control;
+
+ control = task->control;
+
+ /*
+ * Capure the record if we have an event that is always
+ * captured, or the task's real priority is greater than the
+ * watch ceiling, and the global watch or task watch is enabled.
+ */
+
+ if ((events & RTEMS_CAPTURE_RECORD_EVENTS) ||
+ ((task->tcb->real_priority >= capture_ceiling) &&
+ (task->tcb->real_priority <= capture_floor) &&
+ ((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) ||
+ (control && (control->flags & RTEMS_CAPTURE_WATCH)))))
+ {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (capture_count < capture_size)
+ {
+ capture_count++;
+ capture_in->task = task;
+ capture_in->events = (events |
+ (task->tcb->real_priority) |
+ (task->tcb->current_priority << 8));
+
+ if ((events & RTEMS_CAPTURE_RECORD_EVENTS) == 0)
+ task->flags |= RTEMS_CAPTURE_TRACED;
+
+ rtems_capture_get_time (&capture_in->ticks, &capture_in->tick_offset);
+
+ if (capture_in == &capture_records[capture_size - 1])
+ capture_in = capture_records;
+ else
+ capture_in++;
+ }
+ else
+ capture_flags |= RTEMS_CAPTURE_OVERFLOW;
+ rtems_interrupt_enable (level);
+ }
+ }
+}
+
+/*
+ * rtems_capture_create_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is created.
+ *
+ */
+static rtems_boolean
+rtems_capture_create_task (rtems_tcb* current_task,
+ rtems_tcb* new_task)
+{
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* nt;
+
+ ct = current_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ /*
+ * Create the new task's capture control block.
+ */
+ nt = rtems_capture_create_capture_task (new_task);
+
+ /*
+ * If we are logging then record this fact.
+ */
+ rtems_capture_record (ct, RTEMS_CAPTURE_CREATED_BY_EVENT);
+ rtems_capture_record (nt, RTEMS_CAPTURE_CREATED_EVENT);
+
+ return 1 == 1;
+}
+
+/*
+ * rtems_capture_start_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is started.
+ *
+ */
+static rtems_extension
+rtems_capture_start_task (rtems_tcb* current_task,
+ rtems_tcb* started_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* st;
+
+ ct = current_task->extensions[capture_extension_index];
+ st = started_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (st == NULL)
+ st = rtems_capture_create_capture_task (started_task);
+
+ rtems_capture_record (ct, RTEMS_CAPTURE_STARTED_BY_EVENT);
+ rtems_capture_record (st, RTEMS_CAPTURE_STARTED_EVENT);
+
+ rtems_capture_init_stack_usage (st);
+}
+
+/*
+ * rtems_capture_restart_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is restarted.
+ *
+ */
+static rtems_extension
+rtems_capture_restart_task (rtems_tcb* current_task,
+ rtems_tcb* restarted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* rt;
+
+ ct = current_task->extensions[capture_extension_index];
+ rt = restarted_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (rt == NULL)
+ rt = rtems_capture_create_capture_task (restarted_task);
+
+ rtems_capture_record (ct, RTEMS_CAPTURE_RESTARTED_BY_EVENT);
+ rtems_capture_record (rt, RTEMS_CAPTURE_RESTARTED_EVENT);
+
+ rtems_capture_task_stack_usage (rt);
+ rtems_capture_init_stack_usage (rt);
+}
+
+/*
+ * rtems_capture_delete_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is deleted.
+ *
+ */
+static rtems_extension
+rtems_capture_delete_task (rtems_tcb* current_task,
+ rtems_tcb* deleted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* dt;
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ ct = current_task->extensions[capture_extension_index];
+ dt = deleted_task->extensions[capture_extension_index];
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (dt == NULL)
+ dt = rtems_capture_create_capture_task (deleted_task);
+
+ rtems_capture_record (ct, RTEMS_CAPTURE_DELETED_BY_EVENT);
+ rtems_capture_record (dt, RTEMS_CAPTURE_DELETED_EVENT);
+
+ rtems_capture_task_stack_usage (dt);
+
+ /*
+ * This task's tcb will be invalid.
+ */
+ dt->tcb = 0;
+}
+
+/*
+ * rtems_capture_begin_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is begun.
+ *
+ */
+static rtems_extension
+rtems_capture_begin_task (rtems_tcb* begin_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* bt;
+
+ bt = begin_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (bt == NULL)
+ bt = rtems_capture_create_capture_task (begin_task);
+
+ rtems_capture_record (bt, RTEMS_CAPTURE_BEGIN_EVENT);
+}
+
+/*
+ * rtems_capture_exitted_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is exitted. That is
+ * returned rather than was deleted.
+ *
+ */
+static rtems_extension
+rtems_capture_exitted_task (rtems_tcb* exitted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* et;
+
+ et = exitted_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (et == NULL)
+ et = rtems_capture_create_capture_task (exitted_task);
+
+ rtems_capture_record (et, RTEMS_CAPTURE_EXITTED_EVENT);
+
+ rtems_capture_task_stack_usage (et);
+}
+
+/*
+ * rtems_capture_switch_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a context is switched.
+ *
+ */
+static rtems_extension
+rtems_capture_switch_task (rtems_tcb* current_task,
+ rtems_tcb* heir_task)
+{
+ /*
+ * Only perform context switch trace processing if tracing is
+ * enabled.
+ */
+ if (capture_flags & RTEMS_CAPTURE_ON)
+ {
+ uint32_t ticks;
+ uint32_t tick_offset;
+
+ /*
+ * Get the cpature task control block so we can update the
+ * reference anbd perform any watch or trigger functions.
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* ht;
+
+ if (_States_Is_transient (current_task->current_state))
+ {
+ rtems_id ct_id = current_task->Object.id;
+
+ for (ct = capture_tasks; ct; ct = ct->next)
+ if (ct->id == ct_id)
+ break;
+ }
+ else
+ {
+ ct = current_task->extensions[capture_extension_index];
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+ }
+
+ ht = heir_task->extensions[capture_extension_index];
+
+ if (ht == NULL)
+ ht = rtems_capture_create_capture_task (heir_task);
+
+ /*
+ * Update the execution time. Assume the tick will not overflow
+ * for now. This may need to change.
+ */
+ rtems_capture_get_time (&ticks, &tick_offset);
+
+ /*
+ * We could end up with null pointers for both the current task
+ * and the heir task.
+ */
+
+ if (ht)
+ {
+ ht->in++;
+ ht->ticks_in = ticks;
+ ht->tick_offset_in = tick_offset;
+ }
+
+ if (ct)
+ {
+ ct->out++;
+ ct->ticks += ticks - ct->ticks_in;
+
+ if (capture_timestamp)
+ {
+ tick_offset += capture_tick_period - ct->tick_offset_in;
+
+ if (tick_offset < capture_tick_period)
+ ct->tick_offset = tick_offset;
+ else
+ {
+ ct->ticks++;
+ ct->tick_offset = tick_offset - capture_tick_period;
+ }
+ }
+ else
+ {
+ ct->tick_offset += 100;
+ }
+ }
+
+ /*
+ * If we have not triggered then see if this is a trigger condition.
+ */
+ if (!(capture_flags & RTEMS_CAPTURE_TRIGGERED))
+ {
+ rtems_capture_control_t* cc = NULL;
+ rtems_capture_control_t* hc = NULL;
+
+ if (ct)
+ {
+ cc = ct->control;
+
+ /*
+ * Check the current task for a TO_ANY trigger.
+ */
+ if (cc && (cc->flags & RTEMS_CAPTURE_TO_ANY))
+ {
+ capture_flags |= RTEMS_CAPTURE_TRIGGERED;
+ goto triggered;
+ }
+ }
+
+ if (ht)
+ {
+ hc = ht->control;
+
+ /*
+ * Check the next task for a FROM_ANY.
+ */
+ if (hc && (hc->flags & RTEMS_CAPTURE_FROM_ANY))
+ {
+ capture_flags |= RTEMS_CAPTURE_TRIGGERED;
+ goto triggered;
+ }
+ }
+
+ /*
+ * Check is the trigger is from the current task
+ * to the next task.
+ */
+ if (cc && hc && (hc->flags & RTEMS_CAPTURE_FROM_TO))
+ if (rtems_capture_name_in_group (cc->name, hc->from))
+ {
+ capture_flags |= RTEMS_CAPTURE_TRIGGERED;
+ goto triggered;
+ }
+ }
+ else
+ {
+triggered:
+
+ rtems_capture_record (ct, RTEMS_CAPTURE_SWITCHED_OUT_EVENT);
+ rtems_capture_record (ht, RTEMS_CAPTURE_SWITCHED_IN_EVENT);
+ }
+ }
+}
+
+/*
+ * rtems_capture_open
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the realtime capture engine allocating the trace
+ * buffer. It is assumed we have a working heap at stage of initialisation.
+ *
+ */
+rtems_status_code
+rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp)
+{
+ rtems_extensions_table capture_extensions;
+ rtems_name name;
+ rtems_status_code sc;
+
+ /*
+ * See if the capture engine is already open.
+ */
+
+ if (capture_records)
+ return RTEMS_RESOURCE_IN_USE;
+
+ capture_records = malloc (size * sizeof (rtems_capture_record_t));
+
+ if (capture_records == NULL)
+ return RTEMS_NO_MEMORY;
+
+ capture_size = size;
+ capture_count = 0;
+ capture_in = capture_records;
+ capture_out = 0;
+ capture_flags = 0;
+ capture_tasks = NULL;
+ capture_ceiling = 0;
+ capture_floor = 255;
+
+ /*
+ * Create the extension table. This is copied so we
+ * can create it as a local.
+ */
+ capture_extensions.thread_create = rtems_capture_create_task;
+ capture_extensions.thread_start = rtems_capture_start_task;
+ capture_extensions.thread_restart = rtems_capture_restart_task;
+ capture_extensions.thread_delete = rtems_capture_delete_task;
+ capture_extensions.thread_switch = rtems_capture_switch_task;
+ capture_extensions.thread_begin = rtems_capture_begin_task;
+ capture_extensions.thread_exitted = rtems_capture_exitted_task;
+ capture_extensions.fatal = NULL;
+
+ /*
+ * Get the tick period from the BSP Configuration Table.
+ */
+ capture_tick_period = _Configuration_Table->microseconds_per_tick;
+
+ /*
+ * Register the user extension handlers for the CAPture Engine.
+ */
+ name = rtems_build_name ('C', 'A', 'P', 'E');
+ sc = rtems_extension_create (name, &capture_extensions, &capture_id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ capture_id = 0;
+ free (capture_records);
+ capture_records = NULL;
+ }
+ else
+ {
+ capture_extension_index = rtems_get_index (capture_id);;
+ }
+
+ /*
+ * Iterate over the list of existing tasks.
+ */
+
+ return sc;
+}
+
+/*
+ * rtems_capture_close
+ *
+ * DESCRIPTION:
+ *
+ * This function shutdowns the capture engine and release any claimed
+ * resources.
+ */
+rtems_status_code
+rtems_capture_close ()
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+ rtems_capture_control_t* control;
+ rtems_capture_record_t* records;
+ rtems_status_code sc;
+
+ rtems_interrupt_disable (level);
+
+ if (!capture_records)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_SUCCESSFUL;
+ }
+
+ capture_flags &= ~RTEMS_CAPTURE_ON;
+
+ records = capture_records;
+ capture_records = NULL;
+
+ rtems_interrupt_enable (level);
+
+ /*
+ * Delete the extension first. This means we are now able to
+ * release the resources we have without them being used.
+ */
+
+ sc = rtems_extension_delete (capture_id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+
+ task = capture_tasks;
+
+ while (task)
+ {
+ rtems_capture_task_t* delete = task;
+ task = task->next;
+ _Workspace_Free (delete);
+ }
+
+ capture_tasks = NULL;
+
+ control = capture_controls;
+
+ while (control)
+ {
+ rtems_capture_control_t* delete = control;
+ control = control->next;
+ _Workspace_Free (delete);
+ }
+
+ capture_controls = NULL;
+
+ if (capture_records)
+ {
+ free (capture_records);
+ capture_records = NULL;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_control
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of tracing at a global level.
+ */
+rtems_status_code
+rtems_capture_control (rtems_boolean enable)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (!capture_records)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_UNSATISFIED;
+ }
+
+ if (enable)
+ capture_flags |= RTEMS_CAPTURE_ON;
+ else
+ capture_flags &= ~RTEMS_CAPTURE_ON;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function flushes the capture buffer. The prime parameter allows the
+ * capture engine to also be primed again.
+ */
+rtems_status_code
+rtems_capture_flush (rtems_boolean prime)
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+
+ rtems_interrupt_disable (level);
+
+ for (task = capture_tasks; task != NULL; task = task->next)
+ task->flags &= ~RTEMS_CAPTURE_TRACED;
+
+ if (prime)
+ capture_flags &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
+ else
+ capture_flags &= ~RTEMS_CAPTURE_OVERFLOW;
+
+ capture_in = capture_records;
+ capture_out = 0;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function defines a watch for a specific task given a name. A watch
+ * causes it to be traced either in or out of context. The watch can be
+ * optionally enabled or disabled with the set routine. It is disabled by
+ * default.
+ */
+rtems_status_code
+rtems_capture_watch_add (rtems_name name, rtems_id id)
+{
+ rtems_capture_control_t* control;
+
+ if ((name == 0) && (id == 0))
+ return RTEMS_UNSATISFIED;
+
+ control = rtems_capture_find_control (name, id);
+
+ if (control && !id)
+ return RTEMS_TOO_MANY;
+
+ if (!control)
+ control = rtems_capture_create_control (name, id);
+
+ if (!control)
+ return RTEMS_NO_MEMORY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function removes a watch for a specific task given a name. The task
+ * description will still exist if referenced by a trace record in the trace
+ * buffer or a global watch is defined.
+ */
+rtems_status_code
+rtems_capture_watch_del (rtems_name name, rtems_id id)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ rtems_capture_control_t** prev_control;
+ rtems_capture_task_t* task;
+ rtems_boolean found = 0;
+
+ /*
+ * Should this test be for wildcards ?
+ */
+
+ for (prev_control = &capture_controls, control = capture_controls;
+ control != NULL; )
+ {
+ if (rtems_capture_match_name_id (name, id, control->name, control->id))
+ {
+ rtems_interrupt_disable (level);
+
+ for (task = capture_tasks; task != NULL; task = task->next)
+ if (task->control == control)
+ task->control = 0;
+
+ *prev_control = control->next;
+
+ rtems_interrupt_enable (level);
+
+ _Workspace_Free (control);
+
+ control = *prev_control;
+
+ found = 1;
+ }
+ else
+ {
+ prev_control = &control->next;
+ control = control->next;
+ }
+ }
+
+ if (found)
+ return RTEMS_SUCCESSFUL;
+
+ return RTEMS_INVALID_NAME;
+}
+
+/*
+ * rtems_capture_watch_set
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a watch. The watch can be enabled or
+ * disabled.
+ */
+rtems_status_code
+rtems_capture_watch_ctrl (rtems_name name, rtems_id id, rtems_boolean enable)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ rtems_boolean found = 0;
+
+ /*
+ * Find the control and then set the watch. It must exist before it can
+ * be controlled.
+ */
+ for (control = capture_controls; control != NULL; control = control->next)
+ {
+ if (rtems_capture_match_name_id (name, id, control->name, control->id))
+ {
+ rtems_interrupt_disable (level);
+
+ if (enable)
+ control->flags |= RTEMS_CAPTURE_WATCH;
+ else
+ control->flags &= ~RTEMS_CAPTURE_WATCH;
+
+ rtems_interrupt_enable (level);
+
+ found = 1;
+ }
+ }
+
+ if (found)
+ return RTEMS_SUCCESSFUL;
+
+ return RTEMS_INVALID_NAME;
+}
+
+/*
+ * rtems_capture_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a global watch. The watch can be enabled or
+ * disabled. A global watch configures all tasks below the ceiling and above
+ * the floor to be traced.
+ */
+rtems_status_code
+rtems_capture_watch_global (rtems_boolean enable)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ /*
+ * We need to keep specific and global watches separate so
+ * a global enable/disable does not lose a specific watch.
+ */
+ if (enable)
+ capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH;
+ else
+ capture_flags &= ~RTEMS_CAPTURE_GLOBAL_WATCH;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_global_on
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the global watch state.
+ */
+rtems_boolean
+rtems_capture_watch_global_on ()
+{
+ return capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0;
+}
+
+/*
+ * rtems_capture_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch ceiling. Tasks at or greating that the
+ * ceiling priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a higher
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_ceiling (rtems_task_priority ceiling)
+{
+ capture_ceiling = ceiling;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_get_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch ceiling.
+ */
+rtems_task_priority
+rtems_capture_watch_get_ceiling ()
+{
+ return capture_ceiling;
+}
+
+/*
+ * rtems_capture_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch floor. Tasks at or less that the
+ * floor priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a lower
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_floor (rtems_task_priority floor)
+{
+ capture_floor = floor;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_get_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch floor.
+ */
+rtems_task_priority
+rtems_capture_watch_get_floor ()
+{
+ return capture_floor;
+}
+
+/*
+ * rtems_capture_set_trigger
+ *
+ * DESCRIPTION:
+ *
+ * This function sets an edge trigger. Left is the left side of
+ * the edge and right is right side of the edge. The trigger type
+ * can be -
+ *
+ * FROM_ANY : a switch from any task to the right side of the edge.
+ * TO_ANY : a switch from the left side of the edge to any task.
+ * FROM_TO : a switch from the left side of the edge to the right
+ * side of the edge.
+ *
+ * This set trigger routine will create a capture control for the
+ * target task. The task list is searched and any existing tasks
+ * are linked to the new control.
+ *
+ * We can have a number of tasks that have the same name so we
+ * search using names. This means a number of tasks can be
+ * linked to single control.
+ */
+rtems_status_code
+rtems_capture_set_trigger (rtems_name from,
+ rtems_id from_id,
+ rtems_name to,
+ rtems_id to_id,
+ rtems_capture_trigger_t trigger)
+{
+ rtems_capture_control_t* control;
+ int i;
+
+ /*
+ * Find the capture control blocks for the from and to
+ * tasks.
+ */
+ if (trigger == rtems_capture_to_any)
+ {
+ control = rtems_capture_create_control (from, from_id);
+ if (control == NULL)
+ return RTEMS_NO_MEMORY;
+ control->flags |= RTEMS_CAPTURE_TO_ANY;
+ }
+
+ if ((trigger == rtems_capture_from_to) ||
+ (trigger == rtems_capture_from_any))
+ {
+ control = rtems_capture_create_control (to, to_id);
+ if (control == NULL)
+ return RTEMS_NO_MEMORY;
+
+ if (trigger == rtems_capture_from_any)
+ control->flags |= RTEMS_CAPTURE_FROM_ANY;
+ else
+ {
+ control->flags |= RTEMS_CAPTURE_FROM_TO;
+ for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
+ {
+ if (control->from[i] == 0)
+ {
+ control->from[i] = from;
+ control->from_id[i] = from_id;
+ break;
+ }
+ }
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_read
+ *
+ * DESCRIPTION:
+ *
+ * This function reads a number of records from the capture buffer.
+ * The user can optionally block and wait until the buffer as a
+ * specific number of records available or a specific time has
+ * elasped.
+ *
+ * The function returns the number of record that is has that are
+ * in a continous block of memory. If the number of available records
+ * wrap then only those records are provided. This removes the need for
+ * caller to be concerned about buffer wrappings. If the number of
+ * requested records cannot be met due to the wrapping of the records
+ * less than the specified number will be returned.
+ *
+ * The user must release the records. This is achieved with a call to
+ * rtems_capture_release. Calls this function without a release will
+ * result in at least the same number of records being released.
+ *
+ * The 'threshold' parameter is the number of records that must be
+ * captured before returning. If a timeout period is specified (non-0)
+ * any captured records will be returned. These parameters stop
+ * thrashing occuring for a small number of records, yet allows
+ * a user configured latiency to be applied for single events.
+ *
+ * The 'timeout' parameter is in micro-seconds. A value of 0 will disable
+ * the timeout.
+ *
+ */
+rtems_status_code
+rtems_capture_read (uint32_t threshold,
+ uint32_t timeout,
+ uint32_t * read,
+ rtems_capture_record_t** recs)
+{
+ rtems_interrupt_level level;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint32_t count;
+
+ *read = 0;
+ *recs = NULL;
+
+ rtems_interrupt_disable (level);
+
+ /*
+ * Only one reader is allowed.
+ */
+
+ if (capture_flags & RTEMS_CAPTURE_READER_ACTIVE)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ capture_flags |= RTEMS_CAPTURE_READER_ACTIVE;
+ *read = count = capture_count;
+
+ rtems_interrupt_enable (level);
+
+ *recs = &capture_records[capture_out];
+
+ for (;;)
+ {
+ /*
+ * See if the count wraps the end of the record buffer.
+ */
+ if (count && ((capture_out + count) >= capture_size))
+ *read = capture_size - capture_out;
+
+ /*
+ * Do we have a threshold and the current count has not wrapped
+ * around the end of the capture record buffer ?
+ */
+ if ((*read == count) && threshold)
+ {
+ /*
+ * Do we have enough records ?
+ */
+ if (*read < threshold)
+ {
+ rtems_event_set event_out;
+
+ rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &capture_reader);
+
+ rtems_interrupt_disable (level);
+
+ capture_flags |= RTEMS_CAPTURE_READER_WAITING;
+
+ rtems_interrupt_enable (level);
+
+ sc = rtems_event_receive (RTEMS_EVENT_0,
+ RTEMS_WAIT | RTEMS_EVENT_ANY,
+ TOD_MICROSECONDS_TO_TICKS (timeout),
+ &event_out);
+
+ /*
+ * Let the user handle all other sorts of errors. This may
+ * not be the best solution, but oh well, it will do for
+ * now.
+ */
+ if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT))
+ break;
+
+ rtems_interrupt_disable (level);
+
+ *read = count = capture_count;
+
+ rtems_interrupt_enable (level);
+
+ continue;
+ }
+ }
+
+ /*
+ * Always out if we reach here. To loop use continue.
+ */
+ break;
+ }
+
+ rtems_interrupt_disable (level);
+
+ capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE;
+
+ rtems_interrupt_enable (level);
+
+ return sc;
+}
+
+/*
+ * rtems_capture_release
+ *
+ * DESCRIPTION:
+ *
+ * This function releases the requested number of record slots back
+ * to the capture engine. The count must match the number read.
+ */
+rtems_status_code
+rtems_capture_release (uint32_t count)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (count > capture_count)
+ count = capture_count;
+
+ capture_count -= count;
+
+ capture_out = (capture_count + count) % capture_size;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in nano-seconds.
+ */
+uint32_t
+rtems_capture_tick_time ()
+{
+ return capture_tick_period;
+}
+
+/*
+ * rtems_capture_event_text
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a string for an event based on the bit in the
+ * event. The functions takes the bit offset as a number not the bit
+ * set in a bit map.
+ */
+const char*
+rtems_capture_event_text (int event)
+{
+ if ((event < RTEMS_CAPTURE_EVENT_START) || (event > RTEMS_CAPTURE_EVENT_END))
+ return "invalid event id";
+ return capture_event_text[event - RTEMS_CAPTURE_EVENT_START];
+}
+
+/*
+ * rtems_capture_get_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of tasks that the
+ * capture engine has detected.
+ */
+rtems_capture_task_t*
+rtems_capture_get_task_list ()
+{
+ return capture_tasks;
+}
+
+/*
+ * rtems_capture_task_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function updates the stack usage. The task control block
+ * is updated.
+ */
+uint32_t
+rtems_capture_task_stack_usage (rtems_capture_task_t* task)
+{
+ if (task->tcb)
+ {
+ uint32_t * st;
+ uint32_t * s;
+
+ /*
+ * @todo: Assumes all stacks move the same way.
+ */
+ st = task->tcb->Start.Initial_stack.area + task->stack_size;
+ s = task->tcb->Start.Initial_stack.area;
+
+ while (s < st)
+ {
+ if (*s != 0xdeaddead)
+ break;
+ s++;
+ }
+
+ task->stack_clean =
+ s - (uint32_t *) task->tcb->Start.Initial_stack.area;
+ }
+
+ return task->stack_clean;
+}
+
+/*
+ * rtems_capture_get_control_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of control in the
+ * capture engine.
+ */
+rtems_capture_control_t*
+rtems_capture_get_control_list ()
+{
+ return capture_controls;
+}
diff --git a/cpukit/libmisc/capture/capture.h b/cpukit/libmisc/capture/capture.h
new file mode 100644
index 0000000000..6e040efa0e
--- /dev/null
+++ b/cpukit/libmisc/capture/capture.h
@@ -0,0 +1,869 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Capture Engine component.
+
+*/
+
+#ifndef __CAPTURE_H_
+#define __CAPTURE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+
+/*
+ * The number of tasks in a trigger group.
+ */
+#define RTEMS_CAPTURE_TRIGGER_TASKS (32)
+
+/*
+ * rtems_capture_control_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS control holds the trigger and watch configuration for a group of
+ * tasks with the same name.
+ */
+typedef struct rtems_capture_control_s
+{
+ rtems_name name;
+ rtems_id id;
+ uint32_t flags;
+ rtems_name from[RTEMS_CAPTURE_TRIGGER_TASKS];
+ rtems_id from_id[RTEMS_CAPTURE_TRIGGER_TASKS];
+ struct rtems_capture_control_s* next;
+} rtems_capture_control_t;
+
+/*
+ * Control flags.
+ */
+#define RTEMS_CAPTURE_WATCH (1 << 0)
+#define RTEMS_CAPTURE_FROM_ANY (1 << 1)
+#define RTEMS_CAPTURE_TO_ANY (1 << 2)
+#define RTEMS_CAPTURE_FROM_TO (1 << 3)
+
+/*
+ * rtems_capture_control_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS capture control provdes the information about a task, along
+ * with its trigger state. The control is referenced by each
+ * capture record. This is* information neeed by the decoder. The
+ * capture record cannot assume the task will exist when the record is
+ * dumped via the target interface so task info needed for tracing is
+ * copied and held here.
+ *
+ * The inline heper functions provide more details about the info
+ * contained in this structure.
+ *
+ * Note, the tracer code exploits the fact an rtems_name is a
+ * 32bit value.
+ */
+typedef struct rtems_capture_task_s
+{
+ rtems_name name;
+ rtems_id id;
+ uint32_t flags;
+ rtems_tcb* tcb;
+ uint32_t in;
+ uint32_t out;
+ rtems_task_priority start_priority;
+ uint32_t stack_size;
+ uint32_t stack_clean;
+ uint32_t ticks;
+ uint32_t tick_offset;
+ uint32_t ticks_in;
+ uint32_t tick_offset_in;
+ uint32_t last_ticks;
+ uint32_t last_tick_offset;
+ rtems_capture_control_t* control;
+ struct rtems_capture_task_s* next;
+} rtems_capture_task_t;
+
+/*
+ * Task flags.
+ */
+#define RTEMS_CAPTURE_TRACED (1 << 0)
+
+/*
+ * rtems_capture_record_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS capture record. This is a record that is written into
+ * the buffer. The events includes the priority of the task
+ * at the time of the context switch.
+ */
+typedef struct rtems_capture_record_s
+{
+ rtems_capture_task_t* task;
+ uint32_t events;
+ uint32_t ticks;
+ uint32_t tick_offset;
+} rtems_capture_record_t;
+
+/*
+ * The capture record event flags.
+ */
+#define RTEMS_CAPTURE_REAL_PRI_EVENT_MASK (0x000000ff)
+#define RTEMS_CAPTURE_CURR_PRI_EVENT_MASK (0x0000ff00)
+#define RTEMS_CAPTURE_REAL_PRIORITY_EVENT (0)
+#define RTEMS_CAPTURE_CURR_PRIORITY_EVENT (8)
+#define RTEMS_CAPTURE_EVENT_START (16)
+#define RTEMS_CAPTURE_CREATED_BY_EVENT (1 << 16)
+#define RTEMS_CAPTURE_CREATED_EVENT (1 << 17)
+#define RTEMS_CAPTURE_STARTED_BY_EVENT (1 << 18)
+#define RTEMS_CAPTURE_STARTED_EVENT (1 << 19)
+#define RTEMS_CAPTURE_RESTARTED_BY_EVENT (1 << 20)
+#define RTEMS_CAPTURE_RESTARTED_EVENT (1 << 21)
+#define RTEMS_CAPTURE_DELETED_BY_EVENT (1 << 22)
+#define RTEMS_CAPTURE_DELETED_EVENT (1 << 23)
+#define RTEMS_CAPTURE_BEGIN_EVENT (1 << 24)
+#define RTEMS_CAPTURE_EXITTED_EVENT (1 << 25)
+#define RTEMS_CAPTURE_SWITCHED_OUT_EVENT (1 << 26)
+#define RTEMS_CAPTURE_SWITCHED_IN_EVENT (1 << 27)
+#define RTEMS_CAPTURE_TIMESTAMP (1 << 28)
+#define RTEMS_CAPTURE_EVENT_END (28)
+
+/*
+ * rtems_capture_trigger_t
+ *
+ * DESCRIPTION:
+ *
+ * The types of triggers that exist. FIXME: add more here.
+ */
+typedef enum rtems_capture_trigger_t
+{
+ rtems_capture_to_any,
+ rtems_capture_from_any,
+ rtems_capture_from_to
+} rtems_capture_trigger_t;
+
+/*
+ * rtems_capture_timestamp
+ *
+ * DESCRIPTION:
+ *
+ * This defines the callout handler to obtain a time stamp. The
+ * value returned is time count since the last read.
+ *
+ */
+
+typedef void (*rtems_capture_timestamp)
+ (uint32_t * ticks, uint32_t * micro);
+
+/*
+ * rtems_capture_open
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the realtime trace manager allocating the capture
+ * buffer. It is assumed we have a working heap at stage of initialisation.
+ *
+ */
+rtems_status_code
+rtems_capture_open (uint32_t size,
+ rtems_capture_timestamp timestamp);
+
+/*
+ * rtems_capture_close
+ *
+ * DESCRIPTION:
+ *
+ * This function shutdowns the tracer and release any claimed
+ * resources.
+ */
+rtems_status_code
+rtems_capture_close ();
+
+/*
+ * rtems_capture_control
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of tracing at a global level.
+ */
+rtems_status_code
+rtems_capture_control (rtems_boolean enable);
+
+/*
+ * rtems_capture_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function flushes the trace buffer. The prime parameter allows the
+ * capture engine to also be primed again.
+ */
+rtems_status_code
+rtems_capture_flush (rtems_boolean prime);
+
+/*
+ * rtems_capture_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function defines a watch for a specific task given a name. A watch
+ * causes it to be traced either in or out of context. The watch can be
+ * optionally enabled or disabled with the set routine. It is disabled by
+ * default.
+ */
+rtems_status_code
+rtems_capture_watch_add (rtems_name name, rtems_id id);
+
+/*
+ * rtems_capture_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function removes a watch for a specific task given a name. The task
+ * description will still exist if referenced by a trace record in the trace
+ * buffer or a global watch is defined.
+ */
+rtems_status_code
+rtems_capture_watch_del (rtems_name name, rtems_id id);
+
+/*
+ * rtems_capture_watch_set
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a watch. The watch can be enabled or
+ * disabled.
+ */
+rtems_status_code
+rtems_capture_watch_ctrl (rtems_name name, rtems_id id, rtems_boolean enable);
+
+/*
+ * rtems_capture_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a global watch. The watch can be enabled or
+ * disabled. A global watch configures all tasks below the ceiling and above
+ * the floor to be traced.
+ */
+rtems_status_code
+rtems_capture_watch_global (rtems_boolean enable);
+
+/*
+ * rtems_capture_watch_global_on
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the global watch state.
+ */
+rtems_boolean
+rtems_capture_watch_global_on ();
+
+/*
+ * rtems_capture_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch ceiling. Tasks at or greating that the
+ * ceiling priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a higher
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_ceiling (rtems_task_priority ceiling);
+
+/*
+ * rtems_capture_watch_get_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch ceiling.
+ */
+rtems_task_priority
+rtems_capture_watch_get_ceiling ();
+
+/*
+ * rtems_capture_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch floor. Tasks at or less that the
+ * floor priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a lower
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_floor (rtems_task_priority floor);
+
+/*
+ * rtems_capture_watch_get_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch floor.
+ */
+rtems_task_priority
+rtems_capture_watch_get_floor ();
+
+/*
+ * rtems_capture_set_trigger
+ *
+ * DESCRIPTION:
+ *
+ * This function sets an edge trigger. Left is the left side of
+ * the edge and right is right side of the edge. The trigger type
+ * can be -
+ *
+ * FROM_ANY : a switch from any task to the right side of the edge.
+ * TO_ANY : a switch from the left side of the edge to any task.
+ * FROM_TO : a switch from the left side of the edge to the right
+ * side of the edge.
+ *
+ * This set trigger routine will create a trace control for the
+ * target task. The task list is searched and any existing tasks
+ * are linked to the new control.
+ *
+ * We can have a number of tasks that have the same name so we
+ * search using names. This means a number of tasks can be
+ * linked to single control.
+ */
+rtems_status_code
+rtems_capture_set_trigger (rtems_name from,
+ rtems_id from_id,
+ rtems_name to,
+ rtems_id to_id,
+ rtems_capture_trigger_t trigger);
+
+/*
+ * rtems_capture_read
+ *
+ * DESCRIPTION:
+ *
+ * This function reads a number of records from the capture buffer.
+ * The user can optionally block and wait until the buffer as a
+ * specific number of records available or a specific time has
+ * elasped.
+ *
+ * The function returns the number of record that is has that are
+ * in a continous block of memory. If the number of available records
+ * wrap then only those records are provided. This removes the need for
+ * caller to be concerned about buffer wrappings. If the number of
+ * requested records cannot be met due to the wrapping of the records
+ * less than the specified number will be returned.
+ *
+ * The user must release the records. This is achieved with a call to
+ * rtems_capture_release. Calls this function without a release will
+ * result in at least the same number of records being released.
+ *
+ * The 'threshold' parameter is the number of records that must be
+ * captured before returning. If a timeout period is specified (non-0)
+ * any captured records will be returned. These parameters stop
+ * thrashing occuring for a small number of records, yet allows
+ * a user configured latiency to be applied for single events.
+ *
+ * The 'timeout' parameter is in micro-seconds. A value of 0 will disable
+ * the timeout.
+ *
+ */
+rtems_status_code
+rtems_capture_read (uint32_t threshold,
+ uint32_t timeout,
+ uint32_t * read,
+ rtems_capture_record_t** recs);
+
+/*
+ * rtems_capture_release
+ *
+ * DESCRIPTION:
+ *
+ * This function releases the requested number of record slots back
+ * to the capture engine. The count must match the number read.
+ */
+rtems_status_code
+rtems_capture_release (uint32_t count);
+
+/*
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in micro-seconds.
+ */
+uint32_t
+rtems_capture_tick_time ();
+
+/*
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in micro-seconds.
+ */
+uint32_t
+rtems_capture_tick_time ();
+
+/*
+ * rtems_capture_event_text
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a string for an event based on the bit in the
+ * event. The functions takes the bit offset as a number not the bit
+ * set in a bit map.
+ */
+const char*
+rtems_capture_event_text (int event);
+
+/*
+ * rtems_capture_get_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of tasks that the
+ * capture engine has detected.
+ */
+rtems_capture_task_t*
+rtems_capture_get_task_list ();
+
+/*
+ * rtems_capture_next_task
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the pointer to the next task in the list. The
+ * pointer NULL terminates the list.
+ */
+static inline rtems_capture_task_t*
+rtems_capture_next_task (rtems_capture_task_t* task)
+{
+ return task->next;
+}
+
+/*
+ * rtems_capture_task_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns true if the task control block points to
+ * a valid task.
+ */
+static inline rtems_boolean
+rtems_capture_task_valid (rtems_capture_task_t* task)
+{
+ return task->tcb != NULL;
+}
+
+/*
+ * rtems_capture_task_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task id.
+ */
+static inline rtems_id
+rtems_capture_task_id (rtems_capture_task_t* task)
+{
+ return task->id;
+}
+
+/*
+ * rtems_capture_task_state
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task state.
+ */
+static inline States_Control
+rtems_capture_task_state (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->current_state;
+ return 0;
+}
+
+/*
+ * rtems_capture_task_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task name.
+ */
+static inline rtems_name
+rtems_capture_task_name (rtems_capture_task_t* task)
+{
+ return task->name;
+}
+
+/*
+ * rtems_capture_task_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task flags.
+ */
+static inline uint32_t
+rtems_capture_task_flags (rtems_capture_task_t* task)
+{
+ return task->flags;
+}
+
+/*
+ * rtems_capture_task_control
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control if present.
+ */
+static inline rtems_capture_control_t*
+rtems_capture_task_control (rtems_capture_task_t* task)
+{
+ return task->control;
+}
+
+/*
+ * rtems_capture_task_control_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control flags if a control is present.
+ */
+static inline uint32_t
+rtems_capture_task_control_flags (rtems_capture_task_t* task)
+{
+ if (!task->control)
+ return 0;
+ return task->control->flags;
+}
+
+/*
+ * rtems_capture_task_switched_in
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of times the task has
+ * been switched into context.
+ */
+static inline uint32_t
+rtems_capture_task_switched_in (rtems_capture_task_t* task)
+{
+ return task->in;
+}
+
+/*
+ * rtems_capture_task_switched_out
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of times the task has
+ * been switched out of context.
+ */
+static inline uint32_t
+rtems_capture_task_switched_out (rtems_capture_task_t* task)
+{
+ return task->out;
+}
+
+/*
+ * rtems_capture_task_curr_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks start priority. The tracer needs this
+ * to track where the task's priority goes.
+ */
+static inline rtems_task_priority
+rtems_capture_task_start_priority (rtems_capture_task_t* task)
+{
+ return task->start_priority;
+}
+
+/*
+ * rtems_capture_task_real_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks real priority.
+ */
+static inline rtems_task_priority
+rtems_capture_task_real_priority (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->real_priority;
+ return 0;
+}
+
+/*
+ * rtems_capture_task_curr_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks current priority.
+ */
+static inline rtems_task_priority
+rtems_capture_task_curr_priority (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->current_priority;
+ return 0;
+}
+
+/*
+ * rtems_capture_task_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function updates the stack usage. The task control block
+ * is updated.
+ */
+uint32_t
+rtems_capture_task_stack_usage (rtems_capture_task_t* task);
+
+/*
+ * rtems_capture_task_stack_size
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task's stack size.
+ */
+static inline uint32_t
+rtems_capture_task_stack_size (rtems_capture_task_t* task)
+{
+ return task->stack_size;
+}
+
+/*
+ * rtems_capture_task_stack_used
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the amount of stack used.
+ */
+static inline uint32_t
+rtems_capture_task_stack_used (rtems_capture_task_t* task)
+{
+ return task->stack_size - task->stack_clean;
+}
+
+/*
+ * rtems_capture_task_ticks
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time as ticks.
+ */
+static inline uint32_t
+rtems_capture_task_ticks (rtems_capture_task_t* task)
+{
+ return task->ticks;
+}
+
+/*
+ * rtems_capture_task_tick_offset
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time tick offset.
+ */
+static inline uint32_t
+rtems_capture_task_tick_offset (rtems_capture_task_t* task)
+{
+ return task->tick_offset;
+}
+
+/*
+ * rtems_capture_task_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time.
+ */
+static inline unsigned long long
+rtems_capture_task_time (rtems_capture_task_t* task)
+{
+ unsigned long long t = task->ticks;
+ return (t * rtems_capture_tick_time ()) + task->tick_offset;;
+}
+
+/*
+ * rtems_capture_task_delta_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the execution time as a different between the
+ * last time the detla time was and now.
+ */
+static inline unsigned long long
+rtems_capture_task_delta_time (rtems_capture_task_t* task)
+{
+ unsigned long long t = task->ticks - task->last_ticks;
+ uint32_t o = task->tick_offset - task->last_tick_offset;
+
+ task->last_ticks = task->ticks;
+ task->last_tick_offset = task->tick_offset;
+
+ return (t * rtems_capture_tick_time ()) + o;
+}
+
+/*
+ * rtems_capture_task_count
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of tasks the capture
+ * engine knows about.
+ */
+static inline uint32_t
+rtems_capture_task_count ()
+{
+ rtems_capture_task_t* task = rtems_capture_get_task_list ();
+ uint32_t count = 0;
+
+ while (task)
+ {
+ count++;
+ task = rtems_capture_next_task (task);
+ }
+
+ return count;
+}
+
+/*
+ * rtems_capture_get_control_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of controls in the
+ * capture engine.
+ */
+rtems_capture_control_t*
+rtems_capture_get_control_list ();
+
+/*
+ * rtems_capture_next_control
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the pointer to the next control in the list. The
+ * pointer NULL terminates the list.
+ */
+static inline rtems_capture_control_t*
+rtems_capture_next_control (rtems_capture_control_t* control)
+{
+ return control->next;
+}
+
+/*
+ * rtems_capture_control_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control id.
+ */
+static inline rtems_id
+rtems_capture_control_id (rtems_capture_control_t* control)
+{
+ return control->id;
+}
+
+/*
+ * rtems_capture_control_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control name.
+ */
+static inline rtems_name
+rtems_capture_control_name (rtems_capture_control_t* control)
+{
+ return control->name;
+}
+
+/*
+ * rtems_capture_control_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control flags.
+ */
+static inline uint32_t
+rtems_capture_control_flags (rtems_capture_control_t* control)
+{
+ return control->flags;
+}
+
+/*
+ * rtems_capture_control_from_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control from task name.
+ */
+static inline rtems_name
+rtems_capture_control_from_name (rtems_capture_control_t* control, int from)
+{
+ if (from < RTEMS_CAPTURE_TRIGGER_TASKS)
+ return control->from[from];
+ return control->from[0];
+}
+
+/*
+ * rtems_capture_control_from_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control from task id.
+ */
+static inline rtems_id
+rtems_capture_control_from_id (rtems_capture_control_t* control, int from)
+{
+ if (from < RTEMS_CAPTURE_TRIGGER_TASKS)
+ return control->from_id[from];
+ return control->from_id[0];
+}
+
+/*
+ * rtems_capture_control_count
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of controls the capture
+ * engine has.
+ */
+static inline uint32_t
+rtems_capture_control_count ()
+{
+ rtems_capture_control_t* control = rtems_capture_get_control_list ();
+ uint32_t count = 0;
+
+ while (control)
+ {
+ count++;
+ control = rtems_capture_next_control (control);
+ }
+
+ return count;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/cpuuse/README b/cpukit/libmisc/cpuuse/README
new file mode 100644
index 0000000000..20e76f07bc
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/README
@@ -0,0 +1,41 @@
+#
+# $Id$
+#
+
+This directory contains a stack bounds checker. It provides two
+primary features:
+
+ + check for stack overflow at each context switch
+ + provides an educated guess at each task's stack usage
+
+The stack overflow check at context switch works by looking for
+a 16 byte pattern at the logical end of the stack to be corrupted.
+The "guesser" assumes that the entire stack was prefilled with a known
+pattern and assumes that the pattern is still in place if the memory
+has not been used as a stack.
+
+Both of these can be fooled by pushing large holes onto the stack
+and not writing to them... or (much more unlikely) writing the
+magic patterns into memory.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to catch the most common mistake in multitasking
+systems ... too little stack space. Suggestions and comments are appreciated.
+
+NOTES:
+
+1. Stack usage information is questionable on CPUs which push
+ large holes on stack.
+
+2. The stack checker has a tendency to generate a fault when
+ trying to print the helpful diagnostic message. If it comes
+ out, congratulations. If not, then the variable Stack_check_Blown_task
+ contains a pointer to the TCB of the offending task. This
+ is usually enough to go on.
+
+FUTURE:
+
+1. Determine how/if gcc will generate stack probe calls and support that.
+
+2. Get accurate stack usage numbers on i960.. it pushes very large
+ holes on the stack.
diff --git a/cpukit/libmisc/cpuuse/cpuuse.c b/cpukit/libmisc/cpuuse/cpuuse.c
new file mode 100644
index 0000000000..189b542644
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/cpuuse.c
@@ -0,0 +1,148 @@
+/*
+ * CPU Usage Reporter
+ *
+ * COPYRIGHT (c) 1989-1999. 1996.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <rtems/cpuuse.h>
+
+uint32_t CPU_usage_Ticks_at_last_reset;
+
+/*PAGE
+ *
+ * CPU_usage_Dump
+ */
+
+void CPU_usage_Dump( void )
+{
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ Objects_Information *information;
+ uint32_t u32_name;
+ char *cname;
+ char name[5];
+ uint32_t total_units = 0;
+
+ for ( api_index = 1 ;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+
+ if ( the_thread )
+ total_units += the_thread->ticks_executed;
+ }
+ }
+ }
+
+ fprintf(stdout,"CPU Usage by thread\n");
+#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
+ fprintf(stdout, " ID NAME TICKS PERCENT\n" );
+#else
+ fprintf(stdout, " ID NAME TICKS\n" );
+#endif
+
+ for ( api_index = 1 ;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+
+ if ( !the_thread )
+ continue;
+
+ if ( information->is_string ) {
+ cname = the_thread->Object.name;
+ name[ 0 ] = cname[0];
+ name[ 1 ] = cname[1];
+ name[ 2 ] = cname[2];
+ name[ 3 ] = cname[3];
+ name[ 4 ] = '\0';
+ } else {
+ u32_name = (uint32_t )the_thread->Object.name;
+ name[ 0 ] = (u32_name >> 24) & 0xff;
+ name[ 1 ] = (u32_name >> 16) & 0xff;
+ name[ 2 ] = (u32_name >> 8) & 0xff;
+ name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 4 ] = '\0';
+ }
+
+ if ( !isprint(name[0]) ) name[0] = '*';
+ if ( !isprint(name[1]) ) name[1] = '*';
+ if ( !isprint(name[2]) ) name[2] = '*';
+ if ( !isprint(name[3]) ) name[3] = '*';
+
+#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
+ fprintf(stdout, "0x%08x %4s %8d %5.3f\n",
+ the_thread->Object.id,
+ name,
+ the_thread->ticks_executed,
+ (total_units) ?
+ (double)the_thread->ticks_executed / (double)total_units :
+ (double)total_units
+ );
+#else
+ fprintf(stdout, "0x%08x %4s %8d\n",
+ the_thread->Object.id,
+ name,
+ the_thread->ticks_executed
+ );
+#endif
+ }
+ }
+ }
+
+ fprintf(stdout,
+ "\nTicks since last reset = %d\n",
+ _Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset
+ );
+ fprintf(stdout, "\nTotal Units = %d\n", total_units );
+}
+
+/*PAGE
+ *
+ * CPU_usage_Reset
+ */
+
+static void CPU_usage_Per_thread_handler(
+ Thread_Control *the_thread
+)
+{
+ the_thread->ticks_executed = 0;
+}
+
+void CPU_usage_Reset( void )
+{
+ CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
+
+ rtems_iterate_over_all_threads(CPU_usage_Per_thread_handler);
+}
diff --git a/cpukit/libmisc/cpuuse/cpuuse.h b/cpukit/libmisc/cpuuse/cpuuse.h
new file mode 100644
index 0000000000..de874e0fcd
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/cpuuse.h
@@ -0,0 +1,40 @@
+/* cpuuse.h
+ *
+ * This include file contains information necessary to utilize
+ * and install the cpu usage reporting mechanism.
+ *
+ * COPYRIGHT (c) 1989-1999. 1996.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_USE_h
+#define __CPU_USE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * CPU_usage_Dump
+ */
+
+void CPU_usage_Dump( void );
+
+/*
+ * CPU_usage_Reset
+ */
+
+void CPU_usage_Reset( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/devnull/devnull.c b/cpukit/libmisc/devnull/devnull.c
new file mode 100644
index 0000000000..cfc8a750ce
--- /dev/null
+++ b/cpukit/libmisc/devnull/devnull.c
@@ -0,0 +1,184 @@
+/* /dev/null
+ *
+ * Derived from rtems' stub driver.
+ *
+ * Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/devnull.h>
+#include <rtems/libio.h>
+
+/* null_initialize
+ *
+ * This routine is the null device driver init routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+uint32_t NULL_major;
+static char initialized;
+
+rtems_device_driver null_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ rtems_device_driver status;
+
+ if ( !initialized ) {
+ initialized = 1;
+
+ status = rtems_io_register_name(
+ "/dev/null",
+ major,
+ (rtems_device_minor_number) 0
+ );
+
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+
+ NULL_major = major;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* null_open
+ *
+ * This routine is the null device driver open routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargb - pointer to open parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_close
+ *
+ * This routine is the null device driver close routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargb - pointer to close parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_read
+ *
+ * This routine is the null device driver read routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to read parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_write
+ *
+ * This routine is the null device driver write routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to write parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) pargp;
+
+ if ( rw_args )
+ rw_args->bytes_moved = rw_args->count;
+
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_control
+ *
+ * This routine is the null device driver control routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to cntrl parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return NULL_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/devnull/devnull.h b/cpukit/libmisc/devnull/devnull.h
new file mode 100644
index 0000000000..6fdf3b6850
--- /dev/null
+++ b/cpukit/libmisc/devnull/devnull.h
@@ -0,0 +1,71 @@
+/* devnull.h
+ *
+ * Null device driver, derived from rtems' stub driver.
+ *
+ * Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __NULL_DRIVER_h
+#define __NULL_DRIVER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEVNULL_DRIVER_TABLE_ENTRY \
+ { null_initialize, null_open, null_close, null_read, \
+ null_write, null_control }
+
+#define NULL_SUCCESSFUL RTEMS_SUCCESSFUL
+
+rtems_device_driver null_initialize(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_open(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_close(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_read(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_write(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_control(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/dummy/README b/cpukit/libmisc/dummy/README
new file mode 100644
index 0000000000..03bb30834d
--- /dev/null
+++ b/cpukit/libmisc/dummy/README
@@ -0,0 +1,23 @@
+dummy.rel
+=========
+
+A relocatible objects which contains a dummy configuration for RTEMS.
+
+Helps linking standard c-program code with RTEMS, which shall *not* be run
+on a target, such as configure script code fragments generated by autoconf's
+AC_TRY_LINK.
+
+Example:
+
+tar xzvf somepkg.tar.gz
+cd somepkg
+
+LDFLAGS=/usr/local/rtems/<cpu>-rtems/<bsp>/lib/dummy.rel \
+CC="<cpu>-rtems-gcc \
+-B/usr/local/rtems/<cpu>-rtems/<bsp>/lib/ -specs bsp_specs -qrtems" \
+CC_FOR_BUILD="gcc" \
+configure --host=<cpu>-rtems --build=i686-pc-linux-gnu
+make
+
+History:
+Starting dummy.c with a copy of rtems-19990528/c/src/tests/samples/minimum/init.c
diff --git a/cpukit/libmisc/dummy/dummy.c b/cpukit/libmisc/dummy/dummy.c
new file mode 100644
index 0000000000..c59114375c
--- /dev/null
+++ b/cpukit/libmisc/dummy/dummy.c
@@ -0,0 +1,45 @@
+/* Init
+ *
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+rtems_task Init(
+ rtems_task_argument ignored
+)
+{
+}
+
+int main( int, char **, char **);
+
+/* configuration information */
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_MAXIMUM_TASKS 10
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20
+#define CONFIGURE_INIT_TASK_ENTRY_POINT (void *)main
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
+
+/* global variables */
diff --git a/cpukit/libmisc/dumpbuf/dumpbuf.c b/cpukit/libmisc/dumpbuf/dumpbuf.c
new file mode 100644
index 0000000000..120a464a90
--- /dev/null
+++ b/cpukit/libmisc/dumpbuf/dumpbuf.c
@@ -0,0 +1,79 @@
+/*
+ * COPYRIGHT (c) 1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <rtems/dumpbuf.h>
+
+/*
+ * Put the body below Dump_Buffer so it won't get inlined.
+ */
+
+static inline void Dump_Line(
+ unsigned char *buffer,
+ int length
+);
+
+void Dump_Buffer(
+ unsigned char *buffer,
+ int length
+)
+{
+
+ int i, mod, max;
+
+ if ( !length ) return;
+
+ mod = length % 16;
+
+ max = length - mod;
+
+ for ( i=0 ; i<max ; i+=16 )
+ Dump_Line( &buffer[ i ], 16 );
+
+ if ( mod )
+ Dump_Line( &buffer[ max ], mod );
+}
+
+static inline void Dump_Line(
+ unsigned char *buffer,
+ int length
+)
+{
+
+ int i;
+ char line_buffer[120];
+
+ line_buffer[0] = '\0';
+
+ for( i=0 ; i<length ; i++ )
+ sprintf( line_buffer, "%s%02x ", line_buffer, buffer[ i ] );
+
+ for( ; i<16 ; i++ )
+ strcat( line_buffer, " " );
+
+ strcat( line_buffer, "|" );
+ for( i=0 ; i<length ; i++ )
+ sprintf( line_buffer, "%s%c", line_buffer,
+ isprint( buffer[ i ] ) ? buffer[ i ] : '.' );
+
+ for( ; i<16 ; i++ )
+ strcat( line_buffer, " " );
+
+ strcat( line_buffer, "|\n" );
+
+ fprintf(stdout, line_buffer );
+}
diff --git a/cpukit/libmisc/dumpbuf/dumpbuf.h b/cpukit/libmisc/dumpbuf/dumpbuf.h
new file mode 100644
index 0000000000..bcdf4d56ee
--- /dev/null
+++ b/cpukit/libmisc/dumpbuf/dumpbuf.h
@@ -0,0 +1,21 @@
+/*
+ * COPYRIGHT (c) 1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __DUMP_BUFFER_h
+#define __DUMP_BUFFER_h
+
+void Dump_Buffer(
+ unsigned char *buffer,
+ int length
+);
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/fsmount/README b/cpukit/libmisc/fsmount/README
new file mode 100644
index 0000000000..88bfda62e7
--- /dev/null
+++ b/cpukit/libmisc/fsmount/README
@@ -0,0 +1,24 @@
+#
+#
+# fsmount information
+#
+# Author: Thomas Doerfler 02/07/2003
+#
+# README,v 1.1 1999/07/09 17:23:15 joel Exp
+#
+
+fsmount.c contains the function fsmount. It processes the
+fs table given as an parameter to create the listed mount points
+and mount the corresponding file systems to their mount points.
+See "c/src/tests/samples/fileio" for a sample on how to use this
+function.
+
+The field "report_reasons" specifies, what results of the mount point
+creation/mount operations should print to the console.
+
+The field "abort_reasons" specifies, what results of the mount point
+creation/mount operations should abort the function. Do not set the
+"abort_reasons" bit, unless you want to stop the processing of the
+fsmount table after the first successful mount.
+
+
diff --git a/cpukit/libmisc/fsmount/fsmount.c b/cpukit/libmisc/fsmount/fsmount.c
new file mode 100644
index 0000000000..0d5e388f62
--- /dev/null
+++ b/cpukit/libmisc/fsmount/fsmount.c
@@ -0,0 +1,195 @@
+/*===============================================================*\
+| Project: RTEMS fsmount |
++-----------------------------------------------------------------+
+| File: fsmount.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2003 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains the fsmount functions. These functions |
+| are used to mount a list of filesystems (and create their mount |
+| points before) |
+| |
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 02.07.03 creation doe |
+\*===============================================================*/
+#include <rtems.h>
+#include <rtems/fsmount.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <rtems/imfs.h>
+#include <sys/stat.h>
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int rtems_fsmount_create_mountpoint
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| This function will create the mount point given |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ const char *mount_point
+ )
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0, if success, -1 and errno if failed |
+\*=========================================================================*/
+{
+ int rc = 0;
+ char *tok_buffer = NULL;
+ char *token = NULL;
+ int token_len;
+ size_t total_len;
+ IMFS_token_types token_type;
+ struct stat file_info;
+ /*
+ * allocate temp memory to rebuild path name
+ */
+ tok_buffer = calloc(strlen(mount_point)+1,sizeof(char));
+ token = tok_buffer;
+ total_len = 0;
+ do {
+ /*
+ * scan through given string, one segment at a time
+ */
+ token_type = IMFS_get_token(mount_point+total_len,token,&token_len);
+ total_len += token_len;
+ strncpy(tok_buffer,mount_point,total_len);
+ tok_buffer[total_len] = '\0';
+
+ if ((token_type != IMFS_NO_MORE_PATH) &&
+ (token_type != IMFS_CURRENT_DIR) &&
+ (token_type != IMFS_INVALID_TOKEN)) {
+ /*
+ * check, whether segment exists
+ */
+ if (0 != stat(tok_buffer,&file_info)) {
+ /*
+ * if not, create directory
+ */
+ rc = mknod(tok_buffer,S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR,0);
+ }
+ }
+ } while ((rc == 0) &&
+ (token_type != IMFS_NO_MORE_PATH) &&
+ (token_type != IMFS_INVALID_TOKEN));
+
+ /*
+ * return token buffer to heap
+ */
+ if (tok_buffer != NULL) {
+ free(tok_buffer);
+ }
+ return rc;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int rtems_fsmount
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| This function will create the mount points listed and mount the file |
+| systems listed in the calling parameters |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ const fstab_t *fstab_ptr,
+ int fstab_count,
+ int *fail_idx
+ )
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0, if success, -1 and errno if failed |
+\*=========================================================================*/
+{
+ int rc = 0;
+ int tmp_rc;
+ int fstab_idx = 0;
+ rtems_filesystem_mount_table_entry_t *tmp_mt_entry;
+ boolean terminate = FALSE;
+
+ /*
+ * scan through all fstab entries;
+ */
+ while (!terminate &&
+ (fstab_idx < fstab_count)) {
+ tmp_rc = 0;
+ /*
+ * create mount point
+ */
+ if (tmp_rc == 0) {
+ tmp_rc = rtems_fsmount_create_mountpoint(fstab_ptr->mount_point);
+ if (tmp_rc != 0) {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNTPNT_CRTERR)) {
+ fprintf(stdout,"fsmount: creation of mount point \"%s\" failed: %s\n",
+ fstab_ptr->mount_point,
+ strerror(errno));
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNTPNT_CRTERR)) {
+ terminate = TRUE;
+ rc = tmp_rc;
+ }
+ }
+ }
+ /*
+ * mount device to given mount point
+ */
+ if (tmp_rc == RTEMS_SUCCESSFUL) {
+ tmp_rc = mount(&tmp_mt_entry,
+ fstab_ptr->fs_ops,
+ fstab_ptr->mount_options,
+ fstab_ptr->dev,
+ fstab_ptr->mount_point);
+ if (tmp_rc != RTEMS_SUCCESSFUL) {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNT_FAILED)) {
+ fprintf(stdout,"fsmount: mounting of \"%s\" to"
+ " \"%s\" failed: %s\n",
+ fstab_ptr->dev,
+ fstab_ptr->mount_point,
+ strerror(errno));
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNT_FAILED)) {
+ terminate = TRUE;
+ rc = tmp_rc;
+ }
+ }
+ else {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNT_OK)) {
+ fprintf(stdout,"fsmount: mounting of \"%s\" to"
+ " \"%s\" succeeded\n",
+ fstab_ptr->dev,
+ fstab_ptr->mount_point);
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNT_OK)) {
+ terminate = TRUE;
+ }
+ }
+ }
+ /*
+ * proceed to next entry
+ */
+ if (!terminate) {
+ fstab_ptr++;
+ fstab_idx++;
+ }
+ }
+ if (fail_idx != NULL) {
+ *fail_idx = fstab_idx;
+ }
+ return rc;
+}
diff --git a/cpukit/libmisc/fsmount/fsmount.h b/cpukit/libmisc/fsmount/fsmount.h
new file mode 100644
index 0000000000..1b876e6f81
--- /dev/null
+++ b/cpukit/libmisc/fsmount/fsmount.h
@@ -0,0 +1,71 @@
+/*===============================================================*\
+| Project: RTEMS fsmount |
++-----------------------------------------------------------------+
+| File: fsmount.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2003 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains the fsmount functions. These functions |
+| are used to mount a list of filesystems (and create their mount |
+| points before) |
+| |
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 02.07.03 creation doe |
+\*===============================================================*/
+#ifndef _FSMOUNT_H
+#define _FSMOUNT_H
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libcsupport.h>
+
+/*
+ * bits to define, what errors will cause reporting (via printf) and
+ * abort of mount processing
+ * Use a combination of these bits
+ * for the fields "report_reasons" and "abort_reasons"
+ */
+#define FSMOUNT_MNT_OK 0x0001 /* mounted ok */
+#define FSMOUNT_MNTPNT_CRTERR 0x0002 /* cannot create mount point */
+#define FSMOUNT_MNT_FAILED 0x0004 /* mounting failed */
+
+typedef struct {
+ char *dev;
+ char *mount_point;
+ rtems_filesystem_operations_table *fs_ops;
+ rtems_filesystem_options_t mount_options;
+ uint16_t report_reasons;
+ uint16_t abort_reasons;
+} fstab_t;
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int rtems_fsmount
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| This function will create the mount points listed and mount the file |
+| systems listed in the calling parameters |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ const fstab_t *fstab_ptr, /* Ptr to filesystem mount table */
+ int fstab_count, /* number of entries in mount table*/
+ int *fail_idx /* return: index of failed entry */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0, if success, -1 and errno if failed |
+\*=========================================================================*/
+
+#endif /* _FSMOUNT_H */
diff --git a/cpukit/libmisc/monitor/README b/cpukit/libmisc/monitor/README
new file mode 100644
index 0000000000..d5a73da140
--- /dev/null
+++ b/cpukit/libmisc/monitor/README
@@ -0,0 +1,97 @@
+#
+# $Id$
+#
+
+monitor task
+
+The monitor task is an optional task that knows about RTEMS
+data structures and can print out information about them.
+It is a work-in-progress and needs many more commands, but
+is useful now.
+
+The monitor works best when it is the highest priority task,
+so all your other tasks should ideally be at some priority
+greater than 1.
+
+To use the monitor:
+-------------------
+
+ #include <rtems/monitor.h>
+
+ ...
+
+ rtems_monitor_init(0);
+
+ The parameter to rtems_monitor_init() tells the monitor whether
+ to suspend itself on startup. A value of 0 causes the monitor
+ to immediately enter command mode; a non-zero value causes the
+ monitor to suspend itself after creation and wait for explicit
+ wakeup.
+
+
+ rtems_monitor_wakeup();
+
+ wakes up a suspended monitor and causes it to reenter command mode.
+
+Monitor commands
+----------------
+
+ The monitor prompt is 'rtems> '.
+ Can abbreviate commands to "uniquity"
+ There is a 'help' command. Here is the output from various
+ help commands:
+
+ Commands (may be abbreviated)
+
+ help -- get this message or command specific help
+ task -- show task information
+ queue -- show message queue information
+ symbol -- show entries from symbol table
+ pause -- pause monitor for a specified number of ticks
+ fatal -- invoke a fatal RTEMS error
+
+ task [id [id ...] ]
+ display information about the specified tasks.
+ Default is to display information about all tasks on this node
+
+ queue [id [id ... ] ]
+ display information about the specified message queues
+ Default is to display information about all queues on this node
+
+ symbol [ symbolname [symbolname ... ] ]
+ display value associated with specified symbol.
+ Defaults to displaying all known symbols.
+
+ pause [ticks]
+ monitor goes to "sleep" for specified ticks (default is 1)
+ monitor will resume at end of period or if explicitly awakened
+
+ fatal [status]
+ Invoke 'rtems_fatal_error_occurred' with 'status'
+ (default is RTEMS_INTERNAL_ERROR)
+
+ continue
+ put the monitor to sleep waiting for an explicit wakeup from the
+ program running.
+
+
+Sample output from 'task' command
+---------------------------------
+
+ rtems> task
+ ID NAME PRIO STAT MODES EVENTS WAITID WAITARG NOTES
+ ------------------------------------------------------------------------
+ 00010001 UI1 2 READY P:T:nA NONE15: 0x40606348
+ 00010002 RMON 1 READY nP NONE15: 0x40604110
+
+ 'RMON' is the monitor itself, so we have 1 "user" task.
+ Its modes are P:T:nA which translate to:
+
+ preemptable
+ timesliced
+ no ASRS
+
+ It has no events.
+ It has a notepad value for notepad 15 which is 0x40606348
+ (this is the libc thread state)
+
diff --git a/cpukit/libmisc/monitor/mon-command.c b/cpukit/libmisc/monitor/mon-command.c
new file mode 100644
index 0000000000..dc20dcb203
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-command.c
@@ -0,0 +1,745 @@
+/*
+ * Command parsing routines for RTEMS monitor
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef MONITOR_PROMPT
+#define MONITOR_PROMPT "rtems" /* will have '> ' appended */
+#endif
+
+/*
+ * 2001-01-30 KJO (vac4050@cae597.rsc.raytheon.com):
+ * Fixed rtems_monitor_command_lookup() to accept partial
+ * commands to uniqeness. Added support for setting
+ * the monitor prompt via an environment variable:
+ * RTEMS_MONITOR_PROMPT
+ *
+ * CCJ: 26-3-2000, adding command history and command line
+ * editing. This code is donated from My Right Boot and not
+ * covered by GPL, only the RTEMS license.
+ */
+
+/*
+ * Some key labels to define special keys.
+ */
+
+#define KEYS_EXTENDED (0x8000)
+#define KEYS_NORMAL_MASK (0x00ff)
+#define KEYS_INS (0)
+#define KEYS_DEL (1)
+#define KEYS_UARROW (2)
+#define KEYS_DARROW (3)
+#define KEYS_LARROW (4)
+#define KEYS_RARROW (5)
+#define KEYS_HOME (6)
+#define KEYS_END (7)
+#define KEYS_F1 (8)
+#define KEYS_F2 (9)
+#define KEYS_F3 (10)
+#define KEYS_F4 (11)
+#define KEYS_F5 (12)
+#define KEYS_F6 (13)
+#define KEYS_F7 (14)
+#define KEYS_F8 (15)
+#define KEYS_F9 (16)
+#define KEYS_F10 (17)
+
+#define RTEMS_COMMAND_BUFFER_SIZE (75)
+
+static char monitor_prompt[32];
+#ifndef RTEMS_UNIX
+static char buffer[RTEMS_COMMAND_BUFFER_SIZE];
+static int pos;
+static int logged_in;
+#endif
+/*
+ * History data.
+ */
+
+#define RTEMS_COMMAND_HISTORIES (20)
+
+#ifndef RTEMS_UNIX
+static char history_buffer[RTEMS_COMMAND_HISTORIES][RTEMS_COMMAND_BUFFER_SIZE];
+static int history_pos[RTEMS_COMMAND_HISTORIES];
+static int history;
+static int history_next;
+#endif
+
+/*
+ * Translation tables. Not sure if this is the best way to
+ * handle this, how-ever I wish to avoid the overhead of
+ * including a more complete and standard environment such
+ * as ncurses.
+ */
+
+struct translation_table
+{
+ char expecting;
+ struct translation_table *branch;
+ unsigned int key;
+};
+
+#ifndef RTEMS_UNIX
+static struct translation_table trans_two[] =
+{
+ { '~', 0, KEYS_INS },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_three[] =
+{
+ { '~', 0, KEYS_DEL },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab_csi[] =
+{
+ { '2', trans_two, 0 },
+ { '3', trans_three, 0 },
+ { 'A', 0, KEYS_UARROW },
+ { 'B', 0, KEYS_DARROW },
+ { 'D', 0, KEYS_LARROW },
+ { 'C', 0, KEYS_RARROW },
+ { 'F', 0, KEYS_END },
+ { 'H', 0, KEYS_HOME },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab_O[] =
+{
+ { '1', 0, KEYS_F1 },
+ { '2', 0, KEYS_F2 },
+ { '3', 0, KEYS_F3 },
+ { '4', 0, KEYS_F4 },
+ { '5', 0, KEYS_F5 },
+ { '6', 0, KEYS_F6 },
+ { '7', 0, KEYS_F7 },
+ { '8', 0, KEYS_F8 },
+ { '9', 0, KEYS_F9 },
+ { ':', 0, KEYS_F10 },
+ { 'P', 0, KEYS_F1 },
+ { 'Q', 0, KEYS_F2 },
+ { 'R', 0, KEYS_F3 },
+ { 'S', 0, KEYS_F4 },
+ { 'T', 0, KEYS_F5 },
+ { 'U', 0, KEYS_F6 },
+ { 'V', 0, KEYS_F7 },
+ { 'W', 0, KEYS_F8 },
+ { 'X', 0, KEYS_F9 },
+ { 'Y', 0, KEYS_F10 },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab[] =
+{
+ { '[', trans_tab_csi, 0 }, /* CSI command sequences */
+ { 'O', trans_tab_O, 0 }, /* O are the fuction keys */
+ { 0, 0, 0 }
+};
+#endif
+
+/*
+ * Perform a basic tranlation for some ANSI/VT100 key codes.
+ * This code could do with a timeout on the ESC as it is
+ * now lost from the input stream. It is not* used by the
+ * line editor below so considiered not worth the effort.
+ */
+
+#ifndef RTEMS_UNIX
+static unsigned int
+rtems_monitor_getchar (
+)
+{
+ struct translation_table *translation = 0;
+ for (;;)
+ {
+ char c = getchar ();
+ if (c == 27)
+ translation = trans_tab;
+ else
+ {
+ /*
+ * If no translation happing just pass through
+ * and return the key.
+ */
+ if (translation)
+ {
+ /*
+ * Scan the current table for the key, and if found
+ * see if this key is a fork. If so follow it and
+ * wait else return the extended key.
+ */
+ int index = 0;
+ int branched = 0;
+ while ((translation[index].expecting != '\0') ||
+ (translation[index].key != '\0'))
+ {
+ if (translation[index].expecting == c)
+ {
+ /*
+ * A branch is take if more keys are to come.
+ */
+ if (translation[index].branch == 0)
+ return KEYS_EXTENDED | translation[index].key;
+ else
+ {
+ translation = translation[index].branch;
+ branched = 1;
+ break;
+ }
+ }
+ index++;
+ }
+ /*
+ * Who knows what these keys are, just drop them.
+ */
+ if (!branched)
+ translation = 0;
+ }
+ else
+ return c;
+ }
+ }
+}
+#endif
+
+#ifndef RTEMS_UNIX
+/*
+ * The line editor with history.
+ */
+
+static int
+rtems_monitor_line_editor (
+ char *command
+)
+{
+ int repeating = 0;
+
+ memset (buffer, 0, RTEMS_COMMAND_BUFFER_SIZE);
+ history = history_next;
+ pos = 0;
+
+ if (!logged_in)
+ fprintf(stdout,"\nMonitor ready, press enter to login.\n\n");
+ else
+ fprintf(stdout,"%s $ ", monitor_prompt);
+
+ while (1)
+ {
+ unsigned int extended_key = rtems_monitor_getchar ();
+ char c = extended_key & KEYS_NORMAL_MASK;
+
+ /*
+ * Make the extended_key usable as a boolean.
+ */
+ extended_key &= ~KEYS_NORMAL_MASK;
+
+ if (!extended_key && !logged_in)
+ {
+ if (c == '\n')
+ {
+ logged_in = 1;
+ /*
+ * The prompt has changed from `>' to `$' to help know
+ * which version of the monitor code people are using.
+ */
+ fprintf(stdout,"%s $ ", monitor_prompt);
+ }
+ }
+ else
+ {
+ if (extended_key)
+ {
+ switch (c)
+ {
+ case KEYS_END:
+ fprintf(stdout,buffer + pos);
+ pos = (int) strlen (buffer);
+ break;
+
+ case KEYS_HOME:
+ fprintf(stdout,"\r%s $ ", monitor_prompt);
+ pos = 0;
+ break;
+
+ case KEYS_LARROW:
+ if (pos > 0)
+ {
+ pos--;
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_RARROW:
+ if ((pos < RTEMS_COMMAND_BUFFER_SIZE) && (buffer[pos] != '\0'))
+ {
+ putchar (buffer[pos]);
+ pos++;
+ }
+ break;
+
+ case KEYS_UARROW:
+ /*
+ * If we are moving up the histories then we need to save the working
+ * buffer.
+ */
+ if (history)
+ {
+ int end;
+ int bs;
+ if (history == history_next)
+ {
+ memcpy (history_buffer[history_next], buffer,
+ RTEMS_COMMAND_BUFFER_SIZE);
+ history_pos[history_next] = pos;
+ }
+ history--;
+ memcpy (buffer, history_buffer[history],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ pos = history_pos[history];
+ fprintf(stdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_DARROW:
+ if (history < history_next)
+ {
+ int end;
+ int bs;
+ history++;
+ memcpy (buffer, history_buffer[history],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ pos = history_pos[history];
+ fprintf(stdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_DEL:
+ if (buffer[pos] != '\0')
+ {
+ int end;
+ int bs;
+ strcpy (&buffer[pos], &buffer[pos + 1]);
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case '\b':
+ case '\x7e':
+ case '\x7f':
+ if (pos > 0)
+ {
+ int bs;
+ pos--;
+ strcpy (buffer + pos, buffer + pos + 1);
+ fprintf(stdout,"\b%s \b", buffer + pos);
+ for (bs = 0; bs < ((int) strlen (buffer) - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case '\n':
+ /*
+ * Process the command.
+ */
+ fprintf(stdout,"\n");
+ repeating = 1;
+ /*
+ * Only process the history if we have a command and
+ *a history.
+ */
+ if (strlen (buffer))
+ {
+ if (history_next && (history == history_next))
+ {
+ /*
+ * Do not place the last command into the history
+ *if the same.
+ */
+ if (strcmp (history_buffer[history_next - 1], buffer))
+ repeating = 0;
+ }
+ else
+ repeating = 0;
+ }
+ if (!repeating)
+ {
+ memcpy (history_buffer[history_next], buffer,
+ RTEMS_COMMAND_BUFFER_SIZE);
+ history_pos[history_next] = pos;
+ if (history_next < (RTEMS_COMMAND_HISTORIES - 1))
+ history_next++;
+ else
+ {
+ memmove (history_buffer[0], history_buffer[1],
+ RTEMS_COMMAND_BUFFER_SIZE * (RTEMS_COMMAND_HISTORIES - 1));
+ memmove (&history_pos[0], &history_pos[1],
+ sizeof (history_pos[0]) * (RTEMS_COMMAND_HISTORIES - 1));
+ }
+ }
+ else
+ {
+#ifdef ENABLE_ENTER_REPEATS
+ if (history_next)
+ memcpy (buffer, history_buffer[history_next - 1],
+ RTEMS_COMMAND_BUFFER_SIZE);
+#endif
+ }
+ memmove (command, buffer, RTEMS_COMMAND_BUFFER_SIZE);
+ return repeating;
+ break;
+
+ default:
+ if ((pos < (RTEMS_COMMAND_BUFFER_SIZE - 1)) &&
+ (c >= ' ') && (c <= 'z'))
+ {
+ int end;
+ end = strlen (buffer);
+ if ((pos < end) && (end < RTEMS_COMMAND_BUFFER_SIZE))
+ {
+ int ch, bs;
+ for (ch = end + 1; ch > pos; ch--)
+ buffer[ch] = buffer[ch - 1];
+ fprintf(stdout,buffer + pos);
+ for (bs = 0; bs < (end - pos + 1); bs++)
+ putchar ('\b');
+ }
+ buffer[pos++] = c;
+ if (pos > end)
+ buffer[pos] = '\0';
+ putchar (c);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+#endif
+
+/*
+ * make_argv(cp): token-count
+ * Break up the command line in 'cp' into global argv[] and argc (return
+ * value).
+ */
+
+int
+rtems_monitor_make_argv(
+ char *cp,
+ int *argc_p,
+ char **argv)
+{
+ int argc = 0;
+
+ while ((cp = strtok(cp, " \t\n\r")))
+ {
+ argv[argc++] = cp;
+ cp = (char *) NULL;
+ }
+ argv[argc] = (char *) NULL; /* end of argv */
+
+ return *argc_p = argc;
+}
+
+
+/*
+ * Read and break up a monitor command
+ *
+ * We have to loop on the gets call, since it will return NULL under UNIX
+ * RTEMS when we get a signal (eg: SIGALRM).
+ */
+
+int
+rtems_monitor_command_read(char *command,
+ int *argc,
+ char **argv)
+{
+ char *env_prompt;
+
+ env_prompt = getenv("RTEMS_MONITOR_PROMPT");
+
+ /*
+ * put node number in the prompt if we are multiprocessing
+ */
+ if (!rtems_configuration_get_user_multiprocessing_table ())
+ sprintf (monitor_prompt, "%s",
+ (env_prompt == NULL) ? MONITOR_PROMPT: env_prompt);
+ else if (rtems_monitor_default_node != rtems_monitor_node)
+ sprintf (monitor_prompt, "%d-%s-%d", rtems_monitor_node,
+ (env_prompt == NULL) ? MONITOR_PROMPT : env_prompt,
+ rtems_monitor_default_node);
+ else
+ sprintf (monitor_prompt, "%d-%s", rtems_monitor_node,
+ (env_prompt == NULL) ? MONITOR_PROMPT : env_prompt);
+
+#if defined(RTEMS_UNIX)
+ /* RTEMS on unix gets so many interrupt system calls this is hosed */
+ fprintf(stdout,"%s> ", monitor_prompt);
+ fflush (stdout);
+ while (gets(command) == (char *) 0)
+ ;
+#else
+ rtems_monitor_line_editor (command);
+#endif
+
+ return rtems_monitor_make_argv (command, argc, argv);
+}
+
+/*
+ * Look up a command in a command table
+ *
+ */
+
+rtems_monitor_command_entry_t *
+rtems_monitor_command_lookup(
+ rtems_monitor_command_entry_t *table,
+ int argc,
+ char **argv
+)
+{
+ int command_length;
+ rtems_monitor_command_entry_t *found_it = NULL;
+
+ command_length = strlen (argv[0]);
+
+ if ((table == 0) || (argv[0] == 0))
+ return 0;
+
+ while (table)
+ {
+ if (table->command)
+ {
+
+ /*
+ * Check for ambiguity
+ */
+ if (!strncmp (table->command, argv[0], command_length))
+ {
+ if (found_it)
+ {
+ return 0;
+ }
+
+ else
+ found_it = table;
+ }
+ }
+ table = table->next;
+ }
+
+ /*
+ * No ambiguity (the possible partial command was unique after all)
+ */
+ if (found_it)
+ {
+ if (found_it->command_function == 0)
+ return 0;
+
+ return found_it;
+ }
+
+ return 0;
+}
+
+static void
+rtems_monitor_show_help (
+ rtems_monitor_command_entry_t *help_cmd,
+ int max_cmd_len
+)
+{
+#define MAX_HELP_LINE_LENGTH (75 - max_cmd_len - 2)
+
+ if (help_cmd && help_cmd->command)
+ {
+ const char *help = help_cmd->usage;
+ int help_len = strlen (help);
+ int spaces = max_cmd_len - strlen (help_cmd->command);
+ int show_this_line = 0;
+ int line_one = 1;
+ int c;
+
+ fprintf(stdout,"%s", help_cmd->command);
+
+ if (help_len == 0)
+ {
+ fprintf(stdout," - No help associated.\n");
+ return;
+ }
+
+ while (help_len)
+ {
+ fprintf(stdout,"%*c", spaces, ' ');
+
+ if (line_one)
+ fprintf(stdout," - ");
+
+ spaces = max_cmd_len + 2;
+ line_one = 0;
+
+ /*
+ * See if greater then the line length if so, work back
+ * from the end for a space, tab or lf or cr.
+ */
+
+ if (help_len > MAX_HELP_LINE_LENGTH)
+ {
+ for (show_this_line = MAX_HELP_LINE_LENGTH - 1;
+ show_this_line;
+ show_this_line--)
+ if ((help[show_this_line] == ' ') ||
+ (help[show_this_line] == '\n') ||
+ (help[show_this_line] == '\r'))
+ break;
+
+ /*
+ * If show_this_line is 0, it is a very long word !!
+ */
+
+ if (show_this_line == 0)
+ show_this_line = MAX_HELP_LINE_LENGTH - 1;
+ }
+ else
+ show_this_line = help_len;
+
+ for (c = 0; c < show_this_line; c++)
+ if ((help[c] == '\r') || (help[c] == '\n'))
+ show_this_line = c;
+ else
+ putchar (help[c]);
+
+ fprintf(stdout,"\n");
+
+ help += show_this_line;
+ help_len -= show_this_line;
+
+ /*
+ * Move past the line feeds or what ever else is being skipped.
+ */
+
+ while (help_len)
+ {
+ if ((*help != '\r') && (*help != '\n'))
+ break;
+
+ if (*help != ' ')
+ {
+ help++;
+ help_len--;
+ break;
+ }
+ help++;
+ help_len--;
+ }
+ }
+ }
+}
+
+void
+rtems_monitor_command_usage(
+ rtems_monitor_command_entry_t *table,
+ char *command_string
+)
+{
+ rtems_monitor_command_entry_t *command = table;
+ int max_cmd_len = 0;
+
+ /* if first entry in table is a usage, then print it out */
+
+ if (command_string && (*command_string != '\0'))
+ {
+ char *argv[2];
+
+ argv[0] = command_string;
+ argv[1] = 0;
+
+ command = rtems_monitor_command_lookup (table, 1, argv);
+
+ if (command)
+ rtems_monitor_show_help (command, strlen (command_string));
+ else
+ fprintf(stdout,"Unrecognised command; try just 'help'\n");
+ return;
+ }
+
+ /*
+ * Find the largest command size.
+ */
+
+ while (command)
+ {
+ int len = command->command ? strlen (command->command) : 0 ;
+
+ if (len > max_cmd_len)
+ max_cmd_len = len;
+
+ command = command->next;
+ }
+
+ max_cmd_len++;
+
+ command = table;
+
+ /*
+ * Now some nice formatting for the help.
+ */
+
+ while (command)
+ {
+ rtems_monitor_show_help (command, max_cmd_len);
+ command = command->next;
+ }
+}
+
+
+void
+rtems_monitor_help_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose
+)
+{
+ int arg;
+ rtems_monitor_command_entry_t *command;
+
+ command = command_arg->monitor_command_entry;
+
+ if (argc == 1)
+ rtems_monitor_command_usage(command, 0);
+ else
+ {
+ for (arg = 1; argv[arg]; arg++)
+ rtems_monitor_command_usage(command, argv[arg]);
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-config.c b/cpukit/libmisc/monitor/mon-config.c
new file mode 100644
index 0000000000..0928eca7e1
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-config.c
@@ -0,0 +1,134 @@
+/*
+ * RTEMS Config display support
+ *
+ * TODO
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+
+#define DATACOL 15
+#define CONTCOL DATACOL /* continued col */
+
+/*
+ * Fill in entire monitor config table
+ * for sending to a remote monitor or printing on the local system
+ */
+
+void
+rtems_monitor_config_canonical(
+ rtems_monitor_config_t *canonical_config,
+ void *config_void
+)
+{
+ rtems_configuration_table *c = (rtems_configuration_table *) config_void;
+ rtems_api_configuration_table *r = c->RTEMS_api_configuration;
+
+ canonical_config->work_space_start = c->work_space_start;
+ canonical_config->work_space_size = c->work_space_size;
+ canonical_config->maximum_tasks = r->maximum_tasks;
+ canonical_config->maximum_timers = r->maximum_timers;
+ canonical_config->maximum_semaphores = r->maximum_semaphores;
+ canonical_config->maximum_message_queues = r->maximum_message_queues;
+ canonical_config->maximum_partitions = r->maximum_partitions;
+ canonical_config->maximum_regions = r->maximum_regions;
+ canonical_config->maximum_ports = r->maximum_ports;
+ canonical_config->maximum_periods = r->maximum_periods;
+ canonical_config->maximum_extensions = c->maximum_extensions;
+ canonical_config->microseconds_per_tick = c->microseconds_per_tick;
+ canonical_config->ticks_per_timeslice = c->ticks_per_timeslice;
+ canonical_config->number_of_initialization_tasks = r->number_of_initialization_tasks;
+}
+
+/*
+ * This is easy, since there is only 1 (altho we could get them from
+ * other nodes...)
+ */
+
+void *
+rtems_monitor_config_next(
+ void *object_info,
+ rtems_monitor_config_t *canonical_config,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ int n = rtems_get_index(*next_id);
+
+ if (n >= 1)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) c;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_config_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+INITIAL (startup) Configuration Info\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+
+void
+rtems_monitor_config_dump(
+ rtems_monitor_config_t *monitor_config,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length = 0;
+ length += fprintf(stdout,"WORKSPACE");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"start: %p; size: 0x%x\n",
+ monitor_config->work_space_start,
+ monitor_config->work_space_size);
+
+ length = 0;
+ length += fprintf(stdout,"TIME");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"usec/tick: %d; tick/timeslice: %d; tick/sec: %d\n",
+ monitor_config->microseconds_per_tick,
+ monitor_config->ticks_per_timeslice,
+ 1000000 / monitor_config->microseconds_per_tick);
+
+ length = 0;
+ length += fprintf(stdout,"MAXIMUMS");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"tasks: %d; timers: %d; sems: %d; que's: %d; ext's: %d\n",
+ monitor_config->maximum_tasks,
+ monitor_config->maximum_timers,
+ monitor_config->maximum_semaphores,
+ monitor_config->maximum_message_queues,
+ monitor_config->maximum_extensions);
+ length = 0;
+ length += rtems_monitor_pad(CONTCOL, length);
+ length += fprintf(stdout,"partitions: %d; regions: %d; ports: %d; periods: %d\n",
+ monitor_config->maximum_partitions,
+ monitor_config->maximum_regions,
+ monitor_config->maximum_ports,
+ monitor_config->maximum_periods);
+}
diff --git a/cpukit/libmisc/monitor/mon-dname.c b/cpukit/libmisc/monitor/mon-dname.c
new file mode 100644
index 0000000000..4f9cc1aef2
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-dname.c
@@ -0,0 +1,116 @@
+/*
+ * RTEMS monitor driver names support.
+ *
+ * There are 2 "driver" things the monitor knows about.
+ *
+ * 1. Regular RTEMS drivers.
+ * This is a table indexed by major device number and
+ * containing driver entry points only.
+ *
+ * 2. Driver name table.
+ * A separate table of names for drivers.
+ * The table converts driver names to a major number
+ * as index into the driver table and a minor number
+ * for an argument to driver.
+ *
+ * Drivers are displayed with 'driver' command.
+ * Names are displayed with 'dname' command.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+#include <string.h> /* strncpy() */
+
+#define DATACOL 15
+#define CONTCOL DATACOL /* continued col */
+
+void
+rtems_monitor_dname_canonical(
+ rtems_monitor_dname_t *canonical_dname,
+ void *dname_void
+)
+{
+ rtems_driver_name_t *np = (rtems_driver_name_t *) dname_void;
+
+ (void) strncpy(canonical_dname->name_string, np->device_name, sizeof(canonical_dname->name_string));
+ canonical_dname->major = np->major;
+ canonical_dname->minor = np->minor;
+}
+
+void *
+rtems_monitor_dname_next(
+ void *object_information,
+ rtems_monitor_dname_t *canonical_dname,
+ rtems_id *next_id
+)
+{
+ uint32_t n = rtems_get_index(*next_id);
+ rtems_driver_name_t *table = _IO_Driver_name_table;
+ rtems_driver_name_t *np = 0;
+
+/* XXX should we be using _IO_Number_of_devices */
+ for (np = table + n ; n<_IO_Number_of_devices; n++, np++)
+ if (np->device_name)
+ goto done;
+
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+
+done:
+ _Thread_Disable_dispatch();
+
+ /*
+ * dummy up a fake id and name for this item
+ */
+
+ canonical_dname->id = n;
+ canonical_dname->name = rtems_build_name('-', '-', '-', '-');
+
+ *next_id += 1;
+ return np;
+}
+
+void
+rtems_monitor_dname_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ Major:Minor Name\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+void
+rtems_monitor_dname_dump(
+ rtems_monitor_dname_t *monitor_dname,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_pad(6, length);
+ length += rtems_monitor_dump_hex(monitor_dname->major);
+ length += fprintf(stdout,":");
+ length += rtems_monitor_dump_hex(monitor_dname->minor);
+
+ length += rtems_monitor_pad(16, length);
+ length += fprintf(stdout,"%.*s",
+ (int) sizeof(monitor_dname->name_string),
+ (char *) monitor_dname->name_string);
+
+ length += fprintf(stdout,"\n");
+ length = 0;
+}
diff --git a/cpukit/libmisc/monitor/mon-driver.c b/cpukit/libmisc/monitor/mon-driver.c
new file mode 100644
index 0000000000..12e84f414e
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-driver.c
@@ -0,0 +1,140 @@
+/*
+ * RTEMS monitor IO (device drivers) support
+ *
+ * There are 2 "driver" things the monitor knows about.
+ *
+ * 1. Regular RTEMS drivers.
+ * This is a table indexed by major device number and
+ * containing driver entry points only.
+ *
+ * 2. Driver name table.
+ * A separate table of names for drivers.
+ * The table converts driver names to a major number
+ * as index into the driver table and a minor number
+ * for an argument to driver.
+ *
+ * Drivers are displayed with 'driver' command.
+ * Names are displayed with 'name' command.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+
+#define DATACOL 15
+#define CONTCOL DATACOL /* continued col */
+
+
+void
+rtems_monitor_driver_canonical(
+ rtems_monitor_driver_t *canonical_driver,
+ void *driver_void
+)
+{
+ rtems_driver_address_table *d = (rtems_driver_address_table *) driver_void;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->initialization,
+ (void *) d->initialization_entry);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->open,
+ (void *) d->open_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->close,
+ (void *) d->close_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->read,
+ (void *) d->read_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->write,
+ (void *) d->write_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->control,
+ (void *) d->control_entry);
+}
+
+
+void *
+rtems_monitor_driver_next(
+ void *object_info,
+ rtems_monitor_driver_t *canonical_driver,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ uint32_t n = rtems_get_index(*next_id);
+
+ if (n >= c->number_of_device_drivers)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * dummy up a fake id and name for this item
+ */
+
+ canonical_driver->id = n;
+ canonical_driver->name = rtems_build_name('-', '-', '-', '-');
+
+ *next_id += 1;
+ return (void *) (c->Device_driver_table + n);
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_driver_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ Major Entry points\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+void
+rtems_monitor_driver_dump(
+ rtems_monitor_driver_t *monitor_driver,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += fprintf(stdout," %d", monitor_driver->id);
+
+ length += rtems_monitor_pad(13, length);
+ length += fprintf(stdout,"init: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->initialization, verbose);
+ length += fprintf(stdout,"; control: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->control, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(13, length);
+
+ length += fprintf(stdout,"open: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->open, verbose);
+ length += fprintf(stdout,"; close: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->close, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(13, length);
+
+ length += fprintf(stdout,"read: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->read, verbose);
+ length += fprintf(stdout,"; write: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->write, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+}
diff --git a/cpukit/libmisc/monitor/mon-extension.c b/cpukit/libmisc/monitor/mon-extension.c
new file mode 100644
index 0000000000..900fee5b87
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-extension.c
@@ -0,0 +1,102 @@
+/*
+ * RTEMS Monitor extension support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+void
+rtems_monitor_extension_canonical(
+ rtems_monitor_extension_t *canonical_extension,
+ void *extension_void
+)
+{
+ Extension_Control *rtems_extension = (Extension_Control *) extension_void;
+ rtems_extensions_table *e = &rtems_extension->Extension.Callouts;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_create,
+ (void *) e->thread_create);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_start,
+ (void *) e->thread_start);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_restart,
+ (void *) e->thread_restart);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_delete,
+ (void *) e->thread_delete);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_tswitch,
+ (void *) e->thread_switch);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_begin,
+ (void *) e->thread_begin);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_exitted,
+ (void *) e->thread_exitted);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_fatal,
+ (void *) e->fatal);
+}
+
+void
+rtems_monitor_extension_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ ID NAME\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+
+/*
+ * Dump out the canonical form
+ */
+
+void
+rtems_monitor_extension_dump(
+ rtems_monitor_extension_t *monitor_extension,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_dump_id(monitor_extension->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_extension->name);
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"create: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_create, verbose);
+ length += fprintf(stdout,"; start: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_start, verbose);
+ length += fprintf(stdout,"; restart: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_restart, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"delete: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_delete, verbose);
+ length += fprintf(stdout,"; switch: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_tswitch, verbose);
+ length += fprintf(stdout,"; begin: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_begin, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"exitted: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_exitted, verbose);
+ length += fprintf(stdout,"; fatal: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_fatal, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-itask.c b/cpukit/libmisc/monitor/mon-itask.c
new file mode 100644
index 0000000000..f83d0e8561
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-itask.c
@@ -0,0 +1,119 @@
+/*
+ * RTEMS Monitor init task support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+/*
+ * As above, but just for init tasks
+ */
+void
+rtems_monitor_init_task_canonical(
+ rtems_monitor_init_task_t *canonical_itask,
+ void *itask_void
+)
+{
+ rtems_initialization_tasks_table *rtems_itask = itask_void;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_itask->entry,
+ (void *) rtems_itask->entry_point);
+
+ canonical_itask->argument = rtems_itask->argument;
+ canonical_itask->stack_size = rtems_itask->stack_size;
+ canonical_itask->priority = rtems_itask->initial_priority;
+ canonical_itask->modes = rtems_itask->mode_set;
+ canonical_itask->attributes = rtems_itask->attribute_set;
+}
+
+void *
+rtems_monitor_init_task_next(
+ void *object_info,
+ rtems_monitor_init_task_t *canonical_init_task,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ rtems_initialization_tasks_table *itask;
+ uint32_t n = rtems_get_index(*next_id);
+
+ if (n >= c->RTEMS_api_configuration->number_of_initialization_tasks)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ itask = c->RTEMS_api_configuration->User_initialization_tasks_table + n;
+
+ /*
+ * dummy up a fake id and name for this item
+ */
+
+ canonical_init_task->id = n;
+ canonical_init_task->name = itask->name;
+
+ *next_id += 1;
+ return (void *) itask;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_init_task_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ # NAME ENTRY ARGUMENT PRIO MODES ATTRIBUTES STACK SIZE\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_init_task_dump(
+ rtems_monitor_init_task_t *monitor_itask,
+ boolean verbose
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_decimal(monitor_itask->id);
+
+ length += rtems_monitor_pad(7, length);
+ length += rtems_monitor_dump_name(monitor_itask->name);
+
+ length += rtems_monitor_pad(14, length);
+ length += rtems_monitor_symbol_dump(&monitor_itask->entry, verbose);
+
+ length += rtems_monitor_pad(25, length);
+ length += fprintf(stdout,"%d [0x%x]", monitor_itask->argument, monitor_itask->argument);
+
+ length += rtems_monitor_pad(39, length);
+ length += rtems_monitor_dump_priority(monitor_itask->priority);
+
+ length += rtems_monitor_pad(46, length);
+ length += rtems_monitor_dump_modes(monitor_itask->modes);
+
+ length += rtems_monitor_pad(54, length);
+ length += rtems_monitor_dump_attributes(monitor_itask->attributes);
+
+ length += rtems_monitor_pad(66, length);
+ length += fprintf(stdout,"%d [0x%x]", monitor_itask->stack_size, monitor_itask->stack_size);
+
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-manager.c b/cpukit/libmisc/monitor/mon-manager.c
new file mode 100644
index 0000000000..7e7a269cd6
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-manager.c
@@ -0,0 +1,54 @@
+/*
+ * RTEMS Monitor "manager" support.
+ * Used to traverse object (chain) lists and print them out.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+/*
+ * "next" routine for all objects that are RTEMS manager objects
+ */
+
+void *
+rtems_monitor_manager_next(
+ void *table_void,
+ void *canonical,
+ rtems_id *next_id
+)
+{
+ Objects_Information *table = table_void;
+ rtems_monitor_generic_t *copy;
+ Objects_Control *object = 0;
+ Objects_Locations location;
+
+ /*
+ * When we are called, it must be local
+ */
+
+ if ( ! _Objects_Is_local_id(*next_id))
+ goto done;
+
+ object = _Objects_Get_next(table, *next_id, &location, next_id);
+
+ if (object)
+ {
+ copy = (rtems_monitor_generic_t *) canonical;
+ copy->id = object->id;
+ if(table->is_string)
+ _Objects_Copy_name_raw(object->name, &copy->name, sizeof(copy->name));
+ else
+ _Objects_Copy_name_raw(&object->name, &copy->name, sizeof(copy->name));
+ }
+
+done:
+ return object;
+}
diff --git a/cpukit/libmisc/monitor/mon-monitor.c b/cpukit/libmisc/monitor/mon-monitor.c
new file mode 100644
index 0000000000..d45df2dfc0
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-monitor.c
@@ -0,0 +1,591 @@
+/*
+ * RTEMS monitor main body
+ *
+ * TODO:
+ * add stuff to RTEMS api
+ * rtems_get_name(id)
+ * rtems_get_type(id)
+ * rtems_build_id(node, type, num)
+ * Add a command to dump out info about an arbitrary id when
+ * types are added to id's
+ * rtems> id idnum
+ * idnum: node n, object: whatever, id: whatever
+ * allow id's to be specified as n:t:id, where 'n:t' is optional
+ * should have a separate monitor FILE stream (ala the debugger)
+ * remote request/response stuff should be cleaned up
+ * maybe we can use real rpc??
+ * 'info' command to print out:
+ * interrupt stack location, direction and size
+ * floating point config stuff
+ * interrupt config stuff
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <rtems/monitor.h>
+
+#define STREQ(a,b) (strcmp(a,b) == 0)
+
+/* set by trap handler */
+extern rtems_tcb *debugger_interrupted_task;
+extern rtems_context *debugger_interrupted_task_context;
+extern uint32_t debugger_trap;
+
+/*
+ * Various id's for the monitor
+ * They need to be public variables for access by other agencies
+ * such as debugger and remote servers'
+ */
+
+rtems_id rtems_monitor_task_id;
+
+uint32_t rtems_monitor_node; /* our node number */
+uint32_t rtems_monitor_default_node; /* current default for commands */
+
+/*
+ * The rtems symbol table
+ */
+
+rtems_symbol_table_t *rtems_monitor_symbols;
+
+/*
+ * User registered commands.
+ */
+
+rtems_monitor_command_entry_t rtems_registered_commands;
+
+/*
+ * The top-level commands
+ */
+
+rtems_monitor_command_entry_t rtems_monitor_commands[] = {
+ { "config",
+ "Show the system configuration.",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_CONFIG },
+ &rtems_monitor_commands[1],
+ },
+ { "itask",
+ "List init tasks for the system",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_INIT_TASK },
+ &rtems_monitor_commands[2],
+ },
+ { "mpci",
+ "Show the MPCI system configuration, if configured.",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_MPCI },
+ &rtems_monitor_commands[3],
+ },
+ { "pause",
+ "Monitor goes to \"sleep\" for specified ticks (default is 1). "
+ "Monitor will resume at end of period or if explicitly awakened\n"
+ " pause [ticks]",
+ 0,
+ rtems_monitor_pause_cmd,
+ { 0 },
+ &rtems_monitor_commands[4],
+ },
+ { "continue",
+ "Put the monitor to sleep waiting for an explicit wakeup from the "
+ "program running.\n",
+ 0,
+ rtems_monitor_continue_cmd,
+ { 0 },
+ &rtems_monitor_commands[5],
+ },
+ { "go",
+ "Alias for 'continue'",
+ 0,
+ rtems_monitor_continue_cmd,
+ { 0 },
+ &rtems_monitor_commands[6],
+ },
+ { "node",
+ "Specify default node number for commands that take id's.\n"
+ " node [ node number ]",
+ 0,
+ rtems_monitor_node_cmd,
+ { 0 },
+ &rtems_monitor_commands[7],
+ },
+ { "symbol",
+ "Display value associated with specified symbol. "
+ "Defaults to displaying all known symbols.\n"
+ " symbol [ symbolname [symbolname ... ] ]",
+ 0,
+ rtems_monitor_symbol_cmd,
+ { .symbol_table = &rtems_monitor_symbols },
+ &rtems_monitor_commands[8],
+ },
+ { "extension",
+ "Display information about specified extensions. "
+ "Default is to display information about all extensions on this node.\n"
+ " extension [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_EXTENSION },
+ &rtems_monitor_commands[9],
+ },
+ { "task",
+ "Display information about the specified tasks. "
+ "Default is to display information about all tasks on this node.\n"
+ " task [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_TASK },
+ &rtems_monitor_commands[10],
+ },
+ { "queue",
+ "Display information about the specified message queues. "
+ "Default is to display information about all queues on this node.\n"
+ " queue [id [id ... ] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_QUEUE },
+ &rtems_monitor_commands[11],
+ },
+ { "object",
+ "Display information about specified RTEMS objects. "
+ "Object id's must include 'type' information. "
+ "(which may normally be defaulted)\n"
+ " object [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_INVALID },
+ &rtems_monitor_commands[12],
+ },
+ { "driver",
+ "Display the RTEMS device driver table.\n"
+ " driver [ major [ major ... ] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_DRIVER },
+ &rtems_monitor_commands[13],
+ },
+ { "dname",
+ "Displays information about named drivers.\n",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_DNAME },
+ &rtems_monitor_commands[14],
+ },
+ { "exit",
+ "Invoke 'rtems_fatal_error_occurred' with 'status' "
+ "(default is RTEMS_SUCCESSFUL)\n"
+ " exit [status]",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_SUCCESSFUL },
+ &rtems_monitor_commands[15],
+ },
+ { "fatal",
+ "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
+ " fatal [status]",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_TASK_EXITTED }, /* exit value */
+ &rtems_monitor_commands[16],
+ },
+ { "quit",
+ "Alias for 'exit'\n",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_SUCCESSFUL }, /* exit value */
+ &rtems_monitor_commands[17],
+ },
+ { "help",
+ "Provide information about commands. "
+ "Default is show basic command summary.\n"
+ "help [ command [ command ] ]",
+ 0,
+ rtems_monitor_help_cmd,
+ { .monitor_command_entry = rtems_monitor_commands },
+ &rtems_monitor_commands[18],
+ },
+#ifdef CPU_INVOKE_DEBUGGER
+ { "debugger",
+ "Enter the debugger, if possible. "
+ "A continue from the debugger will return to the monitor.\n",
+ 0,
+ rtems_monitor_debugger_cmd,
+ { 0 },
+ &rtems_monitor_commands[19],
+ },
+#endif
+ { 0, 0, 0, 0, { 0 }, &rtems_registered_commands },
+};
+
+
+rtems_status_code
+rtems_monitor_suspend(rtems_interval timeout)
+{
+ rtems_event_set event_set;
+ rtems_status_code status;
+
+ status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
+ RTEMS_DEFAULT_OPTIONS,
+ timeout,
+ &event_set);
+ return status;
+}
+
+void
+rtems_monitor_wakeup(void)
+{
+ rtems_status_code status;
+
+ status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
+}
+
+void
+rtems_monitor_debugger_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+#ifdef CPU_INVOKE_DEBUGGER
+ CPU_INVOKE_DEBUGGER;
+#endif
+}
+
+void
+rtems_monitor_pause_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ if (argc == 1)
+ rtems_monitor_suspend(1);
+ else
+ rtems_monitor_suspend(strtoul(argv[1], 0, 0));
+}
+
+void
+rtems_monitor_fatal_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ if (argc == 1)
+ rtems_fatal_error_occurred(command_arg->status_code);
+ else
+ rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
+}
+
+void
+rtems_monitor_continue_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
+}
+
+void
+rtems_monitor_node_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ uint32_t new_node = rtems_monitor_default_node;
+
+ switch (argc)
+ {
+ case 1: /* no node, just set back to ours */
+ new_node = rtems_monitor_node;
+ break;
+
+ case 2:
+ new_node = strtoul(argv[1], 0, 0);
+ break;
+
+ default:
+ fprintf(stdout,"invalid syntax, try 'help node'\n");
+ break;
+ }
+
+ if ((new_node >= 1) &&
+ _Configuration_MP_table &&
+ (new_node <= _Configuration_MP_table->maximum_nodes))
+ rtems_monitor_default_node = new_node;
+}
+
+
+/*
+ * Function: rtems_monitor_symbols_loadup
+ *
+ * Description:
+ * Create and load the monitor's symbol table.
+ * We are reading the output format of 'gnm' which looks like this:
+ *
+ * 400a7068 ? _Rate_monotonic_Information
+ * 400a708c ? _Thread_Dispatch_disable_level
+ * 400a7090 ? _Configuration_Table
+ *
+ * We ignore the type field.
+ *
+ * Side Effects:
+ * Creates and fills in 'rtems_monitor_symbols' table
+ *
+ * TODO
+ * there should be a BSP #define or something like that
+ * to do this; Assuming stdio is crazy.
+ * Someday this should know BFD
+ * Maybe we could get objcopy to just copy the symbol areas
+ * and copy that down.
+ *
+ */
+
+void
+rtems_monitor_symbols_loadup(void)
+{
+ FILE *fp;
+ char buffer[128];
+
+ if (rtems_monitor_symbols)
+ rtems_symbol_table_destroy(rtems_monitor_symbols);
+
+ rtems_monitor_symbols = rtems_symbol_table_create(10);
+ if (rtems_monitor_symbols == 0)
+ return;
+
+ fp = fopen("symbols", "r");
+
+ if (fp == 0)
+ return;
+
+ while (fgets(buffer, sizeof(buffer) - 1, fp))
+ {
+ char *symbol;
+ char *value;
+ char *ignored_type;
+
+ value = strtok(buffer, " \t\n");
+ ignored_type = strtok(0, " \t\n");
+ symbol = strtok(0, " \t\n");
+
+ if (symbol && ignored_type && value)
+ {
+ rtems_symbol_t *sp;
+ sp = rtems_symbol_create(rtems_monitor_symbols,
+ symbol,
+ (uint32_t ) strtoul(value, 0, 16));
+ if (sp == 0)
+ {
+ fprintf(stdout,"could not define symbol '%s'\n", symbol);
+ goto done;
+ }
+ }
+ else
+ {
+ fprintf(stdout,"parsing error on '%s'\n", buffer);
+ goto done;
+ }
+ }
+
+done:
+ return;
+}
+
+/*
+ * User registered commands.
+ */
+
+int
+rtems_monitor_insert_cmd (
+ rtems_monitor_command_entry_t *command
+)
+{
+ rtems_monitor_command_entry_t **p = &rtems_registered_commands.next;
+
+ command->next = 0;
+
+ while (*p) {
+ if ( STREQ(command->command, (*p)->command) )
+ return 0;
+ p = & (*p)->next;
+ }
+ *p = command;
+ return 1;
+}
+
+int
+rtems_monitor_erase_cmd (
+ rtems_monitor_command_entry_t *command
+)
+{
+ rtems_monitor_command_entry_t **p = & rtems_registered_commands.next;
+
+ while (*p) {
+ if ( STREQ(command->command, (*p)->command) ) {
+ *p = (*p)->next;
+ command->next = 0;
+ return 1;
+ }
+ p = & (*p)->next;
+ }
+ return 0;
+
+}
+
+/*
+ * Main monitor command loop
+ */
+
+void
+rtems_monitor_task(
+ rtems_task_argument monitor_flags
+)
+{
+ rtems_tcb *debugee = 0;
+ rtems_context *rp;
+ rtems_context_fp *fp;
+ char command_buffer[513];
+ int argc;
+ char *argv[64];
+ boolean verbose = FALSE;
+ struct termios term;
+
+ /*
+ * Make the stdin stream characte not line based.
+ */
+
+ if (tcgetattr (STDIN_FILENO, &term) < 0)
+ {
+ fprintf(stdout,"rtems-monitor: cannot get terminal attributes.\n");
+ }
+ else
+ {
+ /*
+ * No echo, no canonical processing.
+ */
+
+ term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
+
+ /*
+ * No sigint on BREAK, CR-to-NL off, input parity off,
+ * don't strip 8th bit on input, output flow control off
+ */
+
+ term.c_lflag &= ~(INPCK | ISTRIP | IXON);
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+
+ if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
+ {
+ fprintf(stdout,"cannot set terminal attributes\n");
+ }
+ }
+
+ if (monitor_flags & RTEMS_MONITOR_SUSPEND)
+ (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
+
+ for (;;)
+ {
+ extern rtems_tcb * _Thread_Executing;
+ rtems_monitor_command_entry_t *command;
+
+ debugee = _Thread_Executing;
+ rp = &debugee->Registers;
+#if (CPU_HARDWARE_FP == TRUE) || (CPU_SOFTWARE_FP == TRUE)
+ fp = debugee->fp_context; /* possibly 0 */
+#else
+ fp = 0;
+#endif
+
+ if (0 == rtems_monitor_command_read(command_buffer, &argc, argv))
+ continue;
+ if ((command = rtems_monitor_command_lookup(rtems_monitor_commands,
+ argc,
+ argv)) == 0)
+ {
+ /* no command */
+ fprintf(stdout,"Unrecognised command; try 'help'\n");
+ continue;
+ }
+
+ command->command_function(argc, argv, &command->command_arg, verbose);
+
+ fflush(stdout);
+ }
+}
+
+
+void
+rtems_monitor_kill(void)
+{
+ if (rtems_monitor_task_id)
+ rtems_task_delete(rtems_monitor_task_id);
+ rtems_monitor_task_id = 0;
+
+ rtems_monitor_server_kill();
+}
+
+void
+rtems_monitor_init(
+ uint32_t monitor_flags
+)
+{
+ rtems_status_code status;
+
+ rtems_monitor_kill();
+
+ status = rtems_task_create(RTEMS_MONITOR_NAME,
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE * 2,
+ RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &rtems_monitor_task_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor task");
+ return;
+ }
+
+ rtems_monitor_node = rtems_get_node(rtems_monitor_task_id);
+ rtems_monitor_default_node = rtems_monitor_node;
+
+ rtems_monitor_symbols_loadup();
+
+ if (monitor_flags & RTEMS_MONITOR_GLOBAL)
+ rtems_monitor_server_init(monitor_flags);
+
+ /*
+ * Start the monitor task itself
+ */
+
+ status = rtems_task_start(rtems_monitor_task_id,
+ rtems_monitor_task,
+ monitor_flags);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not start monitor");
+ return;
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-mpci.c b/cpukit/libmisc/monitor/mon-mpci.c
new file mode 100644
index 0000000000..2cbd48eb3c
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-mpci.c
@@ -0,0 +1,162 @@
+/*
+ * RTEMS MPCI Config display support
+ *
+ * TODO
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+
+#define DATACOL 15
+
+/*
+ * Fill in entire monitor config table
+ * for sending to a remote monitor or printing on the local system
+ */
+
+void
+rtems_monitor_mpci_canonical(
+ rtems_monitor_mpci_t *canonical_mpci,
+ void *config_void
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ rtems_multiprocessing_table *m;
+ rtems_mpci_table *mt;
+
+ m = c->User_multiprocessing_table;
+ if (m == 0)
+ return;
+ mt = m->User_mpci_table;
+
+ canonical_mpci->node = m->node;
+ canonical_mpci->maximum_nodes = m->maximum_nodes;
+ canonical_mpci->maximum_global_objects = m->maximum_global_objects;
+ canonical_mpci->maximum_proxies = m->maximum_proxies;
+
+ canonical_mpci->default_timeout = mt->default_timeout;
+ canonical_mpci->maximum_packet_size = mt->maximum_packet_size;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->initialization,
+ (void *) mt->initialization);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->get_packet,
+ (void *) mt->get_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->return_packet,
+ (void *) mt->return_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->send_packet,
+ (void *) mt->send_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->receive_packet,
+ (void *) mt->receive_packet);
+}
+
+/*
+ * This is easy, since there is only 1 (altho we could get them from
+ * other nodes...)
+ */
+
+void *
+rtems_monitor_mpci_next(
+ void *object_info,
+ rtems_monitor_mpci_t *canonical_mpci,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ int n = rtems_get_index(*next_id);
+
+ if (n >= 1)
+ goto failed;
+
+ if ( ! c->User_multiprocessing_table)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) c;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_mpci_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ max max max default max\n\
+ node nodes globals proxies timeout pktsize\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+
+void
+rtems_monitor_mpci_dump(
+ rtems_monitor_mpci_t *monitor_mpci,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_pad(2, length);
+ length += fprintf(stdout," %d", monitor_mpci->node);
+ length += rtems_monitor_pad(11, length);
+ length += fprintf(stdout,"%d", monitor_mpci->maximum_nodes);
+
+ length += rtems_monitor_pad(18, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->maximum_global_objects);
+
+ length += rtems_monitor_pad(28, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->maximum_proxies);
+
+ length += rtems_monitor_pad(37, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->default_timeout);
+
+ length += rtems_monitor_pad(46, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->maximum_packet_size);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"init: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->initialization, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"get: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->get_packet, verbose);
+ length += fprintf(stdout,"; return: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->return_packet, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"send: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->send_packet, verbose);
+ length += fprintf(stdout,"; receive: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->receive_packet, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+}
diff --git a/cpukit/libmisc/monitor/mon-object.c b/cpukit/libmisc/monitor/mon-object.c
new file mode 100644
index 0000000000..4428234220
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-object.c
@@ -0,0 +1,387 @@
+/*
+ * RTEMS Monitor "object" support.
+ *
+ * Used to traverse object lists and print them out.
+ * An object can be an RTEMS object (chain based stuff) or
+ * a "misc" object such as a device driver.
+ *
+ * Each object has its own file in this directory (eg: extension.c)
+ * That file provides routines to convert a "native" structure
+ * to its canonical form, print a canonical structure, etc.
+ *
+ * TODO:
+ * should allow for non-numeric id's???
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+#include <string.h> /* memcpy() */
+
+#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
+
+/*
+ * add:
+ * next
+ */
+
+rtems_monitor_object_info_t rtems_monitor_object_info[] =
+{
+ { RTEMS_MONITOR_OBJECT_CONFIG,
+ (void *) 0,
+ sizeof(rtems_monitor_config_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_config_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_config_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_config_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_config_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_MPCI,
+ (void *) 0,
+#if defined(RTEMS_MULTIPROCESSING)
+ sizeof(rtems_monitor_mpci_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_mpci_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_mpci_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_mpci_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_mpci_dump,
+#else
+ 0,
+ (rtems_monitor_object_next_fn) 0,
+ (rtems_monitor_object_canonical_fn) 0,
+ (rtems_monitor_object_dump_header_fn) 0,
+ (rtems_monitor_object_dump_fn) 0,
+#endif
+ },
+ { RTEMS_MONITOR_OBJECT_INIT_TASK,
+ (void *) 0,
+ sizeof(rtems_monitor_init_task_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_init_task_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_init_task_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_init_task_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_init_task_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_TASK,
+ (void *) &_RTEMS_tasks_Information,
+ sizeof(rtems_monitor_task_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_task_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_task_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_task_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_QUEUE,
+ (void *) &_Message_queue_Information,
+ sizeof(rtems_monitor_queue_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_queue_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_queue_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_queue_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_EXTENSION,
+ (void *) &_Extension_Information,
+ sizeof(rtems_monitor_extension_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_extension_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_extension_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_extension_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_DRIVER,
+ (void *) 0,
+ sizeof(rtems_monitor_driver_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_driver_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_driver_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_driver_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_driver_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_DNAME,
+ /* XXX now that the driver name table is allocated from the */
+ /* XXX Workspace, this does not work */
+ (void *) 0,
+ /* (void *) _IO_Driver_name_table, */
+ sizeof(rtems_monitor_dname_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_dname_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_dname_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_dname_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_dname_dump,
+ },
+};
+
+/*
+ * Allow id's to be specified without the node number or
+ * type for convenience.
+ */
+
+rtems_id
+rtems_monitor_id_fixup(
+ rtems_id id,
+ uint32_t default_node,
+ rtems_monitor_object_type_t type
+)
+{
+ uint32_t node;
+
+ node = rtems_get_node(id);
+ if (node == 0)
+ {
+ if (rtems_get_class(id) != OBJECTS_NO_CLASS)
+ type = rtems_get_class(id);
+
+ id = _Objects_Build_id(
+ OBJECTS_CLASSIC_API, type, default_node, rtems_get_index(id));
+ }
+ return id;
+}
+
+
+rtems_monitor_object_info_t *
+rtems_monitor_object_lookup(
+ rtems_monitor_object_type_t type
+)
+{
+ rtems_monitor_object_info_t *p;
+ for (p = &rtems_monitor_object_info[0];
+ p < &rtems_monitor_object_info[NUMELEMS(rtems_monitor_object_info)];
+ p++)
+ {
+ if (p->type == type)
+ return p;
+ }
+ return 0;
+}
+
+rtems_id
+rtems_monitor_object_canonical_next_remote(
+ rtems_monitor_object_type_t type,
+ rtems_id id,
+ void *canonical
+)
+{
+ rtems_id next_id;
+ rtems_status_code status;
+ rtems_monitor_server_request_t request;
+ rtems_monitor_server_response_t response;
+
+ /*
+ * Send request
+ */
+
+ request.command = RTEMS_MONITOR_SERVER_CANONICAL;
+ request.argument0 = (uint32_t ) type;
+ request.argument1 = (uint32_t ) id;
+
+ status = rtems_monitor_server_request(rtems_get_node(id), &request, &response);
+ if (status != RTEMS_SUCCESSFUL)
+ goto failed;
+
+ /*
+ * process response
+ */
+
+ next_id = (rtems_id) response.result0;
+ if (next_id != RTEMS_OBJECT_ID_FINAL)
+ (void) memcpy(canonical, &response.payload, response.result1);
+
+ return next_id;
+
+failed:
+ return RTEMS_OBJECT_ID_FINAL;
+
+}
+
+
+rtems_id
+rtems_monitor_object_canonical_next(
+ rtems_monitor_object_info_t *info,
+ rtems_id id,
+ void *canonical
+)
+{
+ rtems_id next_id;
+ void *raw_item;
+
+ if ( ! _Objects_Is_local_id(id))
+ next_id = rtems_monitor_object_canonical_next_remote(info->type,
+ id,
+ canonical);
+ else
+ {
+ next_id = id;
+
+ raw_item = (void *) info->next(info->object_information,
+ canonical,
+ &next_id);
+
+ if (raw_item)
+ {
+ info->canonical(canonical, raw_item);
+ _Thread_Enable_dispatch();
+ }
+ }
+ return next_id;
+}
+
+
+/*
+ * this is routine server invokes locally to get the type
+ */
+
+rtems_id
+rtems_monitor_object_canonical_get(
+ rtems_monitor_object_type_t type,
+ rtems_id id,
+ void *canonical,
+ uint32_t *size_p
+)
+{
+ rtems_monitor_object_info_t *info;
+ rtems_id next_id;
+
+ *size_p = 0;
+
+ info = rtems_monitor_object_lookup(type);
+
+ if (info == 0)
+ return RTEMS_OBJECT_ID_FINAL;
+
+ next_id = rtems_monitor_object_canonical_next(info, id, canonical);
+ *size_p = info->size;
+
+ return next_id;
+}
+
+
+void
+rtems_monitor_object_dump_1(
+ rtems_monitor_object_info_t *info,
+ rtems_id id,
+ boolean verbose
+)
+{
+ rtems_id next_id;
+ rtems_monitor_union_t canonical;
+
+ if ((next_id = rtems_monitor_object_canonical_next(
+ info,
+ id,
+ &canonical)) != RTEMS_OBJECT_ID_FINAL)
+ {
+ /*
+ * If the one we actually got is the one we wanted, then
+ * print it out.
+ * For ones that have an id field, this works fine,
+ * for all others, always dump it out.
+ *
+ * HACK: the way we determine whether there is an id is a hack.
+ *
+ * by the way: the reason we try to not have an id, is that some
+ * of the canonical structures are almost too big for shared
+ * memory driver (eg: mpci)
+ */
+
+ if ((info->next != rtems_monitor_manager_next) ||
+ (id == canonical.generic.id))
+ info->dump(&canonical, verbose);
+ }
+}
+
+void
+rtems_monitor_object_dump_all(
+ rtems_monitor_object_info_t *info,
+ boolean verbose
+)
+{
+ rtems_id next_id;
+ rtems_monitor_union_t canonical;
+
+ next_id = RTEMS_OBJECT_ID_INITIAL(OBJECTS_CLASSIC_API, info->type, rtems_monitor_default_node);
+
+ while ((next_id = rtems_monitor_object_canonical_next(
+ info,
+ next_id,
+ &canonical)) != RTEMS_OBJECT_ID_FINAL)
+ {
+ info->dump(&canonical, verbose);
+ }
+}
+
+void
+rtems_monitor_object_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose
+)
+{
+ int arg;
+ rtems_monitor_object_info_t *info = 0;
+ rtems_monitor_object_type_t type ;
+
+ /* what is the default type? */
+ type = command_arg->monitor_object;
+
+ if (argc == 1)
+ {
+ if (type == RTEMS_MONITOR_OBJECT_INVALID)
+ {
+ fprintf(stdout,"A type must be specified to \"dump all\"\n");
+ goto done;
+ }
+
+ info = rtems_monitor_object_lookup(type);
+ if (info == 0)
+ goto not_found;
+
+ if (info->dump_header)
+ info->dump_header(verbose);
+ rtems_monitor_object_dump_all(info, verbose);
+ }
+ else
+ {
+ uint32_t default_node = rtems_monitor_default_node;
+ rtems_monitor_object_type_t last_type = RTEMS_MONITOR_OBJECT_INVALID;
+ rtems_id id;
+
+ for (arg=1; argv[arg]; arg++)
+ {
+ id = (rtems_id) strtoul(argv[arg], 0, 16);
+ id = rtems_monitor_id_fixup(id, default_node, type);
+ type = (rtems_monitor_object_type_t) rtems_get_class(id);
+
+ /*
+ * Allow the item type to change in the middle
+ * of the command. If the type changes, then
+ * just dump out a new header and keep on going.
+ */
+ if (type != last_type)
+ {
+ info = rtems_monitor_object_lookup(type);
+ if (info == 0)
+ goto not_found;
+
+ if (info->dump_header)
+ info->dump_header(verbose);
+ }
+
+ if (info == 0)
+ {
+not_found: fprintf(stdout,"Invalid or unsupported type %d\n", type);
+ goto done;
+ }
+
+ rtems_monitor_object_dump_1(info, id, verbose);
+
+ default_node = rtems_get_node(id);
+
+ last_type = type;
+ }
+ }
+done:
+ return;
+}
diff --git a/cpukit/libmisc/monitor/mon-prmisc.c b/cpukit/libmisc/monitor/mon-prmisc.c
new file mode 100644
index 0000000000..5104962650
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-prmisc.c
@@ -0,0 +1,268 @@
+/*
+ * Print misc stuff for the monitor dump routines
+ * Each routine returns the number of characters it output.
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <rtems/assoc.h>
+
+#include <stdio.h>
+#include <ctype.h>
+
+void
+rtems_monitor_separator(void)
+{
+ fprintf(stdout,"------------------------------------------------------------------------------\n");
+}
+
+uint32_t
+rtems_monitor_pad(
+ uint32_t destination_column,
+ uint32_t current_column
+)
+{
+ int pad_length;
+
+ if (destination_column <= current_column)
+ pad_length = 1;
+ else
+ pad_length = destination_column - current_column;
+
+ return fprintf(stdout,"%*s", pad_length, "");
+}
+
+uint32_t
+rtems_monitor_dump_char(uint8_t ch)
+{
+ if (isprint(ch))
+ return fprintf(stdout,"%c", ch);
+ else
+ return fprintf(stdout,"%02x", ch);
+}
+
+uint32_t
+rtems_monitor_dump_decimal(uint32_t num)
+{
+ return fprintf(stdout,"%4d", num);
+}
+
+uint32_t
+rtems_monitor_dump_hex(uint32_t num)
+{
+ return fprintf(stdout,"0x%x", num);
+}
+
+uint32_t
+rtems_monitor_dump_assoc_bitfield(
+ rtems_assoc_t *ap,
+ char *separator,
+ uint32_t value
+ )
+{
+ uint32_t b;
+ uint32_t length = 0;
+ const char *name;
+
+ for (b = 1; b; b <<= 1)
+ if (b & value)
+ {
+ if (length)
+ length += fprintf(stdout,"%s", separator);
+
+ name = rtems_assoc_name_by_local(ap, b);
+
+ if (name)
+ length += fprintf(stdout,"%s", name);
+ else
+ length += fprintf(stdout,"0x%x", b);
+ }
+
+ return length;
+}
+
+uint32_t
+rtems_monitor_dump_id(rtems_id id)
+{
+ return fprintf(stdout,"%08x", id);
+}
+
+uint32_t
+rtems_monitor_dump_name(rtems_name name)
+{
+ uint32_t i;
+ uint32_t length = 0;
+ union {
+ uint32_t ui;
+ char c[4];
+ } u;
+
+ u.ui = (uint32_t ) name;
+
+#if (CPU_BIG_ENDIAN == TRUE)
+ for (i=0; i<sizeof(u.c); i++)
+ length += rtems_monitor_dump_char(u.c[i]);
+#else
+ for (i=0; i<sizeof(u.c); i++)
+ length += rtems_monitor_dump_char(u.c[sizeof(u.c)-1-i]);
+#endif
+ return length;
+}
+
+uint32_t
+rtems_monitor_dump_priority(rtems_task_priority priority)
+{
+ return fprintf(stdout,"%3d", priority);
+}
+
+
+rtems_assoc_t rtems_monitor_state_assoc[] = {
+ { "DORM", STATES_DORMANT },
+ { "SUSP", STATES_SUSPENDED },
+ { "TRANS", STATES_TRANSIENT },
+ { "DELAY", STATES_DELAYING },
+ { "Wbuf", STATES_WAITING_FOR_BUFFER },
+ { "Wseg", STATES_WAITING_FOR_SEGMENT },
+ { "Wmsg" , STATES_WAITING_FOR_MESSAGE },
+ { "Wevnt", STATES_WAITING_FOR_EVENT },
+ { "Wsem", STATES_WAITING_FOR_SEMAPHORE },
+ { "Wtime", STATES_WAITING_FOR_TIME },
+ { "Wrpc", STATES_WAITING_FOR_RPC_REPLY },
+ { "Wmutex", STATES_WAITING_FOR_MUTEX },
+ { "Wcvar", STATES_WAITING_FOR_CONDITION_VARIABLE },
+ { "Wjatx", STATES_WAITING_FOR_JOIN_AT_EXIT },
+ { "Wsig", STATES_WAITING_FOR_SIGNAL },
+ { "WRATE", STATES_WAITING_FOR_PERIOD },
+ { "Wisig", STATES_INTERRUPTIBLE_BY_SIGNAL },
+ { 0, 0, 0 },
+};
+
+uint32_t
+rtems_monitor_dump_state(States_Control state)
+{
+ uint32_t length = 0;
+
+ if (state == STATES_READY) /* assoc doesn't deal with this as it is 0 */
+ length += fprintf(stdout,"READY");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_state_assoc,
+ ":",
+ state);
+ return length;
+}
+
+rtems_assoc_t rtems_monitor_attribute_assoc[] = {
+ { "FL", RTEMS_FLOATING_POINT },
+ { "GL", RTEMS_GLOBAL },
+ { "PR", RTEMS_PRIORITY },
+ { "BI", RTEMS_BINARY_SEMAPHORE },
+ { "IN", RTEMS_INHERIT_PRIORITY },
+ { 0, 0, 0 },
+};
+
+uint32_t
+rtems_monitor_dump_attributes(rtems_attribute attributes)
+{
+ uint32_t length = 0;
+
+ if (attributes == RTEMS_DEFAULT_ATTRIBUTES) /* value is 0 */
+ length += fprintf(stdout,"DEFAULT");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_attribute_assoc,
+ ":",
+ attributes);
+ return length;
+}
+
+rtems_assoc_t rtems_monitor_modes_assoc[] = {
+ { "nP", RTEMS_NO_PREEMPT },
+ { "T", RTEMS_TIMESLICE },
+ { "nA", RTEMS_NO_ASR },
+ { 0, 0, 0 },
+};
+
+uint32_t
+rtems_monitor_dump_modes(rtems_mode modes)
+{
+ uint32_t length = 0;
+
+ if (modes == RTEMS_DEFAULT_MODES) /* value is 0 */
+ length += fprintf(stdout,"P:T:nA");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_modes_assoc,
+ ":",
+ modes);
+ return length;
+}
+
+rtems_assoc_t rtems_monitor_events_assoc[] = {
+ { "0", RTEMS_EVENT_0 },
+ { "1", RTEMS_EVENT_1 },
+ { "2", RTEMS_EVENT_2 },
+ { "3", RTEMS_EVENT_3 },
+ { "4", RTEMS_EVENT_4 },
+ { "5", RTEMS_EVENT_5 },
+ { "6", RTEMS_EVENT_6 },
+ { "7", RTEMS_EVENT_7 },
+ { "8", RTEMS_EVENT_8 },
+ { "9", RTEMS_EVENT_9 },
+ { "10", RTEMS_EVENT_10 },
+ { "11", RTEMS_EVENT_11 },
+ { "12", RTEMS_EVENT_12 },
+ { "13", RTEMS_EVENT_13 },
+ { "14", RTEMS_EVENT_14 },
+ { "15", RTEMS_EVENT_15 },
+ { "16", RTEMS_EVENT_16 },
+ { "17", RTEMS_EVENT_17 },
+ { "18", RTEMS_EVENT_18 },
+ { "19", RTEMS_EVENT_19 },
+ { "20", RTEMS_EVENT_20 },
+ { "21", RTEMS_EVENT_21 },
+ { "22", RTEMS_EVENT_22 },
+ { "23", RTEMS_EVENT_23 },
+ { "24", RTEMS_EVENT_24 },
+ { "25", RTEMS_EVENT_25 },
+ { "26", RTEMS_EVENT_26 },
+ { "27", RTEMS_EVENT_27 },
+ { "28", RTEMS_EVENT_28 },
+ { "29", RTEMS_EVENT_29 },
+ { "30", RTEMS_EVENT_30 },
+ { "31", RTEMS_EVENT_31 },
+ { 0, 0, 0 },
+};
+
+uint32_t
+rtems_monitor_dump_events(rtems_event_set events)
+{
+ uint32_t length = 0;
+
+ if (events == EVENT_SETS_NONE_PENDING) /* value is 0 */
+ length += fprintf(stdout,"NONE");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_events_assoc,
+ ":",
+ events);
+ return length;
+}
+
+uint32_t
+rtems_monitor_dump_notepad(uint32_t *notepad)
+{
+ uint32_t length = 0;
+ int i;
+
+ for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++)
+ if (notepad[i])
+ length += fprintf(stdout,"%d: 0x%x ", i, notepad[i]);
+
+ return length;
+}
diff --git a/cpukit/libmisc/monitor/mon-queue.c b/cpukit/libmisc/monitor/mon-queue.c
new file mode 100644
index 0000000000..1714808fd8
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-queue.c
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+void
+rtems_monitor_queue_canonical(
+ rtems_monitor_queue_t *canonical_queue,
+ void *queue_void
+)
+{
+ Message_queue_Control *rtems_queue = (Message_queue_Control *) queue_void;
+
+ canonical_queue->attributes = rtems_queue->attribute_set;
+ canonical_queue->maximum_message_size = rtems_queue->message_queue.maximum_message_size;
+ canonical_queue->maximum_pending_messages = rtems_queue->message_queue.maximum_pending_messages;
+ canonical_queue->number_of_pending_messages = rtems_queue->message_queue.number_of_pending_messages;
+}
+
+void
+rtems_monitor_queue_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ ID NAME ATTRIBUTES PEND MAXPEND MAXSIZE\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+
+/*
+ * Dump out the "next" queue indicated by 'id'.
+ * Returns next one to check.
+ * Returns RTEMS_OBJECT_ID_FINAL when all done
+ */
+
+void
+rtems_monitor_queue_dump(
+ rtems_monitor_queue_t *monitor_queue,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_dump_id(monitor_queue->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_queue->name);
+ length += rtems_monitor_pad(19, length);
+ length += rtems_monitor_dump_attributes(monitor_queue->attributes);
+ length += rtems_monitor_pad(31, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->number_of_pending_messages);
+ length += rtems_monitor_pad(39, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->maximum_pending_messages);
+ length += rtems_monitor_pad(48, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->maximum_message_size);
+
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-server.c b/cpukit/libmisc/monitor/mon-server.c
new file mode 100644
index 0000000000..b04e5f2390
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-server.c
@@ -0,0 +1,307 @@
+/*
+ * RTEMS monitor server (handles requests for info from RTEMS monitors
+ * running on other nodes)
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rtems/monitor.h>
+
+/*
+ * Various id's for the server
+ */
+
+rtems_id rtems_monitor_server_task_id;
+rtems_id rtems_monitor_server_request_queue_id; /* our server */
+rtems_id *rtems_monitor_server_request_queue_ids; /* all servers */
+rtems_id rtems_monitor_server_response_queue_id; /* our server */
+
+
+/*
+ * Send a request to a server task
+ */
+
+rtems_status_code
+rtems_monitor_server_request(
+ uint32_t server_node,
+ rtems_monitor_server_request_t *request,
+ rtems_monitor_server_response_t *response
+)
+{
+ rtems_id server_id;
+ rtems_status_code status;
+ uint32_t size;
+
+ /*
+ * What is id of monitor on target node?
+ * Look it up if we don't know it yet.
+ */
+
+ server_id = rtems_monitor_server_request_queue_ids[server_node];
+ if (server_id == 0)
+ {
+ status = rtems_message_queue_ident(RTEMS_MONITOR_QUEUE_NAME,
+ server_node,
+ &server_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "ident of remote server failed");
+ goto done;
+ }
+
+ rtems_monitor_server_request_queue_ids[server_node] = server_id;
+ }
+
+ request->return_id = rtems_monitor_server_response_queue_id;
+
+ status = rtems_message_queue_send(server_id, request, sizeof(*request));
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "monitor server request send failed");
+ goto done;
+ }
+
+ /*
+ * Await response, if requested
+ */
+
+ if (response)
+ {
+ status = rtems_message_queue_receive(rtems_monitor_server_response_queue_id,
+ response,
+ &size,
+ RTEMS_WAIT,
+ 100);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "server did not respond");
+
+ /* maybe server task was restarted; look it up again next time */
+ rtems_monitor_server_request_queue_ids[server_node] = 0;
+
+ goto done;
+ }
+
+ if (response->command != RTEMS_MONITOR_SERVER_RESPONSE)
+ {
+ status = RTEMS_INCORRECT_STATE;
+ goto done;
+ }
+ }
+
+done:
+ return status;
+}
+
+
+
+/*
+ * monitor server task
+ */
+
+void
+rtems_monitor_server_task(
+ rtems_task_argument monitor_flags
+)
+{
+ rtems_monitor_server_request_t request;
+ rtems_monitor_server_response_t response;
+ rtems_status_code status;
+ uint32_t size;
+
+ for (;;)
+ {
+ status = rtems_message_queue_receive(
+ rtems_monitor_server_request_queue_id,
+ &request,
+ &size,
+ RTEMS_WAIT,
+ (rtems_interval) 0);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "monitor server msg queue receive error");
+ goto failed;
+ }
+
+ if (size != sizeof(request))
+ {
+ rtems_error(0, "monitor server bad size on receive");
+ goto failed;
+ }
+
+ switch (request.command)
+ {
+ case RTEMS_MONITOR_SERVER_CANONICAL:
+ {
+ rtems_monitor_object_type_t object_type;
+ rtems_id id;
+ rtems_id next_id;
+
+ object_type = (rtems_monitor_object_type_t) request.argument0;
+ id = (rtems_id) request.argument1;
+ next_id = rtems_monitor_object_canonical_get(object_type,
+ id,
+ &response.payload,
+ &size);
+
+ response.command = RTEMS_MONITOR_SERVER_RESPONSE;
+ response.result0 = next_id;
+ response.result1 = size;
+
+#define SERVER_OVERHEAD (RTEMS_offsetof(rtems_monitor_server_response_t, \
+ payload))
+
+ status = rtems_message_queue_send(request.return_id,
+ &response,
+ size + SERVER_OVERHEAD);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "response send failed");
+ goto failed;
+ }
+ break;
+ }
+
+ default:
+ {
+ rtems_error(0, "invalid command to monitor server: %d", request.command);
+ goto failed;
+ }
+ }
+ }
+
+failed:
+ rtems_task_delete(RTEMS_SELF);
+}
+
+
+/*
+ * Kill off any old server
+ * Not sure if this is useful, but it doesn't help
+ */
+
+void
+rtems_monitor_server_kill(void)
+{
+ if (rtems_monitor_server_task_id)
+ rtems_task_delete(rtems_monitor_server_task_id);
+ rtems_monitor_server_task_id = 0;
+
+ if (rtems_monitor_server_request_queue_id)
+ rtems_message_queue_delete(rtems_monitor_server_request_queue_id);
+ rtems_monitor_server_request_queue_ids = 0;
+
+ if (rtems_monitor_server_response_queue_id)
+ rtems_message_queue_delete(rtems_monitor_server_response_queue_id);
+ rtems_monitor_server_response_queue_id = 0;
+
+ if (rtems_monitor_server_request_queue_ids)
+ free(rtems_monitor_server_request_queue_ids);
+ rtems_monitor_server_request_queue_ids = 0;
+}
+
+
+void
+rtems_monitor_server_init(
+ uint32_t monitor_flags
+)
+{
+ rtems_status_code status;
+
+ if (_System_state_Is_multiprocessing &&
+ (_Configuration_MP_table->maximum_nodes > 1))
+ {
+ uint32_t maximum_nodes = _Configuration_MP_table->maximum_nodes;
+
+ /*
+ * create the msg que our server will listen
+ * Since we only get msgs from other RTEMS monitors, we just
+ * need reserve space for 1 msg from each node.
+ */
+
+ status = rtems_message_queue_create(
+ RTEMS_MONITOR_QUEUE_NAME,
+ maximum_nodes,
+ sizeof(rtems_monitor_server_request_t),
+ RTEMS_GLOBAL,
+ &rtems_monitor_server_request_queue_id);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor server message queue");
+ goto done;
+ }
+
+ /*
+ * create the msg que our responses will come on
+ * Since monitor just does one thing at a time, we only need 1 item
+ * message queue.
+ */
+
+ status = rtems_message_queue_create(
+ RTEMS_MONITOR_RESPONSE_QUEUE_NAME,
+ 1, /* depth */
+ sizeof(rtems_monitor_server_response_t),
+ RTEMS_GLOBAL,
+ &rtems_monitor_server_response_queue_id);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor response message queue");
+ goto done;
+ }
+
+ /* need an id for queue of each other server we might talk to */
+ /* indexed by node, so add 1 to maximum_nodes */
+ rtems_monitor_server_request_queue_ids =
+ (rtems_id *) malloc((maximum_nodes + 1) * sizeof(rtems_id));
+ (void) memset(rtems_monitor_server_request_queue_ids,
+ 0,
+ (maximum_nodes + 1) * sizeof(rtems_id));
+
+ rtems_monitor_server_request_queue_ids[rtems_monitor_node] =
+ rtems_monitor_server_request_queue_id;
+
+ /*
+ * create the server task
+ */
+ status = rtems_task_create(RTEMS_MONITOR_SERVER_NAME,
+ 1,
+ 0 /* default stack */,
+ RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &rtems_monitor_server_task_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor server task");
+ goto done;
+ }
+
+ /*
+ * Start the server task
+ */
+ status = rtems_task_start(rtems_monitor_server_task_id,
+ rtems_monitor_server_task,
+ monitor_flags);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not start monitor server");
+ goto done;
+ }
+ }
+
+done:
+ return;
+}
diff --git a/cpukit/libmisc/monitor/mon-symbols.c b/cpukit/libmisc/monitor/mon-symbols.c
new file mode 100644
index 0000000000..b83d0243e3
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-symbols.c
@@ -0,0 +1,486 @@
+/*
+ * File: symbols.c
+ *
+ * Description:
+ * Symbol table manager for the RTEMS monitor.
+ * These routines may be used by other system resources also.
+ *
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems/monitor.h>
+#include "symbols.h"
+
+
+rtems_symbol_table_t *
+rtems_symbol_table_create()
+{
+ rtems_symbol_table_t *table;
+
+ table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t));
+ memset((void *) table, 0, sizeof(*table));
+
+ table->growth_factor = 30; /* 30 percent */
+
+ return table;
+}
+
+void
+rtems_symbol_table_destroy(rtems_symbol_table_t *table)
+{
+ rtems_symbol_string_block_t *p, *pnext;
+
+ if (table)
+ {
+ if (table->addresses)
+ (void) free(table->addresses);
+ table->addresses = 0;
+ p = table->string_buffer_head;
+ while (p)
+ {
+ pnext = p->next;
+ free(p);
+ p = pnext;
+ }
+ table->string_buffer_head = 0;
+ table->string_buffer_current = 0;
+
+ free(table);
+ }
+}
+
+rtems_symbol_t *
+rtems_symbol_create(
+ rtems_symbol_table_t *table,
+ char *name,
+ uint32_t value
+ )
+{
+ int symbol_length;
+ size_t newsize;
+ rtems_symbol_t *sp;
+
+ symbol_length = strlen(name) + 1; /* include '\000' in length */
+
+ /* need to grow the table? */
+ if (table->next >= table->size)
+ {
+ if (table->size == 0)
+ newsize = 100;
+ else
+ newsize = table->size + (table->size / (100 / table->growth_factor));
+
+ table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t));
+ if (table->addresses == 0) /* blew it; lost orig */
+ goto failed;
+ table->size = newsize;
+ }
+
+ sp = &table->addresses[table->next];
+ sp->value = value;
+
+ /* Have to add it to string pool */
+ /* need to grow pool? */
+
+ if ((table->string_buffer_head == 0) ||
+ (table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE)
+ {
+ rtems_symbol_string_block_t *p;
+
+ p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t));
+ if (p == 0)
+ goto failed;
+ p->next = 0;
+ if (table->string_buffer_head == 0)
+ table->string_buffer_head = p;
+ else
+ table->string_buffer_current->next = p;
+ table->string_buffer_current = p;
+
+ table->strings_next = 0;
+ }
+
+ sp->name = table->string_buffer_current->buffer + table->strings_next;
+ (void) strcpy(sp->name, name);
+
+ table->strings_next += symbol_length;
+ table->sorted = 0;
+ table->next++;
+
+ return sp;
+
+/* XXX Not sure what to do here. We've possibly destroyed the initial
+ symbol table due to realloc failure */
+failed:
+ return 0;
+}
+
+/*
+ * Qsort entry point for compare by address
+ */
+
+static int
+rtems_symbol_compare(const void *e1,
+ const void *e2)
+{
+ rtems_symbol_t *s1, *s2;
+ s1 = (rtems_symbol_t *) e1;
+ s2 = (rtems_symbol_t *) e2;
+
+ if (s1->value < s2->value)
+ return -1;
+ if (s1->value > s2->value)
+ return 1;
+ return 0;
+}
+
+
+/*
+ * Sort the symbol table using qsort
+ */
+
+static void
+rtems_symbol_sort(rtems_symbol_table_t *table)
+{
+ qsort((void *) table->addresses, (size_t) table->next,
+ sizeof(rtems_symbol_t), rtems_symbol_compare);
+ table->sorted = 1;
+}
+
+
+/*
+ * Search the symbol table by address
+ * This code based on CYGNUS newlib bsearch, but changed
+ * to allow for finding closest symbol <= key
+ */
+
+rtems_symbol_t *
+rtems_symbol_value_lookup(
+ rtems_symbol_table_t *table,
+ uint32_t value
+ )
+{
+ rtems_symbol_t *sp;
+ rtems_symbol_t *base;
+ rtems_symbol_t *best = 0;
+ uint32_t distance;
+ uint32_t best_distance = ~0;
+ uint32_t elements;
+
+ if (table == 0)
+ table = rtems_monitor_symbols;
+
+ if ((table == 0) || (table->size == 0))
+ return 0;
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ base = table->addresses;
+ elements = table->next;
+
+ while (elements)
+ {
+ sp = base + (elements / 2);
+ if (value < sp->value)
+ elements /= 2;
+ else if (value > sp->value)
+ {
+ distance = value - sp->value;
+ if (distance < best_distance)
+ {
+ best_distance = distance;
+ best = sp;
+ }
+ base = sp + 1;
+ elements = (elements / 2) - (elements % 2 ? 0 : 1);
+ }
+ else
+ return sp;
+ }
+
+ if (value == base->value)
+ return base;
+
+ return best;
+}
+
+/*
+ * Search the symbol table for the exact matching address.
+ * If the symbol table has already been sorted, then
+ * call the regular symbol value lookup, however, it it
+ * has not yet been sorted, search it sequentially.
+ * This routine is primarily used for low level symbol
+ * lookups (eg. from exception handler and interrupt routines)
+ * where the penality of sorted is not wanted and where
+ * an exact match is needed such that symbol table order
+ * is not important.
+ */
+const rtems_symbol_t *
+rtems_symbol_value_lookup_exact(
+ rtems_symbol_table_t *table,
+ uint32_t value
+ )
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return NULL;
+ }
+
+ if (table->sorted)
+ {
+ sp = rtems_symbol_value_lookup(table, value);
+ if ( rtems_symbol_value(sp) == value )
+ return sp;
+ else
+ return NULL; /* not an exact match */
+ }
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ if ( sp->value == value )
+ return sp;
+ }
+
+ return NULL;
+
+}
+
+
+/*
+ * Search the symbol table by string name (case independent)
+ */
+
+rtems_symbol_t *
+rtems_symbol_name_lookup(
+ rtems_symbol_table_t *table,
+ char *name
+ )
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return NULL;
+ }
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ if ( strcasecmp(sp->name, name) == 0 )
+ return sp;
+ }
+
+ return NULL;
+}
+
+void *
+rtems_monitor_symbol_next(
+ void *object_info,
+ rtems_monitor_symbol_t *canonical,
+ rtems_id *next_id
+)
+{
+ rtems_symbol_table_t *table;
+ uint32_t n = rtems_get_index(*next_id);
+
+ table = *(rtems_symbol_table_t **) object_info;
+ if (table == 0)
+ goto failed;
+
+ if (n >= table->next)
+ goto failed;
+
+ /* NOTE: symbols do not have id and name fields */
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) (table->addresses + n);
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+void
+rtems_monitor_symbol_canonical(
+ rtems_monitor_symbol_t *canonical_symbol,
+ rtems_symbol_t *sp
+)
+{
+ canonical_symbol->value = sp->value;
+ canonical_symbol->offset = 0;
+ strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name));
+}
+
+
+void
+rtems_monitor_symbol_canonical_by_name(
+ rtems_monitor_symbol_t *canonical_symbol,
+ char *name
+)
+{
+ rtems_symbol_t *sp;
+
+ sp = rtems_symbol_name_lookup(0, name);
+
+ canonical_symbol->value = sp ? sp->value : 0;
+
+ strncpy(canonical_symbol->name, name, sizeof(canonical_symbol->name));
+ canonical_symbol->offset = 0;
+}
+
+void
+rtems_monitor_symbol_canonical_by_value(
+ rtems_monitor_symbol_t *canonical_symbol,
+ void *value_void_p
+)
+{
+ uint32_t value = (uint32_t ) value_void_p;
+ rtems_symbol_t *sp;
+
+ sp = rtems_symbol_value_lookup(0, value);
+ if (sp)
+ {
+ canonical_symbol->value = sp->value;
+ canonical_symbol->offset = value - sp->value;
+ strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name));
+ }
+ else
+ {
+ canonical_symbol->value = value;
+ canonical_symbol->offset = 0;
+ canonical_symbol->name[0] = '\0';
+ }
+}
+
+
+uint32_t
+rtems_monitor_symbol_dump(
+ rtems_monitor_symbol_t *canonical_symbol,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ /*
+ * print the name if it exists AND if value is non-zero
+ * Ie: don't print some garbage symbol for address 0
+ */
+
+ if (canonical_symbol->name[0] && (canonical_symbol->value != 0))
+ {
+ if (canonical_symbol->offset == 0)
+ length += fprintf(stdout,"%.*s",
+ (int) sizeof(canonical_symbol->name),
+ canonical_symbol->name);
+ else
+ length += fprintf(stdout,"<%.*s+0x%x>",
+ (int) sizeof(canonical_symbol->name),
+ canonical_symbol->name,
+ canonical_symbol->offset);
+ if (verbose)
+ length += fprintf(stdout," [0x%x]", canonical_symbol->value);
+ }
+ else
+ length += fprintf(stdout,"[0x%x]", canonical_symbol->value);
+
+ return length;
+}
+
+
+void
+rtems_monitor_symbol_dump_all(
+ rtems_symbol_table_t *table,
+ boolean verbose
+)
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return;
+ }
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ rtems_monitor_symbol_t canonical_symbol;
+
+ rtems_monitor_symbol_canonical(&canonical_symbol, sp);
+ rtems_monitor_symbol_dump(&canonical_symbol, TRUE);
+ fprintf(stdout,"\n");
+ }
+}
+
+
+/*
+ * 'symbol' command
+ */
+
+void
+rtems_monitor_symbol_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ int arg;
+ rtems_symbol_table_t *table;
+
+ table = *command_arg->symbol_table;
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return;
+ }
+
+ /*
+ * Use object command to dump out whole symbol table
+ */
+ if (argc == 1)
+ rtems_monitor_symbol_dump_all(table, verbose);
+ else
+ {
+ rtems_monitor_symbol_t canonical_symbol;
+
+ for (arg=1; argv[arg]; arg++)
+ {
+ rtems_monitor_symbol_canonical_by_name(&canonical_symbol, argv[arg]);
+ rtems_monitor_symbol_dump(&canonical_symbol, verbose);
+ fprintf(stdout,"\n");
+ }
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-task.c b/cpukit/libmisc/monitor/mon-task.c
new file mode 100644
index 0000000000..98e097dc71
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-task.c
@@ -0,0 +1,96 @@
+/*
+ * RTEMS Monitor task support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <string.h> /* memcpy() */
+
+void
+rtems_monitor_task_canonical(
+ rtems_monitor_task_t *canonical_task,
+ void *thread_void
+)
+{
+ Thread_Control *rtems_thread = (Thread_Control *) thread_void;
+ RTEMS_API_Control *api;
+
+ api = rtems_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ canonical_task->entry = rtems_thread->Start.entry_point;
+ canonical_task->argument = rtems_thread->Start.numeric_argument;
+ canonical_task->stack = rtems_thread->Start.Initial_stack.area;
+ canonical_task->stack_size = rtems_thread->Start.Initial_stack.size;
+ canonical_task->priority = rtems_thread->current_priority;
+ canonical_task->state = rtems_thread->current_state;
+ canonical_task->wait_id = rtems_thread->Wait.id;
+ canonical_task->events = api->pending_events;
+
+/* XXX modes and attributes only exist in the RTEMS API .. */
+/* XXX not directly in the core thread.. they will have to be derived */
+/* XXX if they are important enough to include anymore. */
+ canonical_task->modes = 0; /* XXX FIX ME.... rtems_thread->current_modes; */
+ canonical_task->attributes = 0 /* XXX FIX ME rtems_thread->API_Extensions[ THREAD_API_RTEMS ]->attribute_set */;
+ (void) memcpy(canonical_task->notepad, api ->Notepads, sizeof(canonical_task->notepad));
+/* XXX more to fix */
+/*
+ (void) memcpy(&canonical_task->wait_args, &rtems_thread->Wait.Extra, sizeof(canonical_task->wait_args));
+*/
+}
+
+
+void
+rtems_monitor_task_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ ID NAME PRIO STAT MODES EVENTS WAITID WAITARG NOTES\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_task_dump(
+ rtems_monitor_task_t *monitor_task,
+ boolean verbose
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_id(monitor_task->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_task->name);
+ length += rtems_monitor_pad(18, length);
+ length += rtems_monitor_dump_priority(monitor_task->priority);
+ length += rtems_monitor_pad(24, length);
+ length += rtems_monitor_dump_state(monitor_task->state);
+ length += rtems_monitor_pad(31, length);
+ length += rtems_monitor_dump_modes(monitor_task->modes);
+ length += rtems_monitor_pad(39, length);
+ length += rtems_monitor_dump_events(monitor_task->events);
+ if (monitor_task->wait_id)
+ {
+ length += rtems_monitor_pad(47, length);
+ length += rtems_monitor_dump_id(monitor_task->wait_id);
+ length += rtems_monitor_pad(57, length);
+ length += rtems_monitor_dump_hex(monitor_task->wait_args);
+ }
+
+ length += rtems_monitor_pad(65, length);
+ length += rtems_monitor_dump_notepad(monitor_task->notepad);
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/monitor.h b/cpukit/libmisc/monitor/monitor.h
new file mode 100644
index 0000000000..b12f07a012
--- /dev/null
+++ b/cpukit/libmisc/monitor/monitor.h
@@ -0,0 +1,459 @@
+/*
+ * File: monitor.h
+ *
+ * Description:
+ * The RTEMS monitor task include file.
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifndef __MONITOR_H
+#define __MONITOR_H
+
+#include <rtems/error.h> /* rtems_error() */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward decls from symbols.h */
+typedef struct _rtems_symbol_t rtems_symbol_t ;
+typedef struct _rtems_symbol_table_t rtems_symbol_table_t;
+
+/*
+ * Monitor types are derived from rtems object classes
+ */
+
+typedef enum {
+ RTEMS_MONITOR_OBJECT_INVALID = OBJECTS_NO_CLASS,
+ RTEMS_MONITOR_OBJECT_TASK = OBJECTS_RTEMS_TASKS,
+ RTEMS_MONITOR_OBJECT_EXTENSION = OBJECTS_RTEMS_EXTENSIONS,
+ RTEMS_MONITOR_OBJECT_QUEUE = OBJECTS_RTEMS_MESSAGE_QUEUES,
+ RTEMS_MONITOR_OBJECT_SEMAPHORE = OBJECTS_RTEMS_SEMAPHORES,
+ RTEMS_MONITOR_OBJECT_PARTITION = OBJECTS_RTEMS_PARTITIONS,
+ RTEMS_MONITOR_OBJECT_REGION = OBJECTS_RTEMS_REGIONS,
+ RTEMS_MONITOR_OBJECT_PORT = OBJECTS_RTEMS_PORTS,
+
+ /* following monitor objects are not known to RTEMS, but
+ * we like to have "types" for them anyway */
+
+ RTEMS_MONITOR_OBJECT_DRIVER = OBJECTS_RTEMS_CLASSES_LAST+1,
+ RTEMS_MONITOR_OBJECT_DNAME,
+ RTEMS_MONITOR_OBJECT_CONFIG,
+ RTEMS_MONITOR_OBJECT_INIT_TASK,
+ RTEMS_MONITOR_OBJECT_MPCI,
+ RTEMS_MONITOR_OBJECT_SYMBOL
+} rtems_monitor_object_type_t;
+
+/*
+ * rtems_monitor_init() flags
+ */
+
+#define RTEMS_MONITOR_SUSPEND 0x0001 /* suspend monitor on startup */
+#define RTEMS_MONITOR_GLOBAL 0x0002 /* monitor should be global */
+
+
+/*
+ * Public interfaces for RTEMS data structures monitor is aware of.
+ * These are only used by the monitor.
+ *
+ * NOTE:
+ * All the canonical objects that correspond to RTEMS managed "objects"
+ * must have an identical first portion with 'id' and 'name' fields.
+ *
+ * Others do not have that restriction, even tho we would like them to.
+ * This is because some of the canonical structures are almost too big
+ * for shared memory driver (eg: mpci) and we are nickel and diming it.
+ */
+
+/*
+ * Type of a pointer that may be a symbol
+ */
+
+#define MONITOR_SYMBOL_LEN 20
+typedef struct {
+ char name[MONITOR_SYMBOL_LEN];
+ uint32_t value;
+ uint32_t offset;
+} rtems_monitor_symbol_t;
+
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+} rtems_monitor_generic_t;
+
+/*
+ * Task
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ Thread_Entry entry;
+ uint32_t argument;
+ void *stack;
+ uint32_t stack_size;
+ rtems_task_priority priority;
+ States_Control state;
+ rtems_event_set events;
+ rtems_mode modes;
+ rtems_attribute attributes;
+ uint32_t notepad[RTEMS_NUMBER_NOTEPADS];
+ rtems_id wait_id;
+ uint32_t wait_args;
+} rtems_monitor_task_t;
+
+/*
+ * Init task
+ */
+
+typedef struct {
+ rtems_id id; /* not really an id */
+ rtems_name name;
+ /* end of common portion */
+ rtems_monitor_symbol_t entry;
+ uint32_t argument;
+ uint32_t stack_size;
+ rtems_task_priority priority;
+ rtems_mode modes;
+ rtems_attribute attributes;
+} rtems_monitor_init_task_t;
+
+
+/*
+ * Message queue
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_attribute attributes;
+ uint32_t number_of_pending_messages;
+ uint32_t maximum_pending_messages;
+ uint32_t maximum_message_size;
+} rtems_monitor_queue_t;
+
+/*
+ * Extension
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_monitor_symbol_t e_create;
+ rtems_monitor_symbol_t e_start;
+ rtems_monitor_symbol_t e_restart;
+ rtems_monitor_symbol_t e_delete;
+ rtems_monitor_symbol_t e_tswitch;
+ rtems_monitor_symbol_t e_begin;
+ rtems_monitor_symbol_t e_exitted;
+ rtems_monitor_symbol_t e_fatal;
+} rtems_monitor_extension_t;
+
+/*
+ * Device driver
+ */
+
+typedef struct {
+ rtems_id id; /* not really an id (should be tho) */
+ rtems_name name; /* ditto */
+ /* end of common portion */
+ rtems_monitor_symbol_t initialization; /* initialization procedure */
+ rtems_monitor_symbol_t open; /* open request procedure */
+ rtems_monitor_symbol_t close; /* close request procedure */
+ rtems_monitor_symbol_t read; /* read request procedure */
+ rtems_monitor_symbol_t write; /* write request procedure */
+ rtems_monitor_symbol_t control; /* special functions procedure */
+} rtems_monitor_driver_t;
+
+typedef struct {
+ rtems_id id; /* not used for drivers (yet) */
+ rtems_name name; /* not used for drivers (yet) */
+ /* end of common portion */
+ uint32_t major;
+ uint32_t minor;
+ char name_string[64];
+} rtems_monitor_dname_t;
+
+/*
+ * System config
+ */
+
+typedef struct {
+ void *work_space_start;
+ uint32_t work_space_size;
+ uint32_t maximum_tasks;
+ uint32_t maximum_timers;
+ uint32_t maximum_semaphores;
+ uint32_t maximum_message_queues;
+ uint32_t maximum_partitions;
+ uint32_t maximum_regions;
+ uint32_t maximum_ports;
+ uint32_t maximum_periods;
+ uint32_t maximum_extensions;
+ uint32_t microseconds_per_tick;
+ uint32_t ticks_per_timeslice;
+ uint32_t number_of_initialization_tasks;
+} rtems_monitor_config_t;
+
+/*
+ * MPCI config
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+typedef struct {
+ uint32_t node; /* local node number */
+ uint32_t maximum_nodes; /* maximum # nodes in system */
+ uint32_t maximum_global_objects; /* maximum # global objects */
+ uint32_t maximum_proxies; /* maximum # proxies */
+
+ uint32_t default_timeout; /* in ticks */
+ uint32_t maximum_packet_size;
+ rtems_monitor_symbol_t initialization;
+ rtems_monitor_symbol_t get_packet;
+ rtems_monitor_symbol_t return_packet;
+ rtems_monitor_symbol_t send_packet;
+ rtems_monitor_symbol_t receive_packet;
+} rtems_monitor_mpci_t;
+#endif
+
+/*
+ * The generic canonical information union
+ */
+
+typedef union {
+ rtems_monitor_generic_t generic;
+ rtems_monitor_task_t task;
+ rtems_monitor_queue_t queue;
+ rtems_monitor_extension_t extension;
+ rtems_monitor_driver_t driver;
+ rtems_monitor_dname_t dname;
+ rtems_monitor_config_t config;
+#if defined(RTEMS_MULTIPROCESSING)
+ rtems_monitor_mpci_t mpci;
+#endif
+ rtems_monitor_init_task_t itask;
+} rtems_monitor_union_t;
+
+/*
+ * Support for talking to other monitors
+ */
+
+/*
+ * Names of other monitors
+ */
+
+#define RTEMS_MONITOR_NAME (rtems_build_name('R', 'M', 'O', 'N'))
+#define RTEMS_MONITOR_SERVER_NAME (rtems_build_name('R', 'M', 'S', 'V'))
+#define RTEMS_MONITOR_QUEUE_NAME (rtems_build_name('R', 'M', 'S', 'Q'))
+#define RTEMS_MONITOR_RESPONSE_QUEUE_NAME (rtems_build_name('R', 'M', 'R', 'Q'))
+
+#define RTEMS_MONITOR_SERVER_RESPONSE 0x0001
+#define RTEMS_MONITOR_SERVER_CANONICAL 0x0002
+
+typedef struct
+{
+ uint32_t command;
+ rtems_id return_id;
+ uint32_t argument0;
+ uint32_t argument1;
+ uint32_t argument2;
+ uint32_t argument3;
+ uint32_t argument4;
+ uint32_t argument5;
+} rtems_monitor_server_request_t;
+
+typedef struct
+{
+ uint32_t command;
+ uint32_t result0;
+ uint32_t result1;
+ rtems_monitor_union_t payload;
+} rtems_monitor_server_response_t;
+
+extern rtems_id rtems_monitor_task_id;
+
+extern uint32_t rtems_monitor_node; /* our node number */
+extern uint32_t rtems_monitor_default_node; /* current default for commands */
+
+/*
+ * Monitor command function and table entry
+ */
+
+typedef struct rtems_monitor_command_entry_s rtems_monitor_command_entry_t;
+typedef union _rtems_monitor_command_arg_t rtems_monitor_command_arg_t;
+
+typedef void ( *rtems_monitor_command_function_t )(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose
+ );
+
+union _rtems_monitor_command_arg_t {
+ rtems_monitor_object_type_t monitor_object ;
+ rtems_status_code status_code ;
+ rtems_symbol_table_t **symbol_table ;
+ rtems_monitor_command_entry_t *monitor_command_entry ;
+};
+
+struct rtems_monitor_command_entry_s {
+ char *command; /* command name */
+ char *usage; /* usage string for the command */
+ uint32_t arguments_required; /* # of required args */
+ rtems_monitor_command_function_t command_function;
+ /* Some argument for the command */
+ rtems_monitor_command_arg_t command_arg;
+ rtems_monitor_command_entry_t *next;
+};
+
+
+typedef void *(*rtems_monitor_object_next_fn)(void *, void *, rtems_id *);
+typedef void (*rtems_monitor_object_canonical_fn)(void *, void *);
+typedef void (*rtems_monitor_object_dump_header_fn)(boolean);
+typedef void (*rtems_monitor_object_dump_fn)(void *, boolean);
+
+typedef struct {
+ rtems_monitor_object_type_t type;
+ void *object_information;
+ int size; /* of canonical object */
+ rtems_monitor_object_next_fn next;
+ rtems_monitor_object_canonical_fn canonical;
+ rtems_monitor_object_dump_header_fn dump_header;
+ rtems_monitor_object_dump_fn dump;
+} rtems_monitor_object_info_t;
+
+
+/* monitor.c */
+void rtems_monitor_kill(void);
+void rtems_monitor_init(uint32_t );
+void rtems_monitor_wakeup(void);
+void rtems_monitor_pause_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_fatal_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_continue_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_debugger_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_node_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_symbols_loadup(void);
+int rtems_monitor_insert_cmd(rtems_monitor_command_entry_t *);
+int rtems_monitor_erase_cmd(rtems_monitor_command_entry_t *);
+
+void rtems_monitor_task(rtems_task_argument);
+
+/* server.c */
+void rtems_monitor_server_kill(void);
+rtems_status_code rtems_monitor_server_request(uint32_t , rtems_monitor_server_request_t *, rtems_monitor_server_response_t *);
+void rtems_monitor_server_task(rtems_task_argument);
+void rtems_monitor_server_init(uint32_t );
+
+/* command.c */
+int rtems_monitor_make_argv(char *, int *, char **);
+int rtems_monitor_command_read(char *, int *, char **);
+rtems_monitor_command_entry_t *rtems_monitor_command_lookup(
+ rtems_monitor_command_entry_t * table, int argc, char **argv);
+void rtems_monitor_command_usage(rtems_monitor_command_entry_t *, char *);
+void rtems_monitor_help_cmd(int, char **, rtems_monitor_command_arg_t *, boolean);
+
+/* prmisc.c */
+void rtems_monitor_separator(void);
+uint32_t rtems_monitor_pad(uint32_t dest_col, uint32_t curr_col);
+uint32_t rtems_monitor_dump_char(uint8_t ch);
+uint32_t rtems_monitor_dump_decimal(uint32_t num);
+uint32_t rtems_monitor_dump_hex(uint32_t num);
+uint32_t rtems_monitor_dump_id(rtems_id id);
+uint32_t rtems_monitor_dump_name(rtems_name name);
+uint32_t rtems_monitor_dump_priority(rtems_task_priority priority);
+uint32_t rtems_monitor_dump_state(States_Control state);
+uint32_t rtems_monitor_dump_modes(rtems_mode modes);
+uint32_t rtems_monitor_dump_attributes(rtems_attribute attributes);
+uint32_t rtems_monitor_dump_events(rtems_event_set events);
+uint32_t rtems_monitor_dump_notepad(uint32_t *notepad);
+
+/* object.c */
+rtems_id rtems_monitor_id_fixup(rtems_id, uint32_t , rtems_monitor_object_type_t);
+rtems_id rtems_monitor_object_canonical_get(rtems_monitor_object_type_t, rtems_id, void *, uint32_t *size_p);
+rtems_id rtems_monitor_object_canonical_next(rtems_monitor_object_info_t *, rtems_id, void *);
+void *rtems_monitor_object_next(void *, void *, rtems_id, rtems_id *);
+rtems_id rtems_monitor_object_canonical(rtems_id, void *);
+void rtems_monitor_object_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+
+/* manager.c */
+void *rtems_monitor_manager_next(void *, void *, rtems_id *);
+
+/* config.c */
+void rtems_monitor_config_canonical(rtems_monitor_config_t *, void *);
+void *rtems_monitor_config_next(void *, rtems_monitor_config_t *, rtems_id *);
+void rtems_monitor_config_dump_header(boolean);
+void rtems_monitor_config_dump(rtems_monitor_config_t *, boolean verbose);
+
+/* mpci.c */
+#if defined(RTEMS_MULTIPROCESSING)
+void rtems_monitor_mpci_canonical(rtems_monitor_mpci_t *, void *);
+void *rtems_monitor_mpci_next(void *, rtems_monitor_mpci_t *, rtems_id *);
+void rtems_monitor_mpci_dump_header(boolean);
+void rtems_monitor_mpci_dump(rtems_monitor_mpci_t *, boolean verbose);
+#endif
+
+/* itask.c */
+void rtems_monitor_init_task_canonical(rtems_monitor_init_task_t *, void *);
+void *rtems_monitor_init_task_next(void *, rtems_monitor_init_task_t *, rtems_id *);
+void rtems_monitor_init_task_dump_header(boolean);
+void rtems_monitor_init_task_dump(rtems_monitor_init_task_t *, boolean verbose);
+
+/* extension.c */
+void rtems_monitor_extension_canonical(rtems_monitor_extension_t *, void *);
+void rtems_monitor_extension_dump_header(boolean verbose);
+void rtems_monitor_extension_dump(rtems_monitor_extension_t *, boolean);
+
+/* task.c */
+void rtems_monitor_task_canonical(rtems_monitor_task_t *, void *);
+void rtems_monitor_task_dump_header(boolean verbose);
+void rtems_monitor_task_dump(rtems_monitor_task_t *, boolean);
+
+/* queue.c */
+void rtems_monitor_queue_canonical(rtems_monitor_queue_t *, void *);
+void rtems_monitor_queue_dump_header(boolean verbose);
+void rtems_monitor_queue_dump(rtems_monitor_queue_t *, boolean);
+
+/* driver.c */
+void *rtems_monitor_driver_next(void *, rtems_monitor_driver_t *, rtems_id *);
+void rtems_monitor_driver_canonical(rtems_monitor_driver_t *, void *);
+void rtems_monitor_driver_dump_header(boolean);
+void rtems_monitor_driver_dump(rtems_monitor_driver_t *, boolean);
+
+/* dname.c */
+void *rtems_monitor_dname_next(void *, rtems_monitor_dname_t *, rtems_id *);
+void rtems_monitor_dname_canonical(rtems_monitor_dname_t *, void *);
+void rtems_monitor_dname_dump_header(boolean);
+void rtems_monitor_dname_dump(rtems_monitor_dname_t *, boolean);
+
+/* symbols.c */
+rtems_symbol_table_t *rtems_symbol_table_create();
+void rtems_symbol_table_destroy(rtems_symbol_table_t *table);
+
+rtems_symbol_t *rtems_symbol_create(rtems_symbol_table_t *, char *, uint32_t );
+rtems_symbol_t *rtems_symbol_value_lookup(rtems_symbol_table_t *, uint32_t );
+const rtems_symbol_t *rtems_symbol_value_lookup_exact(rtems_symbol_table_t *, uint32_t );
+rtems_symbol_t *rtems_symbol_name_lookup(rtems_symbol_table_t *, char *);
+void *rtems_monitor_symbol_next(void *object_info, rtems_monitor_symbol_t *, rtems_id *);
+void rtems_monitor_symbol_canonical(rtems_monitor_symbol_t *, rtems_symbol_t *);
+void rtems_monitor_symbol_canonical_by_name(rtems_monitor_symbol_t *, char *);
+void rtems_monitor_symbol_canonical_by_value(rtems_monitor_symbol_t *, void *);
+uint32_t rtems_monitor_symbol_dump(rtems_monitor_symbol_t *, boolean);
+void rtems_monitor_symbol_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+
+
+extern rtems_symbol_table_t *rtems_monitor_symbols;
+
+/* FIXME: This should not be here */
+extern rtems_monitor_command_entry_t rtems_monitor_commands[];
+
+#define MONITOR_WAKEUP_EVENT RTEMS_EVENT_0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! __MONITOR_H */
diff --git a/cpukit/libmisc/monitor/symbols.h b/cpukit/libmisc/monitor/symbols.h
new file mode 100644
index 0000000000..6246379a94
--- /dev/null
+++ b/cpukit/libmisc/monitor/symbols.h
@@ -0,0 +1,64 @@
+/*
+ * RTEMS monitor symbol table functions
+ *
+ * Description:
+ * Entry points for symbol table routines.
+ *
+ *
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifndef _INCLUDE_SYMBOLS_H
+#define _INCLUDE_SYMBOLS_H
+
+#include <rtems/monitor.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _rtems_symbol_t {
+ uint32_t value;
+ char *name;
+} ;
+
+#define SYMBOL_STRING_BLOCK_SIZE 4080
+typedef struct rtems_symbol_string_block_s {
+ struct rtems_symbol_string_block_s *next;
+ char buffer[SYMBOL_STRING_BLOCK_SIZE];
+} rtems_symbol_string_block_t;
+
+struct _rtems_symbol_table_t {
+
+ uint32_t sorted; /* are symbols sorted right now? */
+ uint32_t growth_factor; /* % to grow by when needed */
+ uint32_t next; /* next symbol slot to use when adding */
+ uint32_t size; /* max # of symbols */
+
+ /*
+ * Symbol list -- sorted by address (when we do a lookup)
+ */
+
+ rtems_symbol_t *addresses; /* symbol array by address */
+
+ /*
+ * String pool, unsorted, a list of blocks of string data
+ */
+
+ rtems_symbol_string_block_t *string_buffer_head;
+ rtems_symbol_string_block_t *string_buffer_current;
+ uint32_t strings_next; /* next byte to use in this block */
+
+} ;
+
+#define rtems_symbol_name(sp) ((sp)->name)
+#define rtems_symbol_value(sp) ((sp)->value)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_SYMBOLS_H */
diff --git a/cpukit/libmisc/mw-fb/mw_fb.c b/cpukit/libmisc/mw-fb/mw_fb.c
new file mode 100644
index 0000000000..7ea715a18f
--- /dev/null
+++ b/cpukit/libmisc/mw-fb/mw_fb.c
@@ -0,0 +1,194 @@
+/*
+/////////////////////////////////////////////////////////////////////////////
+// $Header$
+//
+// Copyright (c) 2000 - Rosimildo da Silva
+//
+// MODULE DESCRIPTION:
+// Wrapper API around the ioctls calls for the Micro FrameBuffer
+// interface for Embedded Systems
+//
+// All functions returns 0 on success. Any other value should be
+// decoded as an error. A list of errors will be created over time.
+//
+// MODIFICATION/HISTORY:
+//
+// $Log$
+// Revision 1.3 2004/04/15 13:24:46 ralf
+// Remove stray white spaces.
+//
+// Revision 1.2 2003/07/08 08:38:48 ralf
+// 2003-07-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+//
+// * capture/capture-cli.c: Add config-header support.
+// * capture/capture.c: Add config-header support.
+// * cpuuse/cpuuse.c: Add config-header support.
+// * devnull/devnull.c: Add config-header support.
+// * dummy/dummy.c: Add config-header support.
+// * dumpbuf/dumpbuf.c: Add config-header support.
+// * monitor/mon-command.c: Add config-header support.
+// * monitor/mon-config.c: Add config-header support.
+// * monitor/mon-dname.c: Add config-header support.
+// * monitor/mon-driver.c: Add config-header support.
+// * monitor/mon-extension.c: Add config-header support.
+// * monitor/mon-itask.c: Add config-header support.
+// * monitor/mon-manager.c: Add config-header support.
+// * monitor/mon-monitor.c: Add config-header support.
+// * monitor/mon-mpci.c: Add config-header support.
+// * monitor/mon-object.c: Add config-header support.
+// * monitor/mon-prmisc.c: Add config-header support.
+// * monitor/mon-queue.c: Add config-header support.
+// * monitor/mon-server.c: Add config-header support.
+// * monitor/mon-symbols.c: Add config-header support.
+// * monitor/mon-task.c: Add config-header support.
+// * mw-fb/mw_fb.c: Add config-header support.
+// * mw-fb/mw_uid.c: Add config-header support.
+// * rtmonuse/rtmonuse.c: Add config-header support.
+// * serdbg/serdbg.c: Add config-header support.
+// * serdbg/serdbgio.c: Add config-header support.
+// * serdbg/termios_printk.c: Add config-header support.
+// * shell/cmds.c: Add config-header support.
+// * stackchk/check.c: Add config-header support.
+// * untar/untar.c: Add config-header support.
+//
+// Revision 1.1 2000/08/30 08:21:24 joel
+// 2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+//
+// * Added generic Micro FrameBuffer interface for MicroWindows.
+// This interface allows MicroWindows to under RTEMS. A sample
+// driver has been developed for the pc386 BSP. See
+// pc386/fb_vga.c as a sample.
+// * Added Uniform Input Device interface for MicroWindows.
+// See PC386 bsp for sample drivers for mouse and keyboard (console).
+// * mw-bf: New directory.
+// * Makefile.am, configure.in, wrapup/Makefile.am: Account for mw-fb.
+// * mw-fb/Makefile.am: New file.
+// * mw-fb/mw_fb.c: New file.
+// * mw-fb/mw_fb.h: New file.
+// * mw-fb/mw_uid.c: New file.
+// * mw-fb/mw_uid.h: New file.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <rtems/mw_fb.h>
+
+
+/*
+ * This function returns the information regarding the display.
+ * It is called just after the driver be opened to get all needed
+ * information about the driver. No change in the mode of operation
+ * of the driver is done with this call.
+ */
+ int ufb_get_screen_info( int fd, struct fb_screeninfo *info )
+ {
+ return ioctl( fd, FB_SCREENINFO, ( void *)info);
+ }
+
+
+
+/*
+ * Returns the mode of the graphics subsystem
+ */
+ int ufb_get_mode( int fd, int *mode )
+ {
+ struct fb_exec_function exec;
+ exec.func_no = FB_FUNC_GET_MODE;
+ exec.param = ( void *)mode;
+ return ioctl( fd, FB_EXEC_FUNCTION , ( void *)&exec );
+ }
+
+
+/*
+ * Returns the current collor pallete
+ */
+ int ufb_get_palette( int fd, struct fb_cmap *color )
+ {
+ return ioctl( fd, FB_GETPALETTE, ( void *)color );
+ }
+
+
+/*
+ * Set the current collor pallete
+ */
+ int ufb_set_palette( int fd, struct fb_cmap *color )
+ {
+ return ioctl( fd, FB_SETPALETTE, ( void *)color );
+ }
+
+/*
+ * Does all necessary initialization to put the device in
+ * graphics mode
+ */
+ int ufb_enter_graphics( int fd, int mode )
+ {
+ struct fb_exec_function exec;
+ exec.func_no = FB_FUNC_ENTER_GRAPHICS;
+ exec.param = ( void *)mode;
+ return ioctl( fd, FB_EXEC_FUNCTION , ( void *)&exec );
+ }
+
+
+/*
+ * Switch the device back to the default mode of operation.
+ * In most cases it put the device back to plain text mode.
+ */
+ int ufb_exit_graphics( int fd )
+ {
+ struct fb_exec_function exec;
+ exec.func_no = FB_FUNC_EXIT_GRAPHICS;
+ exec.param = 0;
+ return ioctl( fd, FB_EXEC_FUNCTION , ( void *)&exec );
+ }
+
+/*
+ * Tell the driver that the "virtual buffer" is dirty, and an update
+ * of it to the real device, maybe a serial/parallel LCD or whatever
+ * is required
+ */
+ int ufb_buffer_is_dirty( int fd )
+ {
+ struct fb_exec_function exec;
+ exec.func_no = FB_FUNC_IS_DIRTY;
+ exec.param = 0;
+ return ioctl( fd, FB_EXEC_FUNCTION , ( void *)&exec );
+ }
+
+
+
+/*
+ * This function maps the physical ( kernel mode ) address of the framebuffer device
+ * and maps it to the user space address.
+ */
+ int ufb_mmap_to_user_space( int fd, void **fb_addr, void *physical_addr, unsigned long size )
+ {
+ #ifdef __rtems__
+ /* RTEMS runs in ring 0, and there is no distinction between
+ user space and kernel space, so we just return the same
+ pointer to the caller.
+ */
+ *fb_addr = physical_addr;
+ return 0;
+ #else
+ /* other kernels might want to map it to the user space,
+ maybe using mmap()
+ */
+ return 0;
+ #endif
+
+ }
+
+
+/*
+ * This function unmaps memory of the FB from the user's space
+ */
+ int ufb_unmmap_from_user_space( int fd, void *addr )
+ {
+ return 0;
+ }
diff --git a/cpukit/libmisc/mw-fb/mw_fb.h b/cpukit/libmisc/mw-fb/mw_fb.h
new file mode 100644
index 0000000000..fb7b6f6170
--- /dev/null
+++ b/cpukit/libmisc/mw-fb/mw_fb.h
@@ -0,0 +1,170 @@
+/*
+/////////////////////////////////////////////////////////////////////////////
+// $Header$
+//
+// Copyright (c) 2000 - Rosimildo da Silva
+//
+// MODULE DESCRIPTION:
+// Micro FrameBuffer interface for Embedded Systems.
+//
+// MODIFICATION/HISTORY:
+//
+// $Log$
+// Revision 1.1 2000/08/30 08:21:24 joel
+// 2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+//
+// * Added generic Micro FrameBuffer interface for MicroWindows.
+// This interface allows MicroWindows to under RTEMS. A sample
+// driver has been developed for the pc386 BSP. See
+// pc386/fb_vga.c as a sample.
+// * Added Uniform Input Device interface for MicroWindows.
+// See PC386 bsp for sample drivers for mouse and keyboard (console).
+// * mw-bf: New directory.
+// * Makefile.am, configure.in, wrapup/Makefile.am: Account for mw-fb.
+// * mw-fb/Makefile.am: New file.
+// * mw-fb/mw_fb.c: New file.
+// * mw-fb/mw_fb.h: New file.
+// * mw-fb/mw_uid.c: New file.
+// * mw-fb/mw_uid.h: New file.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+*/
+#ifndef _MW_FB_H
+#define _MW_FB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ioctls
+ 0x46 is 'F' */
+#define FB_SCREENINFO 0x4601
+#define FB_GETPALETTE 0x4602
+#define FB_SETPALETTE 0x4603
+#define FB_EXEC_FUNCTION 0x4604
+
+
+#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
+#define FB_TYPE_PLANES 1 /* Non interleaved planes */
+#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
+#define FB_TYPE_TEXT 3 /* Text/attributes */
+#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */
+#define FB_TYPE_VIRTUAL_BUFFER 5 /* Virtual Buffer */
+
+
+#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */
+#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */
+#define FB_VISUAL_TRUECOLOR 2 /* True color */
+#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
+#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
+#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
+
+#define FB_ACCEL_NONE 0 /* no hardware accelerator */
+
+/* no dependency on any other header file */
+typedef unsigned long __u32;
+typedef unsigned short __u16;
+
+struct fb_screeninfo {
+ __u32 xres; /* visible resolution */
+ __u32 yres;
+ __u32 bits_per_pixel; /* guess what */
+ __u32 line_length; /* number of chars per line */
+ volatile char *smem_start; /* Start of frame buffer mem */
+ /* (physical address) */
+ __u32 smem_len; /* Length of frame buffer mem */
+ __u32 type; /* see FB_TYPE_* */
+ __u32 visual; /* see FB_VISUAL_* */
+
+};
+
+struct fb_cmap {
+ __u32 start; /* First entry */
+ __u32 len; /* Number of entries */
+ __u16 *red; /* Red values */
+ __u16 *green;
+ __u16 *blue;
+ __u16 *transp; /* transparency, can be NULL */
+};
+
+/* type of function to be executed at the driver level */
+#define FB_FUNC_ENTER_GRAPHICS 0
+#define FB_FUNC_EXIT_GRAPHICS 1
+#define FB_FUNC_IS_DIRTY 2
+#define FB_FUNC_GET_MODE 3
+
+struct fb_exec_function
+{
+ int func_no;
+ void *param;
+};
+
+
+/* Micro Framebuffer API Wrapper */
+
+/*
+ * This function returns the information regarding the display.
+ * It is called just after the driver be opened to get all needed
+ * information about the driver. No change in the mode of operation
+ * of the driver is done with this call.
+ */
+extern int ufb_get_screen_info( int fd, struct fb_screeninfo *info );
+
+
+/*
+ * Returns the mode of the graphics subsystem
+ */
+extern int ufb_get_mode( int fd, int *mode );
+
+
+/*
+ * Returns the current collor pallete
+ */
+extern int ufb_get_palette( int fd, struct fb_cmap *color );
+
+/*
+ * Set the current collor pallete
+ */
+extern int ufb_set_palette( int fd, struct fb_cmap *color );
+
+/*
+ * Does all necessary initialization to put the device in
+ * graphics mode
+ */
+extern int ufb_enter_graphics( int fd, int mode );
+
+
+/*
+ * Switch the device back to the default mode of operation.
+ * In most cases it put the device back to plain text mode.
+ */
+extern int ufb_exit_graphics( int fd );
+
+
+/*
+ * Tell the driver that the "virtual buffer" is dirty, and an update
+ * of it to the real device, maybe a serial/parallel LCD or whatever
+ * is required
+ */
+extern int ufb_buffer_is_dirty( int fd );
+
+
+/*
+ * This function maps the physical ( kernel mode ) address of the framebuffer device
+ * and maps it to the user space address.
+ */
+ int ufb_mmap_to_user_space( int fd, void **fb_addr, void *physical_addr, unsigned long size );
+
+
+
+/*
+ * This function unmaps memory of the FB from the user's space
+ */
+ int ufb_unmmap_from_user_space( int fd, void *addr );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MW_FB_H */
diff --git a/cpukit/libmisc/mw-fb/mw_uid.c b/cpukit/libmisc/mw-fb/mw_uid.c
new file mode 100644
index 0000000000..07cfca5571
--- /dev/null
+++ b/cpukit/libmisc/mw-fb/mw_uid.c
@@ -0,0 +1,248 @@
+/*
+/////////////////////////////////////////////////////////////////////////////
+// $Header$
+//
+// Copyright (c) 2000 - Rosimildo da Silva
+//
+// MODULE DESCRIPTION:
+// This module implements the input devices interface used by MicroWindows
+// in an embedded system environment.
+// It uses the RTEMS message queue as the repository for the messages posted
+// by the devices registered.
+//
+// MODIFICATION/HISTORY:
+//
+// $Log$
+// Revision 1.6 2004/03/26 06:59:18 ralf
+// 2004-03-26 Ralf Corsepius <ralf_corsepius@rtems.org>
+//
+// * libmisc/capture/capture-cli.c, libmisc/capture/capture.c,
+// libmisc/capture/capture.h, libmisc/cpuuse/cpuuse.c,
+// libmisc/devnull/devnull.c, libmisc/fsmount/fsmount.h,
+// libmisc/monitor/mon-config.c, libmisc/monitor/mon-dname.c,
+// libmisc/monitor/mon-driver.c, libmisc/monitor/mon-extension.c,
+// libmisc/monitor/mon-itask.c, libmisc/monitor/mon-monitor.c,
+// libmisc/monitor/mon-mpci.c, libmisc/monitor/mon-object.c,
+// libmisc/monitor/mon-prmisc.c, libmisc/monitor/mon-queue.c,
+// libmisc/monitor/mon-server.c, libmisc/monitor/mon-symbols.c,
+// libmisc/monitor/monitor.h, libmisc/monitor/symbols.h,
+// libmisc/mw-fb/mw_uid.c, libmisc/rtmonuse/rtmonuse.c,
+// libmisc/serdbg/serdbg.h, libmisc/serdbg/serdbgio.c,
+// libmisc/serdbg/termios_printk.c, libmisc/serdbg/termios_printk.h,
+// libmisc/shell/shell.c, libmisc/shell/shell.h, libmisc/stackchk/check.c,
+// libmisc/stackchk/internal.h: Convert to using c99 fixed size types.
+//
+// Revision 1.5 2003/07/08 08:38:48 ralf
+// 2003-07-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+//
+// * capture/capture-cli.c: Add config-header support.
+// * capture/capture.c: Add config-header support.
+// * cpuuse/cpuuse.c: Add config-header support.
+// * devnull/devnull.c: Add config-header support.
+// * dummy/dummy.c: Add config-header support.
+// * dumpbuf/dumpbuf.c: Add config-header support.
+// * monitor/mon-command.c: Add config-header support.
+// * monitor/mon-config.c: Add config-header support.
+// * monitor/mon-dname.c: Add config-header support.
+// * monitor/mon-driver.c: Add config-header support.
+// * monitor/mon-extension.c: Add config-header support.
+// * monitor/mon-itask.c: Add config-header support.
+// * monitor/mon-manager.c: Add config-header support.
+// * monitor/mon-monitor.c: Add config-header support.
+// * monitor/mon-mpci.c: Add config-header support.
+// * monitor/mon-object.c: Add config-header support.
+// * monitor/mon-prmisc.c: Add config-header support.
+// * monitor/mon-queue.c: Add config-header support.
+// * monitor/mon-server.c: Add config-header support.
+// * monitor/mon-symbols.c: Add config-header support.
+// * monitor/mon-task.c: Add config-header support.
+// * mw-fb/mw_fb.c: Add config-header support.
+// * mw-fb/mw_uid.c: Add config-header support.
+// * rtmonuse/rtmonuse.c: Add config-header support.
+// * serdbg/serdbg.c: Add config-header support.
+// * serdbg/serdbgio.c: Add config-header support.
+// * serdbg/termios_printk.c: Add config-header support.
+// * shell/cmds.c: Add config-header support.
+// * stackchk/check.c: Add config-header support.
+// * untar/untar.c: Add config-header support.
+//
+// Revision 1.4 2002/01/04 18:32:48 joel
+// 2002-01-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+//
+// * mw-fb/mw_uid.c: Apply rtems_set_errno_and_return_minus_one.
+//
+// Revision 1.3 2000/11/30 14:36:46 joel
+// 2000-11-30 Joel Sherrill <joel@OARcorp.com>
+//
+// * mw-fb/mw_uid.c: Removed unnecessary dependency on <bsp.h>.
+//
+// Revision 1.2 2000/08/30 17:12:55 joel
+// 2000-08-30 Joel Sherrill <joel@OARcorp.com>
+//
+// * Many files: Moved posix/include/rtems/posix/seterr.h to
+// score/include/rtems/seterr.h so it would be available within
+// all APIs.
+//
+// Revision 1.1 2000/08/30 08:21:24 joel
+// 2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+//
+// * Added generic Micro FrameBuffer interface for MicroWindows.
+// This interface allows MicroWindows to under RTEMS. A sample
+// driver has been developed for the pc386 BSP. See
+// pc386/fb_vga.c as a sample.
+// * Added Uniform Input Device interface for MicroWindows.
+// See PC386 bsp for sample drivers for mouse and keyboard (console).
+// * mw-bf: New directory.
+// * Makefile.am, configure.in, wrapup/Makefile.am: Account for mw-fb.
+// * mw-fb/Makefile.am: New file.
+// * mw-fb/mw_fb.c: New file.
+// * mw-fb/mw_fb.h: New file.
+// * mw-fb/mw_uid.c: New file.
+// * mw-fb/mw_uid.h: New file.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <rtems.h>
+
+#include <rtems/mw_uid.h>
+#include <rtems/seterr.h>
+
+static rtems_id queue_id = 0;
+static int open_count = 0;
+
+/*
+#define MW_DEBUG_ON 1
+*/
+
+/* open a message queue with the kernel */
+int uid_open_queue( const char *q_name, int flags, size_t max_msgs )
+{
+ static rtems_name queue_name;
+
+ /*
+ * For the first device calling this function we would create the queue.
+ * It is assumed that this call is done at initialization, and no concerns
+ * regarding multi-threading is taken in consideration here.
+ */
+ if( !open_count )
+ {
+ rtems_status_code status;
+ queue_name = rtems_build_name( q_name[0],
+ q_name[1],
+ q_name[2],
+ q_name[3] );
+ status = rtems_message_queue_create( queue_name,
+ max_msgs,
+ sizeof( struct MW_UID_MESSAGE ),
+ RTEMS_FIFO | RTEMS_LOCAL,
+ &queue_id );
+ if( status != RTEMS_SUCCESSFUL )
+ {
+#ifdef MW_DEBUG_ON
+ printk( "UID_Queue: error creating queue: %d\n", status );
+#endif
+ return -1;
+ }
+#ifdef MW_DEBUG_ON
+ printk( "UID_Queue: id=%X\n", queue_id );
+#endif
+ }
+ open_count++;
+ return 0;
+}
+
+
+/* close message queue */
+int uid_close_queue( void )
+{
+ if( open_count == 1 )
+ {
+ rtems_message_queue_delete( queue_id );
+ queue_id = 0;
+ }
+ open_count--;
+ return 0;
+}
+
+/* reads for a message from the device */
+int uid_read_message( struct MW_UID_MESSAGE *m, unsigned long timeout )
+{
+ rtems_status_code status;
+ uint32_t size = 0;
+ unsigned long micro_secs = timeout*1000;
+ int wait = ( timeout != 0 );
+
+ status = rtems_message_queue_receive( queue_id,
+ (void*)m,
+ &size,
+ wait ? RTEMS_WAIT : RTEMS_NO_WAIT,
+ TOD_MICROSECONDS_TO_TICKS(micro_secs ) );
+
+ if( status == RTEMS_SUCCESSFUL )
+ {
+ return size;
+ }
+ else if( ( status == RTEMS_UNSATISFIED ) || ( status == RTEMS_TIMEOUT ) )
+ {
+ /* this macro returns -1 */
+ rtems_set_errno_and_return_minus_one( ETIMEDOUT );
+ }
+ /* Here we have one error condition */
+#ifdef MW_DEBUG_ON
+ printk( "UID_Queue: error reading queue: %d\n", status );
+#endif
+ return -1;
+}
+
+
+/*
+ * add a message to the queue of events. This method cna be used to
+ * simulate hardware events, and it can be very handy during development
+ * a new interface.
+ */
+int uid_send_message( struct MW_UID_MESSAGE *m )
+{
+ rtems_status_code status;
+ status = rtems_message_queue_send( queue_id, ( void * )m,
+ sizeof( struct MW_UID_MESSAGE ) );
+ return status == RTEMS_SUCCESSFUL ? 0 : -1;
+}
+
+/*
+ * register the device to insert events to the message
+ * queue named as the value passed in q_name
+ */
+int uid_register_device( int fd, const char *q_name )
+{
+ return ioctl( fd, MW_UID_REGISTER_DEVICE, q_name );
+}
+
+/* tell this device to stop adding events to the queue */
+int uid_unregister_device( int fd )
+{
+ return ioctl( fd, MW_UID_UNREGISTER_DEVICE, NULL );
+}
+
+/* set the keyboard */
+int uid_set_kbd_mode( int fd, int mode, int *old_mode )
+{
+ if (ioctl( fd, MV_KDGKBMODE, old_mode) < 0)
+ {
+ return -1;
+ }
+ if (ioctl(fd, MV_KDSKBMODE, mode ) < 0 )
+ {
+ return -1;
+ }
+ return 0;
+}
diff --git a/cpukit/libmisc/mw-fb/mw_uid.h b/cpukit/libmisc/mw-fb/mw_uid.h
new file mode 100644
index 0000000000..2bfc258057
--- /dev/null
+++ b/cpukit/libmisc/mw-fb/mw_uid.h
@@ -0,0 +1,160 @@
+/*
+/////////////////////////////////////////////////////////////////////////////
+// $Header$
+//
+// Copyright (c) 2000 - Rosimildo da Silva
+//
+// MODULE DESCRIPTION:
+// This module defines the interface for input devices used by MicroWindows
+// in an embedded system environment.
+//
+// MODIFICATION/HISTORY:
+//
+// $Log$
+// Revision 1.1 2000/08/30 08:21:24 joel
+// 2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+//
+// * Added generic Micro FrameBuffer interface for MicroWindows.
+// This interface allows MicroWindows to under RTEMS. A sample
+// driver has been developed for the pc386 BSP. See
+// pc386/fb_vga.c as a sample.
+// * Added Uniform Input Device interface for MicroWindows.
+// See PC386 bsp for sample drivers for mouse and keyboard (console).
+// * mw-bf: New directory.
+// * Makefile.am, configure.in, wrapup/Makefile.am: Account for mw-fb.
+// * mw-fb/Makefile.am: New file.
+// * mw-fb/mw_fb.c: New file.
+// * mw-fb/mw_fb.h: New file.
+// * mw-fb/mw_uid.c: New file.
+// * mw-fb/mw_uid.h: New file.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+*/
+#ifndef _MW_UID_H
+#define _MW_UID_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 0x41XX -- IOCLT functions for the Micro Input Devices commands */
+#define MW_UID_REGISTER_DEVICE 0x4100
+#define MW_UID_UNREGISTER_DEVICE 0x4101
+
+
+/* devices supported by MicroWindows */
+enum MW_INPUT_DEVICE_TYPE
+{
+ MV_UID_INVALID = 0,
+ MV_UID_REL_POS = 1, /* mouse */
+ MV_UID_ABS_POS = 2, /* touch-screen */
+ MV_UID_KBD = 3, /* keyboard */
+ MV_UID_TIMER = 4 /* timer -- not used */
+};
+
+
+/* matching MicroWindows */
+#define MV_BUTTON_RIGHT 0x01
+#define MV_BUTTON_CENTER 0x02
+#define MV_BUTTON_LEFT 0x04
+
+/* modifiers of the keyboard type devices */
+#define MV_KEY_MODIFIER_SHIFT_DOWN 0x10
+#define MV_KEY_MODIFIER_ALT_DOWN 0x20
+
+/* indication of the LEDS */
+#define MV_KEY_MODIFIER_CAPS_ON 0x04
+#define MV_KEY_MODIFIER_NUN_LOCK_ON 0x02
+#define MV_KEY_SCROLL_LOCK_ON 0x01
+
+/* keyboard modes -- default ASCII */
+#define MV_KEY_MODE_ASCII 0x01
+/*
+ * This mode one event is sent when a key is pressed,
+ * and another one is send when a key is released.
+ */
+#define MV_KEY_MODE_SCANCODE 0x00
+
+
+/* these defines match with the linux keyboard range
+ for ioctls functions for the keyboard interface.
+ 0x4BXX --- keyboard related functions
+ */
+#define MV_KDGKBMODE 0x4B44 /* gets current keyboard mode */
+#define MV_KDSKBMODE 0x4B45 /* sets current keyboard mode */
+
+/*
+ * Message generated by input devices controlled by MicroWindows.
+ */
+struct MW_UID_MESSAGE
+{
+ enum MW_INPUT_DEVICE_TYPE type; /* device type */
+ union
+ {
+ /* fired when keyboard events are raised */
+ struct kbd_t {
+ unsigned short code; /* keycode or scancode */
+ unsigned char modifiers; /* key modifiers */
+ unsigned char mode; /* current Kbd mode */
+ } kbd;
+
+ /* fired when position events are raised, mouse, touch screen, etc */
+ struct pos_t {
+ unsigned short btns; /* indicates which buttons are pressed */
+ short x; /* x location */
+ short y; /* y location */
+ short z; /* z location, 0 for 2D */
+ } pos;
+
+ /* fired by a timer device periodically */
+ struct timer_t {
+ unsigned long frt; /* free running timer */
+ unsigned long seq; /* sequence number */
+ } tmr;
+
+ } m;
+};
+
+
+/*
+ * API for creating/closing/accessing the message queue used by the micro
+ * input device interface. All functions in this interface returns a
+ * zero ( 0 ) on success. One exception for that is the "read" routine
+ * that returns the number of bytes read. Negaive numbers indicate errors
+ *
+ * The implementation of the message queue for RTEMS uses a POSIX message
+ * queue interface. It should be very portable among systems with a POSIX
+ * support.
+ */
+
+/* creates the message queue that holds events from the input devices */
+extern int uid_open_queue( const char *q_name, int flags, size_t max_msgs );
+
+/* closes message queue */
+extern int uid_close_queue( void );
+
+/*
+ * reads a message from the queue. It waits up to the specified
+ * timeout in mili-seconds.
+ */
+extern int uid_read_message( struct MW_UID_MESSAGE *m, unsigned long timeout );
+
+/* write a message to the queue */
+extern int uid_write_message( struct MW_UID_MESSAGE *m );
+
+
+/* register device to insert data to the queue */
+extern int uid_register_device( int fd, const char *q_name );
+
+/* unregister device to stop adding messages to the queue */
+extern int uid_unregister_device( int fd );
+
+/* set the keyboard */
+extern int uid_set_kbd_mode( int fd, int mode, int *old_mode );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MW_UID_H */
diff --git a/cpukit/libmisc/rtmonuse/rtmonuse.c b/cpukit/libmisc/rtmonuse/rtmonuse.c
new file mode 100644
index 0000000000..14fca3b0eb
--- /dev/null
+++ b/cpukit/libmisc/rtmonuse/rtmonuse.c
@@ -0,0 +1,208 @@
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <rtems/rtmonuse.h>
+
+typedef struct {
+ rtems_id id;
+ uint32_t count;
+ uint32_t missed_count;
+ uint32_t min_cpu_time;
+ uint32_t max_cpu_time;
+ uint32_t total_cpu_time;
+ uint32_t min_wall_time;
+ uint32_t max_wall_time;
+ uint32_t total_wall_time;
+} Period_usage_t;
+
+Period_usage_t *Period_usage_Information;
+
+/*PAGE
+ *
+ * Period_usage_Initialize
+ */
+
+void Period_usage_Initialize( void )
+{
+ int maximum;
+
+ maximum = _Configuration_Table->RTEMS_api_configuration->maximum_periods;
+
+ Period_usage_Information = malloc( sizeof(Period_usage_t) * (maximum+1) );
+
+ Period_usage_Reset();
+}
+
+/*PAGE
+ *
+ * Period_usage_Reset
+ */
+
+void Period_usage_Reset( void )
+{
+ uint32_t i;
+ Period_usage_t *the_usage;
+
+ for ( i=0 ;
+ i<_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
+ i++ ) {
+ the_usage = &Period_usage_Information[ i ];
+
+ the_usage->count = 0;
+ the_usage->missed_count = 0;
+ the_usage->min_cpu_time = 0xFFFFFFFF;
+ the_usage->max_cpu_time = 0;
+ the_usage->total_cpu_time = 0;
+ the_usage->min_wall_time = 0xFFFFFFFF;
+ the_usage->max_wall_time = 0;
+ the_usage->total_wall_time = 0;
+
+ }
+}
+
+/*PAGE
+ *
+ * Period_usage_Update
+ */
+
+void Period_usage_Update(
+ rtems_id id
+)
+{
+ rtems_rate_monotonic_period_status rm_status;
+ rtems_status_code status;
+ Period_usage_t *the_usage;
+
+ assert( Period_usage_Information );
+
+ status = rtems_rate_monotonic_get_status( id, &rm_status );
+ assert( status == RTEMS_SUCCESSFUL );
+
+ the_usage = &Period_usage_Information[ rtems_get_index( id ) ];
+
+ the_usage->id = id;
+ the_usage->count++;
+ if ( rm_status.state == RATE_MONOTONIC_EXPIRED )
+ the_usage->missed_count++;
+ the_usage->total_cpu_time += rm_status.ticks_executed_since_last_period;
+ the_usage->total_wall_time += rm_status.ticks_since_last_period;
+
+ /*
+ * Update CPU time
+ */
+
+ if ( rm_status.ticks_executed_since_last_period < the_usage->min_cpu_time )
+ the_usage->min_cpu_time = rm_status.ticks_executed_since_last_period;
+
+ if ( rm_status.ticks_executed_since_last_period > the_usage->max_cpu_time )
+ the_usage->max_cpu_time = rm_status.ticks_executed_since_last_period;
+
+ /*
+ * Update Wall time
+ */
+
+ if ( rm_status.ticks_since_last_period < the_usage->min_wall_time )
+ the_usage->min_wall_time = rm_status.ticks_since_last_period;
+
+ if ( rm_status.ticks_since_last_period > the_usage->max_wall_time )
+ the_usage->max_wall_time = rm_status.ticks_since_last_period;
+
+}
+
+/*PAGE
+ *
+ * Period_usage_Dump
+ */
+
+void Period_usage_Dump( void )
+{
+ uint32_t i;
+ Period_usage_t *the_usage;
+ Rate_monotonic_Control *the_period;
+ uint32_t u32_name;
+ char *cname;
+ char name[5];
+ uint32_t api_index;
+ Objects_Information *information;
+
+ if ( !Period_usage_Information ) {
+ fprintf(stdout, "Period statistics library is not initialized\n" );
+ return;
+ }
+
+ fprintf(stdout, "Period information by period\n" );
+ fprintf(stdout, " ID OWNER PERIODS MISSED CPU TIME WALL TIME\n" );
+
+ /*
+ * RTEMS does not use an index of zero for object ids.
+ */
+
+ for ( i=1 ;
+ i<=_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
+ i++ ) {
+ the_usage = &Period_usage_Information[ i ];
+ if ( the_usage->count == 0 )
+ continue;
+
+ the_period =
+ (Rate_monotonic_Control *)_Rate_monotonic_Information.local_table[ i ];
+
+ name[ 0 ] = ' ';
+ name[ 1 ] = ' ';
+ name[ 2 ] = ' ';
+ name[ 3 ] = ' ';
+ name[ 4 ] = '\0';
+
+ if ( the_period->owner ) {
+ api_index = _Objects_Get_API(the_period->owner->Object.id);
+ information = _Objects_Information_table[ api_index ][ 1 ];
+
+ if ( information->is_string ) {
+ cname = the_period->owner->Object.name;
+ name[ 0 ] = cname[0];
+ name[ 1 ] = cname[1];
+ name[ 2 ] = cname[2];
+ name[ 3 ] = cname[3];
+ name[ 4 ] = '\0';
+ } else {
+ u32_name = (uint32_t )the_period->owner->Object.name;
+ name[ 0 ] = (u32_name >> 24) & 0xff;
+ name[ 1 ] = (u32_name >> 16) & 0xff;
+ name[ 2 ] = (u32_name >> 8) & 0xff;
+ name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 4 ] = '\0';
+ }
+ }
+
+ if ( !isprint(name[0]) ) name[0] = '*';
+ if ( !isprint(name[1]) ) name[1] = '*';
+ if ( !isprint(name[2]) ) name[2] = '*';
+ if ( !isprint(name[3]) ) name[3] = '*';
+
+
+ fprintf(stdout,
+ "0x%08x %4s %6d %3d %d/%d/%5.2f %d/%d/%3.2f\n",
+ the_usage->id,
+ name,
+ the_usage->count,
+ the_usage->missed_count,
+ the_usage->min_cpu_time,
+ the_usage->max_cpu_time,
+ (double) the_usage->total_cpu_time / (double) the_usage->count,
+ the_usage->min_wall_time,
+ the_usage->max_wall_time,
+ (double) the_usage->total_wall_time / (double) the_usage->count
+ );
+ }
+}
diff --git a/cpukit/libmisc/rtmonuse/rtmonuse.h b/cpukit/libmisc/rtmonuse/rtmonuse.h
new file mode 100644
index 0000000000..2741698738
--- /dev/null
+++ b/cpukit/libmisc/rtmonuse/rtmonuse.h
@@ -0,0 +1,18 @@
+/*
+ * $Id$
+ */
+
+#ifndef __RATE_MONOTONIC_USAGE_h
+#define __RATE_MONOTONIC_USAGE_h
+
+void Period_usage_Initialize( void );
+
+void Period_usage_Reset( void );
+
+void Period_usage_Update(
+ rtems_id id
+);
+
+void Period_usage_Dump( void );
+
+#endif
diff --git a/cpukit/libmisc/serdbg/README b/cpukit/libmisc/serdbg/README
new file mode 100644
index 0000000000..338249c928
--- /dev/null
+++ b/cpukit/libmisc/serdbg/README
@@ -0,0 +1,138 @@
+#
+# $Id$
+#
+
+This directory contains three useful packages related to the termios I/O
+system:
+
+PACKAGE SERDBGIO
+================
+"serdbgio" provides the "serial gdb" standard I/O functions "getDebugChar"
+and "putDebugChar" for any device driver supporting polled termios mode.
+
+The initialization function "serdbg_open" opens the v.24 port intended
+for the serial debug connection, and sets the desired baud rate. The
+"getDebugChar" and "putDebugChar" functions then interact with the
+corresponding driver using the calls intended for polled termios
+operation.
+
+Specification for the debug device, baud rate and other parameters is
+done in a global structure of type "serdbg_conf_t". A configuration
+mechanism quite similar to the overall RTEMS configuration is available.
+
+PACKAGE SERDBG
+==============
+"serdbg" provides a means to optionally initialize and/or start a
+serial gdb session as soon as possible, this means as soon as all
+drivers have been initialized. The serial debug I/O functions can
+either be integrated as special routines of the BSP drivers, or using
+the package "serdbgio"
+
+PACKAGE TERMIOS_PRINTK
+======================
+"termios_printk" provides a standard output function suitable to use
+with "printk". It uses the same technique as serdbgio, hooking the
+interface between a polled device driver and the termios system.
+
+
+REQUIREMENTS
+============
+
+- These two packages can be used with any polled termios device
+driver.
+- For standard initialization, they need a modified "bsppost.c"
+to perform the initialization calls.
+
+USAGE
+=====
+
+For using these packages add the following to your "init" module or
+your "system.h" file (Note: most macro settings fall back to a
+default, if not set.):
+
+/*
+ * CONFIGURE_USE_SERDBG
+ * set this macro, if you want to connect gdb over a serial line
+ * when set, the debug stub will be connected after driver
+ * initialization in "bsppost.c"
+ */
+#define CONFIGURE_USE_SERDBG
+
+
+/*
+ * CONFIGURE_SERDBG_SKIP_INIT_BKPT
+ * set this macro, if you do not want the gdb interface to wait for a
+ * debugger connection directly after initialization
+ * If you set this macro, the gdb stub will only hook various
+ * exception vectors when called from "bsppost.c".
+ */
+/* #define CONFIGURE_SERDBG_SKIP_INIT_BKPT */
+
+/*
+ * CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+ * set this macro, if you want "serdbgio" to provide the I/O
+ * functions for the serial gdb connection
+ */
+#define CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+
+/*
+ * CONFIGURE_SERDBG_DEVNAME
+ * use this macro to specify the serial device to use
+ * for "serdbgio".
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ */
+#define CONFIGURE_SERDBG_DEVNAME "/dev/tty03"
+
+/*
+ * CONFIGURE_SERDBG_BAUDRATE
+ * use this macro to specify the baud rate to use
+ * for "serdbgio".
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ */
+#define CONFIGURE_SERDBG_BAUDRATE 57600
+
+/*
+ * CONFIGURE_SERDBG_CALLOUT
+ * use this macro to specify a routine that will called during I/O polling
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ * This function of type "void pollfnc(void)" can be used for e.g.
+ * tickling a watchdog
+ */
+/* #define CONFIGURE_SERDBG_CALLOUT tickle_my_watchdog_fnc */
+
+#include <serdbgcnf.h>
+
+/*
+ * CONFIGURE_USE_TERMIOS_PRINTK
+ * set this macro, if you want printk output to be sent to a serial
+ * driver using the polled termios interface
+ * when set, the printk output function will be connected after driver
+ * initialization in "bsppost.c"
+ */
+#define CONFIGURE_USE_TERMIOS_PRINTK
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_DEVNAME
+ * use this macro to specify the serial device to use
+ * for printk output.
+ * Only used, when CONFIGURE_USE_TERMIOS_PRINTK is set
+ */
+#define CONFIGURE_TERMIOS_PRINTK_DEVNAME "/dev/console"
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_BAUDRATE
+ * use this macro to specify the baudrate to use
+ * for printk output.
+ * Only used, when CONFIGURE_USE_TERMIOS_PRINTK is set
+ */
+#define CONFIGURE_TERMIOS_PRINTK_BAUDRATE 9600
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_CALLOUT
+ * use this macro to specify a routine that will called during I/O polling
+ * This function of type "void pollfnc(void)" can be used for e.g.
+ * tickling a watchdog
+ */
+/* #define CONFIGURE_TERMIOS_PRINTK_CALLOUT tickle_my_watchdog_fnc */
+
+#include <termios_printk_cnf.h>
diff --git a/cpukit/libmisc/serdbg/serdbg.c b/cpukit/libmisc/serdbg/serdbg.c
new file mode 100644
index 0000000000..4bca324934
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbg.c
@@ -0,0 +1,94 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbg.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains intialization and utility functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 04.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <rtems/serdbg.h>
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_init_dbg
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize remote gdb session over serial line |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+{
+ static boolean is_initialized = FALSE;
+
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ extern void set_debug_traps(void);
+ extern void breakpoint(void);
+
+ if (is_initialized) {
+ return RTEMS_SUCCESSFUL;
+ }
+ is_initialized = TRUE;
+ /*
+ * try to open serial device
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if ((serdbg_conf.open_io != NULL) &&
+ (0 > serdbg_conf.open_io(serdbg_conf.devname,serdbg_conf.baudrate))) {
+ fprintf(stderr,
+ "remote_gdb_init: cannot open device %s "
+ "for gdb connection:%s\n",serdbg_conf.devname,strerror(errno));
+ rc = RTEMS_IO_ERROR;
+ }
+ }
+ /*
+ * initialize gdb stub
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ set_debug_traps();
+ }
+ /*
+ * now activate gdb stub
+ */
+ if ((rc == RTEMS_SUCCESSFUL) &&
+ !serdbg_conf.skip_init_bkpt) {
+ breakpoint();
+ }
+
+ /*
+ * return to original function
+ * this may be already unter gdb control
+ */
+ return rc;
+}
diff --git a/cpukit/libmisc/serdbg/serdbg.h b/cpukit/libmisc/serdbg/serdbg.h
new file mode 100644
index 0000000000..00d5d827e1
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbg.h
@@ -0,0 +1,174 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbg.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 04.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _SERDBG_H
+#define _SERDBG_H
+
+#include <rtems.h>
+#include <termios.h>
+
+typedef struct {
+ uint32_t baudrate; /* debug baud rate, e.g. 57600 */
+ void (*callout)(void); /* callout pointer during polling */
+ int (*open_io)(const char *dev_name,uint32_t baudrate); /* I/O open fnc */
+ const char *devname; /* debug device, e.g. "/dev/tty01" */
+ uint8_t skip_init_bkpt; /* if TRUE, do not stop when initializing */
+} serdbg_conf_t;
+
+/*
+ * must be defined in init module...
+ */
+extern serdbg_conf_t serdbg_conf;
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send character to remote debugger |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ char c /* char to send */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| get character from remote debugger |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void /* <none> */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void serdbg_exceptionHandler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| hook directly to an exception vector |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ int vecnum, /* vector index to hook at */
+ void *vector /* address of handler function */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_init
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize remote gdb session over serial line |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+
+/*
+ * stuff from serdbgio.c
+ */
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+
+#endif /* _SERDBG_H */
diff --git a/cpukit/libmisc/serdbg/serdbgcnf.h b/cpukit/libmisc/serdbg/serdbgcnf.h
new file mode 100644
index 0000000000..024e545d5c
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbgcnf.h
@@ -0,0 +1,81 @@
+/*===============================================================*\
+| Project: RTEMS configure remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbgcnf.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _SERDBGCNF_H
+#define _SERDBGCNF_H
+
+#include <rtems/serdbg.h>
+
+#ifdef CONFIGURE_INIT
+
+/*
+ * fallback for baud rate to use
+ */
+#ifndef CONFIGURE_SERDBG_BAUDRATE
+#define CONFIGURE_SERDBG_BAUDRATE 9600
+#endif
+
+/*
+ * fallback for device name to use
+ */
+#ifndef CONFIGURE_SERDBG_DEVNAME
+#define CONFIGURE_SERDBG_DEVNAME "/dev/tty01"
+#endif
+
+/*
+ * fill in serdbg_conf structure
+ */
+serdbg_conf_t serdbg_conf = {
+ CONFIGURE_SERDBG_BAUDRATE,
+
+#ifdef CONFIGURE_SERDBG_CALLOUT
+ CONFIGURE_SERDBG_CALLOUT,
+#else
+ NULL,
+#endif
+
+#ifdef CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+ serdbg_open,
+#else
+ NULL,
+#endif
+
+ CONFIGURE_SERDBG_DEVNAME,
+
+#ifdef CONFIGURE_SERDBG_SKIP_INIT_BKPT
+ TRUE,
+#else
+ FALSE,
+#endif
+};
+
+int serdbg_init(void) {
+#ifdef CONFIGURE_USE_SERDBG
+ extern int serdbg_init_dbg(void);
+ return serdbg_init_dbg();
+#else
+ return 0;
+#endif
+}
+
+#endif /* CONFIGURE_INIT */
+
+#endif /* _SERDBGCNF_H */
diff --git a/cpukit/libmisc/serdbg/serdbgio.c b/cpukit/libmisc/serdbg/serdbgio.c
new file mode 100644
index 0000000000..494a2fab0b
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbgio.c
@@ -0,0 +1,256 @@
+/*===============================================================*\
+| File: serdbgio.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| Hebststr. 8, 82178 Puchheim, Germany |
+| <Thomas.Doerfler@imd-systems.de> |
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| http://www.rtems.com/license/LICENSE. |
+| all rights reserved |
++-----------------------------------------------------------------+
+| TERMIOS serial gdb interface support |
+| the functions in this file allow the standard gdb stubs like |
+| "m68k-stub.c" to access any serial interfaces that work with |
+| RTEMS termios in polled mode |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 10.05.02 creation doe |
+|*****************************************************************|
+|* $Id$
+ *
+|*****************************************************************|
+\*===============================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <errno.h>
+#include <unistd.h> /* close */
+#include <stdio.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <rtems/termiostypes.h>
+#include <rtems/serdbg.h>
+
+
+/*
+ * internal variables
+ */
+int serdbg_fd = -1;
+struct rtems_termios_tty *serdbg_tty;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+{
+ boolean err_occurred = FALSE;
+ rtems_libio_t *iop = NULL;
+ struct termios act_termios;
+ tcflag_t baudcode = B0;
+
+#define FD_STORE_CNT 3
+ int fd_store[FD_STORE_CNT];
+ int fd_store_used = 0;
+
+ /*
+ * translate baudrate into baud code
+ */
+ switch(baudrate) {
+ case 50: baudcode = B50; break;
+ case 75: baudcode = B75; break;
+ case 110: baudcode = B110; break;
+ case 134: baudcode = B134; break;
+ case 150: baudcode = B150; break;
+ case 200: baudcode = B200; break;
+ case 300: baudcode = B300; break;
+ case 600: baudcode = B600; break;
+ case 1200: baudcode = B1200; break;
+ case 1800: baudcode = B1800; break;
+ case 2400: baudcode = B2400; break;
+ case 4800: baudcode = B4800; break;
+ case 9600: baudcode = B9600; break;
+ case 19200: baudcode = B19200; break;
+ case 38400: baudcode = B38400; break;
+ case 57600: baudcode = B57600; break;
+ case 115200: baudcode = B115200; break;
+ case 230400: baudcode = B230400; break;
+ case 460800: baudcode = B460800; break;
+ default : err_occurred = TRUE; errno = EINVAL; break;
+ }
+
+ /*
+ * open device for serdbg operation
+ * skip any fds that are between 0..2, because they are
+ * reserved for stdin/out/err
+ */
+ if (!err_occurred &&
+ (dev_name != NULL) &&
+ (dev_name[0] != '\0')) {
+ do {
+ serdbg_fd = open(dev_name,O_RDWR);
+ if (serdbg_fd < 0) {
+ err_occurred = TRUE;
+ }
+ else {
+ if (serdbg_fd < 3) {
+ if (fd_store_used >= FD_STORE_CNT) {
+ err_occurred = TRUE;
+ }
+ else {
+ fd_store[fd_store_used++] = serdbg_fd;
+ }
+ }
+ }
+ } while (!err_occurred &&
+ (serdbg_fd < 3));
+ }
+ /*
+ * close any fds, that have been placed in fd_store
+ * so fd 0..2 are reusable again
+ */
+ while (--fd_store_used >= 0) {
+ close(fd_store[fd_store_used]);
+ }
+
+ /*
+ * capture tty structure
+ */
+ if (!err_occurred) {
+ iop = &rtems_libio_iops[serdbg_fd];
+ serdbg_tty = iop->data1;
+ }
+ /*
+ * set device baudrate
+ * (and transp mode, this is not really needed)
+ * ...
+ */
+ /*
+ * ... get fd settings
+ */
+ if (!err_occurred &&
+ (0 != tcgetattr(serdbg_fd,&act_termios))) {
+ err_occurred = TRUE;
+ }
+ if (!err_occurred) {
+ act_termios.c_iflag
+ &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ act_termios.c_oflag
+ &= ~OPOST;
+
+ act_termios.c_lflag
+ &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+
+ cfsetospeed(&act_termios,baudcode);
+ cfsetispeed(&act_termios,baudcode);
+
+ if (0 != tcsetattr(serdbg_fd,TCSANOW,&act_termios)) {
+ err_occurred = TRUE;
+ }
+ }
+ return (err_occurred
+ ? -1
+ : 0);
+}
+
+void putDebugChar(char c) __attribute__ ((__weak__));
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ /*
+ * call serdbg polling callout, if available
+ */
+ if (serdbg_conf.callout != NULL) {
+ serdbg_conf.callout();
+ }
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((serdbg_tty != NULL) &&
+ (serdbg_tty->device.write != NULL)) {
+ /*
+ * send character to debug serial port
+ */
+ serdbg_tty->device.write(serdbg_tty->minor,&c,1);
+ }
+}
+
+int getDebugChar(void) __attribute__ ((__weak__));
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+{
+ int c = -1;
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((serdbg_tty != NULL) &&
+ (serdbg_tty->device.pollRead != NULL)) {
+ do {
+ /*
+ * call serdbg polling callout, if available
+ */
+ if (serdbg_conf.callout != NULL) {
+ serdbg_conf.callout();
+ }
+ /*
+ * get character from debug serial port
+ */
+ c = serdbg_tty->device.pollRead(serdbg_tty->minor);
+ } while (c < 0);
+ }
+ return c;
+}
diff --git a/cpukit/libmisc/serdbg/termios_printk.c b/cpukit/libmisc/serdbg/termios_printk.c
new file mode 100644
index 0000000000..6e31bbcfd0
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk.c
@@ -0,0 +1,237 @@
+/*===============================================================*\
+| File: termios_printk.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| Hebststr. 8, 82178 Puchheim, Germany |
+| <Thomas.Doerfler@imd-systems.de> |
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| http://www.rtems.com/license/LICENSE. |
+| all rights reserved |
++-----------------------------------------------------------------+
+| TERMIOS printk support |
+| this module performs low-level printk output using |
+| a polled termios driver |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+|*****************************************************************|
+|* $Id$
+ *
+|*****************************************************************|
+\*===============================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <rtems/termiostypes.h>
+#include <rtems/bspIo.h>
+#include <rtems/termios_printk.h>
+
+/*
+ * internal variables
+ */
+int termios_printk_fd = -1;
+struct rtems_termios_tty *termios_printk_tty;
+
+static void _termios_printk_null_char( char c ) {return;}
+
+BSP_output_char_function_type BSP_output_char = _termios_printk_null_char;
+BSP_polling_getchar_function_type BSP_poll_char;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void termios_printk_outputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ static const char cr = '\r';
+ /*
+ * check, whether printk serial port is available
+ */
+
+ if ((termios_printk_tty != NULL) &&
+ (termios_printk_tty->device.write != NULL)) {
+ /*
+ * call termios_printk polling callout, if available
+ */
+ if (termios_printk_conf.callout != NULL) {
+ termios_printk_conf.callout();
+ }
+ /*
+ * send character to debug serial port
+ */
+ if (c == '\n') {
+ termios_printk_tty->device.write(termios_printk_tty->minor,&cr,1);
+ }
+ termios_printk_tty->device.write(termios_printk_tty->minor,&c,1);
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+char termios_printk_inputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+{
+ int c = -1;
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((termios_printk_tty != NULL) &&
+ (termios_printk_tty->device.pollRead != NULL)) {
+ do {
+ /*
+ * call termios_printk polling callout, if available
+ */
+ if (termios_printk_conf.callout != NULL) {
+ termios_printk_conf.callout();
+ }
+ /*
+ * get character from debug serial port
+ */
+ c = termios_printk_tty->device.pollRead(termios_printk_tty->minor);
+ } while (c < 0);
+ }
+ return c;
+}
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int termios_printk_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+{
+ boolean err_occurred = FALSE;
+ rtems_libio_t *iop = NULL;
+ struct termios act_termios;
+ tcflag_t baudcode = B0;
+
+ if (termios_printk_fd >= 0) {
+ /*
+ * already initialized
+ */
+ return 0;
+ }
+ /*
+ * translate baudrate into baud code
+ */
+ switch(baudrate) {
+ case 50: baudcode = B50; break;
+ case 75: baudcode = B75; break;
+ case 110: baudcode = B110; break;
+ case 134: baudcode = B134; break;
+ case 150: baudcode = B150; break;
+ case 200: baudcode = B200; break;
+ case 300: baudcode = B300; break;
+ case 600: baudcode = B600; break;
+ case 1200: baudcode = B1200; break;
+ case 1800: baudcode = B1800; break;
+ case 2400: baudcode = B2400; break;
+ case 4800: baudcode = B4800; break;
+ case 9600: baudcode = B9600; break;
+ case 19200: baudcode = B19200; break;
+ case 38400: baudcode = B38400; break;
+ case 57600: baudcode = B57600; break;
+ case 115200: baudcode = B115200; break;
+ case 230400: baudcode = B230400; break;
+ case 460800: baudcode = B460800; break;
+ default : err_occurred = TRUE; errno = EINVAL; break;
+ }
+ /*
+ * open device for serdbg operation
+ */
+ if (!err_occurred &&
+ (dev_name != NULL) &&
+ (dev_name[0] != '\0')) {
+ termios_printk_fd = open(dev_name,O_RDWR);
+ if (termios_printk_fd < 0) {
+ err_occurred = TRUE;
+ }
+ }
+ /*
+ * capture tty structure
+ */
+ if (!err_occurred) {
+ iop = &rtems_libio_iops[termios_printk_fd];
+ termios_printk_tty = iop->data1;
+ }
+ /*
+ * set device baudrate
+ * (and transp mode, this is not really needed)
+ * ...
+ */
+ /*
+ * ... get fd settings
+ */
+ if (!err_occurred &&
+ (0 != tcgetattr(termios_printk_fd,&act_termios))) {
+ err_occurred = TRUE;
+ }
+ if (!err_occurred) {
+
+ cfsetospeed(&act_termios,baudcode);
+ cfsetispeed(&act_termios,baudcode);
+
+ if (0 != tcsetattr(termios_printk_fd,TCSANOW,&act_termios)) {
+ err_occurred = TRUE;
+ }
+ }
+ if (!err_occurred) {
+ BSP_output_char = termios_printk_outputchar;
+ BSP_poll_char = termios_printk_inputchar;
+ }
+ return (err_occurred
+ ? -1
+ : 0);
+}
diff --git a/cpukit/libmisc/serdbg/termios_printk.h b/cpukit/libmisc/serdbg/termios_printk.h
new file mode 100644
index 0000000000..d3a3703b11
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk.h
@@ -0,0 +1,95 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: termios_printk.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| printk polled output via termios polled drivers |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _TERMIOS_PRINTK_H
+#define _TERMIOS_PRINTK_H
+
+#include <rtems.h>
+#include <termios.h>
+
+typedef struct {
+ uint32_t baudrate; /* debug baud rate, e.g. 57600 */
+ void (*callout)(void); /* callout pointer during polling */
+ const char *devname; /* debug device, e.g. "/dev/tty01" */
+} termios_printk_conf_t;
+
+/*
+ * must be defined in init module...
+ */
+extern termios_printk_conf_t termios_printk_conf;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void termios_printk_outputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+char termios_printk_inputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int termios_printk_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+#endif /* _TERMIOS_PRINTK_H */
diff --git a/cpukit/libmisc/serdbg/termios_printk_cnf.h b/cpukit/libmisc/serdbg/termios_printk_cnf.h
new file mode 100644
index 0000000000..55aea94d03
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk_cnf.h
@@ -0,0 +1,70 @@
+/*===============================================================*\
+| Project: RTEMS configure remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: termios_printk_cnf.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| printk support via polled termios |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _TERMIOS_PRINTK_CNF_H
+#define _TERMIOS_PRINTK_CNF_H
+
+#include <rtems/termios_printk.h>
+
+#ifdef CONFIGURE_INIT
+
+/*
+ * fallback for baud rate to use
+ */
+#ifndef CONFIGURE_TERMIOS_PRINTK_BAUDRATE
+#define CONFIGURE_TERMIOS_PRINTK_BAUDRATE 9600
+#endif
+
+/*
+ * fallback for device name to use
+ */
+#ifndef CONFIGURE_TERMIOS_PRINTK_DEVNAME
+#define CONFIGURE_TERMIOS_PRINTK_DEVNAME "/dev/console"
+#endif
+
+#ifdef CONFIGURE_USE_TERMIOS_PRINTK
+/*
+ * fill in termios_printk_conf structure
+ */
+termios_printk_conf_t termios_printk_conf = {
+ CONFIGURE_TERMIOS_PRINTK_BAUDRATE,
+
+#ifdef CONFIGURE_TERMIOS_PRINTK_CALLOUT
+ CONFIGURE_TERMIOS_PRINTK_CALLOUT,
+#else
+ NULL,
+#endif
+ CONFIGURE_TERMIOS_PRINTK_DEVNAME,
+};
+#endif
+
+int termios_printk_init(void) {
+#ifdef CONFIGURE_USE_TERMIOS_PRINTK
+ return termios_printk_open(termios_printk_conf.devname,
+ termios_printk_conf.baudrate);
+#else
+ return 0;
+#endif
+}
+
+#endif /* CONFIGURE_INIT */
+
+#endif /* _TERMIOS_PRINTK_CNF_H */
diff --git a/cpukit/libmisc/shell/README b/cpukit/libmisc/shell/README
new file mode 100644
index 0000000000..9798becc37
--- /dev/null
+++ b/cpukit/libmisc/shell/README
@@ -0,0 +1,27 @@
+#
+# $Id$
+#
+
+This directory contains a shell user extension
+primary features:
+
+ + create a user shell terminal task.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to open more shell terminal.
+Suggestions and comments are appreciated.
+
+NOTES:
+
+1. printf() & getchar() works but you can't use
+ 0,1,2 like fildes. You need to use fileno(stdin),fileno(stdout),...
+
+2. You only need a termios dev to start a new session, add your new commands
+ and enjoy it.
+
+3. Telnetd daemon uses this (browse libnetworking/rtems_telnetd)
+ Enjoy it.
+
+FUTURE:
+
+1. Adding new commands in cmds.c to give file manegement to shell.
diff --git a/cpukit/libmisc/shell/cmds.c b/cpukit/libmisc/shell/cmds.c
new file mode 100644
index 0000000000..ba3a4b030e
--- /dev/null
+++ b/cpukit/libmisc/shell/cmds.c
@@ -0,0 +1,526 @@
+/*
+ * Author: Fernando RUIZ CASAS
+ *
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * This file is inspired in rtems_monitor & Chris John MyRightBoot
+ *
+ * But I want to make it more user friendly
+ * A 'monitor' command is added to adapt the call rtems monitor commands
+ * at my call procedure
+ *
+ * TODO: A lot of improvements of course.
+ * cp, mv, ...
+ * hexdump,
+ *
+ * More? Say me it, please...
+ *
+ * The BSP Specific are not welcome here.
+ *
+ * C&S welcome...
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <termios.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stddef.h>
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/imfs.h>
+#include <rtems/shell.h>
+
+/* ----------------------------------------------- *
+ - str to int "0xaffe" "0b010010" "0123" "192939"
+ * ----------------------------------------------- */
+int str2int(char * s) {
+ int sign=1;
+ int base=10;
+ int value=0;
+ int digit;
+ if (!s) return 0;
+ if (*s) {
+ if (*s=='-') {
+ sign=-1;
+ s++;
+ if (!*s) return 0;
+ };
+ if (*s=='0') {
+ s++;
+ switch(*s) {
+ case 'x':
+ case 'X':s++;
+ base=16;
+ break;
+ case 'b':
+ case 'B':s++;
+ base=2;
+ break;
+ default :base=8;
+ break;
+ }
+ };
+ while (*s) {
+ switch(*s) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':digit=*s-'0';
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':digit=*s-'A'+10;
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':digit=*s-'a'+10;
+ break;
+ default:return value*sign;
+ };
+ if (digit>base) return value*sign;
+ value=value*base+digit;
+ s++;
+ };
+ };
+ return value*sign;
+}
+/*----------------------------------------------------------------------------*
+ * RAM MEMORY COMMANDS
+ *----------------------------------------------------------------------------*/
+
+#define mdump_adr (current_shell_env->mdump_adr) /* static value */
+
+int main_mdump(int argc,char * argv[]) {
+ unsigned char n,m,max=0;
+ int adr=mdump_adr;
+ unsigned char * pb;
+ if (argc>1) adr=str2int(argv[1]);
+ if (argc>2) max=str2int(argv[2]);
+ max/=16;
+ if (!max) max=20;
+ for (m=0;m<max;m++) {
+ fprintf(stdout,"0x%08X ",adr);
+ pb=(unsigned char*) adr;
+ for (n=0;n<16;n++)
+ fprintf(stdout,"%02X%c",pb[n],n==7?'-':' ');
+ for (n=0;n<16;n++) {
+ fprintf(stdout,"%c",isprint(pb[n])?pb[n]:'.');
+ };
+ fprintf(stdout,"\n");
+ adr+=16;
+ };
+ mdump_adr=adr;
+ return 0;
+}
+/*----------------------------------------------------------------------------*/
+int main_mwdump(int argc,char * argv[]) {
+ unsigned char n,m,max=0;
+ int adr=mdump_adr;
+ unsigned short * pw;
+ if (argc>1) adr=str2int(argv[1]);
+ if (argc>2) max=str2int(argv[2]);
+ max/=16;
+ if (!max) max=20;
+ for (m=0;m<max;m++) {
+ fprintf(stdout,"0x%08X ",adr);
+ pw=(unsigned short*) adr;
+ for (n=0;n<8;n++)
+ fprintf(stdout,"%02X %02X%c",pw[n]/0x100,pw[n]%0x100,n==3?'-':' ');
+ for (n=0;n<8;n++) {
+ fprintf(stdout,"%c",isprint(pw[n]/0x100)?pw[n]/0x100:'.');
+ fprintf(stdout,"%c",isprint(pw[n]%0x100)?pw[n]%0x100:'.');
+ };
+ fprintf(stdout,"\n");
+ adr+=16;
+ };
+ mdump_adr=adr;
+ return 0;
+}
+/*----------------------------------------------------------------------------*/
+int main_medit(int argc,char * argv[]) {
+ unsigned char * pb;
+ int n,i;
+ if (argc<3) {
+ fprintf(stdout,"too few arguments\n");
+ return 0;
+ };
+ pb=(unsigned char*)str2int(argv[1]);
+ i=2;
+ n=0;
+ while (i<=argc) {
+ pb[n++]=str2int(argv[i++])%0x100;
+ }
+ mdump_adr=(int)pb;
+ return main_mdump(0,NULL);
+}
+/*----------------------------------------------------------------------------*/
+int main_mfill(int argc,char * argv[]) {
+ int adr;
+ int size;
+ unsigned char value;
+ if (argc<4) {
+ fprintf(stdout,"too few arguments\n");
+ return 0;
+ };
+ adr =str2int(argv[1]);
+ size =str2int(argv[2]);
+ value=str2int(argv[3])%0x100;
+ memset((unsigned char*)adr,size,value);
+ mdump_adr=adr;
+ return main_mdump(0,NULL);
+}
+/*----------------------------------------------------------------------------*/
+int main_mmove(int argc,char * argv[]) {
+ int src;
+ int dst;
+ int size;
+ if (argc<4) {
+ fprintf(stdout,"too few arguments\n");
+ return 0;
+ };
+ dst =str2int(argv[1]);
+ src =str2int(argv[2]);
+ size =str2int(argv[3]);
+ memcpy((unsigned char*)dst,(unsigned char*)src,size);
+ mdump_adr=dst;
+ return main_mdump(0,NULL);
+}
+/*----------------------------------------------------------------------------*/
+#ifdef MALLOC_STATS /* /rtems/s/src/lib/libc/malloc.c */
+int main_malloc_dump(int argc,char * argv[]) {
+ void malloc_dump(void);
+ malloc_dump();
+ return 0;
+}
+#endif
+/*----------------------------------------------------------------------------
+ * Reset. Assumes that the watchdog is present.
+ *----------------------------------------------------------------------------*/
+int main_reset (int argc, char **argv)
+{
+ rtems_interrupt_level level;
+ fprintf(stdout,"Waiting for watchdog ... ");
+ tcdrain(fileno(stdout));
+
+ rtems_interrupt_disable (level);
+ for (;;)
+ ;
+ return 0;
+}
+/*----------------------------------------------------------------------------
+ * Alias. make an alias
+ *----------------------------------------------------------------------------*/
+int main_alias (int argc, char **argv)
+{
+ if (argc<3) {
+ fprintf(stdout,"too few arguments\n");
+ return 1;
+ };
+ if (!shell_alias_cmd(argv[1],argv[2])) {
+ fprintf(stdout,"unable to make an alias(%s,%s)\n",argv[1],argv[2]);
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*
+ * Directory commands
+ *-----------------------------------------------------------*/
+int main_ls(int argc, char *argv[])
+{
+ char * fname;
+ DIR *dirp;
+ struct dirent *dp;
+ struct stat stat_buf;
+ struct passwd * pwd;
+ struct group * grp;
+ char * user;
+ char * group;
+ char sbuf[256];
+ char nbuf[1024];
+ int n,size;
+
+ fname=".";
+ if (argc>1) fname=argv[1];
+
+ if ((dirp = opendir(fname)) == NULL)
+ {
+ fprintf(stdout,"%s: No such file or directory.\n", fname);
+ return errno;
+ }
+ n=0;
+ size=0;
+ while ((dp = readdir(dirp)) != NULL)
+ {
+ strcpy(nbuf,fname);
+ if (nbuf[strlen(nbuf)-1]!='/') strcat(nbuf,"/");
+ strcat(nbuf,dp->d_name); /* always the fullpathname. Avoid ftpd problem.*/
+ if (stat(nbuf, &stat_buf) == 0)
+ { /* AWFUL buts works...*/
+ strftime(sbuf,sizeof(sbuf)-1,"%b %d %H:%M",gmtime(&stat_buf.st_mtime));
+ pwd=getpwuid(stat_buf.st_uid);
+ user=pwd?pwd->pw_name:"nouser";
+ grp=getgrgid(stat_buf.st_gid);
+ group=grp?grp->gr_name:"nogrp";
+ fprintf(stdout,"%c%c%c%c%c%c%c%c%c%c %3d %6.6s %6.6s %11d %s %s%c\n",
+ (S_ISLNK(stat_buf.st_mode)?('l'):
+ (S_ISDIR(stat_buf.st_mode)?('d'):('-'))),
+ (stat_buf.st_mode & S_IRUSR)?('r'):('-'),
+ (stat_buf.st_mode & S_IWUSR)?('w'):('-'),
+ (stat_buf.st_mode & S_IXUSR)?('x'):('-'),
+ (stat_buf.st_mode & S_IRGRP)?('r'):('-'),
+ (stat_buf.st_mode & S_IWGRP)?('w'):('-'),
+ (stat_buf.st_mode & S_IXGRP)?('x'):('-'),
+ (stat_buf.st_mode & S_IROTH)?('r'):('-'),
+ (stat_buf.st_mode & S_IWOTH)?('w'):('-'),
+ (stat_buf.st_mode & S_IXOTH)?('x'):('-'),
+ (int)stat_buf.st_nlink,
+ user,group,
+ (int)stat_buf.st_size,
+ sbuf,
+ dp->d_name,
+ S_ISDIR(stat_buf.st_mode)?'/':' ');
+ n++;
+ size+=stat_buf.st_size;
+ }
+ }
+ fprintf(stdout,"%d files %d bytes occupied\n",n,size);
+ closedir(dirp);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_pwd (int argc, char *argv[]) {
+ char dir[1024];
+ getcwd(dir,1024);
+ fprintf(stdout,"%s\n",dir);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_chdir (int argc, char *argv[]) {
+ char *dir;
+ dir="/";
+ if (argc>1) dir=argv[1];
+ if (chdir(dir)) {
+ fprintf(stdout,"chdir to '%s' failed:%s\n",dir,strerror(errno));
+ return errno;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_mkdir (int argc, char *argv[]) {
+ char *dir;
+ int n;
+ n=1;
+ while (n<argc) {
+ dir=argv[n++];
+ if (mkdir(dir,S_IRWXU|S_IRWXG|S_IRWXO)) {
+ fprintf(stdout,"mkdir '%s' failed:%s\n",dir,strerror(errno));
+ };
+ };
+ return errno;
+}
+/*-----------------------------------------------------------*/
+int main_rmdir (int argc, char *argv[])
+{
+ char *dir;
+ int n;
+ n=1;
+ while (n<argc) {
+ dir=argv[n++];
+ if (rmdir(dir)) fprintf(stdout,"rmdir '%s' failed:%s\n",dir,strerror(errno));
+ };
+ return errno;
+}
+/*-----------------------------------------------------------*/
+int main_chroot(int argc,char * argv[]) {
+ char * new_root="/";
+ if (argc==2) new_root=argv[1];
+ if (chroot(new_root)<0) {
+ fprintf(stdout,"error %s:chroot(%s);\n",strerror(errno),new_root);
+ return -1;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_cat (int argc, char *argv[])
+{
+ int n;
+ n=1;
+ while (n<argc) cat_file(stdout,argv[n++]);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_rm (int argc, char *argv[])
+{
+ int n;
+ n=1;
+ while (n<argc) {
+ if (unlink(argv[n])) {
+ fprintf(stdout,"error %s:rm %s\n",strerror(errno),argv[n]);
+ return -1;
+ };
+ n++;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+/* date - print time and date */
+
+int main_date(int argc,char *argv[])
+{
+ time_t t;
+ time(&t);
+ fprintf(stdout,"%s", ctime(&t));
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_logoff(int argc,char *argv[])
+{
+ fprintf(stdout,"logoff from the system...");
+ current_shell_env->exit_shell=TRUE;
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_tty (int argc,char *argv[])
+{
+ fprintf(stdout,"%s\n",ttyname(fileno(stdin)));
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_whoami(int argc,char *argv[])
+{
+ struct passwd * pwd;
+ pwd=getpwuid(getuid());
+ fprintf(stdout,"%s\n",pwd?pwd->pw_name:"nobody");
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_id (int argc,char *argv[])
+{
+ struct passwd * pwd;
+ struct group * grp;
+ pwd=getpwuid(getuid());
+ grp=getgrgid(getgid());
+ fprintf(stdout,"uid=%d(%s),gid=%d(%s),",
+ getuid(),pwd?pwd->pw_name:"",
+ getgid(),grp?grp->gr_name:"");
+ pwd=getpwuid(geteuid());
+ grp=getgrgid(getegid());
+ fprintf(stdout,"euid=%d(%s),egid=%d(%s)\n",
+ geteuid(),pwd?pwd->pw_name:"",
+ getegid(),grp?grp->gr_name:"");
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_umask(int argc,char *argv[])
+{
+ mode_t msk=umask(0);
+ if (argc == 2) msk=str2int(argv[1]);
+ umask(msk);
+ msk=umask(0);
+ fprintf(stdout,"0%o\n", (unsigned int) msk);
+ umask(msk);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_chmod(int argc,char *argv[])
+{
+ int n;
+ mode_t mode;
+ if (argc > 2){
+ mode=str2int(argv[1])&0777;
+ n=2;
+ while (n<argc) chmod(argv[n++],mode);
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*
+ * with this you can call at all the rtems monitor commands.
+ * Not all work fine but you can show the rtems status and more.
+ *-----------------------------------------------------------*/
+int main_monitor(int argc,char * argv[]) {
+ rtems_monitor_command_entry_t *command;
+ rtems_task_ident(RTEMS_SELF,0,&rtems_monitor_task_id);
+ rtems_monitor_node = rtems_get_node(rtems_monitor_task_id);
+ rtems_monitor_default_node = rtems_monitor_node;
+ if ((command=rtems_monitor_command_lookup(rtems_monitor_commands,argc,argv)))
+ command->command_function(argc, argv, &command->command_arg, 0);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+void register_cmds(void) {
+ rtems_monitor_command_entry_t *command;
+ /* monitor topic */
+ command=rtems_monitor_commands;
+ while (command) {
+ if (strcmp("exit",command->command)) /*Exclude EXIT (alias quit)*/
+ shell_add_cmd(command->command,"monitor",
+ command->usage ,main_monitor);
+ command=command->next;
+ };
+ /* dir[ectories] topic */
+ shell_add_cmd ("ls" ,"dir","ls [dir] # list files in the directory" ,main_ls );
+ shell_add_cmd ("chdir" ,"dir","chdir [dir] # change the current directory",main_chdir);
+ shell_add_cmd ("rmdir" ,"dir","rmdir dir # remove directory" ,main_rmdir);
+ shell_add_cmd ("mkdir" ,"dir","mkdir dir # make a directory" ,main_mkdir);
+ shell_add_cmd ("pwd" ,"dir","pwd # print work directory" ,main_pwd );
+ shell_add_cmd ("chroot","dir","chroot [dir] # change the root directory" ,main_chroot);
+ shell_add_cmd ("cat" ,"dir","cat n1 [n2 [n3...]]# show the ascii contents",main_cat );
+ shell_add_cmd ("rm" ,"dir","rm n1 [n2 [n3...]]# remove files" ,main_rm );
+ shell_add_cmd ("chmod" ,"dir","chmod 0777 n1 n2... #change filemode" ,main_chmod);
+
+ shell_alias_cmd("ls" ,"dir");
+ shell_alias_cmd("chdir" ,"cd");
+
+ /* misc. topic */
+ shell_add_cmd ("logoff","misc","logoff from the system" ,main_logoff);
+ shell_alias_cmd("logoff","exit");
+ shell_add_cmd ("date" ,"misc","date" ,main_date);
+ shell_add_cmd ("reset","misc","reset the BSP" ,main_reset);
+ shell_add_cmd ("alias","misc","alias old new" ,main_alias);
+ shell_add_cmd ("tty" ,"misc","show ttyname" ,main_tty );
+ shell_add_cmd ("whoami","misc","show current user" ,main_whoami);
+ shell_add_cmd ("id" ,"misc","show uid,gid,euid,egid" ,main_id );
+ shell_add_cmd ("umask" ,"misc","umask [new_umask]" ,main_umask );
+
+
+ /* memory topic */
+ shell_add_cmd ("mdump","mem" ,"mdump [adr [size]]" ,main_mdump);
+ shell_add_cmd ("wdump","mem" ,"wdump [adr [size]]" ,main_mwdump);
+ shell_add_cmd ("medit","mem" ,"medit adr value [value ...]" ,main_medit);
+ shell_add_cmd ("mfill","mem" ,"mfill adr size value" ,main_mfill);
+ shell_add_cmd ("mmove","mem" ,"mmove dst src size" ,main_mmove);
+#ifdef MALLOC_STATS /* /rtems/s/src/lib/libc/malloc.c */
+ shell_add_cmd ("malloc","mem","mem show memory malloc'ed" ,main_mem);
+#endif
+}
+/*-----------------------------------------------------------*/
diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c
new file mode 100644
index 0000000000..01a9c36ec8
--- /dev/null
+++ b/cpukit/libmisc/shell/shell.c
@@ -0,0 +1,682 @@
+/*
+ *
+ * Instantatiate a new terminal shell.
+ *
+ * Author:
+ *
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * Thanks at:
+ * Chris John
+ *
+ * $Id$
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/system.h>
+#include <rtems/shell.h>
+
+#include <termios.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+
+/* ----------------------------------------------- *
+ * This is a stupidity but is cute.
+ * ----------------------------------------------- */
+uint32_t new_rtems_name(char * rtems_name) {
+ static char b[5];
+ sprintf(b,"%-4.4s",rtems_name);
+ return rtems_build_name(b[0],b[1],b[2],b[3]);
+}
+/* **************************************************************
+ * common linked list of shell commands.
+ * Because the help report is very long
+ * I have a topic for each command.
+ * Help list the topics
+ * help [topic] list the commands for the topic
+ * help [command] help for the command
+ * Can you see help rtems monitor report?
+ * ************************************************************** */
+
+struct shell_topic_tt;
+typedef struct shell_topic_tt shell_topic_t;
+
+struct shell_topic_tt {
+ char * topic;
+ shell_topic_t * next;
+};
+
+
+static shell_cmd_t * shell_first_cmd;
+static shell_topic_t * shell_first_topic;
+/* ----------------------------------------------- *
+ * Using Chain I can reuse the rtems code.
+ * I am more comfortable with this, sorry.
+ * ----------------------------------------------- */
+shell_topic_t * shell_lookup_topic(char * topic) {
+ shell_topic_t * shell_topic;
+ shell_topic=shell_first_topic;
+ while (shell_topic) {
+ if (!strcmp(shell_topic->topic,topic)) return shell_topic;
+ shell_topic=shell_topic->next;
+ };
+ return (shell_topic_t *) NULL;
+}
+/* ----------------------------------------------- */
+shell_topic_t * shell_add_topic(char * topic) {
+ shell_topic_t * current,*aux;
+ if (!shell_first_topic) {
+ aux=malloc(sizeof(shell_topic_t));
+ aux->topic=topic;
+ aux->next=(shell_topic_t*)NULL;
+ return shell_first_topic=aux;
+ } else {
+ current=shell_first_topic;
+ if (!strcmp(topic,current->topic)) return current;
+ while (current->next) {
+ if (!strcmp(topic,current->next->topic)) return current->next;
+ current=current->next;
+ };
+ aux=malloc(sizeof(shell_topic_t));
+ aux->topic=topic;
+ aux->next=(shell_topic_t*)NULL;
+ current->next=aux;
+ return aux;
+ };
+}
+/* ----------------------------------------------- */
+shell_cmd_t * shell_lookup_cmd(char * cmd) {
+ shell_cmd_t * shell_cmd;
+ shell_cmd=shell_first_cmd;
+ while (shell_cmd) {
+ if (!strcmp(shell_cmd->name,cmd)) return shell_cmd;
+ shell_cmd=shell_cmd->next;
+ };
+ return (shell_cmd_t *) NULL;
+}
+/* ----------------------------------------------- */
+shell_cmd_t * shell_add_cmd(char * cmd,
+ char * topic,
+ char * usage,
+ shell_command_t command) {
+ int shell_help(int argc,char * argv[]);
+ shell_cmd_t * shell_cmd,*shell_pvt;
+ if (!shell_first_cmd) {
+ shell_first_cmd=(shell_cmd_t *) malloc(sizeof(shell_cmd_t));
+ shell_first_cmd->name ="help";
+ shell_first_cmd->topic ="help";
+ shell_first_cmd->usage ="help [topic] # list of usage of commands";
+ shell_first_cmd->command=shell_help;
+ shell_first_cmd->alias =(shell_cmd_t *) NULL;
+ shell_first_cmd->next =(shell_cmd_t *) NULL;
+ shell_add_topic(shell_first_cmd->topic);
+ register_cmds();
+ };
+ if (!cmd) return (shell_cmd_t *) NULL;
+ if (!command) return (shell_cmd_t *) NULL;
+ shell_cmd=(shell_cmd_t *) malloc(sizeof(shell_cmd_t));
+ shell_cmd->name =cmd;
+ shell_cmd->topic =topic;
+ shell_cmd->usage =usage;
+ shell_cmd->command=command;
+ shell_cmd->alias =(shell_cmd_t *) NULL;
+ shell_cmd->next =(shell_cmd_t *) NULL;
+ shell_add_topic(shell_cmd->topic);
+ shell_pvt=shell_first_cmd;
+ while (shell_pvt->next) shell_pvt=shell_pvt->next;
+ return shell_pvt->next=shell_cmd;
+}
+/* ----------------------------------------------- *
+ * you can make an alias for every command.
+ * ----------------------------------------------- */
+shell_cmd_t * shell_alias_cmd(char * cmd, char * alias) {
+ shell_cmd_t * shell_cmd,* shell_aux;
+ shell_aux=(shell_cmd_t *) NULL;
+ if (alias) {
+ if ((shell_aux=shell_lookup_cmd(alias))!=NULL) {
+ return NULL;
+ };
+ if ((shell_cmd=shell_lookup_cmd(cmd))!=NULL) {
+ shell_aux=shell_add_cmd(alias,shell_cmd->topic,
+ shell_cmd->usage,shell_cmd->command);
+ if (shell_aux) shell_aux->alias=shell_cmd;
+ };
+ };
+ return shell_aux;
+}
+/* ----------------------------------------------- *
+ * Poor but enough..
+ * TODO: Redirection capture. "" evaluate, ... C&S welcome.
+ * ----------------------------------------------- */
+int shell_make_args(char * cmd,
+ int * pargc,
+ char * argv[]) {
+ int argc=0;
+ while ((cmd=strtok(cmd," \t\r\n"))!=NULL) {
+ argv[argc++]=cmd;
+ cmd=(char*)NULL;
+ };
+ argv[argc]=(char*)NULL;
+ return *pargc=argc;
+}
+/* ----------------------------------------------- *
+ * show the help for one command.
+ * ----------------------------------------------- */
+int shell_help_cmd(shell_cmd_t * shell_cmd) {
+ char * pc;
+ int col,line;
+ fprintf(stdout,"%-10.10s -",shell_cmd->name);
+ col=12;
+ line=1;
+ if (shell_cmd->alias) {
+ fprintf(stdout,"is an <alias> for command '%s'",shell_cmd->alias->name);
+ } else
+ if (shell_cmd->usage) {
+ pc=shell_cmd->usage;
+ while (*pc) {
+ switch(*pc) {
+ case '\r':break;
+ case '\n':putchar('\n');
+ col=0;
+ break;
+ default :putchar(*pc);
+ col++;
+ break;
+ };
+ pc++;
+ if(col>78) { /* What daring... 78?*/
+ if (*pc) {
+ putchar('\n');
+ col=0;
+ };
+ };
+ if (!col && *pc) {
+ fprintf(stdout," ");
+ col=12;line++;
+ };
+ };
+ };
+ puts("");
+ return line;
+}
+/* ----------------------------------------------- *
+ * show the help. The first command implemented.
+ * Can you see the header of routine? Known?
+ * The same with all the commands....
+ * ----------------------------------------------- */
+int shell_help(int argc,char * argv[]) {
+ int col,line,arg;
+ shell_topic_t *topic;
+ shell_cmd_t * shell_cmd=shell_first_cmd;
+ if (argc<2) {
+ fprintf(stdout,"help: ('r' repeat last cmd - 'e' edit last cmd)\n"
+ " TOPIC? The topics are\n");
+ topic=shell_first_topic;
+ col=0;
+ while (topic) {
+ if (!col){
+ col=fprintf(stdout," %s",topic->topic);
+ } else {
+ if ((col+strlen(topic->topic)+2)>78){
+ fprintf(stdout,"\n");
+ col=fprintf(stdout," %s",topic->topic);
+ } else {
+ col+=fprintf(stdout,", %s",topic->topic);
+ };
+ };
+ topic=topic->next;
+ };
+ fprintf(stdout,"\n");
+ return 1;
+ };
+ line=0;
+ for (arg=1;arg<argc;arg++) {
+ if (line>16) {
+ fprintf(stdout,"Press any key to continue...");getchar();
+ fprintf(stdout,"\n");
+ line=0;
+ };
+ topic=shell_lookup_topic(argv[arg]);
+ if (!topic){
+ if ((shell_cmd=shell_lookup_cmd(argv[arg]))==NULL) {
+ fprintf(stdout,"help: topic or cmd '%s' not found. Try <help> alone for a list\n",argv[arg]);
+ line++;
+ } else {
+ line+=shell_help_cmd(shell_cmd);
+ }
+ continue;
+ };
+ fprintf(stdout,"help: list for the topic '%s'\n",argv[arg]);
+ line++;
+ while (shell_cmd) {
+ if (!strcmp(topic->topic,shell_cmd->topic))
+ line+=shell_help_cmd(shell_cmd);
+ if (line>16) {
+ fprintf(stdout,"Press any key to continue...");getchar();
+ fprintf(stdout,"\n");
+ line=0;
+ };
+ shell_cmd=shell_cmd->next;
+ };
+ };
+ puts("");
+ return 0;
+}
+/* ----------------------------------------------- *
+ * TODO: Add improvements. History, edit vi or emacs, ...
+ * ----------------------------------------------- */
+int shell_scanline(char * line,int size,FILE * in,FILE * out) {
+ int c,col;
+ col=0;
+ if (*line) {
+ col=strlen(line);
+ if (out) fprintf(out,"%s",line);
+ };
+ tcdrain(fileno(in ));
+ if (out) tcdrain(fileno(out));
+ for (;;) {
+ line[col]=0;
+ c=fgetc(in);
+ switch (c) {
+ case 0x04:/*Control-d*/
+ if (col) break;
+ case EOF :return 0;
+ case '\n':break;
+ case '\f':if (out) fputc('\f',out);
+ case 0x03:/*Control-C*/
+ line[0]=0;
+ case '\r':if (out) fputc('\n',out);
+ return 1;
+ case 127:
+ case '\b':if (col) {
+ if (out) {
+ fputc('\b',out);
+ fputc(' ',out);
+ fputc('\b',out);
+ };
+ col--;
+ } else {
+ if (out) fputc('\a',out);
+ };
+ break;
+ default :if (!iscntrl(c)) {
+ if (col<size-1) {
+ line[col++]=c;
+ if (out) fputc(c,out);
+ } else {
+ if (out) fputc('\a',out);
+ };
+ } else {
+ if (out)
+ if (c=='\a') fputc('\a',out);
+ };
+ break;
+ };
+ };
+}
+/* ----------------------------------------------- *
+ * - The shell TASK
+ * Poor but enough..
+ * TODO: Redirection. Tty Signals. ENVVARs. Shell language.
+ * ----------------------------------------------- */
+shell_env_t global_shell_env ,
+ * current_shell_env=&global_shell_env;
+
+extern char **environ;
+
+void cat_file(FILE * out,char * name) {
+ FILE * fd;
+ int c;
+ if (out) {
+ fd=fopen(name,"r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) fputc(c,out);
+ fclose(fd);
+ };
+ };
+}
+
+void write_file(char * name,char * content) {
+ FILE * fd;
+ fd=fopen(name,"w");
+ if (fd) {
+ fwrite(content,1,strlen(content),fd);
+ fclose(fd);
+ };
+}
+
+void init_issue(void) {
+ static char issue_inited=FALSE;
+ struct stat buf;
+ if (issue_inited) return;
+ issue_inited=TRUE;
+ getpwnam("root"); /* dummy call to init /etc dir */
+ if (stat("/etc/issue",&buf))
+ write_file("/etc/issue",
+ "Welcome to @V\\n"
+ "Login into @S(@L)\\n");
+ if (stat("/etc/issue.net",&buf))
+ write_file("/etc/issue.net",
+ "Welcome to %v\n"
+ "running on %m\n");
+}
+
+int shell_login(FILE * in,FILE * out) {
+ FILE * fd;
+ int c;
+ time_t t;
+ int times;
+ char name[128];
+ char pass[128];
+ struct passwd * passwd;
+ init_issue();
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+ if (out) {
+ if((current_shell_env->devname[5]!='p')||
+ (current_shell_env->devname[6]!='t')||
+ (current_shell_env->devname[7]!='y')) {
+ fd=fopen("/etc/issue","r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) {
+ if (c=='@') {
+ switch(c=fgetc(fd)) {
+ case 'L':fprintf(out,"%s",current_shell_env->devname);
+ break;
+ case 'B':fprintf(out,"0");
+ break;
+ case 'T':
+ case 'D':time(&t);
+ fprintf(out,"%s",ctime(&t));
+ break;
+ case 'S':fprintf(out,"RTEMS");
+ break;
+ case 'V':fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
+ break;
+ case '@':fprintf(out,"@");
+ break;
+ default :fprintf(out,"@%c",c);
+ break;
+ };
+ } else
+ if (c=='\\') {
+ switch(c=fgetc(fd)) {
+ case '\\':fprintf(out,"\\");
+ break;
+ case 'b':fprintf(out,"\b"); break;
+ case 'f':fprintf(out,"\f"); break;
+ case 'n':fprintf(out,"\n"); break;
+ case 'r':fprintf(out,"\r"); break;
+ case 's':fprintf(out," "); break;
+ case 't':fprintf(out,"\t"); break;
+ case '@':fprintf(out,"@"); break;
+ };
+ } else {
+ fputc(c,out);
+ };
+ };
+ fclose(fd);
+ }
+ } else {
+ fd=fopen("/etc/issue.net","r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) {
+ if (c=='%') {
+ switch(c=fgetc(fd)) {
+ case 't':fprintf(out,"%s",current_shell_env->devname);
+ break;
+ case 'h':fprintf(out,"0");
+ break;
+ case 'D':fprintf(out," ");
+ break;
+ case 'd':time(&t);
+ fprintf(out,"%s",ctime(&t));
+ break;
+ case 's':fprintf(out,"RTEMS");
+ break;
+ case 'm':fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")");
+ break;
+ case 'r':fprintf(out,_RTEMS_version);
+ break;
+ case 'v':fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
+ break;
+ case '%':fprintf(out,"%%");
+ break;
+ default :fprintf(out,"%%%c",c);
+ break;
+ };
+ } else {
+ fputc(c,out);
+ };
+ };
+ fclose(fd);
+ }
+ };
+ };
+ times=0;
+ strcpy(name,"");
+ strcpy(pass,"");
+ for (;;) {
+ times++;
+ if (times>3) break;
+ if (out) fprintf(out,"\nlogin: ");
+ if (!shell_scanline(name,sizeof(name),in,out )) break;
+ if (out) fprintf(out,"Password: ");
+ if (!shell_scanline(pass,sizeof(pass),in,NULL)) break;
+ if (out) fprintf(out,"\n");
+ if ((passwd=getpwnam(name))) {
+ if (strcmp(passwd->pw_passwd,"!")) { /* valid user */
+ setuid(passwd->pw_uid);
+ setgid(passwd->pw_gid);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+ chown(current_shell_env->devname,passwd->pw_uid,0);
+ rtems_current_user_env->euid=passwd->pw_uid;
+ rtems_current_user_env->egid=passwd->pw_gid;
+ if (!strcmp(passwd->pw_passwd,"*")) {
+ /* /etc/shadow */
+ return 0;
+ } else {
+ /* crypt() */
+ return 0;
+ };
+ };
+ };
+ if (out) fprintf(out,"Login incorrect\n");
+ strcpy(name,"");
+ strcpy(pass,"");
+ };
+ return -1;
+}
+
+rtems_task shell_shell(rtems_task_argument task_argument) {
+
+ shell_env_t * shell_env =(shell_env_t*) task_argument;
+ shell_cmd_t * shell_cmd;
+
+ rtems_status_code sc;
+
+ struct termios term;
+ char * devname;
+
+ char curdir[256];
+ char cmd[256];
+ char last_cmd[256]; /* to repeat 'r' */
+ int argc;
+ char * argv[128];
+
+ sc=rtems_task_variable_add(RTEMS_SELF,(void*)&current_shell_env,free);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"rtems_task_variable_add(current_shell_env):");
+ rtems_task_delete(RTEMS_SELF);
+ };
+
+ current_shell_env=shell_env;
+
+ sc=rtems_libio_set_private_env();
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"rtems_libio_set_private_env():");
+ rtems_task_delete(RTEMS_SELF);
+ };
+
+
+ devname=shell_env->devname;
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+
+ stdin =fopen(devname,"r+");
+
+ if (!stdin) {
+ fprintf(stderr,"shell:unable to open stdin.%s:%s\n",devname,strerror(errno));
+ rtems_task_delete(RTEMS_SELF);
+ };
+ setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/
+ /* make a raw terminal,Linux MANuals */
+ if (tcgetattr (fileno(stdin), &term)>=0) {
+ term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ term.c_oflag &= ~OPOST;
+ term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
+ term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ term.c_cflag = CLOCAL | CREAD |(shell_env->tcflag);
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+ if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) {
+ fprintf(stderr,"shell:cannot set terminal attributes(%s)\n",devname);
+ };
+ stdout=fopen(devname,"r+");
+ if (!stdout) {
+ fprintf(stderr,"shell:unable to open stdout.%s:%s\n",devname,strerror(errno));
+ };
+ setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/
+ stderr=fopen(devname,"r+");
+ if (!stderr) {
+ fprintf(stdout,"shell:unable to open stderr.%s:%s\n",devname,strerror(errno));
+ };
+ /* when the future user environment runs ok
+ * a freopen() reopens the terminals. Now this don't work
+ * (sorry but you can't use because FILENO_STDIN!=0. Better fileno(stdin))
+ */
+ };
+ shell_add_cmd(NULL,NULL,NULL,NULL); /* init the chain list*/
+ do {
+ /* Set again root user and root filesystem, side effect of set_priv..*/
+ sc=rtems_libio_set_private_env();
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"rtems_libio_set_private_env():");
+ rtems_task_delete(RTEMS_SELF);
+ };
+ if (!shell_login(stdin,stdout)) {
+ cat_file(stdout,"/etc/motd");
+ strcpy(last_cmd,"");
+ strcpy(cmd,"");
+ fprintf(stdout,"\n"
+ "RTEMS SHELL (Ver.1.0-FRC):%s. "__DATE__". 'help' to list commands.\n",devname);
+ chdir("/"); /* XXX: chdir to getpwent homedir */
+ shell_env->exit_shell=FALSE;
+ for (;;) {
+ /* Prompt section */
+ /* XXX: show_prompt user adjustable */
+ getcwd(curdir,sizeof(curdir));
+ fprintf(stdout,"%s [%s] %c ",shell_env->taskname,curdir,geteuid()?'$':'#');
+ /* getcmd section */
+ if (!shell_scanline(cmd,sizeof(cmd),stdin,stdout)) break; /*EOF*/
+ /* evaluate cmd section */
+ if (!strcmp(cmd,"e")) { /* edit last command */
+ strcpy(cmd,last_cmd);
+ continue;
+ } else
+ if (!strcmp(cmd,"r")) { /* repeat last command */
+ strcpy(cmd,last_cmd);
+ } else
+ if (strcmp(cmd,"")) { /* only for get a new prompt */
+ strcpy(last_cmd,cmd);
+ };
+ /* exec cmd section */
+ /* TODO:
+ * To avoid user crash catch the signals.
+ * Open a new stdio files with posibility of redirection *
+ * Run in a new shell task background. (unix &)
+ * Resuming. A little bash.
+ */
+ if (shell_make_args(cmd,&argc,argv)) {
+ if ((shell_cmd=shell_lookup_cmd(argv[0]))!=NULL) {
+ shell_env->errorlevel=shell_cmd->command(argc,argv);
+ } else {
+ fprintf(stdout,"shell:%s command not found\n",argv[0]);
+ shell_env->errorlevel=-1;
+ };
+ };
+ /* end exec cmd section */
+ if (shell_env->exit_shell) break;
+ cmd[0]=0;
+ };
+ fprintf(stdout,"\nGoodbye from RTEMS SHELL :-(\n");
+ };
+ } while (shell_env->forever);
+ fclose(stdin );
+ fclose(stdout);
+ fclose(stderr);
+ rtems_task_delete(RTEMS_SELF);
+}
+/* ----------------------------------------------- */
+rtems_status_code shell_init (char * task_name,
+ uint32_t task_stacksize,
+ rtems_task_priority task_priority,
+ char * devname,
+ tcflag_t tcflag,
+ int forever) {
+ rtems_id task_id;
+ rtems_status_code sc;
+ shell_env_t * shell_env;
+ sc=rtems_task_create(new_rtems_name(task_name),
+ task_priority,
+ task_stacksize?task_stacksize:RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_LOCAL | RTEMS_FLOATING_POINT,
+ &task_id);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"creating task %s in shell_init()",task_name);
+ return sc;
+ };
+ shell_env=malloc(sizeof(shell_env_t));
+ if (!shell_env) {
+ rtems_task_delete(task_id);
+ sc=RTEMS_NO_MEMORY;
+ rtems_error(sc,"allocating shell_env %s in shell_init()",task_name);
+ return sc;
+ };
+ if (global_shell_env.magic!=new_rtems_name("SENV")) {
+ global_shell_env.magic =new_rtems_name("SENV");
+ global_shell_env.devname ="/dev/console";
+ global_shell_env.taskname ="GLOBAL";
+ global_shell_env.tcflag =0;
+ global_shell_env.exit_shell=0;
+ global_shell_env.forever =TRUE;
+ };
+ shell_env->magic =global_shell_env.magic;
+ shell_env->devname =devname;
+ shell_env->taskname =task_name;
+ shell_env->tcflag =tcflag;
+ shell_env->exit_shell=FALSE;
+ shell_env->forever =forever;
+ return rtems_task_start(task_id,shell_shell,(rtems_task_argument) shell_env);
+}
diff --git a/cpukit/libmisc/shell/shell.h b/cpukit/libmisc/shell/shell.h
new file mode 100644
index 0000000000..c95bef5436
--- /dev/null
+++ b/cpukit/libmisc/shell/shell.h
@@ -0,0 +1,88 @@
+/*
+ *
+ * Instantatiate a new terminal shell.
+ *
+ * Author:
+ *
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * Thanks at:
+ * Chris John
+ *
+ * $Id$
+ */
+
+#ifndef __SHELL_H__
+#define __SHELL_H__
+
+#include <rtems.h>
+#include <stdio.h>
+#include <termios.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*shell_command_t)(int argc,char * argv[]);
+
+struct shell_cmd_tt ;
+typedef struct shell_cmd_tt shell_cmd_t;
+
+struct shell_cmd_tt {
+ char * name;
+ char * usage;
+ char * topic;
+ shell_command_t command;
+ shell_cmd_t * alias;
+ shell_cmd_t * next;
+};
+
+uint32_t new_rtems_name(char * rtems_name);
+shell_cmd_t * shell_lookup_cmd(char * cmd);
+shell_cmd_t * shell_add_cmd(char * cmd,
+ char * topic,
+ char * usage,
+ shell_command_t command);
+shell_cmd_t * shell_alias_cmd(char * cmd, char * alias);
+
+int shell_make_args(char * cmd,
+ int * pargc,
+ char * argv[]);
+
+typedef struct {
+ rtems_name magic; /* 'S','E','N','V': Shell Environment */
+ char * devname;
+ char * taskname;
+ tcflag_t tcflag;
+ /* user extensions */
+ int exit_shell; /* logout */
+ int forever ; /* repeat login */
+ int errorlevel;
+ int mdump_adr;
+} shell_env_t;
+
+int shell_scanline(char * line,int size,FILE * in,FILE * out) ;
+void cat_file(FILE * out,char *name);
+void write_file(char *name,char * content);
+
+rtems_status_code shell_init(char * task_name ,
+ uint32_t task_stacksize,/*0 default*/
+ rtems_task_priority task_priority ,
+ char * devname ,
+ tcflag_t tcflag ,
+ int forever );
+
+extern shell_env_t global_shell_env,
+ * current_shell_env;
+/*--------*/
+/* cmds.c */
+/*--------*/
+int str2int(char * s);
+void register_cmds(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/stackchk/README b/cpukit/libmisc/stackchk/README
new file mode 100644
index 0000000000..0f6e2f2b10
--- /dev/null
+++ b/cpukit/libmisc/stackchk/README
@@ -0,0 +1,56 @@
+#
+# $Id$
+#
+
+Introduction
+============
+
+This directory contains a stack bounds checker. It provides two
+primary features:
+
+ + check for stack overflow at each context switch
+ + provides an educated guess at each task's stack usage
+
+Enabling
+========
+
+Add the stack checker extension to the initial user extension set.
+If using confdefs.h to build your configuration table, this is
+as simple as adding -DSTACK_CHECK_ON to the gcc command line which
+compiles the file defining the configuration table. In the RTEMS
+test suites and samples, this is always init.c
+
+Background
+==========
+
+The stack overflow check at context switch works by looking for
+a 16 byte pattern at the logical end of the stack to be corrupted.
+The "guesser" assumes that the entire stack was prefilled with a known
+pattern and assumes that the pattern is still in place if the memory
+has not been used as a stack.
+
+Both of these can be fooled by pushing large holes onto the stack
+and not writing to them... or (much more unlikely) writing the
+magic patterns into memory.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to catch the most common mistake in multitasking
+systems ... too little stack space. Suggestions and comments are appreciated.
+
+NOTES:
+
+1. Stack usage information is questionable on CPUs which push
+ large holes on stack.
+
+2. The stack checker has a tendency to generate a fault when
+ trying to print the helpful diagnostic message. If it comes
+ out, congratulations. If not, then the variable Stack_check_Blown_task
+ contains a pointer to the TCB of the offending task. This
+ is usually enough to go on.
+
+FUTURE:
+
+1. Determine how/if gcc will generate stack probe calls and support that.
+
+2. Get accurate stack usage numbers on i960.. it pushes very large
+ holes on the stack.
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c
new file mode 100644
index 0000000000..e5ae3c7970
--- /dev/null
+++ b/cpukit/libmisc/stackchk/check.c
@@ -0,0 +1,553 @@
+/*
+ * Stack Overflow Check User Extension Set
+ *
+ * NOTE: This extension set automatically determines at
+ * initialization time whether the stack for this
+ * CPU grows up or down and installs the correct
+ * extension routines for that direction.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+/*
+ * HACK
+ * the stack dump information should be printed by a "fatal" extension.
+ * Fatal extensions only get called via rtems_fatal_error_occurred()
+ * and not when rtems_shutdown_executive() is called.
+ * I hope/think this is changing so that fatal extensions are renamed
+ * to "shutdown" extensions.
+ * When that happens, this #define should be deleted and all the code
+ * it marks.
+ */
+#define DONT_USE_FATAL_EXTENSION
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <rtems/stackchk.h>
+#include "internal.h"
+
+/*
+ * This variable contains the name of the task which "blew" the stack.
+ * It is NULL if the system is all right.
+ */
+
+Thread_Control *Stack_check_Blown_task;
+
+/*
+ * The extension table for the stack checker.
+ */
+
+rtems_extensions_table Stack_check_Extension_table = {
+ Stack_check_Create_extension, /* rtems_task_create */
+ 0, /* rtems_task_start */
+ 0, /* rtems_task_restart */
+ 0, /* rtems_task_delete */
+ Stack_check_Switch_extension, /* task_switch */
+ Stack_check_Begin_extension, /* task_begin */
+ 0, /* task_exitted */
+#ifdef DONT_USE_FATAL_EXTENSION
+ 0, /* fatal */
+#else
+ Stack_check_Fatal_extension, /* fatal */
+#endif
+};
+
+/*
+ * The "magic pattern" used to mark the end of the stack.
+ */
+
+Stack_check_Control Stack_check_Pattern;
+
+/*
+ * Where the pattern goes in the stack area is dependent upon
+ * whether the stack grow to the high or low area of the memory.
+ *
+ */
+
+#if ( CPU_STACK_GROWS_UP == TRUE )
+
+#define Stack_check_Get_pattern_area( _the_stack ) \
+ ((Stack_check_Control *) ((char *)(_the_stack)->area + \
+ (_the_stack)->size - sizeof( Stack_check_Control ) ))
+
+#define Stack_check_Calculate_used( _low, _size, _high_water ) \
+ ((char *)(_high_water) - (char *)(_low))
+
+#define Stack_check_usable_stack_start(_the_stack) \
+ ((_the_stack)->area)
+
+#else
+
+#define Stack_check_Get_pattern_area( _the_stack ) \
+ ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD))
+
+#define Stack_check_Calculate_used( _low, _size, _high_water) \
+ ( ((char *)(_low) + (_size)) - (char *)(_high_water) )
+
+#define Stack_check_usable_stack_start(_the_stack) \
+ ((char *)(_the_stack)->area + sizeof(Stack_check_Control))
+
+#endif
+
+#define Stack_check_usable_stack_size(_the_stack) \
+ ((_the_stack)->size - sizeof(Stack_check_Control))
+
+
+/*
+ * Do we have an interrupt stack?
+ * XXX it would sure be nice if the interrupt stack were also
+ * stored in a "stack" structure!
+ */
+
+
+Stack_Control stack_check_interrupt_stack;
+
+/*
+ * Prototypes necessary for forward references
+ */
+
+void Stack_check_Dump_usage( void );
+
+/*
+ * Fill an entire stack area with BYTE_PATTERN.
+ * This will be used by a Fatal extension to check for
+ * amount of actual stack used
+ */
+
+void
+stack_check_dope_stack(Stack_Control *stack)
+{
+ memset(stack->area, BYTE_PATTERN, stack->size);
+}
+
+
+/*PAGE
+ *
+ * Stack_check_Initialize
+ */
+
+uint32_t stack_check_initialized = 0;
+
+void Stack_check_Initialize( void )
+{
+#if 0
+ rtems_status_code status;
+ Objects_Id id_ignored;
+#endif
+ uint32_t *p;
+#if 0
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ Objects_Information *information;
+#endif
+
+ if (stack_check_initialized)
+ return;
+
+ /*
+ * Dope the pattern and fill areas
+ */
+
+ for ( p = Stack_check_Pattern.pattern;
+ p < &Stack_check_Pattern.pattern[PATTERN_SIZE_WORDS];
+ p += 4
+ )
+ {
+ p[0] = 0xFEEDF00D; /* FEED FOOD to BAD DOG */
+ p[1] = 0x0BAD0D06;
+ p[2] = 0xDEADF00D; /* DEAD FOOD GOOD DOG */
+ p[3] = 0x600D0D06;
+ };
+
+#if 0
+ status = rtems_extension_create(
+ rtems_build_name( 'S', 'T', 'C', 'K' ),
+ &Stack_check_Extension_table,
+ &id_ignored
+ );
+ assert ( status == RTEMS_SUCCESSFUL );
+#endif
+
+ Stack_check_Blown_task = 0;
+
+ /*
+ * If installed by a task, that task will not get setup properly
+ * since it missed out on the create hook. This will cause a
+ * failure on first switch out of that task.
+ * So pretend here that we actually ran create and begin extensions.
+ */
+
+ /* XXX
+ *
+ * Technically this has not been done for any task created before this
+ * happened. So just run through them and fix the situation.
+ */
+#if 0
+ if (_Thread_Executing)
+ {
+ Stack_check_Create_extension(_Thread_Executing, _Thread_Executing);
+ }
+#endif
+
+#if 0
+ for ( api_index = 1;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+ Stack_check_Create_extension( the_thread, the_thread );
+ }
+ }
+ }
+#endif
+
+ /*
+ * If appropriate, setup the interrupt stack for high water testing
+ * also.
+ */
+#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+ if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high)
+ {
+ stack_check_interrupt_stack.area = _CPU_Interrupt_stack_low;
+ stack_check_interrupt_stack.size = (char *) _CPU_Interrupt_stack_high -
+ (char *) _CPU_Interrupt_stack_low;
+
+ stack_check_dope_stack(&stack_check_interrupt_stack);
+ }
+#endif
+
+#ifdef DONT_USE_FATAL_EXTENSION
+#ifdef RTEMS_DEBUG
+ /*
+ * this would normally be called by a fatal extension
+ * handler, but we don't run fatal extensions unless
+ * we fatal error.
+ */
+ atexit(Stack_check_Dump_usage);
+#endif
+#endif
+
+ stack_check_initialized = 1;
+}
+
+/*PAGE
+ *
+ * Stack_check_Create_extension
+ */
+
+boolean Stack_check_Create_extension(
+ Thread_Control *running,
+ Thread_Control *the_thread
+)
+{
+ if (!stack_check_initialized)
+ Stack_check_Initialize();
+
+ if (the_thread /* XXX && (the_thread != _Thread_Executing) */ )
+ stack_check_dope_stack(&the_thread->Start.Initial_stack);
+
+ return TRUE;
+}
+
+/*PAGE
+ *
+ * Stack_check_Begin_extension
+ */
+
+void Stack_check_Begin_extension(
+ Thread_Control *the_thread
+)
+{
+ Stack_check_Control *the_pattern;
+
+ if (!stack_check_initialized)
+ Stack_check_Initialize();
+
+ if ( the_thread->Object.id == 0 ) /* skip system tasks */
+ return;
+
+ the_pattern = Stack_check_Get_pattern_area(&the_thread->Start.Initial_stack);
+
+ *the_pattern = Stack_check_Pattern;
+}
+
+/*PAGE
+ *
+ * Stack_check_report_blown_task
+ * Report a blown stack. Needs to be a separate routine
+ * so that interrupt handlers can use this too.
+ *
+ * Caller must have set the Stack_check_Blown_task.
+ *
+ * NOTE: The system is in a questionable state... we may not get
+ * the following message out.
+ */
+
+void Stack_check_report_blown_task(void)
+{
+ Stack_Control *stack;
+ Thread_Control *running;
+
+ running = Stack_check_Blown_task;
+ stack = &running->Start.Initial_stack;
+
+ fprintf(
+ stderr,
+ "BLOWN STACK!!! Offending task(%p): id=0x%08x; name=0x%08x",
+ running,
+ running->Object.id,
+ (uint32_t )running->Object.name
+ );
+ fflush(stderr);
+
+ if (rtems_configuration_get_user_multiprocessing_table())
+ fprintf(
+ stderr,
+ "; node=%d\n",
+ rtems_configuration_get_user_multiprocessing_table()->node
+ );
+ else
+ fprintf(stderr, "\n");
+ fflush(stderr);
+
+ fprintf(
+ stderr,
+ " stack covers range 0x%08x - 0x%08x (%d bytes)\n",
+ (uint32_t ) stack->area,
+ (uint32_t ) stack->area + stack->size - 1,
+ (uint32_t ) stack->size);
+ fflush(stderr);
+
+ fprintf(
+ stderr,
+ " Damaged pattern begins at 0x%08lx and is %ld bytes long\n",
+ (unsigned long) Stack_check_Get_pattern_area(stack),
+ (long) PATTERN_SIZE_BYTES);
+ fflush(stderr);
+
+ rtems_fatal_error_occurred( (uint32_t ) "STACK BLOWN" );
+}
+
+/*PAGE
+ *
+ * Stack_check_Switch_extension
+ */
+
+void Stack_check_Switch_extension(
+ Thread_Control *running,
+ Thread_Control *heir
+)
+{
+ if ( running->Object.id == 0 ) /* skip system tasks */
+ return;
+
+ if (0 != memcmp( (void *) Stack_check_Get_pattern_area( &running->Start.Initial_stack)->pattern,
+ (void *) Stack_check_Pattern.pattern,
+ PATTERN_SIZE_BYTES))
+ {
+ Stack_check_Blown_task = running;
+ Stack_check_report_blown_task();
+ }
+}
+
+void *Stack_check_find_high_water_mark(
+ const void *s,
+ size_t n
+)
+{
+ const uint32_t *base, *ebase;
+ uint32_t length;
+
+ base = s;
+ length = n/4;
+
+#if ( CPU_STACK_GROWS_UP == TRUE )
+ /*
+ * start at higher memory and find first word that does not
+ * match pattern
+ */
+
+ base += length - 1;
+ for (ebase = s; base > ebase; base--)
+ if (*base != U32_PATTERN)
+ return (void *) base;
+#else
+ /*
+ * start at lower memory and find first word that does not
+ * match pattern
+ */
+
+ base += PATTERN_SIZE_WORDS;
+ for (ebase = base + length; base < ebase; base++)
+ if (*base != U32_PATTERN)
+ return (void *) base;
+#endif
+
+ return (void *)0;
+}
+
+/*PAGE
+ *
+ * Stack_check_Dump_threads_usage
+ * Try to print out how much stack was actually used by the task.
+ *
+ */
+
+void Stack_check_Dump_threads_usage(
+ Thread_Control *the_thread
+)
+{
+ uint32_t size, used;
+ void *low;
+ void *high_water_mark;
+ Stack_Control *stack;
+ uint32_t u32_name;
+ char name_str[5];
+ char *name;
+ Objects_Information *info;
+
+ if ( !the_thread )
+ return;
+
+ /*
+ * XXX HACK to get to interrupt stack
+ */
+
+ if (the_thread == (Thread_Control *) -1)
+ {
+ if (stack_check_interrupt_stack.area)
+ {
+ stack = &stack_check_interrupt_stack;
+ the_thread = 0;
+ }
+ else
+ return;
+ }
+ else
+ stack = &the_thread->Start.Initial_stack;
+
+ low = Stack_check_usable_stack_start(stack);
+ size = Stack_check_usable_stack_size(stack);
+
+ high_water_mark = Stack_check_find_high_water_mark(low, size);
+
+ if ( high_water_mark )
+ used = Stack_check_Calculate_used( low, size, high_water_mark );
+ else
+ used = 0;
+
+ name = name_str;
+ if ( the_thread ) {
+ info = _Objects_Get_information(the_thread->Object.id);
+ if ( info->is_string ) {
+ name = (char *) the_thread->Object.name;
+ } else {
+ u32_name = (uint32_t )the_thread->Object.name;
+ name[ 0 ] = (u32_name >> 24) & 0xff;
+ name[ 1 ] = (u32_name >> 16) & 0xff;
+ name[ 2 ] = (u32_name >> 8) & 0xff;
+ name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 4 ] = '\0';
+ }
+ } else {
+ u32_name = rtems_build_name('I', 'N', 'T', 'R');
+ name[ 0 ] = (u32_name >> 24) & 0xff;
+ name[ 1 ] = (u32_name >> 16) & 0xff;
+ name[ 2 ] = (u32_name >> 8) & 0xff;
+ name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 4 ] = '\0';
+ }
+
+ fprintf(stdout, "0x%08x %4s 0x%08x 0x%08x %8d %8d\n",
+ the_thread ? the_thread->Object.id : ~0,
+ name,
+ (uint32_t ) stack->area,
+ (uint32_t ) stack->area + (uint32_t ) stack->size - 1,
+ size,
+ used
+ );
+}
+
+/*PAGE
+ *
+ * Stack_check_Fatal_extension
+ */
+
+void Stack_check_Fatal_extension(
+ Internal_errors_Source source,
+ boolean is_internal,
+ uint32_t status
+)
+{
+#ifndef DONT_USE_FATAL_EXTENSION
+ if (status == 0)
+ Stack_check_Dump_usage();
+#endif
+}
+
+
+/*PAGE
+ *
+ * Stack_check_Dump_usage
+ */
+
+void Stack_check_Dump_usage( void )
+{
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ uint32_t hit_running = 0;
+ Objects_Information *information;
+
+ if (stack_check_initialized == 0)
+ return;
+
+ fprintf(stdout,"Stack usage by thread\n");
+ fprintf(stdout,
+ " ID NAME LOW HIGH AVAILABLE USED\n"
+ );
+
+ for ( api_index = 1 ;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+ Stack_check_Dump_threads_usage( the_thread );
+ if ( the_thread == _Thread_Executing )
+ hit_running = 1;
+ }
+ }
+ }
+
+ if ( !hit_running )
+ Stack_check_Dump_threads_usage( _Thread_Executing );
+
+ /* dump interrupt stack info if any */
+ Stack_check_Dump_threads_usage((Thread_Control *) -1);
+}
diff --git a/cpukit/libmisc/stackchk/internal.h b/cpukit/libmisc/stackchk/internal.h
new file mode 100644
index 0000000000..c437eb94c1
--- /dev/null
+++ b/cpukit/libmisc/stackchk/internal.h
@@ -0,0 +1,95 @@
+/* internal.h
+ *
+ * This include file contains internal information
+ * for the RTEMS stack checker.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INTERNAL_STACK_CHECK_h
+#define __INTERNAL_STACK_CHECK_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure is used to fill in and compare the "end of stack"
+ * marker pattern.
+ * pattern area must be a multiple of 4 words.
+ */
+
+#ifdef CPU_STACK_CHECK_SIZE
+#define PATTERN_SIZE_WORDS (((CPU_STACK_CHECK_SIZE / 4) + 3) & ~0x3)
+#else
+#define PATTERN_SIZE_WORDS (4)
+#endif
+
+#define PATTERN_SIZE_BYTES (PATTERN_SIZE_WORDS * sizeof(uint32_t ))
+
+typedef struct {
+ uint32_t pattern[ PATTERN_SIZE_WORDS ];
+} Stack_check_Control;
+
+/*
+ * The pattern used to fill the entire stack.
+ */
+
+#define BYTE_PATTERN 0xA5
+#define U32_PATTERN 0xA5A5A5A5
+
+/*
+ * Stack_check_Create_extension
+ */
+
+boolean Stack_check_Create_extension(
+ Thread_Control *running,
+ Thread_Control *the_thread
+);
+
+/*
+ * Stack_check_Begin_extension
+ */
+
+void Stack_check_Begin_extension(
+ Thread_Control *the_thread
+);
+
+/*
+ * Stack_check_Switch_extension
+ */
+
+void Stack_check_Switch_extension(
+ Thread_Control *running,
+ Thread_Control *heir
+);
+
+/*
+ * Stack_check_Fatal_extension
+ */
+
+void Stack_check_Fatal_extension(
+ Internal_errors_Source source,
+ boolean is_internal,
+ uint32_t status
+);
+
+/*
+ * Stack_check_Dump_usage
+ */
+
+void Stack_check_Dump_usage( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/stackchk/stackchk.h b/cpukit/libmisc/stackchk/stackchk.h
new file mode 100644
index 0000000000..efe4ce9803
--- /dev/null
+++ b/cpukit/libmisc/stackchk/stackchk.h
@@ -0,0 +1,82 @@
+/* stackchk.h
+ *
+ * This include file contains information necessary to utilize
+ * and install the stack checker mechanism.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __STACK_CHECK_h
+#define __STACK_CHECK_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Stack_check_Initialize
+ */
+
+void Stack_check_Initialize( void );
+
+/*
+ * Stack_check_Dump_usage
+ */
+
+void Stack_check_Dump_usage( void );
+
+/*
+ * Stack_check_Create_extension
+ */
+
+boolean Stack_check_Create_extension(
+ Thread_Control *running,
+ Thread_Control *the_thread
+);
+
+/*
+ * Stack_check_Begin_extension
+ */
+
+void Stack_check_Begin_extension(
+ Thread_Control *the_thread
+);
+
+/*
+ * Stack_check_Switch_extension
+ */
+
+void Stack_check_Switch_extension(
+ Thread_Control *running,
+ Thread_Control *heir
+);
+
+/*
+ * Extension set definition
+ */
+
+#define STACK_CHECKER_EXTENSION \
+{ \
+ Stack_check_Create_extension, /* rtems_task_create */ \
+ 0, /* rtems_task_start */ \
+ 0, /* rtems_task_restart */ \
+ 0, /* rtems_task_delete */ \
+ Stack_check_Switch_extension, /* task_switch */ \
+ Stack_check_Begin_extension, /* task_begin */ \
+ 0, /* task_exitted */ \
+ 0 /* Stack_check_Fatal_extension */, /* fatal */ \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/untar/README b/cpukit/libmisc/untar/README
new file mode 100644
index 0000000000..24c9e7fa62
--- /dev/null
+++ b/cpukit/libmisc/untar/README
@@ -0,0 +1,26 @@
+#
+#
+# untar information
+#
+# Author: Jake Janovetz 7.6.1999
+#
+# $Id$
+#
+
+untar.c contains two procedures for extracting files from a UNIX
+tar file:
+
+ int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
+ int Untar_FromFile(char *tar_name);
+
+Untar_FromMemory(...) takes its input from a chunk of allocated memory.
+This is particularly useful when the tar is stored in Flash memory or
+comes from the FTP daemon by way of a hook.
+
+Untar_FromFile(...) is identical except the source is from an existing
+file. The fully qualified filename is passed through char *tar_name.
+
+
+
+BUGS: Please email janovetz@uiuc.edu
+-----
diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
new file mode 100644
index 0000000000..ad3b789f08
--- /dev/null
+++ b/cpukit/libmisc/untar/untar.c
@@ -0,0 +1,385 @@
+/* FIXME:
+ * 1. Symbolic links are not created.
+ * 2. Untar_FromMemory has printfs.
+ * 3. Untar_FromMemory uses FILE *fp.
+ * 4. How to determine end of archive?
+ *
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "untar.h"
+
+
+/**************************************************************************
+ * TAR file format:
+ *
+ * Offset Length Contents
+ * 0 100 bytes File name ('\0' terminated, 99 maxmum length)
+ * 100 8 bytes File mode (in octal ascii)
+ * 108 8 bytes User ID (in octal ascii)
+ * 116 8 bytes Group ID (in octal ascii)
+ * 124 12 bytes File size (s) (in octal ascii)
+ * 136 12 bytes Modify time (in octal ascii)
+ * 148 8 bytes Header checksum (in octal ascii)
+ * 156 1 bytes Link flag
+ * 157 100 bytes Linkname ('\0' terminated, 99 maxmum length)
+ * 257 8 bytes Magic ("ustar \0")
+ * 265 32 bytes User name ('\0' terminated, 31 maxmum length)
+ * 297 32 bytes Group name ('\0' terminated, 31 maxmum length)
+ * 329 8 bytes Major device ID (in octal ascii)
+ * 337 8 bytes Minor device ID (in octal ascii)
+ * 345 167 bytes Padding
+ * 512 (s+p)bytes File contents (s+p) := (((s) + 511) & ~511),
+ * round up to 512 bytes
+ *
+ * Checksum:
+ * int i, sum;
+ * char* header = tar_header_pointer;
+ * sum = 0;
+ * for(i = 0; i < 512; i++)
+ * sum += 0xFF & header[i];
+ *************************************************************************/
+
+#define LF_OLDNORMAL '\0' /* Normal disk file, Unix compatible */
+#define LF_NORMAL '0' /* Normal disk file */
+#define LF_LINK '1' /* Link to previously dumped file */
+#define LF_SYMLINK '2' /* Symbolic link */
+#define LF_CHR '3' /* Character special file */
+#define LF_BLK '4' /* Block special file */
+#define LF_DIR '5' /* Directory */
+#define LF_FIFO '6' /* FIFO special file */
+#define LF_CONFIG '7' /* Contiguous file */
+
+#define MAX_NAME_FIELD_SIZE 99
+
+#define MIN(a,b) ((a)>(b)?(b):(a))
+
+
+/**************************************************************************
+ * This converts octal ASCII number representations into an
+ * unsigned long. Only support 32-bit numbers for now.
+ *************************************************************************/
+static unsigned long
+octal2ulong(char *octascii, int len)
+{
+ int i;
+ unsigned long num;
+ unsigned long mult;
+
+ num = 0;
+ mult = 1;
+ for (i=len-1; i>=0; i--)
+ {
+ if ((octascii[i] < '0') || (octascii[i] > '9'))
+ {
+ continue;
+ }
+ num += mult*((unsigned long)(octascii[i] - '0'));
+ mult *= 8;
+ }
+ return(num);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromMemory *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a block of memory. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * unsigned char *tar_buf - Pointer to TAR buffer. *
+ * unsigned long size - Length of TAR buffer. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromMemory(unsigned char *tar_buf, unsigned long size)
+{
+ FILE *fp;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long ptr;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long file_size;
+ unsigned char linkflag;
+
+
+ ptr = 0;
+ while (1)
+ {
+ if (ptr + 512 > size)
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ /* Read the header */
+ bufr = &tar_buf[ptr];
+ ptr += 512;
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ file_size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ /* symlink(fname, linkname); */
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ nblocks = (((file_size) + 511) & ~511) / 512;
+ if ((fp = fopen(fname, "w")) == NULL)
+ {
+ fprintf(stdout,"Untar failed to create file %s\n", fname);
+ ptr += 512 * nblocks;
+ }
+ else
+ {
+ unsigned long sizeToGo = file_size;
+ unsigned long len;
+
+ /***************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the file_size rounded to the nearest 512-byte boundary.
+ **************************************************************/
+ for (i=0; i<nblocks; i++)
+ {
+ len = ((sizeToGo < 512L)?(sizeToGo):(512L));
+ n = fwrite(&tar_buf[ptr], 1, len, fp);
+ if (n != len)
+ {
+ fprintf(stdout,"Error during write\n");
+ break;
+ }
+ ptr += 512;
+ sizeToGo -= n;
+ }
+ fclose(fp);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+
+ return(retval);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromFile *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a TAR file. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * char *tar_name - TAR filename. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromFile(char *tar_name)
+{
+ int fd;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long size;
+ unsigned char linkflag;
+
+
+ retval = UNTAR_SUCCESSFUL;
+ bufr = (char *)malloc(512);
+ if (bufr == NULL)
+ {
+ return(UNTAR_FAIL);
+ }
+
+ fd = open(tar_name, O_RDONLY);
+ while (1)
+ {
+ /* Read the header */
+ /* If the header read fails, we just consider it the end
+ of the tarfile. */
+ if ((n = read(fd, bufr, 512)) != 512)
+ {
+ break;
+ }
+
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ int out_fd;
+
+ /******************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the size rounded to the nearest 512-byte boundary.
+ *****************************************************************/
+ nblocks = (((size) + 511) & ~511) / 512;
+
+ if ((out_fd = creat(fname, 0644)) == -1)
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ }
+ }
+ else
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ n = MIN(n, size - i*512);
+ write(out_fd, bufr, n);
+ }
+ close(out_fd);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+ free(bufr);
+ close(fd);
+
+ return(retval);
+}
diff --git a/cpukit/libmisc/untar/untar.h b/cpukit/libmisc/untar/untar.h
new file mode 100644
index 0000000000..69c4d41ddf
--- /dev/null
+++ b/cpukit/libmisc/untar/untar.h
@@ -0,0 +1,25 @@
+/*
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __UNTAR_H__
+#define __UNTAR_H__
+
+
+#define UNTAR_SUCCESSFUL 0
+#define UNTAR_FAIL 1
+#define UNTAR_INVALID_CHECKSUM 2
+#define UNTAR_INVALID_HEADER 3
+
+
+int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
+int Untar_FromFile(char *tar_name);
+
+
+#endif /* __UNTAR_H__ */