Applied patches from Tony.Thompson@arm.com to implement the Angel remote
authorNick Clifton <nickc@redhat.com>
Thu, 8 Jan 1998 11:12:39 +0000 (11:12 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 8 Jan 1998 11:12:39 +0000 (11:12 +0000)
debugging interface and resurrected associated RDI files.

54 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/configure.tgt
gdb/rdi-share/Makefile.in [new file with mode: 0644]
gdb/rdi-share/README.CYGNUS [new file with mode: 0644]
gdb/rdi-share/adp.h [new file with mode: 0644]
gdb/rdi-share/adperr.h [new file with mode: 0644]
gdb/rdi-share/angel.h [new file with mode: 0644]
gdb/rdi-share/ardi.c [new file with mode: 0644]
gdb/rdi-share/ardi.h [new file with mode: 0644]
gdb/rdi-share/armdbg.h [new file with mode: 0644]
gdb/rdi-share/buffers.h [new file with mode: 0644]
gdb/rdi-share/bytesex.c [new file with mode: 0644]
gdb/rdi-share/bytesex.h [new file with mode: 0644]
gdb/rdi-share/chandefs.h [new file with mode: 0644]
gdb/rdi-share/channels.h [new file with mode: 0644]
gdb/rdi-share/chanpriv.h [new file with mode: 0644]
gdb/rdi-share/configure.in [new file with mode: 0644]
gdb/rdi-share/crc.c [new file with mode: 0644]
gdb/rdi-share/crc.h [new file with mode: 0644]
gdb/rdi-share/dbg_conf.h [new file with mode: 0644]
gdb/rdi-share/dbg_cp.h [new file with mode: 0644]
gdb/rdi-share/dbg_hif.h [new file with mode: 0644]
gdb/rdi-share/dbg_rdi.h [new file with mode: 0644]
gdb/rdi-share/devclnt.h [new file with mode: 0644]
gdb/rdi-share/devices.h [new file with mode: 0644]
gdb/rdi-share/devsw.c [new file with mode: 0644]
gdb/rdi-share/devsw.h [new file with mode: 0644]
gdb/rdi-share/drivers.c [new file with mode: 0644]
gdb/rdi-share/drivers.h [new file with mode: 0644]
gdb/rdi-share/endian.h [new file with mode: 0644]
gdb/rdi-share/etherdrv.c [new file with mode: 0644]
gdb/rdi-share/ethernet.h [new file with mode: 0644]
gdb/rdi-share/host.h [new file with mode: 0644]
gdb/rdi-share/hostchan.c [new file with mode: 0644]
gdb/rdi-share/hostchan.h [new file with mode: 0644]
gdb/rdi-share/hsys.c [new file with mode: 0644]
gdb/rdi-share/hsys.h [new file with mode: 0644]
gdb/rdi-share/logging.c [new file with mode: 0644]
gdb/rdi-share/logging.h [new file with mode: 0644]
gdb/rdi-share/msgbuild.c [new file with mode: 0644]
gdb/rdi-share/msgbuild.h [new file with mode: 0644]
gdb/rdi-share/params.c [new file with mode: 0644]
gdb/rdi-share/params.h [new file with mode: 0644]
gdb/rdi-share/rx.c [new file with mode: 0644]
gdb/rdi-share/rxtx.h [new file with mode: 0644]
gdb/rdi-share/serdrv.c [new file with mode: 0644]
gdb/rdi-share/serpardr.c [new file with mode: 0644]
gdb/rdi-share/sys.h [new file with mode: 0644]
gdb/rdi-share/tx.c [new file with mode: 0644]
gdb/rdi-share/unixcomm.c [new file with mode: 0644]
gdb/rdi-share/unixcomm.h [new file with mode: 0644]
gdb/remote-rdi.c [new file with mode: 0644]
gdb/remote-rdp.c

index 4a920227a8815829b5a38057b33d62d8e75ddd2b..fe86b0504c5ff57d9039aff14f95b39fdcad6ef8 100644 (file)
@@ -1,3 +1,15 @@
+Thu Jan  8 11:03:59 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * remote-rdp.c: Applied patches submitted by Tony.Thompson@arm.com
+       to implement the Angel remote debugging interface.
+
+       * Makefile.in: Add build rules for remote-rdi.c and
+       rdi-share/libangsd.a
+       
+       * configure.tgt: Updated from source on branch.
+       * config/arm/tm-arm.h: Updated from source on branch.
+       * arm-tdep.c: Updated from source on branch.
+
 Mon Jan  5 20:21:59 1998  Mark Alexander  <marka@cygnus.com>
 
        * monitor.h (MO_PRINT_PROGRAM_OUTPUT): Define.
index 7f6e1de8807aaa6b1f44c3ec7c339a70a2ccc74a..c56503f9952f0fa9a08b17ce8b4f479aa7e28d5d 100644 (file)
@@ -163,6 +163,10 @@ WIN32LIBS = @WIN32LIBS@
 ENABLE_GDBTK= @ENABLE_GDBTK@
 ENABLE_IDE= @ENABLE_IDE@
 
+LIBGUI = ../libgui/src/libgui.a
+
+GUI_CFLAGS_X = -I$(srcdir)/../libgui/src
+
 IDE_CFLAGS_X = -I$(srcdir)/../libide/src \
   `if [ x"$(ENABLE_IDE)" != x ] ; then \
     echo -DIDE -I$(srcdir)/../ilu/runtime/mainloop;\
@@ -179,7 +183,7 @@ IDE_DEPS = ../ilu/runtime/mainloop/libilu-Tk.a \
        ../ilu/runtime/c/libilu-c.a ../ilu/runtime/kernel/libilu.a
 
 IDE=$(IDE_X) 
-IDE_CFLAGS=$(IDE_CFLAGS_X)
+IDE_CFLAGS=$(GUI_CFLAGS_X) $(IDE_CFLAGS_X)
 #end-sanitize-gdbtk
 
 ENABLE_CFLAGS= @ENABLE_CFLAGS@
@@ -1359,6 +1363,19 @@ remote-adapt.o: remote-adapt.c $(wait_h) $(defs_h) $(gdbcore_h) \
 remote-array.o: remote-array.c $(wait_h) $(defs_h) $(gdbcore_h) target.h \
       gdb_string.h $(command_h) serial.h monitor.h $(remote_utils_h)
 
+remote-rdi.o: remote-rdi.c $(wait_h) $(defs_h) $(gdbcore_h) \
+       $(inferior_h) gdb_string.h
+
+rdi-share/libangsd.a:  force
+       @dir=rdi-share; \
+       if [ -f ./$${dir}/Makefile ] ; then \
+         r=`pwd`; export r; \
+         srcroot=`cd $(srcdir); pwd`; export srcroot; \
+         (cd $${dir}; $(MAKE) $(FLAGS_TO_PASS) all); \
+       else \
+         true; \
+       fi
+
 remote-rdp.o: remote-rdp.c $(wait_h) $(defs_h) $(gdbcore_h) \
        $(inferior_h) gdb_string.h
 
index 6739d08fe1e869421b205d31d60d1d815dd6071a..3c29d73ced66b87946b751eda922f129009c21d9 100644 (file)
@@ -48,7 +48,17 @@ alpha-*-linux*)              gdb_target=alpha-linux ;;
 
 arc-*-*)               gdb_target=arc ;;
 
-arm-*-* | thumb-*-*)   gdb_target=arm ;;
+arm-*-* | thumb-*-*)   gdb_target=arm
+
+                       # rdi doesn't work for wingdb yet
+                       case $gdb_host in
+                       windows) ;;
+                       *)
+                           configdirs="$configdirs rdi-share"
+                           CONFIG_OBS="$CONFIG_OBS remote-rdi.o rdi-share/libangsd.a"
+                           ;;
+                       esac
+                       ;;
 
 c1-*-*)                        gdb_target=convex ;;
 c2-*-*)                        gdb_target=convex ;;
diff --git a/gdb/rdi-share/Makefile.in b/gdb/rdi-share/Makefile.in
new file mode 100644 (file)
index 0000000..45a9204
--- /dev/null
@@ -0,0 +1,165 @@
+prefix = /usr/local
+
+program_transform_name =
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+tooldir = $(libdir)/$(target_alias)
+
+datadir = $(prefix)/share
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+
+ARM_RELEASE='"Berkeley Licence for Cygnus"'
+
+SHELL = /bin/sh
+
+INSTALL = `cd $(srcdir)/../..;pwd`/install.sh -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
+INSTALL_XFORM1 = $(INSTALL_XFORM) -b=.1
+
+AR = ar
+AR_FLAGS = qv
+RANLIB = ranlib
+
+LD = ld
+
+# If you are compiling with GCC, make sure that either 1) You use the
+# -traditional flag, or 2) You have the fixed include files where GCC
+# can reach them.  Otherwise the ioctl calls in inflow.c
+# will be incorrectly compiled.  The "fixincludes" script in the gcc
+# distribution will fix your include files up.
+#CC=cc
+#CC=gcc -traditional
+GCC=gcc
+
+# Directory containing source files.  Don't clean up the spacing,
+# this exact string is matched for by the "configure" script.
+srcdir = .
+
+# It is also possible that you will need to add -I/usr/include/sys to the
+# CFLAGS section if your system doesn't have fcntl.h in /usr/include (which 
+# is where it should be according to Posix).
+
+# Set this up with gcc if you have gnu ld and the loader will print out
+# line numbers for undefinded refs.
+#CC-LD=gcc -static
+CC-LD=${CC}
+
+# All the includes used for CFLAGS and for lint.
+# -I. for config files.
+# -I${srcdir} possibly for regex.h also.
+# -I${srcdir}/config for more generic config files.
+INCLUDE_CFLAGS = -I. -I${srcdir}
+
+# M{H,T}_CFLAGS, if defined, has host- and target-dependent CFLAGS
+# from the config/ directory.
+GLOBAL_CFLAGS = ${MT_CFLAGS} ${MH_CFLAGS} -DRETRANS -DARM_RELEASE=$(ARM_RELEASE)
+#PROFILE_CFLAGS = -pg
+
+# CFLAGS is specifically reserved for setting from the command line
+# when running make.  I.E.  "make CFLAGS=-Wmissing-prototypes".
+CFLAGS = -g
+
+# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+INTERNAL_CFLAGS = ${CFLAGS} ${GLOBAL_CFLAGS} ${PROFILE_CFLAGS} \
+       ${BFD_CFLAGS} ${MMALLOC_CFLAGS} ${INCLUDE_CFLAGS}
+
+# LDFLAGS is specifically reserved for setting from the command line
+# when running make.
+
+# Host and target-dependent makefile fragments come in here.
+####
+# End of host and target-dependent makefile fragments
+
+# All source files that go into linking GDB remote server.
+
+SFILES = $(srcdir)/
+
+DEPFILES = 
+
+SOURCES = $(SFILES) $(ALLDEPFILES)
+TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS} 
+
+OBS = hostchan.o drivers.o devsw.o rx.o tx.o params.o hsys.o crc.o \
+logging.o msgbuild.o ardi.o serdrv.o serpardr.o etherdrv.o bytesex.o \
+unixcomm.o
+
+# Prevent Sun make from putting in the machine type.  Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+       ${CC} -c ${INTERNAL_CFLAGS} $<
+
+all: libangsd.a
+
+libangsd.a: $(OBS)
+        rm -f libangsd.a
+        $(AR) $(AR_FLAGS) libangsd.a $(OBS)
+        $(RANLIB) libangsd.a
+
+# Traditionally "install" depends on "all".  But it may be useful
+# not to; for example, if the user has made some trivial change to a 
+# source file and doesn't care about rebuilding or just wants to save the
+# time it takes for make to check that all is up to date.
+# install-only is intended to address that need.
+install: all install-only
+install-only: 
+
+uninstall:
+
+installcheck:
+check:
+info dvi:
+install-info:
+clean-info:
+
+config.status:
+       @echo "You must configure rdi-share.  Look at the README file for details."
+       @false
+
+clean:
+       rm -f *.o ${ADD_FILES} *~
+       rm -f gdbserver core make.log
+
+distclean: clean
+       rm -f config.status
+       rm -f Makefile
+
+maintainer-clean realclean: clean
+       rm -f config.status
+       rm -f Makefile
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+       $(SHELL) ./config.status
+
+force:
+
+# GNU Make has an annoying habit of putting *all* the Makefile variables
+# into the environment, unless you include this target as a circumvention.
+# Rumor is that this will be fixed (and this target can be removed)
+# in GNU Make 4.0.
+.NOEXPORT:
+
+# GNU Make 3.63 has a different problem: it keeps tacking command line
+# overrides onto the definition of $(MAKE).  This variable setting
+# will remove them.
+MAKEOVERRIDES=
+
+## This is ugly, but I don't want GNU make to put these variables in
+## the environment.  Older makes will see this as a set of targets
+## with no dependencies and no actions.
+unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET :
+
+# This is the end of "Makefile.in".
diff --git a/gdb/rdi-share/README.CYGNUS b/gdb/rdi-share/README.CYGNUS
new file mode 100644 (file)
index 0000000..4bf06c9
--- /dev/null
@@ -0,0 +1,6 @@
+This is a version of ARM's RDI library which has been been put under a
+free software license.
+
+See ARM's Software Development Tools Reference Manual (Remote
+Debugging chapter), and the file gdb/remote-rdi.c for information
+about how to use it.
diff --git a/gdb/rdi-share/adp.h b/gdb/rdi-share/adp.h
new file mode 100644 (file)
index 0000000..099fa4d
--- /dev/null
@@ -0,0 +1,2528 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *
+ * INTRODUCTION
+ * ------------
+ * The early RDP message definitions were held in an ARM Ltd "armdbg"
+ * source file. Since the relevant header files were not exported
+ * publicly as part of an ARM Ltd core tools release, it was a problem
+ * for developers manipulating the target side of the protocol.
+ *
+ * For Angel, this new (ANSI 'C' clean) header file defines the ADP
+ * protocol. The header should be useable by both host and target
+ * systems, thus avoiding problems that can arise from duplicate
+ * definitions. Care has been taken in the construction of this header
+ * file to avoid any host/target differences.
+ *
+ * MESSAGE FORMAT
+ * --------------
+ * Format of the "data" section of debug and boot agent messages. This is
+ * the standard ADP (Angel Debug Protocol) message format:
+ *
+ *  unsigned32 reason     - Main debug reason code.
+ *  unsigned32 debugID    - Information describing host debug world;
+ *                        - private to host and used in any target initiated
+ *                          messages.
+ *  unsigned32 OSinfo1    \ Target OS information to identify process/thread
+ *  unsigned32 OSinfo2    / memory/world, etc. These two fields are target
+ *                          defined.
+ *  byte       args[n]    - Data for message "reason" code.
+ *
+ * NOTE: The message format is the same for single threaded debugging,
+ * except that the "OSinfo" fields should be -1 (0xFFFFFFFF). Even
+ * single-threaded debugging *MAY* have different host specified
+ * debugID values, so the Angel debug system will preserve the "debugID"
+ * information for replies, and the relevant asynchronous target-to-host
+ * messages. The "debugID" is defined by the host-end of the
+ * protocol, and is used by the host to ensure that messages are
+ * routed to the correct handler program/veneer.
+ *
+ * The reason there are two target specified "OSinfo" words is because
+ * thread identifiers may not be unique when processes/tasks have
+ * private virtual address spaces. It allows more flexibility when
+ * supporting multi-threaded or O/S aware debugging.
+ *
+ * NOTE: The reason that there is no "size" information, is that the
+ * message IDs themselves encode the format of any arguments. Also it
+  * would be a duplication of information used by the physical
+ * transport layer (which is distinct from this logical message
+ * layer). Any routing of messages through programs, hosts,
+ * etc. should be performed at the physical layer, or the boundaries
+ * between physical layers. i.e. packet received on socket in host,
+ * and transferred to serial packet for passing on down the line.
+ *
+ * NOTE: Pointers aren't passed in messages because they are dangerous in
+ * a multi-threaded environment.
+ *
+ * ADP REASON CODE
+ * ---------------
+ * The message reason codes contain some information that ties them to
+ * the channel and direction that the message will be used with. This
+ * will ensure that even if the message "#define name" is not
+ * completely descriptive, the message reason code is.
+ *
+ *      b31    = direction. 0=Host-to-Target; 1=Target-to-Host;
+ *      b30-28 = debug agent multi-threaded control (see below)
+ *      b27-24 = reserved. should be zero.
+ *      b23-16 = channelid. The fixed Angel channel number
+ *               (see "channels.h").
+ *      b15-0  = message reason code.
+ *
+ * It is unfortunate that to aid the error-checking capabilities of
+ * the Angel communications we have changed the message numbers from
+ * the original ARM Ltd RDP. However this also has benefits, in that
+ * the Angel work is meant to be a clean break.
+ *
+ * However, it isn't so bad since even though the numbers are
+ * different, the majority of the reason codes have exactly the same
+ * functionality as the original RDP messages.
+ *
+ * NOTES
+ * -----
+ * It would be ideal to use "rpcgen" (or some equivalent) to
+ * automatically maintain compatibility between the target and host
+ * ends of the protocol. However, ARM Ltd expressed that the message
+ * handling should be hand-coded, to avoid dependance on external
+ * tools.
+ *
+ * All other channels have undefined data formats and are purely
+ * application defined. The C library "_sys_" support will provide a
+ * veneer to perform message block operations as required.
+ *
+ * It is IMPLIED that all of the ADP messages will fit within the
+ * buffer DATASIZE. This has a minimum value, calculated from
+ * BUFFERMINSIZE.
+ *
+ * All messages are passed and received to the channel system in little
+ * endian order (ie. use little endian order when writing a word as
+ * a sequence of bytes within a message).
+ *
+ * A reply / acknowledgement to an ADP message is always sent and has the
+ * same reason code as the original except that the TtoH / HtoT bit is
+ * reversed.  This makes it simple to check that the reply really
+ * is a reply to the message which was just sent!  [Boot Channel messages
+ * also require that this protocol is used].
+ */
+
+#ifndef angel_adp_h
+#define angel_adp_h
+
+#include "chandefs.h"
+
+
+/*
+ * Buffer minimum sizes
+ */
+
+/* the minimum target internal size */
+#define ADP_BUFFER_MIN_SIZE (256)
+
+/* a word is always reserved for internal use in the target */
+#define ADP_BUFFER_MAX_INTERNAL (sizeof(word))
+
+/* the minimum available data portion */
+#define ADP_BUFFER_MIN_DATASIZE \
+    (ADP_BUFFER_MIN_SIZE - ADP_BUFFER_MAX_INTERNAL - CHAN_HEADER_SIZE)
+
+/*
+ * the space taken up by the standard ADP header
+ * (reason, debugID, OSinfo1, OSinfo2)
+ */
+#define ADP_DEFAULT_HEADER_SIZE (4*sizeof(word))
+
+
+/* 8bit ADP version identification */
+#define ADPVSN  (0x03)
+/* This value can be used to identify the protocol version supported
+ * by target or host systems. This version number should only be
+ * changed if the protocol undergoes a non-backward compatible
+ * change. It should *NOT* be used to reflect extensions to the
+ * protocol. Such extensions can be added to the existing protocol
+ * version by allocating new reason codes, and by extending the
+ * ADP_Info message to identify new features.
+ */
+
+/* The following value is used in the OSinfo fields for
+ * single-threaded messages, or where the host wants to alter the
+ * global CPU state. NOTE: The "debugID" field should always be
+ * defined by the host, and returned in target initiated messages. The
+ * only exception to this rule is the ADP_Booted message at the
+ * start-of-day.
+ */
+#define ADP_HandleUnknown (-1)
+
+/******************************************************************
+ *
+ * ADP reason code subfields
+ *
+ */
+
+/* The following bits are used to describe the basic direction of
+ * messages. This allows some extra checking of message validity to be
+ * performed, as well as providing a description of the message that
+ * may not be available in the "cpp" macro:
+ */
+#define HtoT    ((unsigned)0 << 31)     /* Host-to-Target message */
+#define TtoH    ((unsigned)1 << 31)     /* Target-to-Host message */
+
+/* The following bits are used to control how the target system
+ * executes whilst processing messages. This allows for O/S specific
+ * host-based debug programs to interrogate system structures whilst
+ * ensuring that the access is atomic within the constraints imposed
+ * by the target O/S.
+ *
+ * NOTE: That only the channel is inserted into the reason code
+ * automatically.  Thus both direction and multi thread control bits
+ * must be added by the host / target.
+ */
+/* Disable FIQ whilst processing message */
+#define DisableFIQ              (1 << 30)
+/* Disable IRQ whilst processing message */
+#define DisableIRQ              (1 << 29)
+/* Disable O/S pre-emption whilst processing message */
+#define DisablePreemption       (1 << 28)
+
+/* The channel identification number is held in the reason code as a
+ * check:
+ */
+#define ADPCHANNEL(b)   (((b) & 0xFF) << 16)
+
+/* The following macro constructs the reason code number, from the
+ * various fields - note that the direction is NOT inlcuded since
+ * this depends on whether the Host or Target system is including
+ * this file!
+ */
+#define ADPREASON(c,r)        (ADPCHANNEL(c) | ((r) & 0xFFFF))
+
+/* This macros is used when constructing manifests for sub-reason
+ * codes. At the moment it is identical to the main reason macro. If
+ * desired we could add a new bit that explicitly identifies the value
+ * as a sub-reason code, where the corresponding bit in the main
+ * message ID would be zero.
+ */
+#define ADPSUBREASON(c,r)     (ADPCHANNEL(c) | ((r) & 0xFFFF))
+
+/* All other undefined bits are reserved, and should be zero. */
+
+
+
+/*****************************************************************
+ *
+ * channel_BOOT messages
+ *
+ */
+
+/* The BOOT agent only supports a few messages. They are used purely
+ * to control the "start-of-day" connection to a host program. All
+ * Angel systems with host communications *MUST* provide the BOOT
+ * agent, even if they don't have support for either the single- or
+ * multi-threaded debug agents.
+ *
+ * The way the BOOT channel will be used on startup will be as follows:
+ *
+ * a) Target board is powered up before host debugger is invoked
+ *
+ * After switching on the target and initialisation is completed the
+ * target will send an ADP_Booted or ADP_Reset message.  The debugger
+ * has not been started yet so this message will not be received.  In
+ * a serial world this makes it important that any buffers on the host
+ * side are flushed during initialisation of the debugger, and in an
+ * Ethernet world it makes it important that the target can cope with the
+ * message not being received.
+ *
+ * Eventually the Debugger will be started up and will send an
+ * ADP_Reboot or ADP_Reset request.  The target will respond to this with
+ * an ADP_Reboot or ADP_Reset acknowldege and will then reboot, finally
+ * sending an ADP_Rebooted when it has done all it needs to do (very little
+ * in the case of ADP_Reset, but completely rebooting in the case of
+ * ADP_Reboot).  Note that it is important that an ADP_Rebooted message is
+ * sent so that the Debugger does not attempt to send any data after it has
+ * made a request to ADP_Reboot and before it receives an ADP_Rebooted, as
+ * data can be lost be the target during this time.
+ *
+ * The target and host are now ready to start a debug session.
+ *
+ * b) Target board is powered up after host debugger is invoked
+ *
+ * The debugger will send an ADP_Reboot or ADP_Reset request, but will
+ * receive no reply until the target is powered up.
+/ *
+ * When the target is powered up then it will send an ADP_Rebooted
+ * message to the debugger.  The debugger should accept this message
+ * even though it has received no ADP_Reboot or ADP_Reset acknowldege message
+ * from the target.
+ *
+ * The target and host are now ready to start a debug session.
+ *
+ *
+ * If at any point during the bootup sequence and ADP messages are
+ * sent down the S_DBG channel then they should be responded to with a
+ * RDI_NotInitialised error. [This should never happen however].
+ *
+ * An ADP_Boot or ADP Rebooted message should be accepted at
+ * any point, since it is possible for a catastrophe to occur (such as
+ * disconnecteing the host and target during a debug message) which
+ * requires that one or other end be reset.
+ *
+ */
+
+/*
+ * A list of parameter types - for now just baud rate
+ */
+typedef enum ADP_Parameter {
+    AP_PARAMS_START = 0xC000,
+    AP_BAUD_RATE = AP_PARAMS_START,
+    /* extra parameters go in here */
+#ifdef TEST_PARAMS
+    AP_CAFE_MENU,               /* extra just for testing */
+#endif
+    AP_PARAMS_END
+} ADP_Parameter;
+
+#define AP_NUM_PARAMS (AP_PARAMS_END - AP_PARAMS_START)
+
+/*
+ * Parameter types should have associated semantics which can be represented
+ * within one word per parameter, or an associated enum for choices.
+ *
+ * AP_BAUD_RATE: the word contains the exact baud rate, eg. 9600, 38400.
+ */
+
+/* this is not strictly necessary, but it's an example */
+typedef enum ADP_BaudRate {
+    AB_9600  =  9600,
+    AB_19200 = 19200,
+    AB_38400 = 38400,
+    AB_57600 = 57600,
+    AB_115200 = 115200
+} ADP_BaudRate;
+
+#define AB_NUM_BAUD_RATES 5     /* this is more useful, for sizing arrays */
+
+/* This must be set to the max number of options per parameter type */
+#define AP_MAX_OPTIONS (AB_NUM_BAUD_RATES)
+
+
+#define ADP_Booted      ADPREASON(CI_TBOOT,0)
+/* This message is sent by the target after the Angel system has been
+ * initialised.  This message also contains information describing the
+ * Angel world. The information can then be used to check that the
+ * target debug agent and source debugger are compatible.
+ *
+ * Message arguments:
+ *      word    Angel message default buffer size.
+ *      word    Angel message large buffer size (may be same as default)
+ *      word    Angel version ; inc. type (e.g. boot ROM) See (1)
+ *      word    ADP version.  See (2)
+ *      word    ARM Architecture info See (3)
+ *      word    ARM CPU information ; including target endianness. See (4)
+ *      word    Target hardware status. See (5)
+ *      word    Number of bytes in banner message
+ *      bytes   Startup banner message (single-threaded readable
+ *              descriptive text - NOT NULL terminated).
+ *
+ * Reply:
+ *      word    status
+ *
+ *      'status' returns RDIError_NoError for success, and otherwise
+ *      indicates an error.
+ */
+
+/* Angel version word [Reference(1)] : */
+/* Angel version number is a 16bit BCD value */
+#define ADP_ANGELVSN_MASK           (0x0000FFFF)
+#define ADP_ANGELVSN_SHIFT          (0)
+
+/* Type of Angel system */
+#define ADP_ANGELVSN_TYPE_MASK      (0x00FF0000)
+#define ADP_ANGELVSN_TYPE_SHIFT     (16)
+
+typedef enum {
+ ADP_AngelType_bootROM, /* Simple ROM system providing download capability */
+ ADP_AngelType_appROM,  /* ROM based application */
+ ADP_AngelType_appDLOAD,/* Downloaded Angel based application */
+ ADP_AngelType_Last     /* Unknown type. This typedef can be extended */
+                        /* but if the host and target vsns differ */
+                        /* Then one will spot that it dies not understand */
+} ADP_Angel_Types ;     /* this field and can whinge appropriately */
+
+/* First unknown ADP_AngelType */
+#define ADP_ANGELVSN_UNKTYPE_MASK   (0xFF000000)
+#define ADP_ANGELVSN_UNKYPE_SHIFT   (24)
+
+/* Currently only 8 bits are used in the word: */
+/* ADP protocol supported by target [Reference (2)] */
+#define ADP_ANGELVSN_ADP_MASK       (0x000000FF)
+#define ADP_ANGELVSN_ADP_SHIFT      (0)
+
+/* ARM Architecture info: [Reference (3)] */
+/* ARM Architecture Verson of target CPU */
+#define ADP_ARM_ARCH_VSN_MASK       (0x000000FF)
+#define ADP_ARM_ARCH_VSN_SHIFT      (0)
+/* Does the processor support the Thumb Instruction Set */
+#define ADP_ARM_ARCH_THUMB          (0x80000000)
+/* Does the processor support Long Multiplies */
+#define ADP_ARM_ARCH_LONGMUL        (0x40000000)
+/* All other flags are current undefined, and should be zero. */
+
+/* The following flags describe the feature set of the processor: */
+/* Set if cpu supports little-endian model [Reference (4)] */
+#define ADP_CPU_LE              (1 << 0)
+/* Set if cpu supports big-endian model */
+#define ADP_CPU_BE              (1 << 1)
+/* Set if processor has a cache */
+#define ADP_CPU_CACHE           (1 << 2)
+/* Set if processor has a MMU */
+#define ADP_CPU_MMU             (1 << 3)
+/* All other flags are current undefined, and should be zero. */
+
+/* The following flags reflect current Target hardware status: */
+/* [Reference (5)] */
+/* 0 = no MMU or MMU off; 1 = MMU on */
+#define ADP_CPU_MMUOn           (1 << 29)
+/* 0 = no cache or cache off; 1 = cache on */
+#define ADP_CPU_CacheOn         (1 << 30)
+/* 0 = little-endian; 1 = big-endian */
+#define ADP_CPU_BigEndian       (1U << 31)
+/* All other flags are current undefined, and should be zero. */
+
+
+#ifdef LINK_RECOVERY
+
+#define ADP_TargetResetIndication       ADPREASON(CI_TBOOT, 1)
+/*
+ * If parameter negotiation is enabled at the target, it configures itself
+ * to various likely parameter settings and sends this message at each
+ * configuration.  The message describes the default settings, and after
+ * sending at each configuration the target sets itself to the defaults
+ * it has just broadcast, to await either an ack on TBOOT or a request
+ * or reset indication on HBOOT.
+ *
+ * If the host receives this message successfully, it should reset to the
+ * indicated parameters and send a reply.
+ *
+ * Message arguments:
+ *      word    status                   (always 0, makes body same as
+ *                                        ADP_ParamNegotiate response)
+ *      word    n-parameters
+ *      n-parameters * {
+ *              word    ADP_Parameter
+ *              word    parameter-value
+ *      }
+ *
+ * Reply:
+ *      -       empty acknowledgement
+ */
+
+#endif /* def LINK_RECOVERY */
+
+typedef enum ADP_Boot_Ack {
+    AB_NORMAL_ACK,              /* will comply, immediate booted message */
+    AB_LATE_ACK,                /* will comply, late startup */
+    AB_ERROR                    /* cannot comply */
+} ADP_Boot_Ack;
+
+/* If the host sets neither of these in the word sent on a Reset / Reboot
+ * then it doesn;t care about the endianess of the target
+ */
+#define ADP_BootHostFeature_LittleEnd 0x80000000
+#define ADP_BootHostFeature_BigEnd    0x40000000
+
+#define ADP_Reboot      ADPREASON(CI_HBOOT,2)
+/* This message is sent when the host wants the target system to be
+ * completely reset, back to the boot monitor Angel. This is the
+ * method of the host forcing a cold-reboot.
+ * Note that an acknowledgement message will be sent immediately and
+ * that this must be sent before the target can reset.
+ *
+ * The parameter to this function is a bitset of host supported
+ * features. (in fact the same as ADP_Reset below.  This can be used by
+ * the target system to avoid using debug channel bandwidth raising
+ * messages that will be ignored by the host.
+ *
+ * Parameters:
+ *      word    host supported features (see above)
+ *
+ * Reply:
+ *      word    status, one of enum ADP_Boot_Ack above.
+ *
+ * Currently there are no such features defined, so the word indicating
+ * host supported features should be set to 0.
+ */
+
+
+
+#define ADP_Reset       ADPREASON(CI_HBOOT,3)
+/* This message is a request from the host, which should eventually
+ * result in the "ADP_Booted" message being sent by the target.
+ * Note that an acknowledgement message will be sent immediately and
+ * that this must be sent before the target can reset.
+ * This reset message is *ALWAYS* treated as a warm boot, with the target
+ * preserving as much state as possible.
+ *
+ * The parameter to this function is a bitset of host supported
+ * features. This can be used by the target system to avoid using
+ * debug channel bandwitdth raising messages that will be ignored by
+ * the host.
+ *
+ * Parameters:
+ *      word    host supported features (see above)
+ *
+ * Reply:
+ *      word    status, one of enum ADP_Boot_Ack above.
+ *
+ * Currently there are no such features defined, so the word indicating
+ * host supported features should be set to 0.
+ */
+
+
+#ifdef LINK_RECOVERY
+
+#define ADP_HostResetIndication         ADPREASON(CI_HBOOT, 4)
+/*
+ * This is as for ADP_TargetResetIndication, but is sent by the host when
+ * it first starts up in case the target is listening at a non-default
+ * setting.  Having sent at various configurations, the host then listens
+ * at the defaults it has just broadcast, to await either an ack on HBOOT
+ * or a reset indication on TBOOT.
+ *
+ * For arguments and reply, see ADP_TargetResetIndication.
+ */
+
+#endif /* def LINK_RECOVERY */
+
+
+#define ADP_ParamNegotiate              ADPREASON(CI_HBOOT, 5)
+/*
+ * The host sends this messages to negotiate new parameters with the target.
+ * For each parameter the host specifies a range of possibilities, starting
+ * with the most favoured.  All possible combinations of parameters
+ * must be valid.
+ *
+ * If the target can operate at a combination of the offered parameters,
+ * it will reply with the parameters it is willing to use.  AFTER sending
+ * the reply, the target switches to this combination.  On receiving the
+ * reply, the host will switch to the new combination and send a LinkCheck
+ * message (see below).
+ *
+ * If the target cannot operate at any combination of the offered parameters,
+ * it will reply with an error status.
+ *
+ * Message arguments:
+ *      word    n-parameter-blocks
+ *      n-parameter-blocks * {
+ *              word    ADP_Parameter
+ *              word    n-options
+ *              n-options * { word      parameter-value }
+ *      }
+ *
+ * Reply:
+ *      word    status
+ *      if (status == RDIError_NoError) {
+ *              word    n-parameters
+ *              n-parameters * {
+ *                      word    ADP_Parameter
+ *                      word    chosen-value
+ *              }
+ *      }
+ */
+
+#define ADP_LinkCheck                   ADPREASON(CI_HBOOT, 6)
+/*
+ * This should be the first message that the host sends after a successful
+ * parameter negotiation.  It is really just a 'ping'.
+ *
+ * Message arguments:
+ *      -       empty message
+ *
+ * Reply:
+ *      -       empty acknowledgement
+ */
+
+
+/********************************************************************
+ *
+ * CI_HADP messages
+ *
+ */
+
+#define ADP_HADPUnrecognised        ADPREASON(CI_HADP,0)
+/* This message is unusual in that it is normally sent in reply to
+ * another message which is not understood.  This is an exception
+ * to the normal protocol which says that a reply must have the
+ * same base reason code as the original.  There is a single reply
+ * parameter which is the reason code which was not understood.
+ *
+ * As well as being a reply this message can also be sent and will
+ * return as if this message were unrecognised!
+ *
+ * Parameters:
+ *      none
+ *
+ * Reply:
+ *      word    reason code which was not recognised
+ */
+
+
+#define ADP_Info                ADPREASON(CI_HADP,1)
+/* This is the new ADP information message. It is used to interrogate
+ * the target debug agent.  It provides information on the processor,
+ * as well as the state of the debug world. This allows the host to
+ * configure itself to the capabilities of the target.
+ *
+ * We try not to use feature bitsets, since we could quickly run out
+ * of known bits.  Thus when the feature set is extended, this can be
+ * done in a couple of supported ways:
+ *
+ *  If an undivided reason code is to be added (no reason subcodes)
+ *  then add a new ADP_Info code which responds with a flag indicating
+ *  whether that feature is supported by the target.  If this has not
+ *  even been implemented then the reply will be ADP_HADPUnrecognised
+ *
+ *  If a reason code which is subdivided into reason subcodes is
+ *  added then reason subcode 0 should be set aside to indicate
+ *  whether the functionality of that reason code is supported
+ *  by the target.  If it is not even implemented then the reply will
+ *  be ADP_Unrecognised.
+ *
+ * The first parameter to ADP_Info is a reason subcode, and subsequent
+ * parameters are defined by that subcode
+ *
+ * Parameters:
+ *      word         reason subcode
+ *      other arguments as reason subcode determines.
+ *
+ * Reply:
+ *      word         reason subcode
+ *      other argument as reason subcode determines
+ */
+
+/* ADP_Info reason subcodes: */
+
+
+
+#define ADP_Info_NOP                    ADPSUBREASON(CI_HADP,0)
+/* ADP_Info_NOP
+ * ------------
+ * Summary: This message is used to check for ADP_Info being supported.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError for success, non-zero indicates an error.
+ * If an error is returned then there is no handler for the ADP_Info
+ * message. The normal action will be to return an OK status.
+ */
+
+
+#define ADP_Info_Target                 ADPSUBREASON(CI_HADP,1)
+/* ADP_Info_Target
+ * ---------------
+ * Summary:
+ * This reason code is used to interrogate target system details.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word bitset, word model)
+ *
+ * 'status' is RDIError_NoError to indicate OK, or non-zero to indicate
+ * some sort of error.
+ * 'bitset' is described in more detail below, and is mostly compatible
+ * with the old RDI/RDP system to avoid gratuitous changes to the debugger
+ * toolbox.
+ * 'model' is the target hardware ID word, as returned by the ADP_Booted
+ * message.
+ *
+ * NOTE: The minimum and maximum protocol levels are no longer supported.
+ * It is the Angel view that debugging complexity should be shifted to the
+ * host if at all possible.  This means that the host debugger should
+ * always try to configure itself to the features available in the target
+ * debug agent.  This can be done by checking individual messages, rather
+ * than by a blanket version number dictating the feature set.
+ */
+
+/* 'bitset':- */
+/* Target speed in instructions per second = 10**(bits0..3). */
+#define ADP_Info_Target_LogSpeedMask         (0xF)
+
+/* Target is running on [0 = emulator / 1 = hardware] */
+#define ADP_Info_Target_HW                   (1 << 4)
+
+/* Bits 5..10 are currently undefined and should be zero. */
+/* Other bis are kept the same as the RDP in order to */
+/* eliminate the need to change the position of some bits */
+
+/* If set then the debug agent can be reloaded. */
+#define ADP_Info_Target_CanReloadAgent       (1 << 11)
+
+/* Can request AngelBufferSize information. */
+#define ADP_Info_Target_CanInquireBufferSize (1 << 12)
+
+/* Bit 13 is no longer required as it inquired whether
+ * a special RDP Interrupt code was supported
+ */
+
+/* Debug agent can perform profiling. */
+#define ADP_Info_Target_Profiling            (1 << 14)
+
+/* Debug agent can support Thumb code. */
+#define ADP_Info_Target_Thumb                (1 << 15)
+
+/* Bit 16 was the communications channel check.
+ * This is always available on Angel systems.
+ */
+
+#define ADP_Info_Points                 ADPSUBREASON(CI_HADP,2)
+/* ADP_Info_Points
+ * ---------------
+ * Summary: Returns a 32bit wide bitset of break- and watch-point
+ * features supported by the target debug agent.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word breakinfo)
+ *
+ * 'status' returns RDIError_NoError on success or non-zero to indicate
+ * some sort of error.
+ * 'breakinfo' is a 32bit wide bitset described in detail below.  Note
+ * that only bits 1..12 are used.
+ */
+
+/* 'breakinfo':- */
+/* Can trap on address equality. */
+#define ADP_Info_Points_Comparison      (1 << 0)
+
+/* Can trap on address range. */
+#define ADP_Info_Points_Range           (1 << 1)
+
+/* Can trap on 8bit memory reads. */
+#define ADP_Info_Points_ReadByteWatch   (1 << 2)
+
+/* Can trap on 16bit memory reads. */
+#define ADP_Info_Points_ReadHalfWatch   (1 << 3)
+
+/* Can trap on 32bit memory reads. */
+#define ADP_Info_Points_ReadWordWatch   (1 << 4)
+
+/* Can trap on 8bit write accesses. */
+#define ADP_Info_Points_WriteByteWatch  (1 << 5)
+
+/* Can trap on 16bit write accesses. */
+#define ADP_Info_Points_WriteHalfWatch  (1 << 6)
+
+/* Can trap on 32bit write accesses. */
+#define ADP_Info_Points_WriteWordWatch  (1 << 7)
+
+/* Like range, but based on address bitmask<. */
+#define ADP_Info_Points_Mask            (1 << 8)
+
+/* Multi-threaded support only - thread specific breakpoints. */
+#define ADP_Info_Points_ThreadBreak     (1 << 9)
+
+/* Multi-threaded support only - thread specific watchpoints. */
+#define ADP_Info_Points_ThreadWatch     (1 << 10)
+
+/* Allows conditional breakpoints. */
+#define ADP_Info_Points_Conditionals    (1 << 11)
+
+/* Break- and watch-points can be interrogated */
+#define ADP_Info_Points_Status          (1 << 12)
+
+
+#define ADP_Info_Step                   ADPSUBREASON(CI_HADP,3)
+/* ADP_Info_Step
+ * -------------
+ * Summary: Returns a 32bit wide bitmask of the single-stepping
+ * capabilities of the target debug agent.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word stepinfo)
+ *
+ * 'status' returns RDIError_NoError on success, or non-zero to indicate
+ * some kind of error.
+ * 'stepinfo' is a 32bit wide bitmask described in detail below.  Note that
+ * only 3 bits are used.
+ */
+
+/* 'stepinfo':- */
+/* Single-stepping of more than one instruction is possible. */
+#define ADP_Info_Step_Multiple  (1 << 0)
+
+/* Single-stepping until next direct PC change is possible. */
+#define ADP_Info_Step_PCChange  (1 << 1)
+
+/* Single-stepping of a single instruction is possible. */
+#define ADP_Info_Step_Single    (1 << 2)
+
+
+#define ADP_Info_MMU                    ADPSUBREASON(CI_HADP,4)
+/* ADP_Info_MMU
+ * ------------
+ * Summary: Returns information about the memory management system (if
+ * any).
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word meminfo)
+ *
+ * 'status' returns RDIError_NoError to indicate success or non-zero to
+ * indicate some kind of error.
+ * 'meminfo' should be a 32bit unique ID, or zero if there is no MMU
+ * support on the target.
+ */
+
+
+#define ADP_Info_SemiHosting            ADPSUBREASON(CI_HADP,5)
+/* ADP_Info_SemiHosting
+ * --------------------
+ * Summary: This message is used to check whether semi-hosting info calls
+ * are available on the target.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError if semi-hosting info calls are available,
+ * non-zero otherwise.
+ */
+
+
+#define ADP_Info_CoPro                  ADPSUBREASON(CI_HADP,6)
+/* ADP_Info_CoPro
+ * --------------
+ * Summary: This message checks whether CoProcessor info calls are
+ * supported.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError to indicate these facilities
+ * are supported, non-zero otherwise.
+ */
+
+
+#define ADP_Info_Cycles                 ADPSUBREASON(CI_HADP,7)
+/* ADP_Info_Cycles
+ * ---------------
+ * Summary: Returns the number of instructions and cycles executed since
+ * the target was initialised.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word ninstr, word Scycles, word Ncycles,
+ *          word Icycles, word Ccycles, word Fcycles)
+ *
+ * 'status' is RDIError_NoError to indicate success, or non-zero if there
+ * is no target support for gathering cycle count information.
+ * 'ninstr' is the number of instructions executed.
+ * 'Scycles' is the number of S-cycles executed.
+ * 'Ncycles' is the number of N-cycles executed.
+ * 'Icycles' is the number of I-cycles executed.
+ * 'Ccycles' is the number of C-cycles executed.
+ * 'Fcycles' is the number of F-cycles executed.
+ */
+
+
+#define ADP_Info_DescribeCoPro          ADPSUBREASON(CI_HADP,8)
+/* ADP_Info_DescribeCoPro
+ * ----------------------
+ * Summary: Describe the registers of a coprocessor.  Use only if
+ * ADP_Info_CoPro return RDIError_NoError.
+ *
+ * Arguments:
+ * Send:   Arguments of the form:
+ *         (byte cpno, byte rmin, byte rmax, byte nbytes, byte access,
+ *          byte cprt_r_b0, byte cprt_r_b1, byte cprt_w_b0, byte cprt_w_b1)
+ *         And a terminating byte = 0xff.  Must be within maximum buffer size.
+ * Return: (word status)
+ *
+ * 'cpno' is the number of the coprocessor to be described.
+ * 'rmin' is the bottom of a range of registers with the same description.
+ * 'rmax' is the top of a range of registers with the same description.
+ * 'nbytes' is the size of the register.
+ * 'access' describes access to the register and is described in more detail
+ * below.
+ *
+ * If bit 2 of access is set:-
+ * 'cprt_r0' provides bits 0 to 7, and
+ * 'cprt_r1' provides bits 16 to 23 of a CPRT instruction to read the
+ * register.
+ * 'cprt_w0' provides bits 0 to 7, and
+ * 'cprt_w1' provides bits 16 to 23 of a CPRT instruction to write the
+ * register.
+ *
+ * Otherwise, 'cprt_r0' provides bits 12 to 15, and 'cprt_r1' bit 22 of CPDT
+ * instructions to read and write the register ('cprt_w0' and 'cprt_w1' are
+ * junk).
+ */
+
+/* 'access':- */
+/* Readable. */
+#define ADP_Info_DescribeCoPro_Readable   (1 << 0)
+
+/* Writeable. */
+#define ADP_Info_DescribeCoPro_Writeable  (1 << 1)
+
+/* Registers read or written via CPDT instructions (else CPRT) with this
+   bit set. */
+#define ADP_Info_DescribeCoPro_CPDT       (1 << 2)
+
+#define ADP_Info_RequestCoProDesc       ADPSUBREASON(CI_HADP,9)
+/* ADP_Info_RequestCoProDesc
+ * -------------------------
+ * Summary: Requests a description of the registers of a coprocessor.  Use
+ * only if ADP_Info_CoPro return RDIError_NoError.
+ *
+ * Arguments:
+ * Send:   (byte cpno)
+ * Return: Arguments of the form:-
+ *         (word status, byte rmin, byte rmax, byte nbytes, byte access)
+ *         Followed by a terminating byte = 0xFF.  Must be within maximum
+ *         buffer size.
+ * 'cpno' is the number of the coprocessor to describe.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'rmin' is the bottom of a range of registers with the same description.
+ * 'rmax' is the top of a range of registers with the same description.
+ * 'nbytes' is the size in bytes of the register(s).
+ * 'access' is as above in ADP_Info_DescribeCoPro.
+ */
+
+
+#define ADP_Info_AngelBufferSize        ADPSUBREASON(CI_HADP,10)
+/* ADP_Info_AngelBufferSize
+ * ------------------------
+ * Summary: Returns the Angel buffer sizes.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word defaultsize, word maxsize)
+ *
+ * 'status' returns RDIError_NoError to indicate success or non-zero to
+ * indicate some kind of error.
+ * 'defaultsize' is the default Angel ADP buffer size in bytes. This is
+ * at least 256 bytes.
+ * 'maxsize' is the largest Angel ADP buffer size in bytes. This will be
+ * greater than or equal to defaultsize.  The target will accept ADP messages
+ * of up to this length for download, etc.
+ *
+ * Was DownLoadSize in RDP/RDI world.  This is the amount that the target
+ * should transmit in a single operation.  This should now be the Angel
+ * buffer size.  This information is also given in the ADP_Booted message.
+ *
+ * NOTE: The value returned should be the DATASIZE and *NOT* BUFFERDEFSIZE.
+ * This is needed to ensure that the transport protocol information
+ * can be wrapped around the data.
+ */
+
+#define ADP_Info_ChangeableSHSWI        ADPSUBREASON(CI_HADP,11)
+/* ADP_Info_ChangeableSHSWI
+ * ------------------------
+ * Summary: This message is used to check whether it is possible to change
+ * which SWI's are used for semihosting.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError if semi-hosting info calls are available,
+ * non-zero otherwise.
+ */
+
+#define ADP_Info_CanTargetExecute      ADPSUBREASON(CI_HADP,12)
+/* ADP_Info_CanTargetExecute
+ * -------------------------
+ * Summary: This message is used to see if the target is currently in
+ * an executable state.  Typically this is called after the debugger
+ * initialises.  If a non-error statis is returned then the user is
+ * allowed to 'go' immediately.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' returns RDIError_NoError if target is ready to execute.
+ * other values indicate why it cannot execute.
+ */
+
+#define ADP_Info_AgentEndianess     ADPSUBREASON(CI_HADP,13)
+/* ADP_Info_AgentEndianess
+ * -------------------------
+ * Summary: This message is used to determine the endianess of the
+ * debug agent
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * status should be RDIError_LittleEndian or RDIError_BigEndian
+ * any other value indicates the target does not support this
+ * request, so the debugger will have to make a best guess, which
+ * probably means only allow little endian loadagenting.
+ */
+
+
+#define ADP_Control             ADPREASON(CI_HADP,2)
+/* This message allows for the state of the debug agent to be
+ * manipulated by the host.
+ */
+
+/* The following are sub reason codes to ADP control, the first parameter
+ * is the sub reason code which defines the format of subsequent parameters.
+ *
+ * word         sub reason code
+ */
+
+#define ADP_Ctrl_NOP                    ADPSUBREASON(CI_HADP,0)
+/* ADP_Ctrl_NOP
+ * ------------
+ * Summary: This message is used to check that ADP_Ctrl messages are
+ * supported.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate ADP_Ctrl messages are
+ * supported, non-zero otherwise.
+ */
+
+#define ADP_Ctrl_VectorCatch            ADPSUBREASON(CI_HADP,1)
+/* ADP_Ctrl_VectorCatch
+ * --------------------
+ * Summary: Specifies which hardware exceptions should be reported to the
+ * debugger.
+ *
+ * Arguments:
+ * Send:   (word bitmap)
+ * Return: (word status)
+ *
+ * 'bitmap' is a bit-mask of exceptions to be reported, described in more
+ * detail below.  A set bit indicates that the exception should be
+ * reported to the debugger, a clear bit indicates that the corresponding
+ * exception vector should be taken.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+/* 'bitmap':- */
+/* Reset(branch through zero). */
+#define ADP_Ctrl_VectorCatch_BranchThroughZero      (1 << 0)
+
+/* Undefined Instruction. */
+#define ADP_Ctrl_VectorCatch_UndefinedInstr         (1 << 1)
+
+/* Software Interrupt. */
+#define ADP_Ctrl_VectorCatch_SWI                    (1 << 2)
+
+/* Prefetch Abort. */
+#define ADP_Ctrl_VectorCatch_PrefetchAbort          (1 << 3)
+
+/* Data Abort. */
+#define ADP_Ctrl_VectorCatch_DataAbort              (1 << 4)
+
+/* Address Exception. */
+#define ADP_Ctrl_VectorCatch_AddressException       (1 << 5)
+
+/* Interrupt Request. */
+#define ADP_Ctrl_VectorCatch_IRQ                    (1 << 6)
+
+/* Fast Interrupt Request. */
+#define ADP_Ctrl_VectorCatch_FIQ                    (1 << 7)
+
+/* Error. */
+#define ADP_Ctrl_VectorCatch_Error                  (1 << 8)
+
+
+#define ADP_Ctrl_PointStatus_Watch      ADPSUBREASON(CI_HADP,2)
+/* ADP_Ctrl_PointStatus_Watch
+ * --------------------------
+ * Summary: Returns the hardware resource number and the type of that
+ * resource when given a watchpoint handle.  Should only be called if
+ * the value returned by ADP_Info_Points had ADP_Info_Points_Status set.
+ *
+ * Arguments:
+ * Send:   (word handle)
+ * Return: (word status, word hwresource, word type)
+ *
+ * 'handle' is a handle to a watchpoint.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'hwresource' is the hardware resource number. !!!!!
+ * 'type' is the type of the resource.
+ */
+
+
+#define ADP_Ctrl_PointStatus_Break      ADPSUBREASON(CI_HADP,3)
+/* ADP_Ctrl_PointStatus_Break
+ * --------------------------
+ * Summary: Returns the hardware resource number and the type of that
+ * resource when given a breakpoint handle.  Should only be called if
+ * the value returned by ADP_Info_Points had ADP_Info_Points_Status set.
+ *
+ * Arguments:
+ * Send:   (word handle)
+ * Return: (word status, word hwresource, word type)
+ *
+ * 'handle' is a handle to a breakpoint.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'hwresource' is the hardware resource number.
+ * 'type' is the type of the resource.
+ */
+
+#define ADP_Ctrl_SemiHosting_SetState   ADPSUBREASON(CI_HADP,4)
+/* ADP_Ctrl_SemiHosting_SetState
+ * -----------------------------
+ * Summary: Sets whether or not semi-hosting is enabled.
+ *
+ * Arguments:
+ * Send:   (word semihostingstate)
+ * Return: (word status)
+ *
+ * 'semihostingstate' sets semi-hosting to enabled if zero, otherwise
+ * it disables semi-hosting.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_GetState   ADPSUBREASON(CI_HADP,5)
+/* ADP_Ctrl_SemiHosting_GetState
+ * -----------------------------
+ * Summary: Reads whether or not semi-hosting is enabled.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word semihostingstate)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'semihostingstate' is zero if semi-hosting is enabled, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_SetVector  ADPSUBREASON(CI_HADP,6)
+/* ADP_Ctrl_SemiHosting_SetVector
+ * ------------------------------
+ * Summary: Sets the semi-hosting vector.
+ *
+ * Arguments:
+ * Send:   (word semihostingvector)
+ * Return: (word status)
+ *
+ * 'semihostingvector' holds the value the vector is to be set to.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_GetVector  ADPSUBREASON(CI_HADP,7)
+/* ADP_Ctrl_SemiHosting_GetVector
+ * ------------------------------
+ * Summary: Gets the value of the semi-hosting vector.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word semihostingvector)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'semihostingvector' holds the value of the vector.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_Log                    ADPSUBREASON(CI_HADP,8)
+/* ADP_Ctrl_Log
+ * ------------
+ * Summary: Returns the logging state.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word logsetting)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'logsetting' is a bitmap specifying the level of logging desired,
+ *  described in more detail below.  The bits can be ORed together
+ */
+
+/* 'logsetting':- */
+
+/* No logging. */
+#define ADP_Ctrl_Log_NoLogging    (0)
+/* RDI level logging. */
+#define ADP_Ctrl_Log_RDI          (1 << 0)
+/* ADP byte level logging. */
+#define ADP_Ctrl_Log_ADP          (1 << 1)
+
+
+#define ADP_Ctrl_SetLog                 ADPSUBREASON(CI_HADP,9)
+/* ADP_Ctrl_SetLog
+ * ---------------
+ * Summary: Sets the logging state.
+ *
+ * Arguments:
+ * Send:   (word logsetting)
+ * Return: (word status)
+ *
+ * 'logsetting' is the same as in ADP_Ctrl_Log above.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+#define ADP_Ctrl_SemiHosting_SetARMSWI   ADPSUBREASON(CI_HADP,10)
+/* ADP_Ctrl_SemiHosting_SetARMSWI
+ * ------------------------------
+ * Summary: Sets the number of the ARM SWI used for semihosting
+ *
+ * Arguments:
+ * Send:   (word ARM_SWI_number)
+ * Return: (word status)
+ *
+ * The debug agent will interpret ARM SWI's with the SWI number specified
+ * as semihosting SWI's.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_ChangeableSHSWI didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_GetARMSWI   ADPSUBREASON(CI_HADP,11)
+/* ADP_Ctrl_SemiHosting_GetARMSWI
+ * ------------------------------
+ * Summary: Reads the number of the ARM SWI used for semihosting
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word ARM_SWI_number)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * ARM_SWI_number is the SWI number which is used for semihosting.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+#define ADP_Ctrl_SemiHosting_SetThumbSWI   ADPSUBREASON(CI_HADP,12)
+/* ADP_Ctrl_SemiHosting_SetThumbSWI
+ * --------------------------------
+ * Summary: Sets the number of the Thumb SWI used for semihosting
+ *
+ * Arguments:
+ * Send:   (word Thumb_SWI_number)
+ * Return: (word status)
+ *
+ * The debug agent will interpret Thumb SWI's with the SWI number specified
+ * as semihosting SWI's.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: This should only be called if ADP_Info_ChangeableSHSWI didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_SemiHosting_GetThumbSWI   ADPSUBREASON(CI_HADP,13)
+/* ADP_Ctrl_SemiHosting_GetThumbSWI
+ * --------------------------------
+ * Summary: Reads the number of the Thumb SWI used for semihosting
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word ARM_Thumb_number)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * Thumb_SWI_number is the SWI number which is used for semihosting.
+ *
+ * NOTE: This should only be called if ADP_Info_SemiHosting didn't return
+ * an error.
+ */
+
+
+#define ADP_Ctrl_Download_Supported   ADPSUBREASON(CI_HADP,14)
+/* ADP_Ctrl_Download_Supported
+ * ---------------------------
+ * Summary: Can configuration be downloaded?
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError if the configuration can be downloaded,
+ * non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIInfo_DownLoad.
+ */
+
+
+#define ADP_Ctrl_Download_Data       ADPSUBREASON(CI_HADP,15)
+/* ADP_Ctrl_Download_Data
+ * ----------------------
+ * Summary: Loads configuration data.
+ *
+ * Arguments:
+ * Send:   (word nbytes, words data)
+ * Return: (word status)
+ *
+ * 'nbytes' is the number of *bytes* being sent.
+ * 'data' is the configuration data. NOTE: data must not cause the buffer
+ * size to exceed the maximum allowed buffer size.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDP_LoadConfigData.  Should only be used if
+ * ADP_ICEM_AddConfig didn't return an error.
+ */
+
+
+#define ADP_Ctrl_Download_Agent            ADPSUBREASON(CI_HADP,16)
+/* ADP_Ctrl_Download_Agent
+ * -----------------------
+ * Summary: Prepares Debug Agent to receive configuration data which it
+ * should interpret as a new version of the Debug Agent code.
+ *
+ * Arguments:
+ * Send:   (word loadaddress, word size)
+ * Return: (word status)
+ *
+ * 'loadaddress' is the address where the new Debug Agent code should be
+ * loaded.
+ * 'size' is the number of bytes of Debug Agent code to be loaded.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDP_LoadAgent.  The data will be downloaded using
+ * ADP_Ctrl_Download_Data.  The new agent is started with ADP_Ctrl_Start_Agent
+ */
+
+
+#define ADP_Ctrl_Start_Agent                    ADPSUBREASON(CI_HADP,17)
+/* ADP_Ctrl_Start_Agent
+ * -----------------------
+ * Summary: Instruct Debug Agent to begin execution of new agent,
+ * which has been downloaded by ADP_Ctrl_Download_Agent.
+ *
+ * Arguments:
+ * Send:   (word startaddress)
+ * Return: (word status)
+ *
+ * 'startaddress' is the address where the new Debug Agent code should be
+ *  entered, and must satisfy:
+ *     (loadaddress <= startaddress <= (loadaddress + size))
+ *  where 'loadaddress' and  'size' were specified in the
+ *  ADP_Ctrl_Download_Agent message.
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+#define ADP_Ctrl_SetTopMem                      ADPSUBREASON(CI_HADP,18)
+/* ADP_Ctrl_SetTopMem
+ * ------------------
+ * Summary: Sets the top of memory for ICEman2 systems, so that the C Library
+ * can allocate the stack in the correct place on startup.
+ *
+ * Arguments:
+ * Send:   (word mem_top)
+ * Return: (word status)
+ *
+ * This request should only be supported by ICEman2.  Standard Angel systems
+ * should return an error (unrecognised is fine).
+ */
+
+
+#define ADP_Read                ADPREASON(CI_HADP,3)
+#define ADP_ReadHeaderSize      (ADP_DEFAULT_HEADER_SIZE + 2*sizeof(word))
+
+/* ADP_Read
+ * --------
+ * Summary: Request for a transer of memory contents from the target to the
+ * debugger.
+ *
+ * Arguments:
+ * Send:   (word address, word nbytes)
+ * Return: (word status, word rnbytes [, bytes data])
+ *
+ * 'address' is the address from which memory transer should start.
+ * 'nbytes' is the number of bytes to transfer.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'rnbytes' holds the number of requested bytes NOT read (i.e. zero
+ * indicates success, non-zero indicates an error).
+ * 'data' is the number of bytes requested minus 'rnbytes'.
+ */
+
+
+
+#define ADP_Write               ADPREASON(CI_HADP,4)
+#define ADP_WriteHeaderSize     (ADP_DEFAULT_HEADER_SIZE + 2*sizeof(word))
+
+/* ADP_Write
+ * ---------
+ * Summary: Request for a transfer of memory contents from the debugger to
+ * the target.
+ *
+ * Arguments:
+ * Send:   (word address, word nbytes, bytes data)
+ * Return: (word status [, word rnbytes])
+ *
+ * 'address' is the address from which memory transer should start.
+ * 'nbytes' is the number of bytes to transfer.
+ * 'data' holds the bytes to be transferred.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'rnbytes' holds the number of requested bytes NOT written (i.e. zero
+ * indicates success, non-zero indicates an error) if status indicated an
+ * error.
+ */
+
+
+
+#define ADP_CPUread             ADPREASON(CI_HADP,5)
+/* ADP_CPUread
+ * -----------
+ * Summary: This is a request to read values in the CPU.
+ *
+ * Arguments:
+ * Send:   (byte mode, word mask)
+ * Return: (word status, words data)
+ *
+ * 'mode' defines the processor mode from which the transfer should be made.
+ * It is described in more detail below.
+ * 'mask' indicates which registers should be transferred. Setting a bit to
+ * one will cause the designated register to be transferred. The details
+ * of mask are specified below.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'data' holds the values of the registers on successful completion,
+ * otherwise it just holds rubbish.  The lowest numbered register is
+ * transferred first.  NOTE: data must not cause the buffer size to exceed
+ * the maximum allowed buffer size.
+ */
+
+/* 'mode':- */
+/* The mode number is the same as the mode number used by an ARM; a value of
+   255 indicates the current mode. */
+#define ADP_CPUmode_Current     (255)
+
+/* 26bit user mode. */
+#define ADP_CPUread_26bitUser   (0x0)
+
+/* 26bit FIQ mode. */
+#define ADP_CPUread_26bitFIQ    (0x1)
+
+/* 26bit IRQ mode. */
+#define ADP_CPUread_26bitIRQ    (0x2)
+
+/* 26bit Supervisor mode. */
+#define ADP_CPUread_26bitSVC    (0x3)
+
+/* 32bit user mode. */
+#define ADP_CPUread_32bitUser   (0x10)
+
+/* 32bit FIQ mode. */
+#define ADP_CPUread_32bitFIQ    (0x11)
+
+/* 32bit IRQ mode. */
+#define ADP_CPUread_32bitIRQ    (0x12)
+
+/* 32bit Supervisor mode. */
+#define ADP_CPUread_32bitSVC    (0x13)
+
+/* 32bit Abort mode. */
+#define ADP_CPUread_32bitAbort  (0x17)
+
+/* 32bit Undefined mode. */
+#define ADP_CPUread_32bitUndef  (0x1B)
+
+/* #32bit System mode - Added in Architecture 4 ARMs e.g.ARM7TDMI */
+#define ADP_CPUread_32bitSystem (0x1F)
+
+/* 'mask':- */
+/* Request registers RO-R14. */
+#define ADP_CPUread_RegsMask  (0x7FFF)
+
+/* Request Program Counter (including mode and flag bits in 26-bit modes. */
+#define ADP_CPUread_PCmode    (1 << 15)
+
+/* Request Program Counter (without mode and flag bits in 26-bit modes. */
+#define ADP_CPUread_PCnomode  (1 << 16)
+
+/* Requests the transfer of the CPSR */
+#define ADP_CPUread_CPSR      (1 << 17)
+
+/* In processor modes with an SPSR(non-user modes), bit 19 requests its
+   transfer */
+#define ADP_CPUread_SPSR      (1 << 18)
+
+
+
+#define ADP_CPUwrite            ADPREASON(CI_HADP,6)
+/* ADP_CPUwrite
+ * ------------
+ * Summary: This is a request to write values to the CPU.
+ *
+ * Arguments:
+ * Send:   (byte mode, word mask, words data)
+ * Return: (word status)
+ *
+ * 'mode' defines the processor mode to which the transfer should be made.
+ * The mode number is the same as the mode number used by ARM; a value of
+ * 255 indicates the current mode. See ADP_CPUread above for more detail.
+ * 'mask' indicates which registers should be transferred. Setting a bit to
+ * one will cause the designated register to be transferred. The details
+ * of mask are specified above in ADP_CPUread.
+ * 'data' holds the values of the registers to be transferred.  The first
+ * value is written to the lowest numbered register.  NOTE: data must not
+ * cause the buffer size to exceed the maximum allowed buffer size.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+
+#define ADP_CPread              ADPREASON(CI_HADP,7)
+/* ADP_CPread
+ * ----------
+ * Summary: This message requests a co-processors internal state.
+ *
+ * Arguments:
+ * Send:   (byte CPnum, word mask)
+ * Return: (word status, words data)
+ *
+ * 'CPnum' is the number of the co-processor to transfer values from.
+ * 'mask' specifies which registers to transfer and is co-processor
+ * specific.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'data' holds the registers specified in 'mask' if successful, otherwise
+ * just rubbish.  The lowest numbered register is transferred first.
+ * NOTE: data must not cause the buffer size to exceed the maximum allowed
+ * buffer size.
+ */
+
+
+
+#define ADP_CPwrite             ADPREASON(CI_HADP,8)
+/* ADP_CPwrite
+ * -----------
+ * Summary: This message requests a write to a co-processors internal state.
+ *
+ * Arguments:
+ * Send:   (byte CPnum, word mask, words data)
+ * Return: (word status)
+ *
+ * 'CPnum' is the number of the co-processor to transfer values to.
+ * 'mask' specifies which registers to transfer and is co-processor
+ * specific.
+ * 'data' holds the values to transfer to the registers specified in 'mask'.
+ * The first value is written to the lowest numbered register.
+ * NOTE: data must not cause the buffer size to exceed the maximum allowed
+ * buffer size.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+
+#define ADP_SetBreak            ADPREASON(CI_HADP,9)
+/* ADP_SetBreak
+ * ------------
+ * Summary: Sets a breakpoint.
+ *
+ * Arguments:
+ * Send:   (word address, byte type [, word bound])
+ * Return: (word status, word pointhandle, word raddress, word rbound)
+ *
+ * 'address' is the address of the instruction to set the breakpoint on.
+ * 'type' specifies the sort of breakpoint and is described in more detail
+ * below.
+ * 'bound' is included if the least significant 4 bits of type are set to
+ * 5 or above (see below for more detail).
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'pointhandle'  returns a handle to the breakpoint, it will be valid if bit
+ * 7 of 'type' is set.  See below for more detail.
+ * 'raddress' is valid depending on 'type', see below for more detail.
+ * 'rbound' is valid depending on 'type', see below for more detail.
+ */
+
+/* 'type':- */
+/* The least significant 4 bits define the sort of breakpoint to set:- */
+/* Halt if the pc is equal to 'address'. */
+#define ADP_SetBreak_EqualsAddress         (0)
+
+/* Halt if the pc is greater than 'address'. */
+#define ADP_SetBreak_GreaterAddress        (1)
+
+/* Halt if the pc is greater than or equal to 'address'. */
+#define ADP_SetBreak_GEqualsAddress        (2)
+
+/* Halt if the pc is less than 'address'. */
+#define ADP_SetBreak_LessAddress           (3)
+
+/* Halt if the pc is less than or equal to 'address'. */
+#define ADP_SetBreak_LEqualsAddress        (4)
+
+/* Halt if the pc is in the range from 'address' to 'bound' inclusive. */
+#define ADP_SetBreak_Range                 (5)
+
+/* Halt if the pc is not in the range from 'address' to 'bound' inclusive. */
+#define ADP_SetBreak_NotRange              (6)
+
+/* Halt if (pc & 'bound') = 'address'. */
+#define ADP_SetBreak_AndBound              (7)
+
+/* Bits 5,6 and 7 are used as follows :- */
+/* If set this indicates that the breakpoint is on a 16bit (Thumb)
+   instruction rather than a 32bit (ARM) instruction. */
+#define ADP_SetBreak_Thumb                 (1 << 4)
+
+/* This requests that the breakpoint should be conditional (execution halts
+   only if the breakpointed instruction is executed, not if it is
+   conditionally skipped).  If bit 5 is not set, execution halts whenever
+   the breakpointed instruction is reached (whether executed or skipped). */
+#define ADP_SetBreak_Cond                  (1 << 5)
+
+/* This requests a dry run: the breakpoint is not set and the 'raddress', and
+   if appropriate the 'rbound', that would be used, are returned (for
+   comparison and range breakpoints the address and bound used need not be
+   exactly as requested).  A RDIError_NoError 'status' byte indicates that
+   resources are currently available to set the breakpoint, non-zero
+   indicates an error. RDIError_NoMorePoints indicates that the required
+   breakpoint resources are not currently available. */
+#define ADP_SetBreak_DryRun                (1 << 6)
+
+/* If the request is successful, but there are no more breakpoint registers
+   (of the requested type), then the value RDIError_NoMorePoints is
+   returned. */
+
+/* If a breakpoint is set on a location which already has a breakpoint, the
+   first breakpoint will be removed before the new breakpoint is set. */
+
+
+
+#define ADP_ClearBreak          ADPREASON(CI_HADP,10)
+/* ADP_ClearBreak
+ * --------------
+ * Summary: Clears a breakpoint.
+ *
+ * Arguments:
+ * Send:   (word pointhandle)
+ * Return: (word status)
+ *
+ * 'pointhandle' is a handle returned by a previous ADP_SetBreak.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+#define ADP_SetWatch            ADPREASON(CI_HADP,11)
+/* ADP_SetWatch
+ * ------------
+ * Summary: Sets a watchpoint.
+ *
+ * Arguments:
+ * Send:   (word address, byte type, byte datatype [,word bound])
+ * Return: (word status, word pointhandle, word raddress, word rbound)
+ *
+ * 'address' is the address at which to set the watchpoint.
+ * 'type' is the type of watchpoint to set and is described in detail below.
+ * 'datatype' defines the sort of data access to watch for and is described
+ * in more detail below.
+ * 'bound' is included depending on the value of type (see description of
+ * type below).
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'pointhandle' is valid depending on the value of type (see description
+ * of type below).
+ * 'raddress' is valid depending on the value of type (see description
+ * of type below).
+ * 'rbound' is valid depending on the value of type (see description
+ * of type below).
+ */
+
+/* 'type':- */
+/* The least significant 4 bits of 'type' define the sort of watchpoint to
+   set:- */
+/* Halt on a data access to the address equal to 'address'. */
+#define ADP_SetWatch_EqualsAddress          (0)
+
+/* Halt on a data access to an address greater than 'address'. */
+#define ADP_SetWatch_GreaterAddress         (1)
+
+/* Halt on a data access to an address greater than or equal to 'address'. */
+#define ADP_SetWatch_GEqualsAddress         (2)
+
+/* Halt on a data access to an address less than 'address'. */
+#define ADP_SetWatch_LessAddress            (3)
+
+/* Halt on a data access to an address less than or equal to 'address'. */
+#define ADP_SetWatch_LEqualsAddress         (4)
+
+/* Halt on a data access to an address in the range from 'address' to
+   'bound' inclusive. */
+#define ADP_SetWatch_Range                  (5)
+
+/* Halt on a data access to an address not in the range from 'address' to
+   'bound' inclusive. */
+#define ADP_SetWatch_NotRange               (6)
+
+/* Halt if (data-access-address & 'bound')='address'. */
+#define ADP_SetWatch_AndBound               (7)
+
+/* Bits 6 and 7 of 'type' also have further significance:-
+   NOTE: they must not be simulataneously set. */
+
+/* Bit 6 of 'type' set:  Requests a dry run: the watchpoint is not set and
+   the 'address' and, if appropriate, the 'bound', that would be used are
+   returned (for range and comparison watchpoints, the 'address' and 'bound'
+   used need not be exactly as requested).  A RDIError_NoError status byte
+   indicates that resources are currently available to set the watchpoint;
+   RDIError_NoMorePoints indicates that the required watchpoint resources
+   are not currently available. */
+
+/* Bit 7 of 'type' set:  Requests that a handle should be returned for the
+   watchpoint by which it will be identified subsequently.  If bit 7 is
+   set, a handle will be returned ('pointhandle'), whether or not the
+   request succeeds or fails (but, obviously, it will only be meaningful
+   if the request succeesd). */
+
+/* 'datatype':- */
+/* The 'datatype' argument defines the sort of data access to watch for,
+   values can be summed or ORed together to halt on any set of sorts of
+   memory access. */
+
+/* Watch for byte reads. */
+#define ADP_SetWatch_ByteReads           (1)
+
+/* Watch for half-word reads. */
+#define ADP_SetWatch_HalfWordReads       (2)
+
+/* Watch for word reads. */
+#define ADP_SetWatch_WordReads           (4)
+
+/* Watch for half-word reads. */
+#define ADP_SetWatch_ByteWrites          (8)
+
+/* Watch for half-word reads. */
+#define ADP_SetWatch_HalfWordWrites      (16)
+
+/* Watch for half-word reads. */
+#define ADP_SetWatch_WordWrites          (32)
+
+/* On successful completion a RDIError_NoError 'status' byte is returned.  On
+   unsuccessful completion, a non-zero error code byte is returned.  If the
+   request is successful, but there are now no more watchpoint registers
+   (of the requested type), then the value RDIError_NoMorePoints is
+   returned. */
+
+/* If a watchpoint is set on a location which already has a watchpoint, the
+   first watchpoint will be removed before the new watchpoint is set. */
+
+
+#define ADP_ClearWatch          ADPREASON(CI_HADP,12)
+/* ADP_ClearWatch
+ * --------------
+ * Summary: Clears a watchpoint.
+ *
+ * Arguments:
+ * Send:   (word pointhandle)
+ * Return: (word status)
+ *
+ * 'pointhandle' is a handle to a watchpoint returned by a previous
+ * ADP_SetWatch.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+
+
+#define ADP_Execute             ADPREASON(CI_HADP,13)
+/* ADP_Execute
+ * -----------
+ * Summary: This message requests that the target starts executing from
+ * the stored CPU state.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * The message will *ALWAYS* respond immediately with an ACK (unlike the
+ * old RDI definition, which allowed asynchronous message replies).
+ *
+ * Execution will stop when allowed system events occur. The host will
+ * be notified via a ADP_Stopped message (described below).
+ */
+
+
+
+#define ADP_Step                ADPREASON(CI_HADP,14)
+/* ADP_Step
+ * --------
+ * Summary: Execute 'ninstr' instructions.
+ *
+ * Arguments:
+ * Send: (word ninstr)
+ * Return: (word status)
+ *
+ * 'ninstr' is the number of instructions to execute, starting at the
+ * address currently loaded into the CPU program counter.  If it is zero,
+ * the target should execute instructions upto the next instruction that
+ * explicitly alters the Program Counter. i.e. a branch or ALU operation
+ * with the PC as the destination.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * The ADP_Step function (unlike the earlier RDI system) will *ALWAYS*
+ * return an ACK immediately. A subsequent ADP_Stopped message will be
+ * delivered from the target to the host when the ADP_Step operation
+ * has completed.
+ */
+
+
+
+#define ADP_InterruptRequest    ADPREASON(CI_HADP,15)
+/* ADP_InterruptRequest
+ * --------------------
+ * Summary: Interrupt execution.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * On receiving this message the target should attempt to stop execution.
+ */
+
+
+
+#define ADP_HW_Emulation             ADPREASON(CI_HADP,16)
+/* ADP_HW_Emulation
+ * ----------------
+ * The first parameter to ADP_HW_Emulation is a Reason Subcode, and
+ * subsequent parameters are defined by that subcode
+ *
+ * word         reason subcode
+ * other arguments as reason subcode determines
+ *
+ */
+
+/* ADP__HW_Emulation sub-reason codes: */
+
+#define ADP_HW_Emul_Supported         ADPSUBREASON(CI_HADP,0)
+/* ADP_HW_Emul_Supported
+ * ---------------------
+ * Summary: Enquires whether calls to the next 4 messages are available
+ * (MemoryAccess, MemoryMap, Set_CPUspeed, ReadClock).
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate the messages are available,
+ * non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDI_Info_Memory_Stats.
+ */
+
+
+#define ADP_HW_Emul_MemoryAccess      ADPSUBREASON(CI_HADP,1)
+/* ADP_HW_Emul_MemoryAccess
+ * ------------------------
+ * Summary: Get memory access information for memory block with specified
+ * handle.
+ *
+ * Arguments:
+ * Send:   (word handle)
+ * Return: (word status, word nreads, word nwrites, word sreads,
+ *          word swrites, word ns, word s)
+ *
+ * 'handle' is a handle to a memory block.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'nreads' is the number of non-sequential reads.
+ * 'nwrites' is the number of non-sequential writes.
+ * 'sreads' is the number of sequential reads.
+ * 'swrites' is the number of sequential writes.
+ * 'ns' is time in nano seconds.
+ * 's' is time in seconds.
+ *
+ * NOTE: Equivalent to RDIMemory_Access.
+ */
+
+
+#define ADP_HW_Emul_MemoryMap         ADPSUBREASON(CI_HADP,2)
+/* ADP_HW_Emul_MemoryMap
+ * ---------------------
+ * Summary: Sets memory characteristics.
+ *
+ * Arguments:
+ * Send:   (word n,
+    Then 'n' sets of arguments of the form:-
+            word handle, word start, word limit, byte width,
+            byte access, word Nread_ns, word Nwrite_ns, word Sread_ns,
+            word Swrite_ns)
+ * Return: (word status)
+ *
+ * 'n' is the number of sets of arguments.
+ * 'handle' is a handle to the region.
+ * 'start' is the start of this region.
+ * 'limit' is the limit of this region.
+ * 'width' is the memory width, described in detail below.
+ * 'access' is described in detail below.
+ * 'Nread_ns' is the access time for N read cycles in nano seconds.
+ * 'Nwrite_ns' is the access time for N write cycles in nano seconds.
+ * 'Sread_ns' is the access time for S read cycles in nano seconds.
+ * 'Swrite_ns' is the access time for S write cycles in nano seconds.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * NOTE: Equivalent to RDIMemory_Map.
+ */
+
+/* 'width':- */
+/* 8 bit memory width. */
+#define ADP_HW_Emul_MemoryMap_Width8     (0)
+
+/* 16 bit memory width. */
+#define ADP_HW_Emul_MemoryMap_Width16    (1)
+
+/* 32 bit memory width. */
+#define ADP_HW_Emul_MemoryMap_Width32    (2)
+
+/* 'access':- */
+/* Bit 0 - read access. */
+#define ADP_HW_Emul_MemoryMap_Access_Read      (1 << 0)
+
+/* Bit 1 - write access. */
+#define ADP_HW_Emul_MemoryMap_Access_Write     (1 << 1)
+
+/* Bit 2 - latched 32 bit memory. */
+#define ADP_HW_Emul_MemoryMap_Access_Latched   (1 << 2)
+
+
+#define ADP_HW_Emul_SetCPUSpeed       ADPSUBREASON(CI_HADP,3)
+/* ADP_HW_Emul_SetCPUSpeed
+ * -----------------------
+ * Summary: Sets the speed of the CPU.
+ *
+ * Arguments:
+ * Send:   (word speed)
+ * Return: (word status)
+ *
+ * 'speed' is the CPU speed in nano seconds.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDISet_CPUSpeed.
+ */
+
+
+#define ADP_HW_Emul_ReadClock         ADPSUBREASON(CI_HADP,4)
+/* ADP_HW_Emul_ReadClock
+ * ---------------------
+ * Summary: Reads simulated time.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word ns, word s)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'ns' is time in nano seconds.
+ * 's' is time in seconds.
+ *
+ * NOTE: Equivalent to RDIRead_Clock.
+ */
+
+
+#define ADP_ICEbreakerHADP            ADPREASON(CI_HADP,17)
+
+/* The first parameter to ADP_ICEbreaker is a Reason Subcode, and
+ * subsequent parameters are defined by that subcode
+ *
+ * word         reason subcode
+ * other arguments as reason subcode determines
+ *
+ */
+
+/* ADP_ICEbreaker sub-reason codes: */
+
+#define ADP_ICEB_Exists               ADPSUBREASON(CI_HADP,0)
+/* ADP_ICEB_Exists
+ * ---------------
+ * Summary: Is there an ICEbreaker in the system?
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate there is an ICEbreaker,
+ * non-zero otherwise.
+ */
+
+
+#define ADP_ICEB_GetLocks             ADPSUBREASON(CI_HADP,1)
+/* ADP_ICEB_GetLocks
+ * -----------------
+ * Summary: Returns which ICEbreaker registers are locked.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word lockedstate)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'lockedstate' is a bitmap if the ICEbreaker registers locked against use
+ * by IceMan (because explicitly written by the user). Bit n represents
+ * hardware breakpoint n, and if set the register is locked.
+ *
+ * NOTE: Equivalent to RDIIcebreaker_GetLocks.  Should only be used if
+ * ADP_ICEB_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEB_SetLocks             ADPSUBREASON(CI_HADP,2)
+/* ADP_ICEB_SetLocks
+ * -----------------
+ * Summary: Sets which ICEbreaker registers are locked.
+ *
+ * Arguments:
+ * Send:   (word lockedstate)
+ * Return: (word status)
+ *
+ * 'lockedstate' is the same as in ADP_ICEB_GetLocks above.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIIcebreaker_SetLocks.  Should only be used if
+ * ADP_ICEB_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEB_CC_Exists            ADPSUBREASON(CI_HADP,3)
+/* ADP_ICEB_CC_Exists
+ * ------------------
+ * Summary: Is there an ICEbreaker Comms Channel?
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate there is a Comms Channel,
+ * non-zero otherwise.
+ *
+ * NOTE: Should only be used if ADP_ICEB_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEB_CC_Connect_ToHost    ADPSUBREASON(CI_HADP,4)
+/* ADP_ICEB_CC_Connect_ToHost
+ * --------------------------
+ * Summary: Connect Comms Channel in ToHost direction.
+ *
+ * Arguments:
+ * Send:   (byte connect)
+ * Return: (word status)
+ *
+ * 'connect' !!!!!
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDICommsChannel_ToHost.  Should only be used if
+ * ADP_ICEB_CC_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEB_CC_Connect_FromHost  ADPSUBREASON(CI_HADP,5)
+/* ADP_ICEB_CC_Connect_FromHost
+ * ----------------------------
+ * Summary: Connect Comms Channel in FromHost direction.
+ *
+ * Arguments:
+ * Send:   (byte connect)
+ * Return: (word status)
+ *
+ * 'connect' is the same as in ADP_ICEB_CC_Connect_ToHost above.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDICommsChannel_FromHost.  Should only be used if
+ * ADP_ICEB_CC_Exists didn't return an error.
+ */
+
+
+#define ADP_ICEman                    ADPREASON(CI_HADP,18)
+
+/* The first parameter to ADP_ICEman is a Reason Subcode, and
+ * subsequent parameters are defined by that subcode
+ *
+ * word         reason subcode
+ * other arguments as reason subcode determines
+ *
+ */
+
+/* ADP_ICEman sub-reason codes: */
+
+
+#define ADP_ICEM_AddConfig            ADPSUBREASON(CI_HADP,0)
+/* ADP_ICEM_AddConfig
+ * ------------------
+ * Summary: Prepares target to receive configuration data block.
+ *
+ * Arguments:
+ * Send:   (word nbytes)
+ * Return: (word status)
+ *
+ * 'nbytes' is the number of bytes in the configuration block.
+ * 'status' is RDIError_NoError to indicate success, non-zero if a
+ * configuration block of this size can't be accepted.
+ *
+ * NOTE: Equivalent to RDP_AddConfig.
+ */
+
+
+#define ADP_ICEM_SelectConfig         ADPSUBREASON(CI_HADP,1)
+/* ADP_ICEM_SelectConfig
+ * ---------------------
+ * Summary: Selects one of the sets of configuration data blocks and
+ * reinitialises to use the new configuration.
+ *
+ * Arguments:
+ * Send:   (byte aspect, byte namelen, byte matchtype, word vsn_req,
+            bytes name)
+ * Return: (word status, word vsn_sel)
+ *
+ * 'aspect' is one of two values defined below.
+ * 'namelen' is the number of bytes in 'name'.
+ * 'matchtype' specifies how the selected version must match that specified,
+ * and takes one of the values defined below.
+ * 'vsn_req' is the requested version of the named configuration.
+ * 'name' is the name of the configuration.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'vsn_sel' is the version number of the configuration selected on success.
+ *
+ * NOTE: Equivalent to RDP_SelectConfig.
+ */
+
+/* 'aspect':- */
+#define ADP_ICEM_SelectConfig_ConfigCPU       (0)
+#define ADP_ICEM_SelectConfig_ConfigSystem    (1)
+
+/* 'matchtype':- */
+#define ADP_ICEM_SelectConfig_MatchAny        (0)
+#define ADP_ICEM_SelectConfig_MatchExactly    (1)
+#define ADP_ICEM_SelectConfig_MatchNoEarlier  (2)
+
+
+#define ADP_ICEM_ConfigCount          ADPSUBREASON(CI_HADP,2)
+/* ADP_ICEM_ConfigCount
+ * --------------------
+ * Summary: Return number of configurations.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status [, word count])
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'count' returns the number of configurations if status is zero.
+ *
+ * NOTE: Equivalent to RDIConfig_Count.
+ */
+
+
+#define ADP_ICEM_ConfigNth            ADPSUBREASON(CI_HADP,3)
+/* ADP_ICEM_ConfigNth
+ * ------------------
+ * Summary: Gets the nth configuration details.
+ *
+ * Arguments:
+ * Send:   (word confign)
+ * Return: (word status, word version, byte namelen, bytes name)
+ *
+ * 'confign' is the number of the configuration.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'version' is the configuration version number.
+ * 'namelen' is the number of bytes in 'name'.
+ * 'name' is the name of the configuration.
+ *
+ * NOTE: Equivalent to RDIConfig_Nth.
+ */
+
+
+
+#define ADP_Profile                   ADPREASON(CI_HADP,19)
+
+/* The first parameter to ADP_Profile is a Reason Subcode, and
+ * subsequent parameters are defined by that subcode
+ *
+ * word         reason subcode
+ * other arguments as reason subcode determines
+ *
+ */
+
+/* ADP_Profile sub-reason codes: */
+
+
+#define ADP_Profile_Supported         ADPSUBREASON(CI_HADP,0)
+/* ADP_Profile_Supported
+ * ---------------------
+ * Summary: Checks whether profiling is supported.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError if profiling is supported, non-zero otherwise.
+ *
+ * NOTE: Can also be determined using Info_Target.
+ */
+
+
+#define ADP_Profile_Stop              ADPSUBREASON(CI_HADP,1)
+/* ADP_Profile_Stop
+ * ----------------
+ * Summary: Stops profiling.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIProfile_Stop.
+ */
+
+
+#define ADP_Profile_Start             ADPSUBREASON(CI_HADP,2)
+/* ADP_Profile_Start
+ * -----------------
+ * Summary: Starts profiling (PC sampling).
+ *
+ * Arguments:
+ * Send:   (word interval)
+ * Return: (word status)
+ *
+ * 'interval' is the period of PC sampling in micro seconds.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIProfile_Start.
+ */
+
+
+#define ADP_Profile_WriteMap          ADPSUBREASON(CI_HADP,3)
+#define ADP_ProfileWriteHeaderSize    (ADP_DEFAULT_HEADER_SIZE + 4*sizeof(word))
+
+/* ADP_Profile_WriteMap
+ * --------------------
+ * Summary: Downloads a map array, which describes the PC ranges for profiling.
+ *
+ * Arguments: A number of messages each of form:-
+ * Send:   (word len, word size, word offset, words map_data)
+ * Return: (word status)
+ *
+ * 'len' is the number of elements in the entire map array being downloaded.
+ * 'size' is the number of words being downloaded in this message, i.e. the
+ * length of 'map_data'.
+ * 'offset' is the offset into the entire map array which this message starts
+ * from, in words.
+ * 'map_data' consists of 'size' words of map data.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIProfile_WriteMap.
+ */
+
+
+#define ADP_Profile_ReadMap           ADPSUBREASON(CI_HADP,4)
+#define ADP_ProfileReadHeaderSize     (ADP_DEFAULT_HEADER_SIZE + 2*sizeof(word))
+
+/* ADP_Profile_ReadMap
+ * -------------------
+ * Summary: Uploads a set of profile counts which correspond to the current
+ * profile map.
+ *
+ * Arguments: A number of messages, each of the form:
+ * Send:   (word offset, word size)
+ * Return: (word status, words counts)
+ *
+ * 'offset' is the offset in the entire array of counts that this message
+ * starts from, in words.
+ * 'size' is the number of words uploaded in this message (in counts).
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'counts' is 'size' words of profile counts.
+ *
+ * NOTE: Equivalent to RDIProfile_ReadMap.
+ */
+
+
+#define ADP_Profile_ClearCounts       ADPSUBREASON(CI_HADP,5)
+/* ADP_Profile_ClearCounts
+ * -----------------------
+ * Summary: Requests that PC sample counts be set to zero.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDIProfile_ClearCounts.
+ */
+
+#define ADP_InitialiseApplication       ADPREASON(CI_HADP,20)
+/* ADP_InitialiseApplication
+ * -------------------------
+ * Summary: Requests that OS setup up the thread/task so that it can be
+ *          executed.
+ *
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+#define ADP_End                         ADPREASON(CI_HADP,21)
+/* ADP_End
+ * -------
+ * Summary: Sent by the host debugger to tell angel this debugging session
+ *          is is finished
+ * Arguments:
+ * Send: ()
+ * Return: (word status)
+ * status' is RDIError_NoError to indicate success, non-zero otherwise.
+ */
+
+/******************************************************************
+ *
+ * CI_TADP messages
+ *
+ */
+
+#define ADP_TADPUnrecognised        ADPREASON(CI_TADP,0)
+/* This message is unusual in that it is normally sent in reply to
+ * another message which is not understood.  This is an exception
+ * to the normal protocol which says that a reply must have the
+ * same base reason code as the original.  There is a single reply
+ * parameter which is the reason code which was not understood.
+ *
+ * As well as being a reply this message can also be sent and will
+ * return as if this message were unrecognised!
+ *
+ * Parameters:
+ *      none
+ *
+ * Reply:
+ *      word    reason code which was not recognised
+ */
+
+/*-------------------------------------------------------------------------*/
+
+#define ADP_Stopped             ADPREASON(CI_TADP,1)
+/* ADP_Stopped
+ * -----------
+ * Summary: This message is sent to the host when the application stops,
+ * either naturally or due to an exception.
+ *
+ * Parameters:
+ *      word    reason subcode
+ *      other arguments as reason subcode determines.
+ *      Unless stated otherwise (below) there will be none.
+ *
+ * Reply:
+ *      word status     unless reason subcode says otherwise
+ *
+ * This message is sent to the host when execution has stopped. This
+ * can be when the end of the application has been reached, or as the
+ * result of an exception. It can also be the return from an ADP_Step
+ * process, when the requested number of instructions have been
+ * executed., or a breakpoint or watchpoint has been hit etc.
+ */
+
+/* The first set of Stopped subreason codes are for the ARM hardware
+ * vectors. These events will be raised if the
+ * ADP_Control_Vector_Catch allows, or if the target application has
+ * not provided its own handlers.
+ */
+#define ADP_Stopped_BranchThroughZero    ADPSUBREASON(CI_TADP,0)
+#define ADP_Stopped_UndefinedInstr       ADPSUBREASON(CI_TADP,1)
+#define ADP_Stopped_SoftwareInterrupt    ADPSUBREASON(CI_TADP,2)
+#define ADP_Stopped_PrefetchAbort        ADPSUBREASON(CI_TADP,3)
+#define ADP_Stopped_DataAbort            ADPSUBREASON(CI_TADP,4)
+#define ADP_Stopped_AddressException     ADPSUBREASON(CI_TADP,5)
+#define ADP_Stopped_IRQ                  ADPSUBREASON(CI_TADP,6)
+#define ADP_Stopped_FIQ                  ADPSUBREASON(CI_TADP,7)
+
+/* We leave the rest of what would be the bits in the VectorCatch
+ * bitmask free for future expansion.
+ */
+
+/* The following are software reasons for execution stopping: */
+#define ADP_Stopped_BreakPoint         ADPSUBREASON(CI_TADP,32)
+/* Breakpoint was reached
+ *   extra send parameter: word handle - indicates which breakpoint
+ */
+
+#define ADP_Stopped_WatchPoint         ADPSUBREASON(CI_TADP,33)
+/* Watchpoint was triggered
+ *   extra send parameter: word handle - indicates which watchpoint
+ */
+
+#define ADP_Stopped_StepComplete       ADPSUBREASON(CI_TADP,34)
+/* End of ADP_Step request */
+
+#define ADP_Stopped_RunTimeErrorUnknown ADPSUBREASON(CI_TADP,35)
+/*
+ * non-specific fatal runtime support error
+ */
+
+#define ADP_Stopped_InternalError      ADPSUBREASON(CI_TADP,36)
+/*   extra send parameter: word error - indicates the nature of the error
+ *
+ * An Angel internal error has happened.  The error number should be
+ * displayed for the user to report to his software supplier.  Once
+ * this error has been received the internal state of Angel can no longer
+ * be trusted.
+ */
+
+#define ADP_Stopped_UserInterruption   ADPSUBREASON(CI_TADP,37)
+/* Host requested interruption */
+
+#define ADP_Stopped_ApplicationExit    ADPSUBREASON(CI_TADP,38)
+/*   extra send parameter: word exitcode
+ * This indicates that the application has exited via exit(), an exitcode
+ * of zero indiactes successful termination.
+ */
+
+#define ADP_Stopped_StackOverflow      ADPSUBREASON(CI_TADP, 39)
+/*
+ * Software stack overflow has occurred
+ */
+
+#define ADP_Stopped_DivisionByZero     ADPSUBREASON(CI_TADP, 40)
+/*
+ * Division by zero has occurred
+ */
+
+#define ADP_Stopped_OSSpecific         ADPSUBREASON(CI_TADP, 41)
+/*
+ * The OS has requested that execution stops.  The OS will know
+ * why this has happened.
+ */
+
+
+
+/******************************************************************
+ *
+ * CI_TTDCC messages (Target-initiated debug comms channel)
+ *
+ */
+
+#define ADP_TDCC_ToHost             ADPREASON(CI_TTDCC,0)
+/* ADP_TDCC_ToHost
+ * ------------------
+ * Summary: Send Data down Comms Channel in ToHost direction.
+ *
+ * Arguments:
+ * Send:   (word nbytes, words data)
+ * Return: (word status)
+ *
+ * 'nbytes' is number of BYTES to be transferred from the target to the
+ *  host via the Debug Comms channel.
+ * 'data' is (nbytes/sizeof(word)) WORDS of data to be transferred from
+ *  the target to the host via the Debug Comms channel.
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ *
+ * NOTE: Equivalent to RDP_CCToHost and RDP_CCToHostReply (just set the
+ * direction bit).
+ * NOTE II: Current implementations only support single word transfers
+ *          (nbytes = 4).
+ */
+
+
+#define ADP_TDCC_FromHost          ADPREASON(CI_TTDCC,1)
+/* ADP_TDCC_FromHost
+ * --------------------
+ * Summary: Send Data down Comms Channel in FromHost direction.
+ *
+ * Arguments:
+ * Send:   ()
+ * Return: (word status, word nbytes, words data)
+ *
+ * 'status' is RDIError_NoError to indicate success, non-zero otherwise.
+ * 'nbytes' is number of BYTES to be transferred from the host to the
+ *  target via the Debug Comms channel, or zero if the host has no data
+ *  to transfer.
+ * 'data' is (nbytes/sizeof(word)) WORDS of transferred data.
+ *
+ * NOTE: Equivalent to RDP_CCFromHost and RDP_CCFromHostReply (just set the
+ * direction bit).
+ * NOTE II: Current implementations only support single word transfers
+ *          (nbytes = 4).
+ */
+
+
+/*******************************************************************
+ *
+ * Error Codes
+ *
+ */
+
+#define RDIError_NoError                0
+
+#define RDIError_Reset                  1
+#define RDIError_UndefinedInstruction   2
+#define RDIError_SoftwareInterrupt      3
+#define RDIError_PrefetchAbort          4
+#define RDIError_DataAbort              5
+#define RDIError_AddressException       6
+#define RDIError_IRQ                    7
+#define RDIError_FIQ                    8
+#define RDIError_Error                  9
+#define RDIError_BranchThrough0         10
+
+#define RDIError_NotInitialised         128
+#define RDIError_UnableToInitialise     129
+#define RDIError_WrongByteSex           130
+#define RDIError_UnableToTerminate      131
+#define RDIError_BadInstruction         132
+#define RDIError_IllegalInstruction     133
+#define RDIError_BadCPUStateSetting     134
+#define RDIError_UnknownCoPro           135
+#define RDIError_UnknownCoProState      136
+#define RDIError_BadCoProState          137
+#define RDIError_BadPointType           138
+#define RDIError_UnimplementedType      139
+#define RDIError_BadPointSize           140
+#define RDIError_UnimplementedSize      141
+#define RDIError_NoMorePoints           142
+#define RDIError_BreakpointReached      143
+#define RDIError_WatchpointAccessed     144
+#define RDIError_NoSuchPoint            145
+#define RDIError_ProgramFinishedInStep  146
+#define RDIError_UserInterrupt          147
+#define RDIError_CantSetPoint           148
+#define RDIError_IncompatibleRDILevels  149
+
+#define RDIError_CantLoadConfig         150
+#define RDIError_BadConfigData          151
+#define RDIError_NoSuchConfig           152
+#define RDIError_BufferFull             153
+#define RDIError_OutOfStore             154
+#define RDIError_NotInDownload          155
+#define RDIError_PointInUse             156
+#define RDIError_BadImageFormat         157
+#define RDIError_TargetRunning          158
+#define RDIError_DeviceWouldNotOpen     159
+#define RDIError_NoSuchHandle           160
+#define RDIError_ConflictingPoint       161
+
+#define RDIError_LittleEndian           240
+#define RDIError_BigEndian              241
+#define RDIError_SoftInitialiseError    242
+
+#define RDIError_InsufficientPrivilege  253
+#define RDIError_UnimplementedMessage   254
+#define RDIError_UndefinedMessage       255
+
+
+#endif
+
+/* EOF adp_h */
diff --git a/gdb/rdi-share/adperr.h b/gdb/rdi-share/adperr.h
new file mode 100644 (file)
index 0000000..f90f1dc
--- /dev/null
@@ -0,0 +1,74 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Definitions of ADP error codes
+ */
+
+#ifndef angsd_adperrs_h
+#define angsd_adperrs_h
+/*
+ * ADP failure codes start at 256 to distinguish them for debug purposes
+ */
+enum AdpErrs
+{
+    adp_ok = 0,
+    adp_failed = 256,
+    adp_malloc_failure,
+    adp_illegal_args,
+    adp_device_not_found,
+    adp_device_open_failed,
+    adp_device_already_open,
+    adp_device_not_open,
+    adp_bad_channel_id,
+    adp_callback_already_registered,
+    adp_write_busy,
+    adp_bad_packet,
+    adp_seq_high,
+    adp_seq_low,
+    adp_timeout_on_open,
+    adp_abandon_boot_wait,
+    adp_late_startup,
+    adp_new_agent_starting
+};
+
+#ifndef __cplusplus
+typedef enum AdpErrs AdpErrs;
+#endif
+
+#define AdpMess_Failed             "ADP Error - unspecific failure"
+#define AdpMess_MallocFailed       "ADP Error - malloc failed"
+#define AdpMess_IllegalArgs        "ADP Error - illegal arguments"
+#define AdpMess_DeviceNotFound     "ADP Error - invalid device specified"
+#define AdpMess_DeviceOpenFailed   "ADP Error - specified device failed to open"
+#define AdpMess_DeviceAlreadyOpen  "ADP Error - device already open"
+#define AdpMess_DeviceNotOpen      "ADP Error - device not open"
+#define AdpMess_BadChannelId       "ADP Error - bad channel Id"
+#define AdpMess_CBAlreadyRegd      "ADP Error - callback already registered"
+#define AdpMess_WriteBusy          "ADP Error - write busy"
+#define AdpMess_BadPacket          "ADP Error - bad packet"
+#define AdpMess_SeqHigh            "ADP Error - sequence number too high"
+#define AdpMess_SeqLow             "ADP Error - sequence number too low"
+#define AdpMess_TimeoutOnOpen      "ADP Error - target did not respond"
+#define AdpMess_AbandonBootWait    "abandoned wait for late startup"
+#define AdpMess_LateStartup        "Target compiled with LATE_STARTUP set.\n" \
+                                   "Waiting for target...\n"                  \
+                                   "Press <Ctrl-C> to abort.\n"
+#define AdpMessLen_LateStartup    (3*80)
+#define AdpMess_NewAgentStarting   "New Debug Agent about to start.\n"
+#endif /* ndef angsd_adperr_h */
+
+/* EOF adperr.h */
diff --git a/gdb/rdi-share/angel.h b/gdb/rdi-share/angel.h
new file mode 100644 (file)
index 0000000..60a5f31
--- /dev/null
@@ -0,0 +1,177 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*> angel.h <*/
+/*---------------------------------------------------------------------------*/
+/* This header file is the main holder for the declarations and
+ * prototypes for the core Angel system. Some Angel concepts are
+ * described at the start of this file to ensure that a complete view
+ * of the Angel world can be derived purely from the source.
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * NOTE: Currently the Angel source is designed to be simple,
+ * understandable and easy to port to new hardware platforms. However,
+ * this does not always yield the highest performing system. The
+ * current layered approach introduces an overhead to the performance
+ * of the system. In a true commercial target, this code should be
+ * re-designed to build a system where the Angel logical message
+ * system, device driver and hardware accesses are merged to provide
+ * the best performance.
+ */
+/*---------------------------------------------------------------------------*/
+/* Angel overview:
+
+... some comments describing Angel ...
+
+ * Angel is designed as a kit-of-parts that can be used to provide
+ * run-time support for the development of ARM applications. The main
+ * core of Angel is in providing support for the "debug" message
+ * communication with a host system. These messages do not just cover
+ * debugging ARM processes, but also the process of downloading ARM
+ * programs or attaching to executing processes on the target.
+ *
+ * A stand-alone ROM based Angel world is the basic starting point for
+ * a system, since it will allow programs to be downloaded to the
+ * target. The ROM version of Angel will provide the generic debug
+ * support, but no system specific routines. The preferred method of
+ * using Angel is as a link library. This ensures that applications
+ * carry with them the Angel routines necessary to support debugging
+ * (and also ensure that the Angel version is up-to-date, independant
+ * of the version in the target ROM). Eventually, once a program has
+ * been fully debugged, a ROMmed version of the program can be
+ * generated with the Angel code being provided in the application.
+
+.. more comments ..
+
+ * The standard Angel routines do *NOT* perform any dynamic memory
+ * allocation. To simplify the source, and aid the porting to a non C
+ * library world, memory is either pre-allocated (as build-time
+ * globals) or actually given to the particular Angel routine by the
+ * active run-time. This ensures that the interaction between Angel
+ * and the target O/S is minimised.
+ *
+ * Notes: We sub-include more header files to keep the source
+ * modular. Since Angel is a kit-of-parts alternative systems may need
+ * to change the prototypes of particular functions, whilst
+ * maintaining a fixed external interface. e.g. using the standard
+ * DEBUG messages, but with a different communications world.
+ */
+/*---------------------------------------------------------------------------*/
+
+#ifndef __angel_h
+#define __angel_h
+
+/*---------------------------------------------------------------------------*/
+/*-- Global Angel definitions and manifests ---------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* When building Angel we may not include the standard library
+ * headers. However, it is useful coding using standard macro names
+ * since it makes the code easier to understand.
+ */
+
+typedef unsigned int  word ;
+typedef unsigned char byte ;
+
+/* The following typedefs can be used to access I/O registers: */
+typedef volatile unsigned int  vuword ;
+typedef volatile unsigned char vubyte ;
+
+/*
+ * The following typedefs are used when defining objects that may also
+ * be created on a host system, where the word size is not
+ * 32bits. This ensures that the same data values are manipulated.
+ */
+#ifdef TARGET
+typedef unsigned int unsigned32;
+typedef signed int   signed32;
+typedef        int   int32;
+
+typedef unsigned short int unsigned16;
+typedef signed   short int signed16;
+
+/*
+ * yet another solution for the bool/boolean problem, this one is
+ * copied from Scott's modifications to clx/host.h
+ */
+# ifdef IMPLEMENT_BOOL_AS_ENUM
+   enum _bool { _false, _true };
+#  define _bool enum _bool
+# elif defined(IMPLEMENT_BOOL_AS_INT) || !defined(__cplusplus)
+#  define _bool int
+#  define _false 0
+#  define _true 1
+# endif
+
+# ifdef _bool
+#  define bool _bool
+# endif
+
+# ifndef true
+#  define true _true
+#  define false _false
+# endif
+
+# ifndef YES
+#  define YES   true
+#  define NO    false
+# endif
+
+# undef TRUE             /* some OSF headers define as 1 */
+# define TRUE  true
+
+# undef FALSE            /* some OSF headers define as 1 */
+# define FALSE false
+
+# ifndef NULL
+#  define NULL 0
+# endif
+
+#else
+
+# include "host.h"
+
+#endif
+
+#ifndef IGNORE
+# define IGNORE(x) ((x)=(x))
+#endif
+
+/* The following typedef allows us to cast between integral and
+ * function pointers. This isn't allowed by direct casting when
+ * conforming to the ANSI spec.
+ */
+typedef union ansibodge
+{
+ word  w ;
+ word *wp ;
+ void *vp ;
+ byte *bp ;
+ void (*vfn)(void) ;
+ word (*wfn)(void) ;
+ int  (*ifn)(void) ;
+ byte (*bfn)(void) ;
+} ansibodge ;
+
+/*---------------------------------------------------------------------------*/
+
+/* The amount setup aside by the run-time system for stack overflow
+ * handlers to execute in. This must be at least 256bytes, since that
+ * value is assumed by the current ARM Ltd compiler.
+ * This space is _only_ kept for the USR stack, not any of the privileged
+ * mode stacks, as stack overflow on these is always fatal - there is
+ * no point attemptingto recover.  In addition is is important that
+ * Angel should keep privileged stack space requirements to a minimum.
+ */
+#define APCS_STACKGUARD 256
+
+#endif /* __angel_h */
+
+/* EOF angel.h */
diff --git a/gdb/rdi-share/ardi.c b/gdb/rdi-share/ardi.c
new file mode 100644 (file)
index 0000000..f61f724
--- /dev/null
@@ -0,0 +1,2672 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARDI.c
+ * Angel Remote Debug Interface
+ *
+ *
+ * $Revision$
+ *     $Date$
+ *
+ * This file is based on /plg/pisd/rdi.c, but instead of using RDP it uses
+ * ADP messages.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define uint HIDE_HPs_uint
+#include <signal.h>
+#undef uint
+
+
+#include "endian.h"
+#include "ardi.h"
+#include "buffers.h"
+#include "channels.h"
+#include "hostchan.h"
+#include "host.h"
+#include "bytesex.h"
+#include "dbg_cp.h"
+#include "adp.h"
+#include "hsys.h"
+#include "logging.h"
+#include "msgbuild.h"
+#include "rxtx.h"
+#include "devsw.h"
+#include "params.h"
+
+#ifdef COMPILING_ON_WINDOWS
+#  define IGNORE(x) (x = x)   /* must go after #includes to work on Windows */
+#endif
+#define NOT(x) (!(x))
+
+#define ADP_INITIAL_TIMEOUT_PERIOD 5
+
+static volatile int executing;
+static int rdi_log = 0 ; /* debugging  ? */
+
+/* we need a starting point for our first buffers, this is a safe one */
+int Armsd_BufferSize = ADP_BUFFER_MIN_SIZE;
+int Armsd_LongBufSize = ADP_BUFFER_MIN_SIZE;
+
+#ifdef WIN32
+  extern int interrupted;
+  extern int swiprocessing;
+#endif
+
+static char dummycline = 0;
+char *ardi_commandline = &dummycline ; /* exported in ardi.h */
+
+extern unsigned int heartbeat_enabled;
+
+static unsigned char *cpwords[16];
+
+typedef struct stoppedProcListElement {
+  struct stoppedProcListElement *next;
+  angel_RDI_TargetStoppedProc *fn;
+  void *arg;
+} stoppedProcListElement;
+
+static stoppedProcListElement *stopped_proc_list=NULL;
+
+const struct Dbg_HostosInterface *angel_hostif;
+static hsys_state *hstate;
+
+static void angel_DebugPrint(const char *format, ...)
+{ va_list ap;
+  va_start(ap, format);
+  angel_hostif->dbgprint(angel_hostif->dbgarg, format, ap);
+  va_end(ap);
+}
+
+#ifdef RDI_VERBOSE
+#define TracePrint(s) \
+  if (rdi_log & 2) angel_DebugPrint("\n"); \
+  if (rdi_log & 1) angel_DebugPrint s
+#else
+#define TracePrint(s)
+#endif
+
+typedef struct receive_dbgmsg_state {
+  volatile int received;
+  Packet *packet;
+} receive_dbgmsg_state;
+
+static receive_dbgmsg_state dbgmsg_state;
+
+static void receive_debug_packet(Packet *packet, void *stateptr)
+{
+  receive_dbgmsg_state *state = stateptr;
+
+  state->packet = packet;
+  state->received = 1;
+}
+
+static int register_debug_message_handler(void)
+{
+  int err;
+  dbgmsg_state.received = 0;
+
+  err = Adp_ChannelRegisterRead(CI_HADP, receive_debug_packet, &dbgmsg_state);
+#ifdef DEBUG
+  if (err!=adp_ok) angel_DebugPrint("register_debug_message_handler failed %i\n", err);
+#endif
+  return err;
+}
+
+
+static int wait_for_debug_message(int *rcode, int *debugID,
+                                  int *OSinfo1, int *OSinfo2,
+                                  int *status, Packet **packet)
+{
+  unsigned int reason;
+
+#ifdef DEBUG
+  angel_DebugPrint("wait_for_debug_message waiting for %X\n", *rcode);
+#endif
+
+  for ( ; dbgmsg_state.received == 0 ; )
+    Adp_AsynchronousProcessing(async_block_on_read);
+
+#ifdef DEBUG
+  angel_DebugPrint("wait_for_debug_message got packet\n");
+#endif
+
+  *packet = dbgmsg_state.packet;
+
+  Adp_ChannelRegisterRead(CI_HADP, NULL, NULL);
+
+  /*
+   * TODO:
+   * If ADP_Unrecognised return error.
+   * If ADP_Acknowledge - handle appropriately.
+   * If expected message read arguments and return RDIError_NoError.
+   * Note: if RDIError occurs then the data values returned are junk
+   */
+
+  unpack_message(BUFFERDATA((*packet)->pk_buffer), "%w%w%w%w%w", &reason, debugID,
+                 OSinfo1, OSinfo2, status);
+  if (reason&0xffffff == ADP_HADPUnrecognised)
+    return RDIError_UnimplementedMessage;
+  if (reason != (unsigned ) *rcode) {
+    if((reason&0xffffff) == ADP_HADPUnrecognised)
+      return RDIError_UnimplementedMessage;
+    else {
+      angel_DebugPrint("ARDI ERROR: Expected reasoncode %x got reasoncode %x.\n",
+             *rcode, reason);
+      return RDIError_Error;
+    }
+  }
+  else
+    return RDIError_NoError;
+  return RDIError_Error;    /* stop a pesky ANSI compiler warning */
+}
+
+
+/*
+ * Handler and registration for logging messages from target
+ */
+static void TargetLogCallback( Packet *packet, void *state )
+{
+    p_Buffer     reply = BUFFERDATA(packet->pk_buffer);
+    unsigned int len   = packet->pk_length;
+    IGNORE(state);
+    angel_hostif->write(angel_hostif->hostosarg,
+                        (char *)reply, len - CHAN_HEADER_SIZE);
+    DevSW_FreePacket(packet);
+
+    packet = DevSW_AllocatePacket(4); /* better not ask for 0 */
+    /* the reply is the ACK - any contents are ignored */
+    if (packet != NULL)
+       Adp_ChannelWrite( CI_TLOG, packet );
+}
+
+static void TargetLogInit( void )
+{
+    AdpErrs err = Adp_ChannelRegisterRead( CI_TLOG, TargetLogCallback, NULL );
+
+#ifdef DEBUG
+    if (err != adp_ok)
+       angel_DebugPrint("CI_TLOG RegisterRead failed %d\n", err);
+#else
+    IGNORE(err);
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_open-----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+typedef struct NegotiateState {
+      bool             negotiate_resp;
+      bool             negotiate_ack;
+      bool             link_check_resp;
+      ParameterConfig *accepted_config;
+} NegotiateState;
+
+static void receive_negotiate(Packet *packet, void *stateptr)
+{
+    unsigned reason, debugID, OSinfo1, OSinfo2, status;
+    NegotiateState *n_state = (NegotiateState *)stateptr;
+    p_Buffer reply = BUFFERDATA(packet->pk_buffer);
+
+    unpack_message( reply, "%w%w%w%w",
+                    &reason, &debugID, &OSinfo1, &OSinfo2 );
+    reply += ADP_DEFAULT_HEADER_SIZE;
+
+#ifdef DEBUG
+    angel_DebugPrint( "receive_negotiate: reason %x\n", reason );
+#endif
+
+    switch ( reason )
+    {
+        case ADP_ParamNegotiate | TtoH:
+        {
+            n_state->negotiate_resp = TRUE;
+
+            status = GET32LE( reply );
+            reply += sizeof(word);
+#ifdef DEBUG
+            angel_DebugPrint( "ParamNegotiate status %u\n", status );
+#endif
+            if ( status == RDIError_NoError )
+            {
+                if ( Angel_ReadParamConfigMessage(
+                         reply, n_state->accepted_config ) )
+                   n_state->negotiate_ack = TRUE;
+            }
+            break;
+        }
+
+        case ADP_LinkCheck | TtoH:
+        {
+#ifdef DEBUG
+            angel_DebugPrint( "PONG!\n" );
+#endif
+            n_state->link_check_resp = TRUE;
+            break;
+        }
+
+        default:
+        {
+#ifdef DEBUG
+            angel_DebugPrint( "Unexpected!\n" );
+#endif
+            break;
+        }
+    }
+    DevSW_FreePacket( packet );
+}
+
+# include <sys/types.h>
+#ifdef __unix
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+/*
+ * convert a config into a single-valued options list
+ */
+static ParameterOptions *config_to_options( const ParameterConfig *config )
+{
+    unsigned int        num_params;
+    size_t              size;
+    ParameterOptions   *base_p;
+
+    num_params  = config->num_parameters;
+    size        =
+        sizeof(ParameterOptions)
+        + num_params*(sizeof(ParameterList) + sizeof(unsigned int));
+    base_p      = malloc( size );
+
+    if ( base_p != NULL )
+    {
+        unsigned int    u;
+        ParameterList  *list_p          =
+            (ParameterList *)((char *)base_p + sizeof(ParameterOptions));
+        unsigned int   *option_p        =
+            (unsigned int *)(list_p + num_params);
+
+        base_p->num_param_lists = num_params;
+        base_p->param_list = list_p;
+
+        for ( u = 0; u < num_params; ++u )
+        {
+            option_p[u]                 = config->param[u].value;
+            list_p[u].type              = config->param[u].type;
+            list_p[u].num_options       = 1;
+            list_p[u].option            = &option_p[u];
+        }
+    }
+
+    return base_p;
+}
+
+static AdpErrs negotiate_params( const ParameterOptions *user_options )
+{
+    Packet                    *packet;
+    unsigned int               count;
+    static Parameter           params[AP_NUM_PARAMS];
+    static ParameterConfig     accepted_config = { AP_NUM_PARAMS, params };
+
+    time_t t;
+
+    static volatile NegotiateState    n_state = {
+        FALSE, FALSE, FALSE, &accepted_config };
+
+#ifdef DEBUG
+    angel_DebugPrint( "negotiate_params\n" );
+#endif
+
+    Adp_ChannelRegisterRead( CI_HBOOT, receive_negotiate, (void *)&n_state );
+
+    packet = (Packet *)DevSW_AllocatePacket(Armsd_BufferSize);
+    count = msgbuild( BUFFERDATA(packet->pk_buffer), "%w%w%w%w",
+                      ADP_ParamNegotiate | HtoT, 0,
+                      ADP_HandleUnknown, ADP_HandleUnknown );
+    count += Angel_BuildParamOptionsMessage(
+        BUFFERDATA(packet->pk_buffer) + count, user_options );
+    packet->pk_length = count;
+    Adp_ChannelWriteAsync( CI_HBOOT, packet );
+
+#ifdef DEBUG
+    angel_DebugPrint( "sent negotiate packet\n" );
+#endif
+
+    t=time(NULL);
+
+    do {
+      Adp_AsynchronousProcessing(async_block_on_nothing);
+
+      if ((time(NULL)-t) > ADP_INITIAL_TIMEOUT_PERIOD) {
+        return adp_timeout_on_open;
+      }
+    } while ( ! n_state.negotiate_resp );
+
+    if ( n_state.negotiate_ack )
+    {
+        /* select accepted config */
+        Adp_Ioctl( DC_SET_PARAMS, (void *)n_state.accepted_config );
+
+        /*
+         * 960430 KWelton
+         *
+         * There is a race in the renegotiation protocol: the
+         * target has to have had time to load new config before
+         * we send the link check packet - insert a deliberate
+         * pause (100ms) to give the target some time
+         */
+        Adp_delay(100000);
+
+        /* do link check */
+        msgsend( CI_HBOOT, "%w%w%w%w", ADP_LinkCheck | HtoT, 0,
+                 ADP_HandleUnknown, ADP_HandleUnknown );
+#ifdef DEBUG
+        angel_DebugPrint("sent link check\n");
+#endif
+
+        do {
+            Adp_AsynchronousProcessing(async_block_on_read);
+        } while ( ! n_state.link_check_resp );
+        Adp_initSeq();
+    }
+    return adp_ok;
+}
+
+static int late_booted = FALSE;
+static bool ardi_handler_installed = FALSE;
+
+#ifdef __unix
+static struct sigaction old_action;
+#else
+static void (*old_handler)();
+#endif
+
+static bool boot_interrupted = FALSE;
+
+static void ardi_sigint_handler(int sig) {
+#ifdef DEBUG
+    if (sig != SIGINT)
+       angel_DebugPrint("Expecting SIGINT got %d.\n", sig);
+#else
+    IGNORE(sig);
+#endif
+    boot_interrupted = TRUE;
+#ifndef __unix
+    signal(SIGINT, ardi_sigint_handler);
+#endif
+}
+
+static void install_ardi_handler( void ) {
+  if (!ardi_handler_installed) {
+    /* install a new Ctrl-C handler so we can abandon waiting */
+#ifdef __unix
+    struct sigaction new_action;
+    sigemptyset(&new_action.sa_mask);
+    new_action.sa_handler = ardi_sigint_handler;
+    new_action.sa_flags = 0;
+    sigaction(SIGINT, &new_action, &old_action);
+#else
+    old_handler = signal(SIGINT, ardi_sigint_handler);
+#endif
+    ardi_handler_installed = TRUE;
+  }
+}
+
+static int angel_RDI_errmess(char *buf, int blen, int errnum);
+
+static void receive_reset_acknowledge(Packet *packet, void *stateptr) {
+  unsigned reason, debugID, OSinfo1, OSinfo2, status;
+  IGNORE(stateptr);
+
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", &reason, &debugID,
+                 &OSinfo1, &OSinfo2, &status);
+  if (reason==(ADP_Reset | TtoH) && status==AB_NORMAL_ACK) {
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: Successfully received normal reset acknowledgement\n");
+    late_booted = FALSE;
+#endif
+  } else if (reason==(ADP_Reset | TtoH) && status==AB_LATE_ACK) {
+    char late_msg[AdpMessLen_LateStartup];
+    int  late_len;
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: Successfully received LATE reset acknowledgement\n");
+#endif
+    late_booted = TRUE;
+    install_ardi_handler();
+    late_len = angel_RDI_errmess(late_msg,
+                                 AdpMessLen_LateStartup, adp_late_startup);
+    angel_hostif->write(angel_hostif->hostosarg, late_msg, late_len);
+  } else {
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: Bad reset ack: reason=%8X, status=%8X\n", reason, status);
+#endif
+  }
+  DevSW_FreePacket(packet);
+}
+
+static int booted_not_received;
+static unsigned int angel_version;
+static unsigned int adp_version;
+static unsigned int arch_info;
+static unsigned int cpu_info;
+static unsigned int hw_status;
+
+static void receive_booted(Packet *packet, void *stateptr) {
+  unsigned reason, debugID, OSinfo1, OSinfo2, banner_length, bufsiz, longsiz;
+  unsigned i, count;
+
+  IGNORE(stateptr);
+
+  count = unpack_message(BUFFERDATA(packet->pk_buffer),
+                         "%w%w%w%w%w%w%w%w%w%w%w%w",
+                 &reason, &debugID, &OSinfo1, &OSinfo2, &bufsiz, &longsiz,
+                 &angel_version, &adp_version,
+                 &arch_info, &cpu_info, &hw_status, &banner_length);
+  if (reason==(ADP_Booted | TtoH)) {
+#ifdef MONITOR_DOWNLOAD_PACKETS
+    angel_DebugPrint("DEBUG: Successfully received Booted\n");
+    angel_DebugPrint("       cpu_info=%8X, hw_status=%8X, bufsiz=%d, longsiz=%d\n",
+           cpu_info, hw_status, bufsiz, longsiz);
+#endif
+    /* Get the banner from the booted message */
+    for (i=0; i<banner_length; i++)
+      angel_hostif->writec(angel_hostif->hostosarg,
+                          (BUFFERDATA(packet->pk_buffer)+count)[i]);
+
+    booted_not_received=0;
+#ifndef NO_HEARTBEAT
+    heartbeat_enabled = TRUE;
+#endif
+    Armsd_BufferSize = bufsiz + CHAN_HEADER_SIZE;
+    Armsd_LongBufSize = longsiz + CHAN_HEADER_SIZE;
+  } else {
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: Bad Booted msg: reason=%8X\n", reason);
+#endif
+  }
+  DevSW_FreePacket(packet);
+}
+
+
+/* forward declaration */
+static int angel_negotiate_defaults( void );
+
+/* Open communications. */
+int angel_RDI_open(
+    unsigned type, Dbg_ConfigBlock const *config,
+    Dbg_HostosInterface const *hostif, struct Dbg_MCState *dbg_state)
+{
+  Packet *packet;
+  int status, reasoncode, debugID, OSinfo1, OSinfo2, err;
+  ParameterOptions *user_options = NULL;
+
+  time_t t;
+
+  IGNORE( dbg_state );
+
+  if ((type & 1) == 0) {
+    /* cold start */
+    if (hostif != NULL) {
+      angel_hostif = hostif;
+      err = HostSysInit(hostif, &ardi_commandline, &hstate);
+      if (err != RDIError_NoError) {
+#ifdef DEBUG
+        angel_DebugPrint("DEBUG: HostSysInit error %i\n",err);
+#endif
+        return err;
+      }
+    }
+    TargetLogInit();
+  }
+
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Buffer allocated in angel_RDI_open(type=%i).\n",type);
+#endif
+
+  if ((type & 1) == 0) {
+    /* cold start */
+    unsigned endian;
+    Adp_Ioctl( DC_GET_USER_PARAMS, (void *)&user_options );
+    if ( user_options != NULL ) {
+      err = negotiate_params( user_options );
+      if (err != adp_ok) return err;
+    }
+    else {
+      ParameterConfig *default_config = NULL;
+      Adp_Ioctl( DC_GET_DEFAULT_PARAMS, (void *)&default_config );
+      if ( default_config != NULL ) {
+        ParameterOptions *default_options = config_to_options(default_config);
+        err = negotiate_params( default_options );
+        if (err != adp_ok) return err;
+      }
+    }
+
+    /* Register handlers before sending any messages */
+    booted_not_received=1;
+    Adp_ChannelRegisterRead(CI_HBOOT, receive_reset_acknowledge, NULL);
+    Adp_ChannelRegisterRead(CI_TBOOT, receive_booted, NULL);
+    endian = 0;
+    if (config!=NULL) {
+      if (config->bytesex & RDISex_Little) endian |= ADP_BootHostFeature_LittleEnd;
+      if (config->bytesex & RDISex_Big) endian |= ADP_BootHostFeature_BigEnd;
+    }
+    msgsend(CI_HBOOT,"%w%w%w%w%w", ADP_Reset | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown, endian);
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: Transmitted Reset message in angel_RDI_open.\n");
+#endif
+
+    /* We will now either get an acknowledgement for the Reset message
+     * or if the target was started after the host, we will get a
+     * rebooted message first.
+     */
+
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: waiting for a booted message\n");
+#endif
+
+    {
+      boot_interrupted = FALSE;
+
+      if (late_booted)
+        install_ardi_handler();
+
+      t=time(NULL);
+
+      do {
+        Adp_AsynchronousProcessing(async_block_on_nothing);
+        if ((time(NULL)-t) > ADP_INITIAL_TIMEOUT_PERIOD && !late_booted) {
+          return adp_timeout_on_open;
+        }
+      } while (booted_not_received && !boot_interrupted);
+
+      if (ardi_handler_installed)
+      {
+        /* uninstall our Ctrl-C handler */
+#ifdef __unix
+        sigaction(SIGINT, &old_action, NULL);
+#else
+        signal(SIGINT, old_handler);
+#endif
+      }
+
+      if (boot_interrupted) {
+        angel_negotiate_defaults();
+        return adp_abandon_boot_wait;
+      }
+    }
+
+    booted_not_received=1;
+    Adp_ChannelRegisterRead(CI_HBOOT, NULL, NULL);
+
+    /* Leave the booted handler installed */
+    msgsend(CI_TBOOT, "%w%w%w%w%w", ADP_Booted | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown, 0);
+    Adp_initSeq();
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: Transmitted ADP_Booted acknowledgement.\n");
+    angel_DebugPrint("DEBUG: Boot sequence completed, leaving angel_RDI_open.\n");
+#endif
+
+    return (hw_status & ADP_CPU_BigEndian )? RDIError_BigEndian :
+      RDIError_LittleEndian;
+  }
+  else {
+    /* warm start */
+    register_debug_message_handler();
+
+    msgsend(CI_HADP, "%w%w%w%w",
+            ADP_InitialiseApplication | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown);
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: Transmitted Initialise Application\n");
+#endif
+    reasoncode=ADP_InitialiseApplication | TtoH;
+    err = wait_for_debug_message(&reasoncode, &debugID, &OSinfo1, &OSinfo2,
+                                &status, &packet);
+    if (err != RDIError_NoError) return err;
+    return status;
+  }
+  return -1;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_close----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+static int angel_negotiate_defaults( void ) {
+    int err = adp_ok;
+    ParameterConfig *default_config = NULL;
+    Adp_Ioctl( DC_GET_DEFAULT_PARAMS, (void *)&default_config );
+    if ( default_config != NULL ) {
+        ParameterOptions *default_options = config_to_options(default_config);
+        err = negotiate_params( default_options );
+        free( default_options );
+    }
+    return err;
+}
+
+int angel_RDI_close(void) {
+/*Angel host exit */
+  int err;
+  int status,debugID, OSinfo1,OSinfo2;
+  int reason;
+  Packet *packet = NULL;;
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Entered angel_RDI_Close.\n");
+#endif
+
+  register_debug_message_handler();
+
+  heartbeat_enabled = FALSE;
+
+  err = msgsend(CI_HADP,"%w%w%w%w",ADP_End | HtoT,0,
+          ADP_HandleUnknown, ADP_HandleUnknown);
+  if (err != RDIError_NoError) return err;
+  reason = ADP_End | TtoH;
+  err =  wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                                  &status, &packet);
+  DevSW_FreePacket(packet);
+  if (err != RDIError_NoError) return err;
+  if (status == RDIError_NoError) {
+    err = angel_negotiate_defaults();
+    if (err != adp_ok) return err;
+    Adp_Ioctl( DC_RESET, NULL ); /* just to be safe */
+    return HostSysExit(hstate);
+  }
+  else
+      return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_read-----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Read memory contents from target to host: use ADP_Read */
+int angel_RDI_read(ARMword source, void *dest, unsigned *nbytes)
+{
+  Packet *packet=NULL;
+  int len;                               /* Integer to hold message length. */
+  unsigned int nbtogo = *nbytes, nbinpacket, nbdone=0;
+  int rnbytes = 0, status, reason, debugID, OSinfo1, OSinfo2, err;
+  unsigned int maxlen = Armsd_BufferSize-CHAN_HEADER_SIZE-ADP_ReadHeaderSize;
+
+  /* Print debug trace information, this is just copied straight from rdi.c
+     and I can see no reason why it should have to be changed. */
+  TracePrint(("angel_RDI_read: source=%.8lx dest=%p nbytes=%.8x\n",
+                (unsigned long)source, dest, *nbytes));
+  if (*nbytes == 0) return RDIError_NoError;       /* Read nothing - easy! */
+  /* check the buffer size */
+  while (nbtogo >0) {
+    register_debug_message_handler();
+
+    nbinpacket = (nbtogo <= maxlen) ? nbtogo : maxlen;
+    len = msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_Read | HtoT, 0,
+                  ADP_HandleUnknown, ADP_HandleUnknown, source+nbdone,
+                  nbinpacket);
+    reason=ADP_Read | TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                                &status, &packet);
+    TracePrint(("angel_RDI_read: nbinpacket =%d status=%08x err = %d\n",
+                nbinpacket,status,err));
+    if (err != RDIError_NoError) return err;       /* Was there an error? */
+    if (status == RDIError_NoError){
+      rnbytes += PREAD(LE,(unsigned int *)(BUFFERDATA(packet->pk_buffer)+20));
+      TracePrint(("angel_RDI_read: rnbytes = %d\n",rnbytes));
+      memcpy(((unsigned char *)dest)+nbdone, BUFFERDATA(packet->pk_buffer)+24,
+             nbinpacket);
+    }
+    nbdone += nbinpacket;
+    nbtogo -= nbinpacket;
+  }
+  *nbytes -= rnbytes;
+  return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_write----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Transfer memory block from host to target.  Use ADP_Write>. */
+int angel_RDI_write(const void *source, ARMword dest, unsigned *nbytes)
+{
+  Packet *packet;/* Message buffers. */
+  unsigned int len, nbtogo = *nbytes, nboffset = 0, nbinpacket;
+  int status, reason, debugID, OSinfo1, OSinfo2, err;
+  unsigned int maxlen = Armsd_LongBufSize-CHAN_HEADER_SIZE-ADP_WriteHeaderSize;
+
+  TracePrint(("angel_RDI_write: source=%p dest=%.8lx nbytes=%.8x\n",
+                 source, (unsigned long)dest, *nbytes));
+
+  if (*nbytes == 0) return RDIError_NoError;
+
+  *nbytes = 0;
+  while (nbtogo > 0) {
+    packet = (Packet *) DevSW_AllocatePacket(Armsd_LongBufSize);
+    nbinpacket = (nbtogo <= maxlen) ? nbtogo : maxlen;
+    len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w",
+                   ADP_Write | HtoT, 0, ADP_HandleUnknown,
+                   ADP_HandleUnknown, dest+nboffset, nbinpacket);
+    /* Copy the data into the packet. */
+
+    memcpy(BUFFERDATA(packet->pk_buffer)+len,
+           ((const unsigned char *) source)+nboffset, nbinpacket);
+    nboffset += nbinpacket;
+    packet->pk_length = nbinpacket+len;
+
+#ifdef MONITOR_DOWNLOAD_PACKETS
+    angel_DebugPrint("angel_RDI_write packet size=%i, bytes done=%i\n",
+            nbinpacket, nboffset);
+#endif
+
+    register_debug_message_handler();
+    Adp_ChannelWrite(CI_HADP, packet);
+    reason=ADP_Write | TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                                &status, &packet);
+    nbtogo -= nbinpacket;
+    if (err != RDIError_NoError) return err;
+    if (status == RDIError_NoError)
+      *nbytes += nbinpacket;
+
+    DevSW_FreePacket(packet);
+  }
+  return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_CPUread--------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Reads the values of registers in the CPU, uses ADP_CPUwrite. */
+int angel_RDI_CPUread(unsigned mode, unsigned long mask, ARMword *buffer)
+{
+  unsigned int i, j;
+  Packet *packet = NULL;
+  int err, status, reason, debugID, OSinfo1, OSinfo2;
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Entered angel_RDI_CPUread.\n");
+#endif
+  for (i=0, j=0 ; i < RDINumCPURegs ; i++)
+    if (mask & (1L << i)) j++;            /* Count the number of registers. */
+
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%c%w", ADP_CPUread | HtoT, 0,
+          ADP_HandleUnknown, ADP_HandleUnknown, mode, mask);
+  reason = ADP_CPUread | TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return err;
+  }
+  if(status == RDIError_NoError) {
+    for (i=0; i<j; i++)
+      buffer[i] = GET32LE(BUFFERDATA(packet->pk_buffer)+20+(i*4));
+    TracePrint(("angel_RDI_CPUread: mode=%.8x mask=%.8lx", mode, mask));
+    DevSW_FreePacket(packet);
+#ifdef RDI_VERBOSE
+    if (rdi_log & 1) {
+      unsigned k;
+      for (k = 0, j = 0 ; j <= 20 ; j++)
+        if (mask & (1L << j)) {
+          angel_DebugPrint("%c%.8lx",k%4==0?'\n':' ',
+                           (unsigned long)buffer[k]);
+          k++ ;
+        }
+      angel_DebugPrint("\n") ;
+    }
+#endif
+
+  }
+  return status;
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_CPUwrite-------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Write CPU registers: use ADP_CPUwrite. */
+int angel_RDI_CPUwrite(unsigned mode, unsigned long mask,
+                      ARMword const *buffer){
+
+  unsigned i, j, c;
+  Packet *packet;
+  int status, reason, debugID, OSinfo1, OSinfo2, err, len;
+
+  TracePrint(("angel_RDI_CPUwrite: mode=%.8x mask=%.8lx", mode, mask));
+#ifdef RDI_VERBOSE
+ if (rdi_log & 1) {
+    for (j = 0, i = 0 ; i <= 20 ; i++)
+       if (mask & (1L << i)) {
+          angel_DebugPrint("%c%.8lx",j%4==0?'\n':' ',
+                           (unsigned long)buffer[j]);
+          j++ ;
+          }
+    angel_DebugPrint("\n") ;
+    }
+#endif
+ packet = (Packet *)DevSW_AllocatePacket(Armsd_BufferSize);
+ for (i=0, j=0; i < RDINumCPURegs ; i++)
+   if (mask & (1L << i)) j++; /* count the number of registers */
+
+ len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%b%w",
+                ADP_CPUwrite | HtoT, 0,
+                ADP_HandleUnknown, ADP_HandleUnknown, mode, mask);
+ for(c=0; c<j; c++)
+   PUT32LE(BUFFERDATA(packet->pk_buffer)+len+(c*4), buffer[c]);
+ packet->pk_length = len+(j*4);
+ register_debug_message_handler();
+
+ Adp_ChannelWrite(CI_HADP, packet);
+ reason = ADP_CPUwrite | TtoH;
+ err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                             &status, &packet);
+ unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", &reason, &debugID,
+                &OSinfo1, &OSinfo2, &status);
+ DevSW_FreePacket(packet);
+ if (err != RDIError_NoError)
+   return err;      /* Was there an error? */
+ else
+   return status;
+ }
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_CPread---------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Read coprocessor's internal state.  See dbg_cp.h for help.
+ * Use ADP_CPRead.
+ * It would appear that the correct behaviour at this point is to leave
+ * the unpacking to a the caller and to simply copy the stream of data
+ * words into the buffer
+ */
+
+int angel_RDI_CPread(unsigned CPnum, unsigned long mask, ARMword *buffer){
+  Packet *packet = NULL;
+  int i, j, status, reasoncode, OSinfo1, OSinfo2, err, debugID;
+  unsigned char *rmap = cpwords[CPnum];
+  int n;
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Entered angel_RDI_CPread.\n");
+#endif
+  if (rmap == NULL) return RDIError_UnknownCoPro;
+
+  register_debug_message_handler();
+  n = rmap[-1];
+  msgsend(CI_HADP, "%w%w%w%w%b%w", ADP_CPread | HtoT, 0,
+          ADP_HandleUnknown, ADP_HandleUnknown, CPnum, mask);
+  reasoncode=ADP_CPread | TtoH;
+  err = wait_for_debug_message(&reasoncode, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return err;          /* Was there an error? */
+  }
+  for (j=i=0; i < n ; i++) /* count the number of registers */
+    if (mask & (1L << i)) {
+      j++;
+    }
+  for (i=0; i<j; i++)
+    buffer[i] = PREAD32(LE, BUFFERDATA(packet->pk_buffer) + 20 + (i*4));
+  DevSW_FreePacket(packet);
+  TracePrint(("angel_RDI_CPread: CPnum=%.8x mask=%.8lx\n", CPnum, mask));
+#ifdef RDI_VERBOSE
+  if (rdi_log & 1) {
+    for (i = 0, j = 0; j < n ; j++) {
+      if (mask & (1L << j)) {
+        int nw = rmap[j];
+        angel_DebugPrint("%2d ", j);
+        while (--nw > 0)
+          angel_DebugPrint("%.8lx ", (unsigned long)buffer[i++]);
+        angel_DebugPrint("%.8lx\n", (unsigned long)buffer[i++]);
+      }
+    }
+  }
+#endif
+  return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_CPwrite--------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Write coprocessor's internal state.  See dbg_cp.h for help. Use
+ * ADP_CPwrite.
+ */
+
+int angel_RDI_CPwrite(unsigned CPnum, unsigned long mask,
+                      ARMword const *buffer)
+{
+  Packet *packet = NULL;
+  int i, j, len, status, reason, OSinfo1, OSinfo2, err, debugID;
+  unsigned char *rmap = cpwords[CPnum];
+  int n;
+
+  if (rmap == NULL) return RDIError_UnknownCoPro;
+  n = rmap[-1];
+
+  TracePrint(("angel_RDI_CPwrite: CPnum=%d mask=%.8lx\n", CPnum, mask));
+
+#ifdef RDI_VERBOSE
+ if (rdi_log & 1) {
+    for (i = 0, j = 0; j < n ; j++)
+       if (mask & (1L << j)) {
+          int nw = rmap[j];
+          angel_DebugPrint("%2d ", j);
+          while (--nw > 0)
+             angel_DebugPrint("%.8lx ", (unsigned long)buffer[i++]);
+          angel_DebugPrint("%.8lx\n", (unsigned long)buffer[i++]);
+       }
+ }
+#endif
+
+  for (j=i=0; i < n ; i++) /* Count the number of registers. */
+    if (mask & (1L << i)) j++;
+  packet = DevSW_AllocatePacket(Armsd_BufferSize);
+  len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%c%w",
+                 ADP_CPwrite | HtoT, 0,
+                 ADP_HandleUnknown, ADP_HandleUnknown, CPnum, mask);
+  for(i=0;  i<j; i++)
+    len+=msgbuild(BUFFERDATA(packet->pk_buffer) + len, "%w", buffer[i]);
+  packet->pk_length = len;
+  register_debug_message_handler();
+  Adp_ChannelWrite(CI_HADP, packet);    /* Transmit message. */
+  reason=ADP_CPwrite | TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  DevSW_FreePacket(packet);
+  if (err != RDIError_NoError)
+    return err;
+  else
+    return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_pointinq-------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Do test calls to ADP_SetBreak/ADP_SetWatch to see if resources exist to
+   carry out request. */
+int angel_RDI_pointinq(ARMword *address, unsigned type, unsigned datatype,
+                       ARMword *bound)
+{
+  Packet *packet = NULL;
+  int len, status, reason, OSinfo1, OSinfo2, err=RDIError_NoError;
+       /* stop a compiler warning */
+  int debugID, pointhandle;
+  TracePrint(
+      ("angel_RDI_pointinq: address=%.8lx type=%d datatype=%d bound=%.8lx ",
+      (unsigned long)*address, type, datatype, (unsigned long)*bound));
+       /* for a buffer.  */
+  packet = DevSW_AllocatePacket(Armsd_BufferSize);
+  len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%b",
+                 ((datatype == 0) ? ADP_SetBreak : ADP_SetWatch) | HtoT, 0,
+                 ADP_HandleUnknown, ADP_HandleUnknown, address, type);
+  if (datatype == 0)
+    len += msgbuild(BUFFERDATA(packet->pk_buffer) + 21, "%w", bound);
+  else
+    len += msgbuild(BUFFERDATA(packet->pk_buffer) + 21, "%b%w", datatype, bound);
+
+  register_debug_message_handler();
+  packet->pk_length = len;
+  Adp_ChannelWrite(CI_HADP, packet);
+  reason = ((datatype == 0) ? ADP_SetBreak : ADP_SetWatch | TtoH);
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return err;        /* Was there an error? */
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w",
+                 &reason, &debugID, &OSinfo1, &OSinfo2, &status,
+                 &pointhandle, &address, &bound);
+  DevSW_FreePacket(packet);
+  return err;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_setbreak-------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Set a breakpoint: Use ADP_SetBreak */
+int angel_RDI_setbreak(ARMword address, unsigned type, ARMword bound,
+                      PointHandle *handle)
+{
+  int status, reason, OSinfo1, OSinfo2, err, debugID;
+  int tmpval, tmpaddr, tmpbnd;
+  Packet *packet;
+  TracePrint(("angel_RDI_setbreak address=%.8lx type=%d bound=%.8lx \n",
+              (unsigned long)address, type, (unsigned long)bound));
+
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w%b%w",
+          ADP_SetBreak| HtoT, 0,  ADP_HandleUnknown,
+          ADP_HandleUnknown, address, type, bound);
+  reason = ADP_SetBreak |TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return err;         /* Was there an error? */
+  }
+  /* Work around varargs problem... -sts */
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w",
+                 &reason, &debugID, &OSinfo1, &OSinfo2, &status,
+                 &tmpval, &tmpaddr, &tmpbnd);
+  *handle = tmpval;
+  address = tmpaddr;
+  bound = tmpbnd;
+  DevSW_FreePacket(packet);
+  if (status != RDIError_NoError) return status;
+  TracePrint(("returns handle %.8lx\n", (unsigned long)*handle));
+  return RDIError_NoError;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_clearbreak-----------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Clear a breakpoint: Use ADP_ClearBreak. */
+int angel_RDI_clearbreak(PointHandle handle)
+{
+  Packet *packet = NULL;
+  int status, reason, OSinfo1, OSinfo2, err, debugID;
+
+  TracePrint(("angel_RDI_clearbreak: handle=%.8lx\n", (unsigned long)handle));
+
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w",
+          ADP_ClearBreak| HtoT, 0,  ADP_HandleUnknown,
+          ADP_HandleUnknown, handle);
+  reason = ADP_ClearBreak|TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    angel_DebugPrint("***RECEIVE DEBUG MESSAGE RETURNED ERR = %d.\n", err);
+    return err;          /* Was there an error? */
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w",  &reason,
+                 &debugID, &OSinfo1, &OSinfo2, &status);
+  DevSW_FreePacket(packet);
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Clear Break completed OK.\n");
+#endif
+  return RDIError_NoError;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_setwatch-------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Set a watchpoint: use ADP_SetWatch. */
+int angel_RDI_setwatch(ARMword address, unsigned type, unsigned datatype,
+                       ARMword bound, PointHandle *handle)
+{
+  Packet *packet = NULL;
+  int status, reason, OSinfo1, OSinfo2, err, debugID;
+
+  TracePrint(("angel_RDI_setwatch: address=%.8lx type=%d bound=%.8lx ",
+              (unsigned long)address, type, (unsigned long)bound));
+
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w%b%b%w",
+          ADP_SetWatch| HtoT, 0,  ADP_HandleUnknown,
+          ADP_HandleUnknown, address, type, datatype, bound);
+
+  reason = ADP_SetWatch | TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return err;        /* Was there an error? */
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w",
+                 &reason, &debugID, &OSinfo1, &OSinfo2, &status,
+                 handle, &address, &bound);
+  DevSW_FreePacket(packet);
+  TracePrint(("returns handle %.8lx\n", (unsigned long)*handle));
+  return RDIError_NoError;
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_clearwatch-----------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Clear a watchpoint: use ADP_ClearWatch. */
+int angel_RDI_clearwatch(PointHandle handle) {
+
+  int status, reason, OSinfo1, OSinfo2, err, debugID;
+  Packet *packet = NULL;
+
+  TracePrint(("angel_RDI_clearwatch: handle=%.8lx\n", (unsigned long)handle));
+
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w",
+          ADP_ClearWatch| HtoT, 0,  ADP_HandleUnknown,
+          ADP_HandleUnknown, handle);
+  reason = ADP_ClearWatch|TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return err;        /* Was there an error? */
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w",  &reason, &debugID,
+                 &OSinfo1, &OSinfo2, &status);
+  DevSW_FreePacket(packet);
+  return RDIError_NoError;
+}
+
+typedef struct {
+  unsigned stopped_reason;
+  int stopped_status;
+  int data;
+} adp_stopped_struct;
+
+
+int angel_RDI_OnTargetStopping(angel_RDI_TargetStoppedProc *fn,
+                               void *arg)
+{
+  stoppedProcListElement **lptr = &stopped_proc_list;
+
+  /* Find the address of the NULL ptr at the end of the list */
+  for (; *lptr!=NULL ; lptr = &((*lptr)->next))
+    ; /* Do nothing */
+
+  *lptr = (stoppedProcListElement *) malloc(sizeof(stoppedProcListElement));
+  if (*lptr == NULL) return RDIError_OutOfStore;
+  (*lptr)->fn = fn;
+  (*lptr)->arg = arg;
+
+  return RDIError_NoError;
+}
+
+static int CallStoppedProcs(unsigned reason)
+{
+  stoppedProcListElement *p = stopped_proc_list;
+  int err=RDIError_NoError;
+  
+  for (; p!=NULL ; p=p->next) {
+    int local_err = p->fn(reason, p->arg);
+    if (local_err != RDIError_NoError) err=local_err;
+  }
+
+  return err;
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_execute--------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+static int HandleStoppedMessage(Packet *packet, void *stateptr) {
+  unsigned int err,  reason, debugID, OSinfo1, OSinfo2, count;
+  adp_stopped_struct *stopped_info;
+  stopped_info = (adp_stopped_struct *) stateptr;
+  IGNORE(stateptr);
+  count = unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w",
+                         &reason, &debugID,
+                         &OSinfo1, &OSinfo2,
+                         &stopped_info->stopped_reason, &stopped_info->data);
+  DevSW_FreePacket(packet);
+
+  if (reason != (ADP_Stopped | TtoH)) {
+#ifdef DEBUG
+    angel_DebugPrint("Expecting stopped message, got %x", reason);
+#endif
+    return RDIError_Error;
+  }
+  else {
+    executing = FALSE;
+#ifdef DEBUG
+    angel_DebugPrint("Received stopped message.\n");
+#endif
+  }
+
+  err = msgsend(CI_TADP,  "%w%w%w%w%w", (ADP_Stopped | HtoT), 0,
+                ADP_HandleUnknown, ADP_HandleUnknown, RDIError_NoError);
+#ifdef DEBUG
+  angel_DebugPrint("Transmiting stopped acknowledge.\n");
+#endif
+  if (err != RDIError_NoError) angel_DebugPrint("Transmit failed.\n");
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Stopped reason : %x\n", stopped_info->stopped_reason);
+#endif
+  switch (stopped_info->stopped_reason) {
+  case ADP_Stopped_BranchThroughZero:
+    stopped_info->stopped_status = RDIError_BranchThrough0;
+    break;
+  case ADP_Stopped_UndefinedInstr:
+    stopped_info->stopped_status = RDIError_UndefinedInstruction;
+    break;
+  case ADP_Stopped_SoftwareInterrupt:
+    stopped_info->stopped_status = RDIError_SoftwareInterrupt;
+    break;
+  case ADP_Stopped_PrefetchAbort:
+    stopped_info->stopped_status = RDIError_PrefetchAbort;
+    break;
+  case ADP_Stopped_DataAbort:
+    stopped_info->stopped_status = RDIError_DataAbort;
+    break;
+  case ADP_Stopped_AddressException:
+    stopped_info->stopped_status = RDIError_AddressException;
+    break;
+  case ADP_Stopped_IRQ:
+    stopped_info->stopped_status = RDIError_IRQ;
+    break;
+  case ADP_Stopped_BreakPoint:
+    stopped_info->stopped_status = RDIError_BreakpointReached;
+    break;
+  case ADP_Stopped_WatchPoint:
+    stopped_info->stopped_status = RDIError_WatchpointAccessed;
+    break;
+  case ADP_Stopped_StepComplete:
+    stopped_info->stopped_status = RDIError_ProgramFinishedInStep;
+    break;
+  case ADP_Stopped_RunTimeErrorUnknown:
+  case ADP_Stopped_StackOverflow:
+  case ADP_Stopped_DivisionByZero:
+    stopped_info->stopped_status = RDIError_Error;
+    break;
+  case ADP_Stopped_FIQ:
+    stopped_info->stopped_status = RDIError_FIQ;
+    break;
+  case ADP_Stopped_UserInterruption:
+  case ADP_Stopped_OSSpecific:
+    stopped_info->stopped_status = RDIError_UserInterrupt;
+    break;
+  case ADP_Stopped_ApplicationExit:
+    stopped_info->stopped_status = RDIError_NoError;
+    break;
+  default:
+    stopped_info->stopped_status = RDIError_NoError;
+    break;
+  }
+  return RDIError_NoError;
+}
+
+static volatile bool interrupt_request = FALSE;
+
+static void interrupt_target( void )
+{
+    Packet *packet = NULL;
+    int err;
+    int reason, debugID, OSinfo1, OSinfo2, status;
+
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: interrupt_target.\n");
+#endif
+
+    register_debug_message_handler();
+    msgsend(CI_HADP, "%w%w%w%w", ADP_InterruptRequest | HtoT, 0,
+                   ADP_HandleUnknown, ADP_HandleUnknown);
+
+    reason = ADP_InterruptRequest |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+    DevSW_FreePacket(packet);
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: got interrupt ack ok err = %d, status=%i\n",
+                     err, status);
+#endif
+
+    return;
+}
+
+#ifdef TEST_DC_APPL
+  extern void test_dc_appl_handler( const DeviceDescr *device,
+                                    Packet *packet );
+#endif
+
+/* Core functionality for execute and step */
+static int angel_RDI_ExecuteOrStep(PointHandle *handle, word type, 
+                                   unsigned ninstr)
+{
+  int err;
+  adp_stopped_struct stopped_info;
+  void* stateptr = (void *)&stopped_info;
+  ChannelCallback HandleStoppedMessageFPtr=(ChannelCallback) HandleStoppedMessage;
+  int status, reasoncode, debugID, OSinfo1, OSinfo2;
+  Packet *packet = NULL;
+
+  TracePrint(("angel_RDI_ExecuteOrStep\n"));
+
+  err = Adp_ChannelRegisterRead(CI_TADP,
+                                HandleStoppedMessageFPtr, stateptr);
+  if (err != RDIError_NoError) {
+#ifdef DEBUG
+    angel_DebugPrint("TADP Register failed.\n");
+#endif
+    return err;
+  }
+  /* Set executing TRUE here, as it must be set up before the target has
+   * had any chance at all to execute, or it may send its stopped message
+   * before we get round to setting executing = TRUE !!!
+   */
+  executing = TRUE;
+
+  register_debug_message_handler();
+
+#ifdef TEST_DC_APPL
+  Adp_Install_DC_Appl_Handler( test_dc_appl_handler );
+#endif
+
+#ifdef DEBUG
+  angel_DebugPrint("Transmiting %s message.\n",
+                   type == ADP_Execute ? "execute": "step");
+#endif
+
+  register_debug_message_handler();
+  /* Extra ninstr parameter for execute message will simply be ignored */
+  err = msgsend(CI_HADP,"%w%w%w%w%w", type | HtoT, 0,
+                ADP_HandleUnknown, ADP_HandleUnknown, ninstr);
+#if DEBUG
+  if (err != RDIError_NoError) angel_DebugPrint("Transmit failed.\n");
+#endif
+
+  reasoncode = type | TtoH;
+  err = wait_for_debug_message( &reasoncode, &debugID, &OSinfo1, &OSinfo2,
+                                &status, &packet );
+  if (err != RDIError_NoError)
+     return err;
+  else if (status != RDIError_NoError)
+     return status;
+
+#ifdef DEBUG
+  angel_DebugPrint("Waiting for program to finish...\n");
+#endif
+
+  while( executing )
+  {
+      if (interrupt_request)
+      {
+        interrupt_target();
+        interrupt_request = FALSE;
+      }
+      Adp_AsynchronousProcessing( async_block_on_nothing );
+  }
+
+#ifdef TEST_DC_APPL
+  Adp_Install_DC_Appl_Handler( NULL );
+#endif
+
+  (void)Adp_ChannelRegisterRead(CI_TADP, NULL, NULL);
+
+  *handle = (PointHandle)stopped_info.data;
+
+  CallStoppedProcs(stopped_info.stopped_reason);
+
+  return stopped_info.stopped_status;
+}
+
+/* Request that the target starts executing from the stored CPU state: use
+   ADP_Execute. */
+int angel_RDI_execute(PointHandle *handle)
+{
+    return angel_RDI_ExecuteOrStep(handle, ADP_Execute, 0);
+}
+
+#ifdef __WATCOMC__
+typedef void handlertype(int);
+
+static int interrupted=0;
+
+static void myhandler(int sig) {
+  IGNORE(sig);
+  interrupted=1;
+  signal(SIGINT, myhandler);
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_step-----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Step 'ninstr' through the code: use ADP_Step. */
+int angel_RDI_step(unsigned ninstr, PointHandle *handle)
+{
+    int err = angel_RDI_ExecuteOrStep(handle, ADP_Step, ninstr);
+    if (err == RDIError_ProgramFinishedInStep)
+       return RDIError_NoError;
+    else
+       return err;
+}
+
+
+static void SetCPWords(int cpnum, struct Dbg_CoProDesc const *cpd) {
+  int i, rmax = 0;
+  for (i = 0; i < cpd->entries; i++)
+    if (cpd->regdesc[i].rmax > rmax)
+      rmax = cpd->regdesc[i].rmax;
+
+  { unsigned char *rmap = (unsigned char *)malloc(rmax + 2);
+    *rmap++ = rmax + 1;
+    for (i = 0; i < cpd->entries; i++) {
+      int r;
+      for (r = cpd->regdesc[i].rmin; r <= cpd->regdesc[i].rmax; r++)
+        rmap[r] = (cpd->regdesc[i].nbytes+3) / 4;
+      }
+/*    if (cpwords[cpnum] != NULL) free(cpwords[cpnum]); */
+    cpwords[cpnum] = rmap;
+  }
+}
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_info-----------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Use ADP_Info, ADP_Ctrl and ADP_Profile calls to implement these,
+   see adp.h for more details. */
+
+static int angel_cc_exists( void )
+{
+  Packet *packet = NULL;
+  int err;
+  int reason, debugID, OSinfo1, OSinfo2, subreason, status;
+
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: ADP_ICEB_CC_Exists.\n");
+#endif
+
+  if ( angel_RDI_info( RDIInfo_Icebreaker, NULL, NULL ) == RDIError_NoError ) {
+    register_debug_message_handler();
+    msgsend(CI_HADP, "%w%w%w%w%w", ADP_ICEbreakerHADP | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown,
+            ADP_ICEB_CC_Exists );
+    reason = ADP_ICEbreakerHADP |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                                &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    }
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+                   &debugID, &OSinfo1, &OSinfo2,  &subreason, &status);
+    if (subreason !=  ADP_ICEB_CC_Exists) {
+      DevSW_FreePacket(packet);
+      return RDIError_Error;
+    }
+    else
+      return status;
+  }
+  else
+    return RDIError_UnimplementedMessage;
+}
+
+typedef struct {
+  RDICCProc_ToHost *tohost; void *tohostarg;
+  RDICCProc_FromHost *fromhost; void *fromhostarg;
+  bool registered;
+} CCState;
+static CCState ccstate = { NULL, NULL, NULL, NULL, FALSE };
+
+static void HandleDCCMessage( Packet *packet, void *stateptr )
+{
+  unsigned int reason, debugID, OSinfo1, OSinfo2;
+  int count;
+  CCState *ccstate_p = (CCState *)stateptr;
+
+  count = unpack_message( BUFFERDATA(packet->pk_buffer), "%w%w%w%w",
+                          &reason, &debugID, &OSinfo1, &OSinfo2 );
+  switch ( reason )
+  {
+      case ADP_TDCC_ToHost | TtoH:
+      {
+           /* only handles a single word of data, for now */
+
+          unsigned int nbytes, data;
+
+          unpack_message( BUFFERDATA(packet->pk_buffer)+count, "%w%w",
+                          &nbytes, &data );
+#ifdef DEBUG
+          angel_DebugPrint( "DEBUG: received CC_ToHost message: nbytes %d data %08x.\n",
+                  nbytes, data );
+#endif
+          ccstate_p->tohost( ccstate_p->tohostarg, data );
+          msgsend(CI_TTDCC, "%w%w%w%w%w",
+                  ADP_TDCC_ToHost | HtoT, debugID, OSinfo1, OSinfo2,
+                  RDIError_NoError );
+          break;
+      }
+
+      case ADP_TDCC_FromHost | TtoH:
+      {
+           /* only handles a single word of data, for now */
+
+          int valid;
+          ARMword data;
+
+          ccstate_p->fromhost( ccstate_p->fromhostarg, &data, &valid );
+#ifdef DEBUG
+          angel_DebugPrint( "DEBUG: received CC_FromHost message, returning: %08x %s.\n",
+                  data, valid ? "VALID" : "INvalid" );
+#endif
+          msgsend(CI_TTDCC, "%w%w%w%w%w%w%w",
+                  ADP_TDCC_FromHost | HtoT, debugID, OSinfo1, OSinfo2,
+                  RDIError_NoError, valid ? 1 : 0, data );
+          break;
+      }
+
+      default:
+#ifdef DEBUG
+      angel_DebugPrint( "Unexpected TDCC message %08x received\n", reason );
+#endif
+      break;
+  }
+  DevSW_FreePacket(packet);
+  return;
+}
+
+static void angel_check_DCC_handler( CCState *ccstate_p )
+{
+    int err;
+
+    if ( ccstate_p->tohost != NULL || ccstate_p->fromhost != NULL )
+    {
+        /* doing DCC, so need a handler */
+        if ( ! ccstate_p->registered )
+        {
+#ifdef DEBUG
+            angel_DebugPrint( "Registering handler for TTDCC channel.\n" );
+#endif
+            err = Adp_ChannelRegisterRead( CI_TTDCC, HandleDCCMessage,
+                                           ccstate_p );
+            if ( err == adp_ok )
+               ccstate_p->registered = TRUE;
+#ifdef DEBUG
+            else
+               angel_DebugPrint( "angel_check_DCC_handler: register failed!\n" );
+#endif
+        }
+    }
+    else
+    {
+        /* not doing DCC, so don't need a handler */
+        if ( ccstate_p->registered )
+        {
+#ifdef DEBUG
+            angel_DebugPrint( "Unregistering handler for TTDCC channel.\n" );
+#endif
+            err = Adp_ChannelRegisterRead( CI_TTDCC, NULL, NULL );
+            if ( err == adp_ok )
+               ccstate_p->registered = FALSE;
+#ifdef DEBUG
+            else
+               angel_DebugPrint( "angel_check_DCC_handler: unregister failed!\n" );
+#endif
+        }
+    }
+}
+
+
+static int CheckSubMessageReply(int reason, int subreason) {
+  Packet *packet = NULL;
+  int status, debugID, OSinfo1, OSinfo2;
+  int err = RDIError_NoError;
+  reason |= TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                               &status, &packet);
+  if (err != RDIError_NoError) {
+    status = err;
+  } else {
+    int sr;
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+                   &OSinfo1, &OSinfo2, &sr, &status);
+    if (subreason != sr) status = RDIError_Error;
+  }
+  DevSW_FreePacket(packet);
+  return status;
+}
+
+static int SendSubMessageAndCheckReply(int reason, int subreason) {
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w", reason | HtoT, 0,
+          ADP_HandleUnknown, ADP_HandleUnknown,
+          subreason);
+  return CheckSubMessageReply(reason, subreason);
+}
+
+static int SendSubMessageWordAndCheckReply(int reason, int subreason, ARMword word) {
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w%w", reason | HtoT, 0,
+          ADP_HandleUnknown, ADP_HandleUnknown,
+          subreason, word);
+  return CheckSubMessageReply(reason, subreason);
+}
+
+static int SendSubMessageGetWordAndCheckReply(int reason, int subreason, ARMword *resp) {
+  Packet *packet = NULL;
+  int status, debugID, OSinfo1, OSinfo2;
+  int err = RDIError_NoError;
+
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w", reason | HtoT, 0,
+          ADP_HandleUnknown, ADP_HandleUnknown,
+          subreason);
+  reason |= TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                               &status, &packet);
+  if (err != RDIError_NoError) {
+    status = err;
+  } else {
+    int sr;
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w", &reason, &debugID,
+                   &OSinfo1, &OSinfo2,  &sr, &status, resp);
+    if (subreason != sr) status = RDIError_Error;
+  }
+  DevSW_FreePacket(packet);
+  return status;
+}
+
+static int const hostsex = 1;
+
+int angel_RDI_info(unsigned type, ARMword *arg1, ARMword *arg2) {
+  Packet *packet = NULL;
+  int len, status, c, reason, subreason, debugID, OSinfo1, OSinfo2;
+  int err=RDIError_NoError, cpnum=0;
+  struct Dbg_CoProDesc *cpd;
+  int count, i;
+  unsigned char *bp;
+
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Entered angel_RDI_info.\n");
+#endif
+  switch (type) {
+  case RDIInfo_Target:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_Target.\n");
+#endif
+
+    register_debug_message_handler();
+    msgsend(CI_HADP, "%w%w%w%w%w", ADP_Info | HtoT, 0,
+                 ADP_HandleUnknown, ADP_HandleUnknown, ADP_Info_Target);
+    reason = ADP_Info |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    }
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w", &reason,
+                   &debugID, &OSinfo1, &OSinfo2,  &subreason, &status,
+                   arg1, arg2);
+    DevSW_FreePacket(packet);
+
+    if (subreason !=  ADP_Info_Target)
+      return RDIError_Error;
+    else
+      return status;
+
+  case RDISignal_Stop:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDISignal_Stop.\n");
+    if (interrupt_request)
+       angel_DebugPrint("       STILL WAITING to send previous interrupt request\n");
+#endif
+    interrupt_request = TRUE;
+    return RDIError_NoError;
+
+  case RDIInfo_Points:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_Points.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_Info, ADP_Info_Points, arg1);
+
+  case RDIInfo_Step:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_Step.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_Info, ADP_Info_Step, arg1);
+
+  case RDISet_Cmdline:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDISet_Cmdline.\n");
+#endif
+    if (ardi_commandline != &dummycline)
+      free(ardi_commandline);
+    ardi_commandline = (char *)malloc(strlen((char*)arg1) + 1) ;
+    (void)strcpy(ardi_commandline, (char *)arg1) ;
+    return RDIError_NoError;
+
+  case RDIInfo_SetLog:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_SetLog.\n");
+#endif
+    rdi_log = (int) *arg1;
+    return RDIError_NoError;
+
+  case RDIInfo_Log:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_Log.\n");
+#endif
+    *arg1 = rdi_log;
+    return RDIError_NoError;
+
+
+  case RDIInfo_MMU:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_MMU.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_Info, ADP_Info_MMU, arg1);
+
+  case RDIInfo_SemiHosting:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_SemiHosting.\n");
+#endif
+    return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_SemiHosting);
+
+  case RDIInfo_CoPro:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_CoPro.\n");
+#endif
+    return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_CoPro);
+
+  case RDICycles:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDICycles.\n");
+#endif
+    register_debug_message_handler();
+    msgsend(CI_HADP, "%w%w%w%w%w", ADP_Info | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown, ADP_Info_Cycles);
+    reason = ADP_Info |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    }
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+                 &OSinfo1, &OSinfo2,  &subreason, &status);
+    DevSW_FreePacket(packet);
+    if (subreason !=  ADP_Info_Cycles)
+      return RDIError_Error;
+    if (status != RDIError_NoError) return status;
+    for (c=0; c<12; c++)
+      arg1[c]=GET32LE(BUFFERDATA(packet->pk_buffer)+24+(c*4));
+    return status;
+
+  case RDIInfo_DescribeCoPro:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_DescribeCoPro.\n");
+#endif
+    cpnum = *(int *)arg1;
+    cpd = (struct Dbg_CoProDesc *)arg2;
+    packet = DevSW_AllocatePacket(Armsd_BufferSize);
+    if (angel_RDI_info(ADP_Info_CoPro, NULL, NULL) != RDIError_NoError)
+      return RDIError_Error;
+    len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", ADP_Info | HtoT, 0,
+                   ADP_HandleUnknown, ADP_HandleUnknown,
+                   ADP_Info_DescribeCoPro);
+    len +=msgbuild(BUFFERDATA(packet->pk_buffer)+20, "%b%b%b%b%b", cpnum,
+                   cpd->regdesc[cpnum].rmin, cpd->regdesc[cpnum].rmax,
+                   cpd->regdesc[cpnum].nbytes, cpd->regdesc[cpnum].access);
+    if (cpd->regdesc[cpnum].access&0x3 == 0x3){
+      len += msgbuild(BUFFERDATA(packet->pk_buffer)+25, "%b%b%b%b%b",
+                      cpd->regdesc[cpnum].accessinst.cprt.read_b0,
+                      cpd->regdesc[cpnum].accessinst.cprt.read_b1,
+                      cpd->regdesc[cpnum].accessinst.cprt.write_b0,
+                      cpd->regdesc[cpnum].accessinst.cprt.write_b1, 0xff);
+    }
+    else {
+      len += msgbuild(BUFFERDATA(packet->pk_buffer)+25, "%b%b%b%b%b%",
+                      cpd->regdesc[cpnum].accessinst.cpdt.rdbits,
+                      cpd->regdesc[cpnum].accessinst.cpdt.nbit,0,0, 0xff);
+    }
+    register_debug_message_handler();
+    packet->pk_length = len;
+    Adp_ChannelWrite(CI_HADP, packet); /* Transmit message. */
+    reason = ADP_Info |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                                &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    }
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+                   &OSinfo1, &OSinfo2, &subreason, &status);
+    DevSW_FreePacket(packet);
+    if (subreason != ADP_Info_DescribeCoPro)
+      return RDIError_Error;
+    else
+      return status;
+
+  case RDIInfo_RequestCoProDesc:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: RDIInfo_RequestCoProDesc.\n");
+#endif
+    cpnum = *(int *)arg1;
+    cpd = (struct Dbg_CoProDesc *)arg2;
+    packet = DevSW_AllocatePacket(Armsd_BufferSize);
+    len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w", ADP_Info | HtoT, 0,
+                   ADP_HandleUnknown, ADP_HandleUnknown,
+                   ADP_Info_RequestCoProDesc);
+    len += msgbuild(BUFFERDATA(packet->pk_buffer)+20, "%b", *(int *)arg1);
+    packet->pk_length = len;
+    register_debug_message_handler();
+    Adp_ChannelWrite(CI_HADP, packet); /* Transmit message. */
+    reason = ADP_Info |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    }
+    count = unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+                           &debugID, &OSinfo1, &OSinfo2,  &subreason, &status);
+    if (subreason !=  ADP_Info_RequestCoProDesc) {
+      DevSW_FreePacket(packet);
+      return RDIError_Error;
+    } else if ( status != RDIError_NoError ) {
+      DevSW_FreePacket(packet);
+      return status;
+    } else {
+      bp = BUFFERDATA(packet->pk_buffer)+count;
+      for ( i = 0; *bp != 0xFF && i < cpd->entries; ++i ) {
+        cpd->regdesc[i].rmin = *bp++;
+        cpd->regdesc[i].rmax = *bp++;
+        cpd->regdesc[i].nbytes = *bp++;
+        cpd->regdesc[i].access = *bp++;
+      }
+      cpd->entries = i;
+      if ( *bp != 0xFF )
+        status = RDIError_BufferFull;
+      else
+        SetCPWords( cpnum, cpd );
+      DevSW_FreePacket(packet);
+      return status;
+    }
+
+  case RDIInfo_GetLoadSize:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Info_AngelBufferSize.\n");
+#endif
+    register_debug_message_handler();
+    msgsend(CI_HADP, "%w%w%w%w%w", ADP_Info | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown,
+            ADP_Info_AngelBufferSize);
+    reason = ADP_Info |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    }
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+                   &debugID, &OSinfo1, &OSinfo2,  &subreason, &status);
+    if (subreason !=  ADP_Info_AngelBufferSize) {
+      DevSW_FreePacket(packet);
+      return RDIError_Error;
+    }
+    else {
+      word defaultsize, longsize;
+      unpack_message(BUFFERDATA(packet->pk_buffer)+24, "%w%w",
+                     &defaultsize, &longsize);
+      *arg1 = longsize - ADP_WriteHeaderSize;   /* space for ADP header */
+#ifdef MONITOR_DOWNLOAD_PACKETS
+      angel_DebugPrint("DEBUG: ADP_Info_AngelBufferSize: got (%d, %d), returning %d.\n",
+             defaultsize, longsize, *arg1);
+#endif
+      DevSW_FreePacket(packet);
+      return status;
+    }
+
+  case RDIVector_Catch:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_VectorCatch %lx.\n", *arg1);
+#endif
+    return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_VectorCatch, *arg1);
+
+  case RDISemiHosting_SetState:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_SetState %lx.\n", *arg1);
+#endif
+    return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_SetState, *arg1);
+
+  case RDISemiHosting_GetState:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_GetState.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_GetState, arg1);
+
+  case RDISemiHosting_SetVector:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_SetVector %lx.\n", *arg1);
+#endif
+    return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_SetVector, *arg1);
+
+  case RDISemiHosting_GetVector:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_GetVector.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_GetVector, arg1);
+
+  case RDISemiHosting_SetARMSWI:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_SetARMSWI.\n");
+#endif
+    return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_SetARMSWI, *arg1);
+
+  case RDISemiHosting_GetARMSWI:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_GetARMSWI.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_GetARMSWI, arg1);
+
+  case RDISemiHosting_SetThumbSWI:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_SetThumbSWI.\n");
+#endif
+    return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_SetThumbSWI, *arg1);
+
+  case RDISemiHosting_GetThumbSWI:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SemiHosting_GetThumbSWI.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_Control, ADP_Ctrl_SemiHosting_GetThumbSWI, arg1);
+
+  case RDIInfo_SetTopMem:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_SetTopMem.\n");
+#endif
+    return SendSubMessageWordAndCheckReply(ADP_Control, ADP_Ctrl_SetTopMem, *arg1);
+
+  case RDIPointStatus_Watch:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_PointStatus_Watch.\n");
+#endif
+    register_debug_message_handler();
+    msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_Control | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown,
+            ADP_Ctrl_PointStatus_Watch, *arg1 );
+    reason = ADP_Control |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    }
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w", &reason,
+                   &debugID, &OSinfo1, &OSinfo2,  &subreason, &status,
+                   arg1, arg2);
+    if (subreason !=  ADP_Ctrl_PointStatus_Watch) {
+      DevSW_FreePacket(packet);
+      return RDIError_Error;
+    }
+    else
+      return status;
+
+  case RDIPointStatus_Break:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_PointStatus_Break.\n");
+#endif
+    register_debug_message_handler();
+    msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_Control | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown,
+            ADP_Ctrl_PointStatus_Break, *arg1 );
+    reason = ADP_Control |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    }
+    unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w", &reason,
+                   &debugID, &OSinfo1, &OSinfo2,  &subreason, &status,
+                   arg1, arg2);
+    if (subreason !=  ADP_Ctrl_PointStatus_Break) {
+      DevSW_FreePacket(packet);
+      return RDIError_Error;
+    }
+    else
+      return status;
+
+  case RDIInfo_DownLoad:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Ctrl_Download_Supported.\n");
+#endif
+    return SendSubMessageAndCheckReply(ADP_Control, ADP_Ctrl_Download_Supported);
+
+  case RDIConfig_Count:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_ICEM_ConfigCount.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_ICEman, ADP_ICEM_ConfigCount, arg1);
+
+  case RDIConfig_Nth:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_ICEM_ConfigNth.\n");
+#endif
+    register_debug_message_handler();
+    msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_ICEman | HtoT, 0,
+            ADP_HandleUnknown, ADP_HandleUnknown,
+            ADP_ICEM_ConfigNth, *arg1 );
+    reason = ADP_ICEman |TtoH;
+    err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+    if (err != RDIError_NoError) {
+      DevSW_FreePacket(packet);
+      return err;
+    } else {
+      RDI_ConfigDesc *cd = (RDI_ConfigDesc *)arg2;
+      unsigned char n;
+      len = unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%b",
+                           &reason, &debugID,
+                           &OSinfo1, &OSinfo2,  &subreason, &status,
+                           &cd->version, &n);
+      if (subreason !=  ADP_ICEM_ConfigNth) {
+        DevSW_FreePacket(packet);
+        return RDIError_Error;
+      }
+      else {
+        memcpy( cd->name, BUFFERDATA(packet->pk_buffer)+len, n+1 );
+        cd->name[n] = 0;
+        return status;
+      }
+    }
+
+  case RDIInfo_Icebreaker:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_ICEB_Exists.\n");
+#endif
+    return SendSubMessageAndCheckReply(ADP_ICEbreakerHADP, ADP_ICEB_Exists);
+
+  case RDIIcebreaker_GetLocks:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_ICEB_GetLocks.\n");
+#endif
+    return SendSubMessageGetWordAndCheckReply(ADP_ICEbreakerHADP, ADP_ICEB_GetLocks, arg1);
+
+  case RDIIcebreaker_SetLocks:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_ICEB_SetLocks.\n");
+#endif
+    return SendSubMessageWordAndCheckReply(ADP_ICEbreakerHADP, ADP_ICEB_SetLocks, *arg1);
+
+  case RDICommsChannel_ToHost:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_ICEB_CC_Connect_ToHost.\n");
+#endif
+    if ( angel_cc_exists() == RDIError_NoError ) {
+
+    /*
+     * The following three lines of code have to be removed in order to get
+     * the Windows Angel Channel Viewer working with the Thumb comms channel.
+     * At the moment it allows the ARMSD command line to register a CCIN/CCOUT
+     * callback which stops the ACV working!
+     */
+#ifdef __unix
+      ccstate.tohost = (RDICCProc_ToHost *)arg1;
+      ccstate.tohostarg = arg2;
+      angel_check_DCC_handler( &ccstate );
+#endif
+#ifdef _WIN32
+      
+#endif
+
+      register_debug_message_handler();
+      msgsend(CI_HADP, "%w%w%w%w%w%b", ADP_ICEbreakerHADP | HtoT, 0,
+              ADP_HandleUnknown, ADP_HandleUnknown,
+              ADP_ICEB_CC_Connect_ToHost, (arg1 != NULL) );
+      return CheckSubMessageReply(ADP_ICEbreakerHADP, ADP_ICEB_CC_Connect_ToHost);
+    } else {
+      return RDIError_UnimplementedMessage;
+    }
+
+  case RDICommsChannel_FromHost:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_ICEB_CC_Connect_FromHost.\n");
+#endif
+    if ( angel_cc_exists() == RDIError_NoError ) {
+
+      ccstate.fromhost = (RDICCProc_FromHost *)arg1;
+      ccstate.fromhostarg = arg2;
+      angel_check_DCC_handler( &ccstate );
+
+      register_debug_message_handler();
+      msgsend(CI_HADP, "%w%w%w%w%w%b", ADP_ICEbreakerHADP | HtoT, 0,
+              ADP_HandleUnknown, ADP_HandleUnknown,
+              ADP_ICEB_CC_Connect_FromHost, (arg1 != NULL) );
+      return CheckSubMessageReply(ADP_ICEbreakerHADP, ADP_ICEB_CC_Connect_FromHost);
+    } else {
+      return RDIError_UnimplementedMessage;
+    }
+
+  case RDIProfile_Stop:
+    return SendSubMessageAndCheckReply(ADP_Profile, ADP_Profile_Stop);
+
+  case RDIProfile_ClearCounts:
+    return SendSubMessageAndCheckReply(ADP_Profile, ADP_Profile_ClearCounts);
+
+  case RDIProfile_Start:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: ADP_Profile_Start %ld.\n", (long)*arg1);
+#endif
+    return SendSubMessageWordAndCheckReply(ADP_Profile, ADP_Profile_Start, *arg1);
+
+  case RDIProfile_WriteMap:
+    { RDI_ProfileMap *map = (RDI_ProfileMap *)arg1;
+      int32 maplen = map->len,
+            offset,
+            size;
+      int32 chunk = (Armsd_LongBufSize-CHAN_HEADER_SIZE-ADP_ProfileWriteHeaderSize) / sizeof(ARMword);
+                     /* Maximum number of words sendable in one message */
+      int oldrev = bytesex_reversing();
+      int host_little = *(uint8 const *)&hostsex;
+#ifdef DEBUG
+      angel_DebugPrint("DEBUG: ADP_Profile_WriteMap %ld.\n", maplen);
+#endif
+      status = RDIError_NoError;
+      if (!host_little) {
+        bytesex_reverse(1);
+        for (offset = 0; offset < maplen; offset++)
+          map->map[offset] = bytesex_hostval(map->map[offset]);
+      }
+      for (offset = 0; offset < maplen; offset += size) {
+        unsigned hdrlen;
+        size = maplen - offset;
+        packet = (Packet *)DevSW_AllocatePacket(Armsd_LongBufSize);
+        if (size > chunk) size = chunk;
+        hdrlen = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w%w",
+                          ADP_Profile | HtoT, 0, ADP_HandleUnknown,
+                          ADP_HandleUnknown, ADP_Profile_WriteMap,
+                          maplen, size, offset);
+
+        /* Copy the data into the packet. */
+        memcpy(BUFFERDATA(packet->pk_buffer)+hdrlen,
+               &map->map[offset], (size_t)size * sizeof(ARMword));
+        packet->pk_length = size * sizeof(ARMword) + hdrlen;
+        register_debug_message_handler();
+        Adp_ChannelWrite(CI_HADP, packet);
+        reason = ADP_Profile | TtoH;
+        err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                                     &status, &packet);
+        if (err == RDIError_NoError) {
+          unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+                         &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+          if (subreason !=  ADP_Profile_WriteMap) {
+            err = RDIError_Error;
+          }
+          DevSW_FreePacket(packet);
+        }
+        if (err != RDIError_NoError) { status = err; break; }
+      }
+      if (!host_little) {
+        for (offset = 0; offset < maplen; offset++)
+          map->map[offset] = bytesex_hostval(map->map[offset]);
+        bytesex_reverse(oldrev);
+      }
+      return status;
+    }
+
+  case RDIProfile_ReadMap:
+    { int32 maplen = *(int32 *)arg1,
+            offset = 0,
+            size;
+      int32 chunk = (Armsd_BufferSize-CHAN_HEADER_SIZE-ADP_ProfileReadHeaderSize) / sizeof(ARMword);
+#ifdef DEBUG
+      angel_DebugPrint("DEBUG: ADP_Profile_ReadMap %ld.\n", maplen);
+#endif
+      status = RDIError_NoError;
+      for (offset = 0; offset < maplen; offset += size) {
+        size = maplen - offset;
+        if (size > chunk) size = chunk;
+        register_debug_message_handler();
+        msgsend(CI_HADP, "%w%w%w%w%w%w%w", ADP_Profile | HtoT, 0,
+                ADP_HandleUnknown, ADP_HandleUnknown,
+                ADP_Profile_ReadMap, offset, size);
+        reason = ADP_Profile | TtoH;
+        err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                                     &status, &packet);
+        if (err != RDIError_NoError) return err;
+        unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+                       &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+        memcpy(&arg2[offset], BUFFERDATA(packet->pk_buffer)+ADP_ProfileReadHeaderSize,
+               size * sizeof(ARMword));
+        DevSW_FreePacket(packet);
+        if (status != RDIError_NoError) break;
+      }
+      { int oldrev = bytesex_reversing();
+        int host_little = *(uint8 const *)&hostsex;
+        if (!host_little) {
+          bytesex_reverse(1);
+          for (offset = 0; offset < maplen; offset++)
+            arg2[offset] = bytesex_hostval(arg2[offset]);
+        }
+        bytesex_reverse(oldrev);
+      }
+      return status;
+    }
+
+  case RDIInfo_CanTargetExecute:
+#ifdef DEBUG
+    printf("DEBUG: RDIInfo_CanTargetExecute.\n");
+#endif
+    return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_CanTargetExecute);
+
+  case RDIInfo_AgentEndianess:
+    return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_AgentEndianess);
+
+  default:
+#ifdef DEBUG
+    angel_DebugPrint("DEBUG: Fell through ADP_Info, default case taken.\n");
+    angel_DebugPrint("DEBUG: type = 0x%x.\n", type);
+#endif
+    if (type & RDIInfo_CapabilityRequest) {
+      switch (type & ~RDIInfo_CapabilityRequest) {
+        case RDISemiHosting_SetARMSWI:
+          return SendSubMessageAndCheckReply(ADP_Info, ADP_Info_ChangeableSHSWI);
+        default:
+#ifdef DEBUG
+          angel_DebugPrint(
+          "DEBUG: ADP_Info - Capability Request(%d) - reporting unimplemented \n",
+                 type & ~RDIInfo_CapabilityRequest);
+#endif
+          break;
+      }
+    }
+    return RDIError_UnimplementedMessage;
+  }
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_AddConfig------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Add a configuration: use ADP_ICEM_AddConfig. */
+int angel_RDI_AddConfig(unsigned long nbytes) {
+  Packet *packet = NULL;
+  int status, reason, subreason, debugID, OSinfo1, OSinfo2, err;
+
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Entered angel_RDI_AddConfig.\n");
+#endif
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_ICEman | HtoT,
+          0, ADP_HandleUnknown, ADP_HandleUnknown,
+          ADP_ICEM_AddConfig, nbytes);
+  reason=ADP_ICEman | TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return -1;
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+                 &OSinfo1, &OSinfo2, &subreason, &status);
+  DevSW_FreePacket(packet);
+  if ( subreason != ADP_ICEM_AddConfig )
+    return RDIError_Error;
+  else
+    return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_LoadConfigData-------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Load configuration data: use ADP_Ctrl_Download_Data. */
+int angel_RDI_LoadConfigData(unsigned long nbytes, char const *data) {
+  Packet *packet = NULL;
+  int len, status, reason, subreason, debugID, OSinfo1, OSinfo2, err;
+
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Entered angel_RDI_LoadConfigData (%d bytes)\n", nbytes);
+#endif
+#if 0
+  if (err = angel_RDI_AddConfig(nbytes) != RDIError_NoError)
+    return err;
+#endif
+  packet = DevSW_AllocatePacket(Armsd_LongBufSize);
+  len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w",
+                 ADP_Control | HtoT, 0,
+                 ADP_HandleUnknown, ADP_HandleUnknown,
+                 ADP_Ctrl_Download_Data, nbytes);
+  memcpy(BUFFERDATA(packet->pk_buffer)+len, data, nbytes);
+  len += nbytes;
+  packet->pk_length = len;
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: packet len %d.\n", len);
+#endif
+  register_debug_message_handler();
+  Adp_ChannelWrite(CI_HADP, packet);
+  reason=ADP_Control | TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return -1;
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+                 &OSinfo1, &OSinfo2, &subreason, &status);
+  DevSW_FreePacket(packet);
+  if ( subreason != ADP_Ctrl_Download_Data )
+    return RDIError_Error;
+  else
+    return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_SelectConfig---------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Select a configuration: use ADP_ICEM_SelecConfig.*/
+int angel_RDI_SelectConfig(RDI_ConfigAspect aspect, char const *name,
+                           RDI_ConfigMatchType matchtype, unsigned versionreq,
+                            unsigned *versionp)
+{
+  Packet *packet = NULL;
+  int len, status, reason, subreason, debugID, OSinfo1, OSinfo2, err;
+
+#ifdef DEBUG
+  angel_DebugPrint("DEBUG: Entered angel_RDI_SelectConfig.\n");
+#endif
+  packet = DevSW_AllocatePacket(Armsd_BufferSize);
+  len = msgbuild(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%b%b%b%w",
+                 ADP_ICEman | HtoT, 0,
+                 ADP_HandleUnknown, ADP_HandleUnknown,
+                 ADP_ICEM_SelectConfig, aspect, strlen(name),
+                 matchtype, versionreq);
+  /* copy the name into the buffer */
+  memcpy(BUFFERDATA(packet->pk_buffer)+len, name, strlen(name));
+  len += strlen(name);
+  packet->pk_length = len;
+  register_debug_message_handler();
+  Adp_ChannelWrite(CI_HADP, packet);
+  reason=ADP_ICEman | TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return err;
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w%w",
+                 &reason, &debugID, &OSinfo1, &OSinfo2,
+                 &subreason, &status, versionp);
+  DevSW_FreePacket(packet);
+  if ( subreason != ADP_ICEM_SelectConfig )
+    return RDIError_Error;
+  else
+    return status;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*----angel_RDI_LoadAgent------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+/* Load a new debug agent: use ADP_Ctrl_Download_Agent. */
+int angel_RDI_LoadAgent(ARMword dest, unsigned long size,
+                       getbufferproc *getb, void *getbarg)
+{
+  Packet *packet = NULL;
+  int  status, reason, subreason, debugID, OSinfo1, OSinfo2, err;
+  time_t t;
+
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+  angel_DebugPrint("DEBUG: Entered angel_RDI_LoadAgent.\n");
+#endif
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w%w%w", ADP_Control | HtoT,
+          0, ADP_HandleUnknown, ADP_HandleUnknown,
+          ADP_Ctrl_Download_Agent, dest, size);
+  reason=ADP_Control | TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return -1;
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason, &debugID,
+                 &OSinfo1, &OSinfo2, &subreason, &status);
+    DevSW_FreePacket(packet);
+  if ( subreason != ADP_Ctrl_Download_Agent )
+    return RDIError_Error;
+  if ( status != RDIError_NoError )
+    return status;
+
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+  angel_DebugPrint("DEBUG: starting agent data download.\n");
+#endif
+  { unsigned long pos = 0, segsize;
+    for (; pos < size; pos += segsize) {
+      char *b = getb(getbarg, &segsize);
+      if (b == NULL) return RDIError_NoError;
+      err = angel_RDI_LoadConfigData( segsize, b );
+      if (err != RDIError_NoError) return err;
+    }
+  }
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+  angel_DebugPrint("DEBUG: finished downloading new agent.\n");
+#endif
+
+  /* renegotiate back down */
+  err = angel_negotiate_defaults();
+  if (err != adp_ok)
+     return err;
+
+  /* Output a message to tell the user what is going on.  This is vital
+   * when switching from ADP EICE to ADP over JTAG, as then the user
+   * has to reset the target board !
+   */
+  { char msg[256];
+    int len=angel_RDI_errmess(msg, 256, adp_new_agent_starting);
+    angel_hostif->write(angel_hostif->hostosarg, msg, len);
+  }
+
+  /* get new image started */
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+  angel_DebugPrint("DEBUG: sending start message for new agent.\n");
+#endif
+
+  register_debug_message_handler();
+  msgsend(CI_HADP, "%w%w%w%w%w%w", ADP_Control | HtoT,
+          0, ADP_HandleUnknown, ADP_HandleUnknown,
+          ADP_Ctrl_Start_Agent, dest);
+  reason=ADP_Control | TtoH;
+  err = wait_for_debug_message(&reason, &debugID, &OSinfo1, &OSinfo2,
+                              &status, &packet);
+  if (err != RDIError_NoError) {
+    DevSW_FreePacket(packet);
+    return -1;
+  }
+  unpack_message(BUFFERDATA(packet->pk_buffer), "%w%w%w%w%w%w", &reason,
+                 &debugID, &OSinfo1, &OSinfo2, &subreason, &status);
+    DevSW_FreePacket(packet);
+  if ( subreason != ADP_Ctrl_Start_Agent )
+    return RDIError_Error;
+  if ( status != RDIError_NoError )
+    return status;
+
+  /* wait for image to start up */
+  heartbeat_enabled = FALSE;
+  t=time(NULL);
+  do {
+    Adp_AsynchronousProcessing(async_block_on_nothing);
+    if ((time(NULL)-t) > 2) {
+#ifdef DEBUG
+      angel_DebugPrint("DEBUG: no booted message from new image yet.\n");
+#endif
+      break;
+    }
+  } while (booted_not_received);
+  booted_not_received=1;
+
+  /* Give device driver a chance to do any necessary resyncing with new agent.
+   * Only used by etherdrv.c at the moment.
+   */
+  (void)Adp_Ioctl( DC_RESYNC, NULL );
+
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+  angel_DebugPrint("DEBUG: reopening to new agent.\n");
+#endif
+  err = angel_RDI_open(0, NULL, NULL, NULL);
+  switch ( err )
+  {
+      case RDIError_NoError:
+      {
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+          angel_DebugPrint( "LoadAgent: Open returned RDIError_NoError\n" );
+#endif
+          break;
+      }
+
+      case RDIError_LittleEndian:
+      {
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+          angel_DebugPrint( "LoadAgent: Open returned RDIError_LittleEndian (OK)\n" );
+#endif
+          err = RDIError_NoError;
+          break;
+      }
+
+      case RDIError_BigEndian:
+      {
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+          angel_DebugPrint( "LoadAgent: Open returned RDIError_BigEndian (OK)\n" );
+#endif
+          err = RDIError_NoError;
+          break;
+      }
+
+      default:
+      {
+#if defined(DEBUG) || defined(DEBUG_LOADAGENT)
+          angel_DebugPrint( "LoadAgent: Open returned %d - unexpected!\n", err );
+#endif
+          break;
+      }
+  }
+#ifndef NO_HEARTBEAT
+  heartbeat_enabled = TRUE;
+#endif
+  return err;
+}
+
+static int angel_RDI_errmess(char *buf, int blen, int errnum) {
+  char *s=NULL;
+  int n;
+
+  switch (errnum) {
+    case adp_malloc_failure:
+      s=AdpMess_MallocFailed; break;
+    case adp_illegal_args:
+      s=AdpMess_IllegalArgs; break;
+    case adp_device_not_found:
+      s=AdpMess_DeviceNotFound; break;
+    case adp_device_open_failed:
+      s=AdpMess_DeviceOpenFailed; break;
+    case adp_device_already_open:
+      s=AdpMess_DeviceAlreadyOpen; break;
+    case adp_device_not_open:
+      s=AdpMess_DeviceNotOpen; break;
+    case adp_bad_channel_id:
+      s=AdpMess_BadChannelId; break;
+    case adp_callback_already_registered:
+      s=AdpMess_CBAlreadyRegd; break;
+    case adp_write_busy:
+      s=AdpMess_WriteBusy; break;
+    case adp_bad_packet:
+      s=AdpMess_BadPacket; break;
+    case adp_seq_high:
+      s=AdpMess_SeqHigh; break;
+    case adp_seq_low:
+      s=AdpMess_SeqLow; break;
+    case adp_timeout_on_open:
+      s=AdpMess_TimeoutOnOpen; break;
+    case adp_failed:
+      s=AdpMess_Failed; break;
+    case adp_abandon_boot_wait:
+      s=AdpMess_AbandonBootWait; break;
+    case adp_late_startup:
+      s=AdpMess_LateStartup; break;
+    case adp_new_agent_starting:
+      s=AdpMess_NewAgentStarting; break;
+    default: return 0;
+  }
+  n=strlen(s);
+  if (n>blen-1) n=blen-1;
+  memcpy(buf, s, n);
+  buf[n++]=0;
+  return n;
+}
+
+extern const struct RDIProcVec angel_rdi;
+const struct RDIProcVec angel_rdi = {
+    "ADP",
+    angel_RDI_open,
+    angel_RDI_close,
+    angel_RDI_read,
+    angel_RDI_write,
+    angel_RDI_CPUread,
+    angel_RDI_CPUwrite,
+    angel_RDI_CPread,
+    angel_RDI_CPwrite,
+    angel_RDI_setbreak,
+    angel_RDI_clearbreak,
+    angel_RDI_setwatch,
+    angel_RDI_clearwatch,
+    angel_RDI_execute,
+    angel_RDI_step,
+    angel_RDI_info,
+    angel_RDI_pointinq,
+
+    angel_RDI_AddConfig,
+    angel_RDI_LoadConfigData,
+    angel_RDI_SelectConfig,
+
+    0, /*angel_RDI_drivernames,*/
+    0,   /* cpunames */
+
+    angel_RDI_errmess,
+
+    angel_RDI_LoadAgent
+};
+
+/* EOF ardi.c */
+
+/* Not strictly necessary, but allows linking this code into armsd. */
+
+struct foo {
+    char *name;
+    int (*action)();
+    char *syntax;
+    char **helpmessage;
+    int doafterend;
+    int dobeforestart;
+    int doinmidline;
+} hostappl_CmdTable[1] = {{"", NULL}};
+
+void
+hostappl_Init()
+{
+}
+
+int
+hostappl_Backstop()
+{
+  return -30;
+}
diff --git a/gdb/rdi-share/ardi.h b/gdb/rdi-share/ardi.h
new file mode 100644 (file)
index 0000000..66acd1a
--- /dev/null
@@ -0,0 +1,85 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ardi.h
+ * ADP RDI interfaces
+ *
+ * $Revision$
+ *     $Date$
+ */
+
+#include "host.h"
+
+typedef unsigned32 ARMword;
+
+#include "dbg_rdi.h"
+#include "dbg_conf.h"
+
+extern char *commandline;
+extern ARMword last_vector_catch;
+
+/* This is the size of buffers that are asked for by standard channels
+ * Non standard channels may wish to copy this!
+ */
+extern int Armsd_BufferSize;
+
+typedef int (*host_ChannelBufferFilledFnPtr)(unsigned int ,unsigned char ** ,void *);
+
+int angel_RDI_open(
+    unsigned type, Dbg_ConfigBlock const *config,
+    Dbg_HostosInterface const *hostif, struct Dbg_MCState *dbg_state);
+int angel_RDI_close(void);
+
+int angel_RDI_read(ARMword source, void *dest, unsigned *nbytes);
+int angel_RDI_write(const void *source, ARMword dest, unsigned *nbytes);
+
+int angel_RDI_CPUread(unsigned mode, unsigned long mask, ARMword *buffer);
+int angel_RDI_CPUwrite(unsigned mode, unsigned long mask,
+                       ARMword const *buffer);
+
+int angel_RDI_CPread(unsigned CPnum, unsigned long mask, ARMword *buffer);
+int angel_RDI_CPwrite(unsigned CPnum, unsigned long mask,
+                      ARMword const *buffer);
+
+int angel_RDI_setbreak(ARMword address, unsigned type, ARMword bound,
+                      PointHandle *handle);
+int angel_RDI_clearbreak(PointHandle handle);
+
+int angel_RDI_setwatch(ARMword address, unsigned type, unsigned datatype,
+                      ARMword bound, PointHandle *handle);
+int angel_RDI_clearwatch(PointHandle handle);
+
+int angel_RDI_pointinq(ARMword *address, unsigned type, unsigned datatype,
+                      ARMword *bound);
+
+int angel_RDI_execute(PointHandle *handle);
+
+int angel_RDI_step(unsigned ninstr, PointHandle *handle);
+
+int angel_RDI_info(unsigned type, ARMword *arg1, ARMword *arg2);
+
+int angel_RDI_AddConfig(unsigned long nbytes);
+
+int angel_RDI_LoadConfigData(unsigned long nbytes, char const *data);
+
+int angel_RDI_SelectConfig(RDI_ConfigAspect aspect, char const *name,
+                          RDI_ConfigMatchType matchtype, unsigned versionreq,
+                          unsigned *versionp);
+
+RDI_NameList const *angel_RDI_drivernames(void);
+
+int angel_RDI_LoadAgent(ARMword dest, unsigned long size, getbufferproc *getb,
+                        void *getbarg);
+
+extern const struct Dbg_HostosInterface *angel_hostif;
+
+typedef int angel_RDI_TargetStoppedProc(unsigned stopped_reason, void *arg);
+
+extern int angel_RDI_OnTargetStopping(angel_RDI_TargetStoppedProc *fn,
+                                      void *arg);
diff --git a/gdb/rdi-share/armdbg.h b/gdb/rdi-share/armdbg.h
new file mode 100644 (file)
index 0000000..b5fae11
--- /dev/null
@@ -0,0 +1,1452 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM symbolic debugger toolbox interface
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+/* Minor points of uncertainty are indicated by a question mark in the
+   LH margin.
+
+   Wherever an interface is required to iterate over things of some class,
+   I prefer something of the form  EnumerateXXs(..., XXProc *p, void *arg)
+   which results in a call of p(xx, arg) for each xx, rather than something
+   of the form
+     for (xxh = StartIterationOverXXs(); (xx = Next(xxh)) != 0; ) { ... }
+     EndIterationOverXXs(xxh);
+   Others may disagree.
+   (Each XXProc returns an Error value: if this is not Err_OK, iteration
+   stops immediately and the EnumerateXXs function returns that value).
+
+   ptrace has been retired as of insufficient utility.  If such fuctionality is
+   required, it can be constructed using breakpoints.
+
+   The file form of all name fields in debug areas is in-line, with a length
+   byte and no terminator.  The debugger toolbox makes an in-store translation,
+   where the strings are out of line (the namep variant in asdfmt.h) and have a
+   terminating zero byte: the pointer is to the first character of the string
+   with the length byte at ...->n.namep[-1].
+ */
+
+#ifndef armdbg__h
+#define armdbg__h
+
+#include <stddef.h>
+
+#include "host.h"
+#include "msg.h"
+
+typedef unsigned32 ARMaddress;
+typedef unsigned32 ARMword;
+typedef unsigned16 ARMhword;
+
+#include "dbg_conf.h"
+#include "dbg_rdi.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef unsigned char Dbg_Byte;
+
+typedef int Dbg_Error;
+
+typedef struct Dbg_MCState Dbg_MCState;
+/* A representation of the state of the target.  The structure is not revealed.
+   A pointer to one of these is returned by Dbg_Initialise(), is passed to all
+   toolbox calls which refer to the state of the target, and is discarded
+   by Dbg_Finalise().
+   Nothing in the toolbox itself precludes there being multiple targets, each
+   with its own state.
+ */
+
+/* Most toolbox interfaces return an error status.  Only a few of the status
+   values are expected to be interesting to clients and defined here; the
+   rest are private (but a textual form can be produced by ErrorToChars()).
+ */
+
+#define Error_OK 0
+
+/* Partitioning of the error code space: errors below Dbg_Error_Base are RDI
+   errors (as defined in dbg_rdi.h). Codes above Dbg_Error_Limit are
+   available to clients, who may impose some further structure.
+ */
+#define Dbg_Error_Base 0x1000
+#define Dbg_Error_Limit 0x2000
+
+#define DbgError(n) ((Dbg_Error)(Dbg_Error_Base+(n)))
+
+#define Dbg_Err_OK Error_OK
+#define Dbg_Err_Interrupted             DbgError(1)
+#define Dbg_Err_Overflow                DbgError(2)
+#define Dbg_Err_FileNotFound            DbgError(3)
+#define Dbg_Err_ActivationNotPresent    DbgError(4)
+#define Dbg_Err_OutOfHeap               DbgError(5)
+#define Dbg_Err_TypeNotSimple           DbgError(6)
+#define Dbg_Err_BufferFull              DbgError(7)
+#define Dbg_Err_AtStackBase             DbgError(8)
+#define Dbg_Err_AtStackTop              DbgError(9)
+#define Dbg_Err_DbgTableFormat          DbgError(10)
+#define Dbg_Err_NotVariable             DbgError(11)
+#define Dbg_Err_NoSuchBreakPoint        DbgError(12)
+#define Dbg_Err_NoSuchWatchPoint        DbgError(13)
+#define Dbg_Err_FileLineNotFound        DbgError(14)
+#define Dbg_Err_DbgTableVersion         DbgError(15)
+#define Dbg_Err_NoSuchPath              DbgError(16)
+#define Dbg_Err_StateChanged            DbgError(17)
+#define Dbg_Err_SoftInitialiseError     DbgError(18)
+#define Dbg_Err_CoProRegNotWritable     DbgError(19)
+#define Dbg_Err_NotInHistory            DbgError(20)
+#define Dbg_Err_ContextSyntax           DbgError(21)
+#define Dbg_Err_ContextNoLine           DbgError(22)
+#define Dbg_Err_ContextTwoLines         DbgError(23)
+#define Dbg_Err_VarReadOnly             DbgError(24)
+#define Dbg_Err_FileNewerThanImage      DbgError(25)
+#define Dbg_Err_NotFound                DbgError(26)
+
+   /* functions which evaluate expressions may return this value, to indicate
+      that execution became suspended within a function called in the debugee */
+
+/* Functions returning characters take a BufDesc argument, with fields buffer
+   and bufsize being input arguments describing the buffer to be filled, and
+   filled being set on return to the number of bytes written to the buffer
+   (omitting the terminating 0).
+ */
+
+typedef struct Dbg_BufDesc Dbg_BufDesc;
+
+typedef void Dbg_BufferFullProc(Dbg_BufDesc *bd);
+
+struct Dbg_BufDesc {
+    char *buffer;
+    size_t size,
+           filled;
+    Dbg_BufferFullProc *p;
+    void *arg;
+};
+
+#define Dbg_InitBufDesc(bd, buf, bytes) \
+    ((bd).buffer = (buf), (bd).size = (bytes), (bd).filled = 0,\
+     (bd).p = NULL, (bd).arg = NULL)
+
+#define Dbg_InitBufDesc_P(bd, buf, bytes, fn, a) \
+    ((bd).buffer = (buf), (bd).size = (bytes), (bd).filled = 0,\
+     (bd).p = (fn), (bd).arg = (a))
+
+Dbg_Error Dbg_StringToBuf(Dbg_BufDesc *buf, char const *s);
+Dbg_Error Dbg_BufPrintf(Dbg_BufDesc *buf, char const *form, ...);
+#ifdef NLS
+Dbg_Error Dbg_MsgToBuf(Dbg_BufDesc *buf, msg_t t);
+Dbg_Error Dbg_BufMsgPrintf(Dbg_BufDesc *buf, msg_t form, ...);
+#else
+#define Dbg_MsgToBuf Dbg_StringToBuf
+#define Dbg_BufMsgPrintf Dbg_BufPrintf
+#endif
+Dbg_Error Dbg_CharToBuf(Dbg_BufDesc *buf, int ch);
+
+int Dbg_CIStrCmp(char const *s1, char const *s2);
+/* Case-independent string comparison, interface as for strcmp */
+
+int Dbg_CIStrnCmp(char const *s1, char const *s2, size_t n);
+/* Case-independent string comparison, interface as for strncmp */
+
+void Dbg_ErrorToChars(Dbg_MCState *state, Dbg_Error err, Dbg_BufDesc *buf);
+
+typedef int Dbg_RDIResetCheckProc(int);
+/* Type of a function to be called after each RDI operation performed by the
+   toolbox, with the status from the operation as argument.  The value returned
+   is treated as the status.  (The intent is to allow the toolbox's client to
+   take special action to handle RDIDbg_Error_Reset).
+ */
+
+typedef struct Dbg_CoProDesc Dbg_CoProDesc;
+
+typedef Dbg_Error Dbg_CoProFoundProc(Dbg_MCState *state, int cpno, Dbg_CoProDesc const *cpd);
+/* Type of a function to be called when the shape of a coprocessor is discovered
+   by enquiry of the target or agent (via RequestCoProDesc)
+ */
+
+typedef struct RDIProcVec RDIProcVec;
+
+Dbg_Error Dbg_RequestReset(Dbg_MCState *);
+
+Dbg_Error Dbg_Initialise(
+    Dbg_ConfigBlock *config, Dbg_HostosInterface const *i,
+    Dbg_RDIResetCheckProc *checkreset, Dbg_CoProFoundProc *coprofound,
+    RDIProcVec const *rdi, Dbg_MCState **statep);
+/* values in config are updated if they call for default values */
+
+void Dbg_Finalise(Dbg_MCState *state, bool targetdead);
+
+typedef struct {
+    char name[16];
+    RDI_MemDescr md;
+    RDI_MemAccessStats a;
+} Dbg_MemStats;
+
+/*--------------------------------------------------------------------------*/
+
+/* Symbol table management.
+   The structure of a Dbg_SymTable is not revealed.  It is created by
+   Dbg_ReadSymbols() or by Dbg_LoadFile(), and associated with the argument
+   Dbg_MCState.
+   Many symbol tables may be concurrently active.
+   A Dbg_SymTable is removed either explicitly (by call to Dbg_DeleteSymbols)
+   or implicitly when a symbol table for an overlapping address range is read.
+
+   There is a pre-defined symbol table containing entries for ARM registers,
+   co-processor registers and the like.
+ */
+
+typedef struct Dbg_SymTable Dbg_SymTable;
+
+typedef struct Dbg_ImageFragmentDesc {
+    ARMaddress base, limit;
+} Dbg_ImageFragmentDesc;
+
+typedef enum {
+    Dbg_Lang_None,
+    Dbg_Lang_C,
+    Dbg_Lang_Pascal,
+    Dbg_Lang_Fortran,
+    Dbg_Lang_Asm,
+    Dbg_Lang_Cpp
+} Dbg_Lang;
+
+typedef struct Dbg_ImageDesc {
+    Dbg_Lang lang;
+    int executable;
+    ARMaddress robase, rolimit, rwbase, rwlimit;
+    int nfrags;
+    Dbg_ImageFragmentDesc *fragments;
+    char *name;
+} Dbg_ImageDesc;
+
+Dbg_ImageDesc *Dbg_ImageAreas(Dbg_SymTable *st);
+
+Dbg_SymTable *Dbg_LastImage(Dbg_MCState *state);
+
+Dbg_SymTable *Dbg_NewSymTable(Dbg_MCState *state, const char *name);
+
+Dbg_Error Dbg_ReadSymbols(Dbg_MCState *state, const char *filename, Dbg_SymTable **st);
+/* Just read the symbols from the named image.  <st> is set to the allocated
+   symbol table.
+?  Maybe we could usefully allow other formats than AIF images to describe
+   the symbols (eg) of shared libraries
+ */
+
+typedef struct Dbg_SymInfo {
+    int isize;
+    ARMaddress addr;
+    char *name;
+} Dbg_SymInfo;
+
+Dbg_SymInfo *Dbg_AsmSym(Dbg_SymTable *st, ARMaddress addr);
+int32 Dbg_AsmAddr(Dbg_SymTable *st, int32 line);
+int32 Dbg_AsmLine(Dbg_SymTable *st, ARMaddress addr);
+int32 Dbg_AsmLinesInRange(Dbg_SymTable *st, ARMaddress start, ARMaddress end);
+
+Dbg_Error Dbg_LoadFile(Dbg_MCState *state, const char *filename, Dbg_SymTable **st);
+/* load the image into target memory, and read its symbols.  <st> is set to
+   the allocated symbol table.
+   A null filename reloads the most recently loaded file (and rereads its
+   symbols).
+   Loading an image leaves breakpoints unchanged.  If a client wishes
+   otherwise, it must remove the breakpoints explicitly.
+*/
+
+Dbg_Error Dbg_CallGLoadFile(Dbg_MCState *state, const char *filename, Dbg_SymTable **st);
+
+typedef void Dbg_ImageLoadProc(Dbg_MCState *, Dbg_SymTable *);
+Dbg_Error Dbg_OnImageLoad(Dbg_MCState *, Dbg_ImageLoadProc *);
+/* Register function to be called back whenever an image is loaded, or symbols
+ * for an image read. (To allow multiple toolbox clients to coexist).
+ */
+
+Dbg_Error Dbg_LoadAgent(Dbg_MCState *state, const char *filename);
+/* Load a debug agent, and start it.
+   Symbols in the image for the agent are ignored.
+*/
+
+Dbg_Error Dbg_RelocateSymbols(Dbg_SymTable *st, ARMaddress reloc);
+/* add <reloc> to the value of all symbols in <st> describing absolute memory
+   locations.  The intent is to allow the symbols in a load-time relocating
+   image (for example) to be useful.
+ */
+
+Dbg_Error Dbg_DeleteSymbols(Dbg_MCState *state, Dbg_SymTable **st);
+
+typedef enum Dbg_LLSymType {
+    llst_code,
+    llst_code16,
+    llst_data,
+    llst_const,
+    llst_unknown,
+    llst_max
+} Dbg_LLSymType;
+/* Since AIF images contain no type information for low-level symbols, this
+   classification is only a guess, and some symbols describing constants will
+   incorrectly be described as code or data.
+ */
+
+typedef Dbg_Error Dbg_SymProc(
+    Dbg_MCState *state,
+    const char *symbol, Dbg_LLSymType symtype, ARMaddress value,
+    void *arg);
+
+Dbg_Error Dbg_EnumerateLowLevelSymbols(
+    Dbg_MCState *state, const char *match, Dbg_SymProc *p,
+    void *arg);
+/* Call  p(name, value)  for each low level symbol in the tables of <state>
+   whose name matches the regular expression <match> (a NULL <match> matches
+   any name).  Symbols are enumerated in no particular order.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/* Functions are provided here to allow quick mass access to register values
+   for display.  There is no comparable need for quick mass update, so writing
+   should be via Assign().
+ */
+
+typedef struct Dbg_RegSet {
+    ARMword
+        user[15],
+        pc,
+        psr,
+        fiq[7],
+        spsr_fiq,
+        irq[2],
+        spsr_irq,
+        svc[2],
+        spsr_svc,
+        abort[2],
+        spsr_abort,
+        undef[2],
+        spsr_undef;
+} Dbg_RegSet;
+
+/* bits in the modemask argument for ReadRegisters */
+
+#define Dbg_MM_User     1
+#define Dbg_MM_FIQ      2
+#define Dbg_MM_IRQ      4
+#define Dbg_MM_SVC      8
+#define Dbg_MM_Abort 0x10
+#define Dbg_MM_Undef 0x20
+#define Dbg_MM_System 0x40
+
+Dbg_Error Dbg_ReadRegisters(Dbg_MCState *state, Dbg_RegSet *regs, int modemask);
+
+Dbg_Error Dbg_WriteRegister(Dbg_MCState *state, int rno, int modemask, ARMword val);
+
+int Dbg_StringToMode(const char *name);
+
+int Dbg_ModeToModeMask(ARMword mode);
+
+/* Some implementations of the FP instruction set keep FP values loaded into
+   registers in their unconverted format, converting only when necessary.
+   Some RDI implementations deliver these values uninterpreted.
+   (For the rest, register values will always have type F_Extended).
+ */
+
+typedef enum { F_Single, F_Double, F_Extended, F_Packed, /* fpe340 values */
+               F_Internal,                               /* new fpe : mostly as extended */
+               F_None } Dbg_FPType;
+
+typedef struct { ARMword w[3]; } Dbg_TargetExtendedVal;
+typedef struct { ARMword w[3]; } Dbg_TargetPackedVal;
+typedef struct { ARMword w[2]; } Dbg_TargetDoubleVal;
+typedef struct { ARMword w[1]; } Dbg_TargetFloatVal;
+
+typedef union { Dbg_TargetExtendedVal e; Dbg_TargetPackedVal p;
+                Dbg_TargetDoubleVal d; Dbg_TargetFloatVal f; } Dbg_TargetFPVal;
+
+#define TargetSizeof_Extended 12
+#define TargetSizeof_Packed   12
+#define TargetSizeof_Double   8
+#define TargetSizeof_Float    4
+
+typedef struct Dbg_FPRegVal {
+     Dbg_FPType type;
+     Dbg_TargetFPVal v;
+} Dbg_FPRegVal;
+
+typedef struct Dbg_FPRegSet {
+    Dbg_FPRegVal f[8];
+    ARMword fpsr, fpcr;
+} Dbg_FPRegSet;
+
+Dbg_Error Dbg_ReadFPRegisters(Dbg_MCState *state, Dbg_FPRegSet *regs);
+
+Dbg_Error Dbg_WriteFPRegisters(Dbg_MCState *state, int32 mask, Dbg_FPRegSet *regs);
+
+Dbg_Error Dbg_FPRegToDouble(DbleBin *d, Dbg_FPRegVal const *f);
+/* Converts from a FP register value (in any format) to a double with
+   approximately the same value (or returns Dbg_Err_Overflow)
+ */
+
+void Dbg_DoubleToFPReg(Dbg_FPRegVal *f, DbleBin const *d);
+/* Converts the double <d> to a Dbg_FPRegVal with type F_Extended */
+
+/*--------------------------------------------------------------------------*/
+
+#include "dbg_cp.h"
+
+Dbg_Error Dbg_DescribeCoPro(Dbg_MCState *state, int cpnum, Dbg_CoProDesc *p);
+
+Dbg_Error Dbg_DescribeCoPro_RDI(Dbg_MCState *state, int cpnum, Dbg_CoProDesc *p);
+
+Dbg_Error Dbg_ReadCPRegisters(Dbg_MCState *state, int cpnum, ARMword *regs);
+
+Dbg_Error Dbg_WriteCPRegisters(Dbg_MCState *state, int cpnum, int32 mask, ARMword *regs);
+
+/*--------------------------------------------------------------------------*/
+
+Dbg_Error Dbg_ReadWords(
+    Dbg_MCState *state,
+    ARMword *words, ARMaddress addr, unsigned count);
+/* Reads a number of (32-bit) words from target store.  The values are in host
+   byte order; if they are also to be interpreted as bytes Dbg_SwapByteOrder()
+   must be called to convert to target byte order.
+ */
+
+Dbg_Error Dbg_WriteWords(
+    Dbg_MCState *state,
+    ARMaddress addr, const ARMword *words, unsigned count);
+/* Writes a number of (32-bit) words to target store.  The values are in host
+   byte order (if what is being written is actually a byte string it must be
+   converted by Dbg_SwapByteOrder()).
+ */
+
+Dbg_Error Dbg_ReadHalf(Dbg_MCState *state, ARMhword *val, ARMaddress addr);
+Dbg_Error Dbg_WriteHalf(Dbg_MCState *state, ARMaddress addr, ARMword val);
+
+Dbg_Error Dbg_ReadBytes(Dbg_MCState *state, Dbg_Byte *val, ARMaddress addr, unsigned count);
+Dbg_Error Dbg_WriteBytes(Dbg_MCState *state, ARMaddress addr, const Dbg_Byte *val, unsigned count);
+
+void Dbg_HostWords(Dbg_MCState *state, ARMword *words, unsigned wordcount);
+/* (A noop unless host and target bytesexes differ) */
+
+ARMword Dbg_HostWord(Dbg_MCState *state, ARMword v);
+
+ARMhword Dbg_HostHalf(Dbg_MCState *state, ARMword v);
+
+/*--------------------------------------------------------------------------*/
+
+/* Types describing various aspects of position within code.
+   There are rather a lot of these, in the interests of describing precisely
+   what fields must be present (rather than having a single type with many
+   fields which may or may not be valid according to context).
+ */
+
+typedef struct Dbg_LLPos {
+    Dbg_SymTable *st;
+    char *llsym;
+    ARMaddress offset;
+} Dbg_LLPos;
+
+typedef struct Dbg_File {
+    Dbg_SymTable *st;
+    char *file;
+} Dbg_File;
+
+typedef struct Dbg_Line {
+    unsigned32 line;      /* linenumber in the file */
+    unsigned16 statement, /* within the line (1-based) */
+               charpos;   /* ditto */
+} Dbg_Line;
+/* As an output value from toolbox functions, both statement and charpos are set
+   if the version of the debugger tables for the section concerned permits.
+   On input, <charpos> is used only if <statement> is 0 (in which case, if
+   <charpos> is non-0, Dbg_Err_DbgTableVersion is returned if the version of
+   the debugger tables concerned is too early.
+ */
+
+typedef struct Dbg_FilePos {
+    Dbg_File f;
+    Dbg_Line line;
+} Dbg_FilePos;
+
+typedef struct Dbg_ProcDesc {
+    Dbg_File f;
+    char *name;
+} Dbg_ProcDesc;
+
+typedef struct Dbg_ProcPos {
+    Dbg_ProcDesc p;
+    Dbg_Line line;
+} Dbg_ProcPos;
+
+/* Support for conversions between position representations */
+
+Dbg_Error Dbg_ProcDescToLine(Dbg_MCState *state, Dbg_ProcDesc *proc, Dbg_Line *line);
+/* If proc->f.file is null (and there is just one function proc->name), it is
+   updated to point to the name of the file containing (the start of)
+   proc->name.
+ */
+
+Dbg_Error Dbg_FilePosToProc(Dbg_MCState *state, const Dbg_FilePos *pos, char **procname);
+
+/* Conversions from position representations to and from code addresses */
+
+Dbg_Error Dbg_AddressToProcPos(
+    Dbg_MCState *state, ARMaddress addr,
+    Dbg_ProcPos *pos);
+Dbg_Error Dbg_AddressToLLPos(
+    Dbg_MCState *state, ARMaddress addr,
+    Dbg_LLPos *pos, Dbg_LLSymType *res_type, int system_names);
+
+Dbg_Error Dbg_ProcPosToAddress(
+    Dbg_MCState *state, const Dbg_ProcPos *pos,
+    ARMaddress *res);
+Dbg_Error Dbg_LLPosToAddress(
+    Dbg_MCState *state, const Dbg_LLPos *pos,
+    ARMaddress *res);
+
+typedef struct {
+    ARMaddress start, end;
+} Dbg_AddressRange;
+
+typedef Dbg_Error Dbg_AddressRangeProc(void *arg, int32 first, int32 last, Dbg_AddressRange const *range);
+
+Dbg_Error Dbg_MapAddressRangesForFileRange(
+    Dbg_MCState *state,
+    Dbg_SymTable *st, const char *f, int32 first, int32 last, Dbg_AddressRangeProc *p, void *arg);
+
+typedef struct Dbg_Environment Dbg_Environment;
+/* A Dbg_Environment describes the context required to make sense of a variable
+   name and access its value.  Its format is not revealed.  Dbg_Environment
+   values are allocated by Dbg_NewEnvironment() and discarded by
+   Dbg_DeleteEnvironment().
+ */
+
+Dbg_Environment *Dbg_NewEnvironment(Dbg_MCState *state);
+void Dbg_DeleteEnvironment(Dbg_MCState *state, Dbg_Environment *env);
+
+Dbg_Error Dbg_StringToEnv(
+    Dbg_MCState *state, char *str, Dbg_Environment *resenv,
+    int forcontext, Dbg_Environment const *curenv);
+
+Dbg_Error Dbg_ProcPosToEnvironment(
+    Dbg_MCState *state, const Dbg_ProcPos *pos, int activation,
+    const Dbg_Environment *current, Dbg_Environment *res);
+
+/* Conversion from a position representation to an Dbg_Environment (as required
+   to access variable values).  Only a Dbg_ProcPos argument here; other
+   representations need to be converted first.
+
+   Returns <res> describing the <activation>th instance of the function
+   described by <pos>, up from the stack base if <activation> is negative,
+   else down from <current>.
+   If this function returns Dbg_Err_ActivationNotPresent, the result
+   Dbg_Environment is still valid for accessing non-auto variables.
+ */
+
+typedef struct Dbg_DeclSpec Dbg_DeclSpec;
+
+Dbg_Error Dbg_EnvToProcItem(
+    Dbg_MCState *state, Dbg_Environment const *env, Dbg_DeclSpec *proc);
+
+Dbg_Error Dbg_ContainingEnvironment(
+    Dbg_MCState *state, const Dbg_Environment *context, Dbg_Environment *res);
+/* Set <res> to describe the containing function, file if <context> is within
+   a top-level function (or error if <context> already describes a file).
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/* ASD debug table pointers are not by themselves sufficient description,
+   since there's an implied section context.  Hence the DeclSpec and TypeSpec
+   structures.
+ */
+
+
+#ifndef Dbg_TypeSpec_Defined
+
+struct Dbg_DeclSpec { void *a; };
+
+#ifdef CALLABLE_COMPILER
+typedef void *Dbg_TypeSpec;
+
+/* The intention here is to give an alternative definition for Dbg_BasicType
+   which follows.
+ */
+
+#define Dbg_T_Void      xDbg_T_Void
+#define Dbg_T_Bool      xDbg_T_Bool
+#define Dbg_T_SByte     xDbg_T_SByte
+#define Dbg_T_SHalf     xDbg_T_Half
+#define Dbg_T_SWord     xDbg_T_SWord
+#define Dbg_T_UByte     xDbg_T_UByte
+#define Dbg_T_UHalf     xDbg_T_UHalf
+#define Dbg_T_UWord     xDbg_T_UWord
+#define Dbg_T_Float     xDbg_T_Float
+#define Dbg_T_Double    xDbg_T_Double
+#define Dbg_T_LDouble   xDbg_T_LDouble
+#define Dbg_T_Complex   xDbg_T_Complex
+#define Dbg_T_DComplex  xDbg_T_DComplex
+#define Dbg_T_String    xDbg_T_String
+#define Dbg_T_Function  xDbg_T_Function
+
+#define Dbg_BasicType   xDbg_BaiscType
+#define Dbg_PrimitiveTypeToTypeSpec xDbg_PrimitiveTypeToTypeSpec
+
+#else
+/* We want a Dbg_TypeSpec to be a an opaque type, but of known size (so the
+   toolbox's clients can allocate the store to hold one); unfortunately, we
+   can do this only by having one definition for the toolbox's clients and
+   one (elsewhere) for the toolbox itself.
+ */
+
+typedef struct Dbg_TypeSpec Dbg_TypeSpec;
+struct Dbg_TypeSpec { void *a; int32 b; };
+#endif /* CALLABLE_COMPILER */
+
+typedef enum {
+    Dbg_T_Void,
+
+    Dbg_T_Bool,
+
+    Dbg_T_SByte,
+    Dbg_T_SHalf,
+    Dbg_T_SWord,
+
+    Dbg_T_UByte,
+    Dbg_T_UHalf,
+    Dbg_T_UWord,
+
+    Dbg_T_Float,
+    Dbg_T_Double,
+    Dbg_T_LDouble,
+
+    Dbg_T_Complex,
+    Dbg_T_DComplex,
+
+    Dbg_T_String,
+
+    Dbg_T_Function
+} Dbg_BasicType;
+
+#endif
+
+void Dbg_PrimitiveTypeToTypeSpec(Dbg_TypeSpec *ts, Dbg_BasicType t);
+
+bool Dbg_TypeIsIntegral(Dbg_TypeSpec const *ts);
+
+bool Dbg_TypeIsPointer(Dbg_TypeSpec const *ts);
+
+bool Dbg_TypeIsFunction(Dbg_TypeSpec const *ts);
+
+bool Dbg_PruneType(Dbg_TypeSpec *tsres, Dbg_TypeSpec const *ts);
+/* Return to tsres a version of ts which has been pruned by the removal of all
+   toplevel typedefs. Result is YES if the result has changed.
+ */
+
+typedef Dbg_Error Dbg_FileProc(Dbg_MCState *state, const char *name, const Dbg_DeclSpec *procdef, void *arg);
+
+Dbg_Error Dbg_EnumerateFiles(Dbg_MCState *state, Dbg_SymTable *st, Dbg_FileProc *p, void *arg);
+/* The top level for a high level enumerate.  Lower levels are performed by
+   EnumerateDeclarations (below).
+ */
+
+typedef enum {
+    ds_Invalid,
+    ds_Type,
+    ds_Var,
+    ds_Proc,
+    ds_Enum,
+    ds_Function,
+    ds_Label
+} Dbg_DeclSort;
+
+Dbg_DeclSort Dbg_SortOfDeclSpec(Dbg_DeclSpec const *decl);
+
+char *Dbg_NameOfDeclSpec(Dbg_DeclSpec const *decl);
+
+Dbg_TypeSpec Dbg_TypeSpecOfDeclSpec(Dbg_DeclSpec const *decl);
+
+typedef enum {
+    cs_None,
+    cs_Extern,
+    cs_Static,
+    cs_Auto,
+    cs_Reg,
+    cs_Var,
+    cs_Farg,
+    cs_Fcarg,
+    cs_Local,
+    cs_Filtered,
+    cs_Globalreg
+} Dbg_StgClass;
+
+Dbg_StgClass Dbg_StgClassOfDeclSpec(Dbg_DeclSpec const *decl);
+
+bool Dbg_VarsAtSameAddress(Dbg_DeclSpec const *d1, Dbg_DeclSpec const *d2);
+
+bool Dbg_VarsDecribedForDeclSpec(Dbg_DeclSpec const *decl);
+
+int Dbg_ArgCountOfDeclSpec(Dbg_DeclSpec const *decl);
+
+typedef struct Dbg_DComplex { DbleBin r, i; } Dbg_DComplex;
+
+typedef union Dbg_ConstantVal {
+    int32 l;
+    unsigned32 u;
+    DbleBin d;
+    Dbg_DComplex fc;
+    ARMaddress a;
+    char *s;
+} Dbg_ConstantVal;
+
+typedef struct Dbg_Constant {
+    Dbg_TypeSpec type;
+    Dbg_ConstantVal val;
+} Dbg_Constant;
+
+typedef enum Dbg_ValueSort {
+    vs_register,
+    vs_store,
+    vs_constant,
+    vs_local,
+    vs_filtered,
+    vs_none,
+    vs_error
+} Dbg_ValueSort;
+
+/* vs_local allows the use of symbol table entries to describe entities within
+   the debugger's own address space, accessed in the same way as target
+   variables.
+   vs_filtered describes entities which may be read or written only via an
+   access function (eg r15)
+ */
+
+#define fpr_base 16
+/* There's only one register ValueSort (reflecting asd table StgClass);
+   fp register n is encoded as register n+fpr_base.
+ */
+
+typedef struct Dbg_Value Dbg_Value;
+
+typedef Dbg_Error Dbg_AccessFn(Dbg_MCState *state, int write, Dbg_Value *self, Dbg_Constant *c);
+/* <write> == 0: read a vs_filtered value, updating the value self.
+   <write> == 1: update a vs_filtered value, with the value described by c.
+   <self> allows use of the same Dbg_AccessFn for several different entities
+   (using different val.f.id fields).
+ */
+
+typedef Dbg_Error Dbg_FormatFn(int decode, char *b, ARMword *valp, void *formatarg);
+
+typedef struct { Dbg_AccessFn *f; int id; } Dbg_AccessFnRec;
+
+struct Dbg_Value {
+    Dbg_TypeSpec type;
+    Dbg_ValueSort sort;
+    Dbg_FormatFn *formatp;
+    void *formatarg;
+    int f77csize;
+    union {
+        struct { int no; ARMaddress frame; } r;
+        ARMaddress ptr;
+        Dbg_ConstantVal c;
+        void *localp;
+        Dbg_AccessFnRec f;
+        Dbg_Error err;
+    } val;
+};
+
+Dbg_Error Dbg_AddLLSymbol(Dbg_SymTable *st, char const *name, Dbg_LLSymType type, ARMword val);
+
+Dbg_Error Dbg_AddSymbol(Dbg_SymTable *st, char const *name, Dbg_Value const *val);
+
+typedef struct Dbg_DeclSpecF {
+  Dbg_DeclSpec decl;
+  Dbg_FormatFn *formatp;
+  void *formatarg;
+} Dbg_DeclSpecF;
+
+typedef Dbg_Error Dbg_DeclProc(Dbg_MCState *state, Dbg_Environment const *context,
+                       Dbg_DeclSpecF const *var, Dbg_DeclSort sort, int masked,
+                       void *arg);
+
+Dbg_Error Dbg_EnumerateDeclarations(Dbg_MCState *state, Dbg_Environment const *context,
+                            Dbg_DeclProc *p, void *arg);
+/* call p once for every declaration local to the function described by
+   <context> (or file if <context> describes a place outside a function).
+   p's argument <masked> is true if the variable is not visible, thanks to
+   a declaration in an inner scope.
+ */
+
+Dbg_Error Dbg_ValueOfVar(Dbg_MCState *state, const Dbg_Environment *context,
+                 const Dbg_DeclSpec *var, Dbg_Value *val);
+/* Different from Dbg_EvalExpr() in that the thing being evaluated is described
+   by a Dbg_DeclSpec (which must be for a variable), rather than a string
+   needing to be decoded and associated with a symbol-table item.  Intended to
+   be called from a Dbg_DeclProc called from Dbg_EnumerateDeclarations.
+ */
+
+Dbg_Error Dbg_EvalExpr(Dbg_MCState *state, Dbg_Environment const *context,
+               char const *expr, int flags, Dbg_Value *val);
+
+Dbg_Error Dbg_EvalExpr_ep(Dbg_MCState *state, Dbg_Environment const *context,
+                  char const *expr, char **exprend, int flags, Dbg_Value *val);
+
+/* Both Dbg_ValueOfVar and Dbg_EvalExpr mostly deliver a value still containing
+   an indirection (since it may be wanted as the lhs of an assignment)
+ */
+
+void Dbg_RealLocation(Dbg_MCState *state, Dbg_Value *val);
+/* If val describes a register, this may really be a register, or a place on
+   the stack where the register's value is saved. In the latter case, val
+   is altered to describe the save place. (In all others, it remains
+   unchanged).
+ */
+
+Dbg_Error Dbg_DereferenceValue(Dbg_MCState *state, const Dbg_Value *value, Dbg_Constant *c);
+/* This fails if <value> describes a structure or array, returning
+   Dbg_Err_TypeNotSimple
+ */
+
+typedef struct Dbg_Expr Dbg_Expr;
+/* The result of parsing an expression in an environment: its structure is not
+   revealed.  (Clients may wish to parse just once an expression which may be
+   evaluated often).  In support of which, the following two functions partition
+   the work of Dbg_EvalExpr().
+ */
+
+#define Dbg_exfl_heap 1    /* allocate Expr on the heap (FreeExpr must then be
+                              called to discard it).  Otherwise, it goes in a
+                              place overwritten by the next call to ParseExpr
+                              or EvalExpr
+                            */
+#define Dbg_exfl_needassign 2
+#define Dbg_exfl_lowlevel   4
+
+int Dbg_SetInputRadix(Dbg_MCState *state, int radix);
+char *Dbg_SetDefaultIntFormat(Dbg_MCState *state, char *format);
+
+Dbg_Error Dbg_ParseExpr(
+    Dbg_MCState *state, Dbg_Environment const *env, char *string,
+    char **end, Dbg_Expr **res, int flags);
+/* Just parse the argument string, returning a pointer to a parsed expression
+   and a pointer to the first non-white space character in the input string
+   which is not part of the parsed expression. (If macro expansion has taken
+   place, the returned pointer will not be into the argument string at all,
+   rather into the expanded version of it).
+ */
+
+Dbg_Error Dbg_ParseExprCheckEnd(
+    Dbg_MCState *state, Dbg_Environment const *env, char *string,
+    Dbg_Expr **res, int flags);
+/* As Dbg_ParseExpr, but the parsed expression is required completely to fill
+   the argument string (apart possibly for trailing whitespace), and an error
+   is returned if it does not.
+ */
+
+Dbg_Error Dbg_ParsedExprToValue(
+    Dbg_MCState *state, const Dbg_Environment *env, Dbg_Expr *expr, Dbg_Value *v);
+
+Dbg_Error Dbg_ReadDecl(
+    Dbg_MCState *state, Dbg_Environment const *env, char *string,
+    Dbg_TypeSpec *p, char **varp, int flags);
+/* Read a variable declaration, returing a description of the type of the
+   variable to p, and a pointer to its name to varp.
+ */
+
+bool Dbg_IsCastToArrayType(Dbg_MCState *state, Dbg_Expr *expr);
+
+void Dbg_FreeExpr(Dbg_Expr *expr);
+
+Dbg_Error Dbg_CopyType(Dbg_TypeSpec *tdest, Dbg_TypeSpec const *tsource);
+Dbg_Error Dbg_FreeCopiedType(Dbg_TypeSpec *ts);
+
+Dbg_Error Dbg_TypeOfExpr(Dbg_MCState *state, Dbg_Expr *tree, Dbg_TypeSpec *restype);
+
+Dbg_Error Dbg_ExprToVar(const Dbg_Expr *expr, Dbg_DeclSpec *var, Dbg_Environment *env);
+
+Dbg_Error Dbg_Assign(Dbg_MCState *state, const Dbg_Value *lv, const Dbg_Value *rv);
+
+typedef enum Dbg_TypeSort {
+  ts_simple,
+  ts_union,
+  ts_struct,
+  ts_array
+} Dbg_TypeSort;
+
+Dbg_TypeSort Dbg_TypeSortOfValue(Dbg_MCState *state, const Dbg_Value *val, int *fieldcount);
+
+Dbg_Error Dbg_TypeToChars(const Dbg_TypeSpec *var, Dbg_BufDesc *buf);
+
+Dbg_Error Dbg_TypeSize(Dbg_MCState *state, const Dbg_TypeSpec *type, unsigned32 *res);
+
+typedef int Dbg_ValToChars_cb(Dbg_MCState *state, Dbg_Value *subval, const char *fieldname,
+                          Dbg_BufDesc *buf, void *arg);
+
+Dbg_Error Dbg_ValToChars(Dbg_MCState *state, Dbg_Value *val, int base,
+                 Dbg_ValToChars_cb *cb, void *arg,
+                 const char *form, Dbg_BufDesc *buf);
+/*
+   <base> is used for (any size) integer values.
+   If <val> is of an array or structure type, <cb> is called for each element,
+   with <arg> as its last parameter, and <subbuf> describing the space remaining
+   in <buf>.  If <cb> returns 0, conversion ceases.
+ */
+
+Dbg_Error Dbg_NthElement(
+    Dbg_MCState *state,
+    const Dbg_Value *val, unsigned32 n, char **fieldname, Dbg_Value *subval);
+
+typedef Dbg_Error Dbg_HistoryProc(void *, int, Dbg_Value *);
+
+Dbg_Error Dbg_RegisterHistoryProc(Dbg_MCState *state, Dbg_HistoryProc *p, void *arg);
+
+typedef enum {
+  ls_cpu,
+  ls_store,
+  ls_copro,
+  ls_local,
+  ls_filtered
+} Dbg_LocSort;
+
+typedef struct {
+  Dbg_LocSort sort;
+  union {
+    struct { ARMaddress addr, size; } store;
+    struct { int modemask; int r; } cpu;
+    struct { int no; int r; } cp;
+    void *localp;
+    Dbg_AccessFnRec f;
+  } loc;
+} Dbg_Loc;
+
+typedef Dbg_Error Dbg_ObjectWriteProc(Dbg_MCState *state, Dbg_Loc const *loc);
+Dbg_Error Dbg_OnObjectWrite(Dbg_MCState *state, Dbg_ObjectWriteProc *p);
+/* Register function to be called back whenever the toolbox has written to any
+ * object accessible by the debuggee (or to local variables belonging to a
+ * toolbox client). The write has already been done.
+ * (To allow multiple toolbox clients to coexist).
+ */
+
+Dbg_Error Dbg_ObjectWritten(Dbg_MCState *state, Dbg_Loc const *loc);
+
+/*--------------------------------------------------------------------------*/
+
+/* Control of target program execution.
+   Currently, only synchronous operation is provided.
+   Execution could possibly be asynchronous where the target is a seperate
+   processor, but is necessarily synchronous if the target is Armulator.
+   Unfortunately, this may require modification to the RDI implementation
+   if multitasking is required but the the host system provides it only
+   cooperatively, or if there is no system-provided way to generate SIGINT.
+ */
+
+Dbg_Error Dbg_SetCommandline(Dbg_MCState *state, const char *args);
+/* Set the argument string to the concatenation of the name of the most
+   recently loaded image and args.
+ */
+
+typedef enum Dbg_ProgramState {
+    ps_notstarted,
+    /* Normal ways of stopping */
+    ps_atbreak, ps_atwatch, ps_stepdone,
+    ps_interrupted,
+    ps_stopped,
+    /* abnormal (but unsurprising) ways of stopping */
+    ps_lostwatch,
+    ps_branchthrough0, ps_undef, ps_caughtswi, ps_prefetch,
+    ps_abort, ps_addrexcept, ps_caughtirq, ps_caughtfiq,
+    ps_error,
+    /* only as a return value from Call() */
+    ps_callfailed, ps_callreturned,
+    /* internal inconsistencies */
+    ps_broken,                  /* target has "broken" */
+    ps_unknownbreak,
+    ps_unknown
+} Dbg_ProgramState;
+
+int Dbg_IsCallLink(Dbg_MCState *state, ARMaddress pc);
+
+typedef struct {
+    Dbg_FPRegVal fpres;
+    ARMword intres;
+} Dbg_CallResults;
+
+Dbg_CallResults *Dbg_GetCallResults(Dbg_MCState *state);
+
+#define Dbg_S_STATEMENTS 0
+#define Dbg_S_INSTRUCTIONS 1
+#define Dbg_S_STEPINTOPROCS 2
+
+Dbg_Error Dbg_Step(Dbg_MCState *state, int32 stepcount, int stepby, Dbg_ProgramState *status);
+/*  <stepby> is a combination of the Dbg_S_... values above */
+
+Dbg_Error Dbg_StepOut(Dbg_MCState *state, Dbg_ProgramState *status);
+
+bool Dbg_CanGo(Dbg_MCState *state);
+
+bool Dbg_IsExecuting(Dbg_MCState *state);
+
+Dbg_Error Dbg_Go(Dbg_MCState *state, Dbg_ProgramState *status);
+
+Dbg_Error Dbg_Stop(Dbg_MCState *state);
+/* Asynchronous Stop request, for call from SIGINT handler.  On return to the
+   caller, the call of Dbg_Go, Dbg_Step or Dbg_Call which started execution
+   should return ps_interrupted.
+ */
+
+typedef void Dbg_ExecuteProc(Dbg_MCState *state, Dbg_ProgramState status);
+Dbg_Error Dbg_OnExecute(Dbg_MCState *, Dbg_ExecuteProc *);
+/* Register function to be called back whenever execution stops.
+ * (To allow multiple toolbox clients to coexist).
+ */
+
+Dbg_Error Dbg_SetReturn(Dbg_MCState *state,
+                const Dbg_Environment *context, const Dbg_Value *value);
+/* Prepare continuation by returning <value> from the function activation
+   described by <context>.  (Dbg_Go() or Dbg_Step() actually perform the
+   continuation).
+ */
+
+Dbg_Error Dbg_SetExecution(Dbg_MCState *state, Dbg_Environment *context);
+/* Set the pc in a high-level fashion */
+
+Dbg_Error Dbg_ProgramStateToChars(Dbg_MCState *state, Dbg_ProgramState event, Dbg_BufDesc *buf);
+/* This is guaranteed to give a completely accurate description of <event> if
+   this was the value returned by the most recent call of Dbg_Go, Dbg_Step,
+   or Dbg_Call.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+Dbg_Error Dbg_CurrentEnvironment(Dbg_MCState *state, Dbg_Environment *context);
+
+Dbg_Error Dbg_PrevFrame(Dbg_MCState *state, Dbg_Environment *context);
+/* towards the base of the stack */
+
+Dbg_Error Dbg_NextFrame(Dbg_MCState *state, Dbg_Environment *context);
+/* away from the base of the stack */
+
+typedef struct Dbg_AnyPos {
+    enum { pos_source, pos_ll, pos_none } postype;
+    ARMaddress pc;
+    union {
+        Dbg_ProcPos source;
+        Dbg_LLPos ll;
+        ARMaddress none;
+    } pos;
+} Dbg_AnyPos;
+
+Dbg_Error Dbg_EnvironmentToPos(Dbg_MCState *state, const Dbg_Environment *context, Dbg_AnyPos *pos);
+/* <pos> is set to a Dbg_ProcPos if these is one corresponding to <context>
+   else a Dbg_LLPos if there is one.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/* Source file management.
+   Pretty vestigial.  Handles source path (per loaded image),
+   and translates from line-number (as given in debugger tables) to character
+   position (as required to access files)
+ */
+
+Dbg_Error Dbg_ClearPaths(Dbg_MCState *state, Dbg_SymTable *st);
+Dbg_Error Dbg_AddPath(Dbg_MCState *state, Dbg_SymTable *st, const char *path);
+Dbg_Error Dbg_DeletePath(Dbg_MCState *state, Dbg_SymTable *st, const char *path);
+
+typedef enum {
+  Dbg_PathsCleared,
+  Dbg_PathAdded,
+  Dbg_PathDeleted
+} Dbg_PathAlteration;
+
+typedef void Dbg_PathAlteredProc(
+    Dbg_MCState *state, Dbg_SymTable *st, char const *path,
+    Dbg_PathAlteration sort);
+
+Dbg_Error Dbg_OnPathAlteration(Dbg_MCState *state, Dbg_PathAlteredProc *p);
+/* Register function to be called back whenever one of the source path
+ * modification functions above is called. (To allow multiple toolbox
+ * clients to coexist).
+ */
+
+typedef struct Dbg_FileRec Dbg_FileRec;
+typedef struct {
+  unsigned32 linecount;
+  Dbg_FileRec *handle;
+  char *fullname;
+} Dbg_FileDetails;
+
+Dbg_Error Dbg_GetFileDetails(
+    Dbg_MCState *state, const Dbg_File *fname, Dbg_FileDetails *res);
+Dbg_Error Dbg_FinishedWithFile(Dbg_MCState *state, Dbg_FileRec *handle);
+
+Dbg_Error Dbg_GetFileDetails_fr(
+    Dbg_MCState *state, Dbg_FileRec *handle, Dbg_FileDetails *res);
+/* Refresh details about the file associated with <handle> (in particular,
+ * its linecount).
+ */
+
+Dbg_Error Dbg_FileLineLength(
+    Dbg_MCState *state, Dbg_FileRec *handle, int32 lineno, int32 *len);
+/* Return to <len> the length of line <lineno> of the file associated with
+ * <handle> (without necessarily reading from the file).
+ */
+
+Dbg_Error Dbg_GetFileLine_fr(
+    Dbg_MCState *state, Dbg_FileRec *handle, int32 lineno, Dbg_BufDesc *buf);
+/* Return to <buf> the contents of line <lineno> of the file associated with
+ * <handle> (including its terminating newline).
+ */
+
+Dbg_Error Dbg_StartFileAccess(Dbg_MCState *state, Dbg_FileRec *handle);
+Dbg_Error Dbg_EndFileAccess(Dbg_MCState *state, Dbg_FileRec *handle);
+/* These two calls bracket a sequence of calls to GetFileLine. Between the
+ * calls, the toolbox is permitted to retain state allowing more rapid
+ * access to text on the file associated with <handle>.
+ */
+
+Dbg_Error Dbg_ControlSourceFileAccess(
+    Dbg_MCState *state, uint32 cachesize, bool closefiles);
+/* Control details of how the toolbox manages source files.
+ *   If <cachesize> is non-zero, the text from the most recently accessed
+ *     source files (of total size not to exceed <cachesize>) is saved in
+ *     store on first access to the file; subsequent access to the text of
+ *     the file uses this copy.
+ *   If <closefiles> is true, no stream is left attached to uncached source
+ *     files after Dbg_EndFileAccess has been closed. Otherwise, the toolbox
+ *     may retain such streams, in order to improve access.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+/* disassembly */
+
+/*
+ ? More exact control is wanted here, but that requires a more complicated
+ ? disass callback interface.
+ */
+
+typedef const char *Dbg_SWI_Decode(Dbg_MCState *state, ARMword swino);
+
+Dbg_Error Dbg_InstructionAt(Dbg_MCState *state, ARMaddress addr,
+                    int isize, ARMhword *inst, Dbg_SymTable *st,
+                    Dbg_SWI_Decode *swi_name, Dbg_BufDesc *buf, int *length);
+/* <isize> describes the form of disassembly wanted: 2 for 16-bit, 4 for 32-bit,
+ * 0 for 16- or 32-bit depending whether addr addresses 16- or 32-bit code.
+ * <inst> is a pointer to a pair of halfwords *in target byte order*
+ * Possibly only the first halfword will be consumed: the number of bytes used
+ * is returned via <length>.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+int Dbg_RDIOpen(Dbg_MCState *state, unsigned type);
+int Dbg_RDIInfo(Dbg_MCState *state, unsigned type, ARMword *arg1, ARMword *arg2);
+
+/*--------------------------------------------------------------------------*/
+
+typedef enum {
+    Dbg_Point_Toolbox,
+    Dbg_Point_RDI_Unknown,
+    Dbg_Point_RDI_SW,
+    Dbg_Point_RDI_HW
+} Dbg_PointType;
+
+/* breakpoint management
+   Associated with a breakpoint there may be any of
+     a count
+     an expression
+     a function
+   the breakpoint is activated if
+        the expression evaluates to a non-zero value (or fails to evaluate).
+     && decrementing the count reaches zero (the count is then reset to its
+        initial value).
+     && the function, called with the breakpoint address as argument, returns
+        a non-zero value.
+?  (The order here may be open to debate.  Note that the first two are in
+    the opposite order in armsd, but I think this order more rational)
+ */
+
+typedef enum Dbg_BreakPosType {
+    bt_procpos,
+    bt_procexit,
+    bt_address
+} Dbg_BreakPosType;
+
+typedef union {
+      Dbg_ProcPos procpos;
+      Dbg_ProcDesc procexit;
+      ARMaddress address;
+} Dbg_BreakPosPos;
+
+typedef struct Dbg_BreakPos {
+    Dbg_BreakPosType sort;
+    Dbg_BreakPosPos loc;
+} Dbg_BreakPos;
+
+typedef int Dbg_BPProc(Dbg_MCState *state, void *BPArg, Dbg_BreakPos *where);
+
+typedef struct Dbg_BreakStatus {
+    int index;
+    int initcount, countnow;
+    Dbg_BreakPos where;
+    char *expr;
+    Dbg_BPProc *p; void *p_arg;
+    int incomplete;
+    Dbg_PointType type;
+    ARMword hwresource;
+} Dbg_BreakStatus;
+
+Dbg_Error Dbg_StringToBreakPos(
+    Dbg_MCState *state, Dbg_Environment *env, char const *str, size_t len,
+    Dbg_BreakPos *bpos, char *b);
+
+Dbg_Error Dbg_SetBreakPoint(Dbg_MCState *state, Dbg_BreakPos *where,
+                    int count,
+                    const char *expr,
+                    Dbg_BPProc *p, void *arg);
+Dbg_Error Dbg_SetBreakPoint16(Dbg_MCState *state, Dbg_BreakPos *where,
+                    int count,
+                    const char *expr,
+                    Dbg_BPProc *p, void *arg);
+Dbg_Error Dbg_SetBreakPointNaturalSize(Dbg_MCState *state, Dbg_BreakPos *where,
+                    int count,
+                    const char *expr,
+                    Dbg_BPProc *p, void *arg);
+/* Setting a breakpoint at the same address as a previous breakpoint
+   completely removes the previous one.
+ */
+
+Dbg_Error Dbg_DeleteBreakPoint(Dbg_MCState *state, Dbg_BreakPos *where);
+
+Dbg_Error Dbg_SuspendBreakPoint(Dbg_MCState *state, Dbg_BreakPos *where);
+/* Temporarily remove the break point (until Reinstated) but leave intact
+   its associated expr, the value its count has reached, etc.
+?  The debugger toolbox itself wants this, but I'm not sure what use a client
+   could have for it.  Ditto Reinstate...
+ */
+
+Dbg_Error Dbg_ReinstateBreakPoint(Dbg_MCState *state, Dbg_BreakPos *where);
+/* Undo the effect of Dbg_SuspendBreakPoint
+ */
+
+Dbg_Error Dbg_DeleteAllBreakPoints(Dbg_MCState *state);
+
+Dbg_Error Dbg_SuspendAllBreakPoints(Dbg_MCState *state);
+
+Dbg_Error Dbg_ReinstateAllBreakPoints(Dbg_MCState *state);
+
+typedef Dbg_Error Dbg_BPEnumProc(Dbg_MCState *state, Dbg_BreakStatus *status, void *arg);
+
+Dbg_Error Dbg_EnumerateBreakPoints(Dbg_MCState *state, Dbg_BPEnumProc *p, void *arg);
+
+Dbg_Error Dbg_BreakPointStatus(Dbg_MCState *state,
+                       const Dbg_BreakPos *where, Dbg_BreakStatus *status);
+
+typedef void Dbg_BreakAlteredProc(Dbg_MCState *state, ARMaddress addr, bool set);
+Dbg_Error Dbg_OnBreak(Dbg_MCState *state, Dbg_BreakAlteredProc *p);
+/* Register function to be called back whenever a breakpoint is set or
+ * cleared. (To allow multiple toolbox clients to coexist).
+ */
+
+bool Dbg_StoppedAtBreakPoint(Dbg_MCState *state, const Dbg_BreakPos *where);
+/* Called after execution which resulted in ps_atbreak, to find out whether
+   the specified breakpoint was hit (could be >1, eg. exit break and another
+   high-level breakpoint at the same position).
+   Returns NO if specified breakpoint not found, or execution didn't stop
+   with ps_atbreak status.
+ */
+
+/*--------------------------------------------------------------------------*/
+
+typedef struct {
+  Dbg_Value val;
+  char *name;
+} Dbg_WatchPos;
+
+typedef int Dbg_WPProc(Dbg_MCState *state, void *WPArg, Dbg_WatchPos *where);
+
+typedef struct Dbg_WPStatus {
+    int index;
+    int initcount, countnow;
+    Dbg_WatchPos what, target;
+    char *expr;
+    Dbg_WPProc *p; void *p_arg;
+    Dbg_PointType type;
+    ARMword hwresource;
+    int skip;
+} Dbg_WPStatus;
+
+Dbg_Error Dbg_SetWatchPoint(
+    Dbg_MCState *state, Dbg_Environment *context, char const *watchee,
+    char const *target,
+    int count,
+    char const *expr,
+    Dbg_WPProc *p, void *arg);
+
+/* Cause a watchpoint event if the value of <watchee> changes to the value of
+   <target> (or changes at all if <target> is NULL).  <watchee> should
+   evaluate either to an L-value (when the size of the object being watched is
+   determined by its type) or to an integer constant (when the word with this
+   address is watched).
+ */
+
+Dbg_Error Dbg_DeleteWatchPoint(Dbg_MCState *state, Dbg_Environment *context, char const *watchee);
+
+
+Dbg_Error Dbg_SetWatchPoint_V(
+    Dbg_MCState *state,
+    char const *name, Dbg_Value const *val, char const *tname, Dbg_Value const *tval,
+    int count,
+    char const *expr,
+    Dbg_WPProc *p, void *arg);
+
+Dbg_Error Dbg_DeleteWatchPoint_V(Dbg_MCState *state, Dbg_Value const *val);
+
+
+Dbg_Error Dbg_DeleteAllWatchPoints(Dbg_MCState *state);
+
+typedef Dbg_Error Dbg_WPEnumProc(Dbg_MCState *state, Dbg_WPStatus const *watchee, void *arg);
+
+Dbg_Error Dbg_EnumerateWatchPoints(Dbg_MCState *state, Dbg_WPEnumProc *p, void *arg);
+
+Dbg_Error Dbg_WatchPointStatus(Dbg_MCState *state,
+                       Dbg_WatchPos const *where, Dbg_WPStatus *status);
+
+typedef void Dbg_WPRemovedProc(void *arg, Dbg_WPStatus const *wp);
+Dbg_Error Dbg_RegisterWPRemovalProc(Dbg_MCState *state, Dbg_WPRemovedProc *p, void *arg);
+/* When a watchpoint goes out of scope it is removed by the toolbox, and the
+   function registered here gets called back to adjust its view
+ */
+
+typedef void Dbg_WatchAlteredProc(Dbg_MCState *state, Dbg_Value const *where, bool set);
+Dbg_Error Dbg_OnWatch(Dbg_MCState *state, Dbg_WatchAlteredProc *p);
+/* Register function to be called back whenever a watchpoint is set or
+ * cleared. (To allow multiple toolbox clients to coexist).
+ */
+
+/*--------------------------------------------------------------------------*/
+
+Dbg_Error Dbg_ProfileLoad(Dbg_MCState *state);
+
+Dbg_Error Dbg_ProfileStart(Dbg_MCState *state, ARMword interval);
+Dbg_Error Dbg_ProfileStop(Dbg_MCState *state);
+
+Dbg_Error Dbg_ProfileClear(Dbg_MCState *state);
+
+Dbg_Error Dbg_WriteProfile(Dbg_MCState *state, char const *filename,
+                           char const *toolid, char const *arg);
+
+/*--------------------------------------------------------------------------*/
+
+Dbg_Error Dbg_ConnectChannel_ToHost(Dbg_MCState *state, RDICCProc_ToHost *p, void *arg);
+Dbg_Error Dbg_ConnectChannel_FromHost(Dbg_MCState *state, RDICCProc_FromHost *p, void *arg);
+
+/*--------------------------------------------------------------------------*/
+
+/* Configuration data management */
+
+Dbg_Error Dbg_LoadConfigData(Dbg_MCState *state, char const *filename);
+
+Dbg_Error Dbg_SelectConfig(
+    Dbg_MCState *state,
+    RDI_ConfigAspect aspect, char const *name, RDI_ConfigMatchType matchtype,
+    unsigned versionreq, unsigned *versionp);
+
+Dbg_Error Dbg_ParseConfigVersion(
+    char const *s, RDI_ConfigMatchType *matchp, unsigned *versionp);
+
+typedef Dbg_Error Dbg_ConfigEnumProc(Dbg_MCState *state, RDI_ConfigDesc const *desc, void *arg);
+
+Dbg_Error Dbg_EnumerateConfigs(Dbg_MCState *state, Dbg_ConfigEnumProc *p, void *arg);
+
+/*--------------------------------------------------------------------------*/
+
+/* Angel OS support */
+
+Dbg_Error Dbg_CreateTask(Dbg_MCState **statep, Dbg_MCState *parent, bool inherit);
+/* This is called when a task is to be debugged which has not been debugged
+   before - ie. there is no existing Dbg_MCState for this task. It
+   initialises a new Dbg_MCState and returns a pointer to it.
+   <parent> is any valid previously-created MCCState. If <inherit> is TRUE,
+   the new MCState inherits certain features from it (eg. symbols).
+   Otherwise, only features which are the same across all tasks are inherited,
+   (eg. global breakpoints).
+ */
+
+Dbg_Error Dbg_DeleteTask(Dbg_MCState *state);
+/* This is called when a task dies, and frees up everything which relates to that
+   task which is controlled by armdbg.
+ */
+
+Dbg_Error Dbg_DetachTask(Dbg_MCState *state);
+
+Dbg_Error Dbg_AttachTask(Dbg_MCState *state);
+/* These are called to request a switch of the current task.  First
+   Dbg_DetachTask should be called with the state of the old task.
+   Dbg_DetachTask will ensure that any cached state held by armdbg for
+   the old task is immediately written out to the target.
+
+   After Dbg_DetachTask is called and before Dbg_AttachTask is called
+   the OS channel manager should tell the target that any future
+   requests from the debugger will be fore the new task.
+
+   If the new task does not have an armdbg state structure
+   already, then Dbg_CreateTask should be called to create one (see
+   above).  Then Dbg_AttachTask is called to tell armdbg to treat the
+   new armdbg state as the current task.
+ */
+
+typedef Dbg_Error Dbg_TaskSwitchProc(void *arg, Dbg_MCState *newstate);
+
+Dbg_Error Dbg_OnTaskSwitch(Dbg_MCState *state, Dbg_TaskSwitchProc *fn, void *arg);
+/* The front end may register a callback which gets called by armdbg whenever
+   Dbg_AttachTask is called.  This callback tells the front end the new current
+   Dbg_MCState it should use to call armdbg.
+   [Note that this is only useful if there is one front end shared between all
+    tasks rather than one front end per task]
+   The value of <arg> passed to Dbg_OnTaskSwitch is passed to <fn>
+   when it is called.
+ */
+
+typedef Dbg_Error Dbg_RestartProc(
+    void *arg, Dbg_MCState *curstate, Dbg_MCState **newstate);
+
+Dbg_Error Dbg_OnRestart(Dbg_MCState *state, Dbg_RestartProc *fn, void *arg);
+/* This is used by the OS channels layer to register a callback which
+   will be made by the debugger toolbox early in the process of resuming
+   execution.
+
+   This callback must determine which task will be resumed when the target
+   restarts execution.  If this is not already the current task then it must
+   call Dbg_DetachTask and Dbg_AttachTask as decribed above to switch to the
+   task about to be resumed and return the state for the new task in
+   <newstate>.
+
+   This will ensure that armdbg updates the correct task on execution as well
+   as ensuring that stepping over a breakpointed instruction on restarting
+   happens correctly.
+
+   The value of <arg> passed to Dbg_OnRestart is passed to <fn>
+   when it is called.
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* End of armdbg.h */
diff --git a/gdb/rdi-share/buffers.h b/gdb/rdi-share/buffers.h
new file mode 100644 (file)
index 0000000..78549de
--- /dev/null
@@ -0,0 +1,111 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Public interface to buffer management
+ */
+
+#ifndef angel_buffers_h
+#define angel_buffers_h
+
+#include "chandefs.h"           /* CHAN_HEADER_SIZE */
+
+
+/* the handle to a buffer */
+typedef unsigned char *p_Buffer;
+
+
+/*
+ * Angel Packets are structured as a fixed size header, followed
+ * by the packet data
+ */
+#ifdef TARGET
+# define BUFFERDATA(b)  (b)     /* channels layer takes care of it */
+#else
+# define BUFFERDATA(b)  (&((b)[CHAN_HEADER_SIZE]))
+#endif
+
+
+/*
+ * The buffer management function prototypes are only applicable
+ * when compiling target code
+ */
+#ifdef TARGET
+
+/*
+ * Function: Angel_BufferQuerySizes
+ *  Purpose: Request infomation on the default and maximum buffer sizes
+ *           that can be allocated
+ *
+ *   Params:
+ *             In/Out: default_size, max_size: pointers to place the
+ *                     sizes in on return
+ */
+
+void Angel_BufferQuerySizes(unsigned int *default_size, 
+                            unsigned int *max_size );
+
+/*
+ * Function: Angel_RxEnginBuffersLeft
+ *  Purpose: return the number of free buffers 
+ *
+ *   Params:
+ *            Returns: number of free buffers
+ */
+unsigned int Angel_BuffersLeft( void );
+
+/*
+ * Function: Angel_BufferAlloc
+ *  Purpose: allocate a buffer that is at least req_size bytes long 
+ *
+ *   Params:
+ *              Input: req_size     the required size of the buffer
+ *
+ *              Returns: pointer to the buffer NULL if unable to 
+ *                       fulfil the request
+ */
+p_Buffer     Angel_BufferAlloc(unsigned int  req_size);
+
+/*
+ * Function: Angel_BufferRelease
+ *  Purpose: release a buffer back to the free pool
+ *
+ *   Params:
+ *              Input: pointer to the buffer to free
+ */
+void Angel_BufferRelease(p_Buffer buffer);
+
+
+/* return values for angel_InitBuffers */
+typedef enum buf_init_error{
+  INIT_BUF_OK,
+  INIT_BUF_FAIL
+} buf_init_error;
+
+/*
+ * Function: Angel_InitBuffers
+ *  Purpose: Initalised and malloc the buffer pool
+ *
+ *   Params:
+ *              Returns: see above
+ */
+
+buf_init_error  Angel_InitBuffers(void);
+
+#endif /* def TARGET */
+
+#endif /* ndef angel_buffers_h */
+
+/* EOF buffers.h */
diff --git a/gdb/rdi-share/bytesex.c b/gdb/rdi-share/bytesex.c
new file mode 100644 (file)
index 0000000..0c6aaae
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * bytesex.c - Code to support byte-sex independence
+ * Copyright: (C) 1991, Advanced RISC Machines Ltd., Cambridge, England.
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#include "bytesex.h"
+
+static int reversing_bytes = 0;
+
+void bytesex_reverse(yes_or_no)
+int yes_or_no;
+{ reversing_bytes = yes_or_no;
+}
+
+int bytesex_reversing()
+{
+  return reversing_bytes;
+}
+
+int32 bytesex_hostval(v)
+int32 v;
+{ /* Return v with the same endian-ness as the host */
+  /* This mess generates better ARM code than the more obvious mess */
+  /* and may eventually peephole to optimal code...                 */
+  if (reversing_bytes)
+  { unsigned32 t;
+    /* t = v ^ (v ror 16) */
+    t = v ^ ((v << 16) | (((unsigned32)v) >> 16));
+    t &= ~0xff0000;
+    /* v = v ror 8 */
+    v = (v << 24) | (((unsigned32)v) >> 8);
+    v = v ^ (t >> 8);
+  }
+  return v;
+}
+
+int32 bytesex_hostval_16(v)
+int32 v;
+{
+  if (reversing_bytes) {
+    v = ((v >> 8) & 0xff) | ((v << 8) & 0xff00);
+  }
+  return v;
+}
diff --git a/gdb/rdi-share/bytesex.h b/gdb/rdi-share/bytesex.h
new file mode 100644 (file)
index 0000000..4b53ef3
--- /dev/null
@@ -0,0 +1,42 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+  Title:     Code to support byte-sex independence
+  Copyright: (C) 1991, Advanced RISC Machines Ltd., Cambridge, England.
+*/
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef __bytesex_h
+#define __bytesex_h
+
+#include "host.h"
+
+void bytesex_reverse(int yes_or_no);
+/*
+ * Turn sex-reversal on or off - 0 means off, non-0 means on.
+ */
+
+int bytesex_reversing(void);
+/*
+ * Return non-0 if reversing the byte sex, else 0.
+ */
+
+int32 bytesex_hostval(int32 v);
+/*
+ * Return v or byte-reversed v, according to whether sex-reversval
+ * is on or off.
+ */
+
+int32 bytesex_hostval_16(int32 v);
+/* Return v or byte-reversed v for a 16 bit value */
+
+#endif
diff --git a/gdb/rdi-share/chandefs.h b/gdb/rdi-share/chandefs.h
new file mode 100644 (file)
index 0000000..d97f0b5
--- /dev/null
@@ -0,0 +1,50 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Enumeration with all supported channels
+ */
+
+#ifndef angel_chandefs_h
+#define angel_chandefs_h
+
+enum channelIDs {
+  CI_PRIVATE = 0,               /* channels protocol control messages */
+  CI_HADP,                      /* ADP, host originated */
+  CI_TADP,                      /* ADP, target originated */
+  CI_HBOOT,                     /* Boot, host originated */
+  CI_TBOOT,                     /* Boot, target originated */
+  CI_CLIB,                      /* Semihosting C library support */
+  CI_HUDBG,                     /* User debug support, host originated */
+  CI_TUDBG,                     /* User debug support, target originated */
+  CI_HTDCC,                     /* Thumb direct comms channel, host orig. */
+  CI_TTDCC,                     /* Thumb direct comms channel, target orig. */
+  CI_TLOG,                      /* Target debug/logging */
+  CI_NUM_CHANNELS
+};
+
+typedef unsigned ChannelID;
+
+
+/*
+ * Size in bytes of the channel header.
+ * This is a duplicate of XXX in chanpriv.h, but we don't want everyone
+ * to have access to all of chanpriv.h, so we'll double-check in chanpriv.h.
+ */
+#define CHAN_HEADER_SIZE (4)
+
+#endif /* ndef angel_chandefs_h */
+
+/* EOF chandefs.h */
diff --git a/gdb/rdi-share/channels.h b/gdb/rdi-share/channels.h
new file mode 100644 (file)
index 0000000..b43ebc1
--- /dev/null
@@ -0,0 +1,384 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: User interface to the channels layer
+ */
+
+#ifndef angel_channels_h
+#define angel_channels_h
+
+/*
+ * This provides the public interface to the channels layer read and write
+ * routines, and buffer management routines.
+ */
+
+/* Nested header files, if required */
+
+#include "devices.h"
+#include "chandefs.h"
+#include "adperr.h"
+
+/* General purpose constants, macros, enums, typedefs */
+
+/* use the default device */
+#define CH_DEFAULT_DEV ((DeviceID)-1)
+
+/* return codes */
+typedef enum ChanError {
+  CE_OKAY,                      /* no error */
+  CE_ABANDONED,                 /* abandoned due to device switch */
+  CE_DEV_ERROR,                 /* unexpected error from device driver */
+  CE_BUSY,                      /* channel in use */
+  CE_BUFF_ERROR,                /* unable to get buffer */
+  CE_PRIVATE                    /* start of internal error codes */
+} ChanError;
+
+
+/* Publically-accessible globals */
+
+/*
+ * The following two globals are only valid after angel_InitialiseChannels()
+ * has been called.
+ */
+
+/* the default size of a channel buffer, for global use */
+extern unsigned Angel_ChanBuffSize;
+
+/* the size of a long buffer, for global use */
+extern unsigned Angel_ChanLongSize;
+
+#ifdef TARGET
+AdpErrs send_resend_msg(DeviceID devid);
+#endif
+
+/*
+ * Function: angel_InitialiseChannels
+ *  Purpose: initialise the channels layer
+ *
+ *   Params:
+ *              Input: -
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: -
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+void angel_InitialiseChannels( void );
+
+/*
+ * Function: adp_init_seq
+ *  Purpose: initialise sequence numbers and free anyt leftover buffers
+ *
+ *   Params:
+ *              Input: -
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: - adp_ok if things went ok else an error code
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+AdpErrs adp_init_seq(void);
+
+/*
+ * Function: angel_ChannelAllocBuffer
+ *  Purpose: allocate a buffer that is at least req_size bytes long
+ *
+ *   Params:
+ *              Input: req_size        the minimum size required
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: pointer to allocated buffer, or
+ *                     NULL if unable to allocate suitable buffer
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+p_Buffer angel_ChannelAllocBuffer(unsigned req_size);
+
+
+/*
+ * Function: angel_ChannelReleaseBuffer
+ *  Purpose: release a buffer back to the free pool
+ *
+ *   Params:
+ *              Input: buffer   the buffer to release
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: -
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+void angel_ChannelReleaseBuffer(p_Buffer buffer);
+
+
+/*
+ * Function: angel_ChannelSend
+ *  Purpose: blocking send of a packet via a channel
+ *
+ *   Params:
+ *              Input: devid         Device to use, or CH_DEFAULT_DEV
+ *                     chanid        Channel to use for tx 
+ *                     buffer        Pointer to data to send
+ *                     len           Length of data to send
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: CE_OKAY       Transmission completed
+ *                     CE_BAD_CHAN   Channel id invalid
+ *                     CE_ABANDONED  Tx abandoned due to device switch
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+ChanError angel_ChannelSend(DeviceID devid, ChannelID chanid,
+                            const p_Buffer buffer, unsigned len);
+
+
+/*
+ * Function: angel_ChannelSendAsync
+ *  Purpose: asynchronous send of a packet via a channel
+ *
+ *   Params:
+ *              Input: devid         Device to use, or CH_DEFAULT_DEV
+ *                     chanid        Channel to use for tx 
+ *                     buffer        Pointer to data to send
+ *                     len           Length of data to send
+ *                     callback      Function to call on completion
+ *                     callback_data Pointer to pass to callback
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: CE_OKAY       Transmission underway
+ *                     CE_BAD_CHAN   Channel id invalid
+ *                     CE_ABANDONED  Tx abandoned due to device switch
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * register an asynchronous send on the given channel
+ * (blocks until send can be commenced)
+ */
+
+typedef void (*ChanTx_CB_Fn)(ChannelID  chanid,         /* which channel  */
+                             void      *callback_data); /* as supplied... */
+                             
+
+ChanError angel_ChannelSendAsync(          DeviceID      devid,
+                                           ChannelID     chanid,
+                                     const p_Buffer      buffer,
+                                           unsigned      len, 
+                                           ChanTx_CB_Fn  callback, 
+                                           void         *callback_data);
+
+
+/*
+ * Function: angel_ChannelRead
+ *  Purpose: blocking read of a packet from a channel
+ *
+ *   Params:
+ *              Input: devid         Device to use, or CH_DEFAULT_DEV
+ *                     chanid        Channel to use for rx
+ *             Output: buffer        The buffer, supplied and filled
+ *                     len           How many bytes there are in the buffer
+ *             In/Out: -
+ *
+ *            Returns: CE_OKAY       Reception successful
+ *                     CE_BAD_CHAN   Channel id invalid
+ *                     CE_ABANDONED  Tx abandoned due to device switch
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Note that in the present version, if an asynchronous read has been
+ * registered, a blocking read will be refused with CE_BUSY.
+ */
+ChanError angel_ChannelRead(DeviceID      devid,
+                            ChannelID     chanid,
+                            p_Buffer     *buffer, 
+                            unsigned     *len);
+
+
+/*
+ * Function: angel_ChannelReadAsync
+ *  Purpose: asynchronous read of a packet via a channel
+ *
+ *   Params:
+ *              Input: devid         Device to use, or CH_DEFAULT_DEV
+ *                     chanid        Channel to wait on
+ *                     callback      Function to call on completion, or NULL
+ *                     callback_data Pointer to pass to callback
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: CE_OKAY       Read request registered
+ *                     CE_BAD_CHAN   Channel id invalid
+ *                     CE_BUSY       Someone else is using the channel
+ *                                   (in a single threaded world)
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Register an asynchronous read on the given channel.  There can only be one
+ * async. reader per channel, and blocking reads are not permitted whilst
+ * an async. reader is registered.
+ *
+ * Reader can unregister by specifying NULL as the callback function.
+ */
+
+typedef void (*ChanRx_CB_Fn)(DeviceID   devID,   /* ID of receiving device  */
+                             ChannelID  chanID,  /* ID of receiving channel */
+                             p_Buffer   buff,    /* pointer to buffer       */
+                             unsigned   len,     /* length of data          */
+                             void      *cb_data  /* callback data           */
+                             );
+
+ChanError angel_ChannelReadAsync(DeviceID      devid,
+                                 ChannelID     chanid,
+                                 ChanRx_CB_Fn  callback, 
+                                 void         *callback_data);
+
+
+/*
+ * Function: angel_ChannelReadAll
+ *  Purpose: register an asynchronous read across all devices
+ *
+ *   Params:
+ *              Input: chanid        Channel to look for (usually HBOOT)
+ *                     callback      Function to call on completion
+ *                     callback_data Pointer to pass to callback
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: CE_OKAY       Read request registered
+ *                     CE_BAD_CHAN   Channel id invalid
+ *                     CE_BUSY       Someone else is reading all devices
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Register an asynchronous read across all devices.  This is a 'fallback',
+ * which will be superseded (temporarily) by a registered reader or blocking 
+ * read on a specific device.
+ */
+
+ChanError angel_ChannelReadAll(         ChannelID     chanid,
+                                        ChanRx_CB_Fn  callback,
+                                        void         *callback_data);
+
+
+
+/*
+ * Function: angel_ChannelSendThenRead
+ *  Purpose: blocking write to followed by read from a channel
+ *
+ *   Params:
+ *              Input: devid         Device to use, or CH_DEFAULT_DEV
+ *                     chanid        Channel to use for rx
+ *             In/Out: buffer        On entry:  the packet to be sent
+ *                                   On return: the packet received
+ *                     len           On entry:  length of packet to be sent
+ *                                   On return: length of packet rx'd
+ *             In/Out: -
+ *
+ *            Returns: CE_OKAY       Tx and Reception successful
+ *                     CE_BAD_CHAN   Channel id invalid
+ *                     CE_ABANDONED  Tx abandoned due to device switch
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Note that in the present version, if an asynchronous read has been
+ * registered, this will be refused with CE_BUSY.
+ */
+ChanError angel_ChannelSendThenRead(DeviceID      devid,
+                                    ChannelID     chanid,
+                                    p_Buffer     *buffer, 
+                                    unsigned     *len);
+
+
+/*
+ * Function: angel_ChannelSelectDevice
+ *  Purpose: select the device to be used for all channel comms
+ *
+ *   Params:
+ *              Input: device        ID of device to use as the default
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: CE_OKAY       Default device selected
+ *                     CE_BAD_DEV    Invalid device ID
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: Any channel operations in progress are
+ *                     abandoned.
+ *
+ * select the device for all channels comms
+ */
+
+ChanError angel_ChannelSelectDevice(DeviceID device);
+
+
+/*
+ * Function: angel_ChannelReadActiveDevice
+ *  Purpose: reads the device id of the currently active device
+ *
+ *   Params:
+ *              Input: device        address of a DeviceID variable
+ *             Output: *device       ID of device currently being used
+ *             In/Out: -
+ *
+ *            Returns: CE_OKAY       Default device selected
+ */
+
+ChanError angel_ChannelReadActiveDevice(DeviceID *device);
+
+#endif /* ndef angel_channels_h */
+
+/* EOF channels.h */
diff --git a/gdb/rdi-share/chanpriv.h b/gdb/rdi-share/chanpriv.h
new file mode 100644 (file)
index 0000000..155e864
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Private header for channels implementations
+ */
+
+#ifndef angel_chanpriv_h
+#define angel_chanpriv_h
+
+/*
+ * This describes the internal structure and flags for a channels packet.
+ */
+
+/* byte positions within channel packet */
+#define CF_CHANNEL_BYTE_POS  0
+#define CF_HOME_SEQ_BYTE_POS 1
+#define CF_OPPO_SEQ_BYTE_POS 2
+#define CF_FLAGS_BYTE_POS    3
+#define CF_DATA_BYTE_POS     4
+
+/* flags for FLAGS field */
+#define CF_RELIABLE  (1 << 0)    /* use reliable channels protocol */
+#define CF_RESEND    (1 << 1)    /* this is a renegotiation packet */
+#define CF_HEARTBEAT (1 << 2)    /* heartbeat packet - prod target into sync */
+
+/* byte positions within buffer */
+#define CB_LINK_BYTE_POS        0   /* the link pointer */
+#define CB_CHAN_HEADER_BYTE_POS 4   /* the channel frame starts here */
+
+/* macro to get buffer position of packet component */
+#define CB_PACKET(x) (CB_CHAN_HEADER_BYTE_POS + (x))
+
+/* byte offset of packet data within buffer */
+#define CB_CHAN_DATA_BYTE_POS   (CB_PACKET(CF_DATA_BYTE_POS))
+
+/* access the link in a buffer, where b is byte pointer to buffer */
+#define CB_LINK(b) ((p_Buffer)(&(b)[0]))
+
+#define invalidChannelID(chan)  (((int)(chan)) < 0 || \
+                                 (chan) >= CI_NUM_CHANNELS)
+
+#endif /* ndef angel_chanpriv_h */
+
+/* EOF chanpriv.h */
diff --git a/gdb/rdi-share/configure.in b/gdb/rdi-share/configure.in
new file mode 100644 (file)
index 0000000..cd4a715
--- /dev/null
@@ -0,0 +1,44 @@
+srcname="RDI library"
+srctrigger=ardi.c
+
+# per-host:
+
+. ${srcdir}/../configure.host
+
+echo "rdi-share/configure.in: host is $host, target is $target"
+
+if [ ! -f ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ]; then
+       echo '***' "GDB remote does not support host ${host}" 1>&2
+       exit 1
+fi
+
+#  We really shouldn't depend on there being a space after XM_FILE= ...
+hostfile=`awk '$1 == "XM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
+
+# per-target:
+
+. ${srcdir}/../configure.tgt
+
+echo "rdi-share/configure.in: host_cpu is $host_cpu, target_cpu is $target_cpu"
+
+if [ ! -f ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt ]; then
+       echo '***' "GDB remote does not support target ${target}" 1>&2
+       exit 1
+fi
+
+if [ -z "${removing}" ] ; then
+       cat ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt | awk '$1 == "#msg" {
+               print substr($0,6)}'
+fi
+
+#  We really shouldn't depend on there being a space after TM_FILE= ...
+targetfile=`awk '$1 == "TM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt`
+
+if [ "${target}" = "${host}" ] ; then
+       nativefile=`awk '$1 == "NAT_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
+fi
+
+host_makefile_frag=../config/${gdb_host_cpu}/${gdb_host}.mh
+target_makefile_frag=../config/${gdb_target_cpu}/${gdb_target}.mt
+
+# post-target:
diff --git a/gdb/rdi-share/crc.c b/gdb/rdi-share/crc.c
new file mode 100644 (file)
index 0000000..cfa6522
--- /dev/null
@@ -0,0 +1,257 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * crc.c - provides some "standard" CRC calculation routines.
+ *
+ */
+#include "crc.h"    /* describes this code */
+
+/**********************************************************************/
+
+/*
+ * crc32                                                IEEE-802.3 32bit CRC
+ * -----                                                --------------------
+ */
+
+/* This table was generated by the "crctable" program */
+static const unsigned int crc32table[256] = {
+                   /* 0x00 */ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+                   /* 0x04 */ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+                   /* 0x08 */ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+                   /* 0x0C */ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+                   /* 0x10 */ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+                   /* 0x14 */ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+                   /* 0x18 */ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+                   /* 0x1C */ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+                   /* 0x20 */ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+                   /* 0x24 */ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+                   /* 0x28 */ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+                   /* 0x2C */ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+                   /* 0x30 */ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+                   /* 0x34 */ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+                   /* 0x38 */ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+                   /* 0x3C */ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+                   /* 0x40 */ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+                   /* 0x44 */ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+                   /* 0x48 */ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+                   /* 0x4C */ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+                   /* 0x50 */ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+                   /* 0x54 */ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+                   /* 0x58 */ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+                   /* 0x5C */ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+                   /* 0x60 */ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+                   /* 0x64 */ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+                   /* 0x68 */ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+                   /* 0x6C */ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+                   /* 0x70 */ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+                   /* 0x74 */ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+                   /* 0x78 */ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+                   /* 0x7C */ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+                   /* 0x80 */ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+                   /* 0x84 */ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+                   /* 0x88 */ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+                   /* 0x8C */ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+                   /* 0x90 */ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+                   /* 0x94 */ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+                   /* 0x98 */ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+                   /* 0x9C */ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+                   /* 0xA0 */ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+                   /* 0xA4 */ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+                   /* 0xA8 */ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+                   /* 0xAC */ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+                   /* 0xB0 */ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+                   /* 0xB4 */ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+                   /* 0xB8 */ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+                   /* 0xBC */ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+                   /* 0xC0 */ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+                   /* 0xC4 */ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+                   /* 0xC8 */ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+                   /* 0xCC */ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+                   /* 0xD0 */ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+                   /* 0xD4 */ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+                   /* 0xD8 */ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+                   /* 0xDC */ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+                   /* 0xE0 */ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+                   /* 0xE4 */ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+                   /* 0xE8 */ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+                   /* 0xEC */ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+                   /* 0xF0 */ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+                   /* 0xF4 */ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+                   /* 0xF8 */ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+                   /* 0xFC */ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
+                                            };
+unsigned int crc32(unsigned char *address, unsigned int size, unsigned int crc)
+{
+#if 0
+  /* FAST, but bigger and only good for word-aligned data */
+  unsigned int *daddr = (unsigned int *)address;
+  unsigned int  data = FALSE; /* little-endian by default */
+
+ /*
+  * TODO: We should really get the current processor big- or
+  * little-endian state and set "data" accordingly.
+  */
+
+  /* Perform word loop to save on memory accesses */
+  if (data)
+    /* big-endian */
+    for (; (size > 0); size -= sizeof(unsigned int))
+    {
+      data = *daddr++;
+      crc = (((crc >> 8) & 0x00FFFFFF) ^
+             crc32table[(crc ^ ((data >> 24) & 0xFF)) & 0xFF]);
+      crc = (((crc >> 8) & 0x00FFFFFF) ^
+             crc32table[(crc ^ ((data >> 16) & 0xFF)) & 0xFF]);
+      crc = (((crc >> 8) & 0x00FFFFFF) ^
+             crc32table[(crc ^ ((data >>  8) & 0xFF)) & 0xFF]);
+      crc = (((crc >> 8) & 0x00FFFFFF) ^
+             crc32table[(crc ^ ((data >>  0) & 0xFF)) & 0xFF]);
+    }
+  else
+    for (; (size > 0); size -= sizeof(unsigned int))
+    {
+      data = *daddr++;
+      crc = (((crc >> 8) & 0x00FFFFFF) ^
+             crc32table[(crc ^ ((data >>  0) & 0xFF)) & 0xFF]);
+      crc = (((crc >> 8) & 0x00FFFFFF) ^
+             crc32table[(crc ^ ((data >>  8) & 0xFF)) & 0xFF]);
+      crc = (((crc >> 8) & 0x00FFFFFF) ^
+             crc32table[(crc ^ ((data >> 16) & 0xFF)) & 0xFF]);
+      crc = (((crc >> 8) & 0x00FFFFFF) ^
+             crc32table[(crc ^ ((data >> 24) & 0xFF)) & 0xFF]);
+    }
+#else
+  for (; (size > 0); size--)
+    /* byte loop */
+    crc = (((crc >> 8) & 0x00FFFFFF) ^
+           crc32table[(crc ^ *address++) & 0x000000FF]);
+#endif
+
+  return(crc);
+}
+
+/**********************************************************************/
+
+/*
+ * crc16                                                     16bit CRC-CCITT
+ * -----                                                     ---------------
+ * This function provides a table driven 16bit CRC generation for byte data.
+ * This CRC is also known as the HDLC CRC.
+ */
+/*
+ * 960201 KWelton
+ *
+ *TODO: Is this correct?  The compiler predefines __arm, *not* __ARM
+ */
+#ifdef __ARM
+/*
+ * To make the code quicker on the ARM, we double the table size and
+ * use integer slots rather than short slots for the table.
+ */
+static const unsigned int crctableA[16] = {
+#else
+static const unsigned short crctableA[16] = {
+#endif
+                                             0x0000,
+                                             0x1081,
+                                             0x2102,
+                                             0x3183,
+                                             0x4204,
+                                             0x5285,
+                                             0x6306,
+                                             0x7387,
+                                             0x8408,
+                                             0x9489,
+                                             0xA50A,
+                                             0xB58B,
+                                             0xC60C,
+                                             0xD68D,
+                                             0xE70E,
+                                             0xF78F
+                                            };
+
+#ifdef __ARM
+/* See comments above */
+static const unsigned int crctableB[16] = {
+#else
+static const unsigned short crctableB[16] = {
+#endif
+                                             0x0000,
+                                             0x1189,
+                                             0x2312,
+                                             0x329B,
+                                             0x4624,
+                                             0x57AD,
+                                             0x6536,
+                                             0x74BF,
+                                             0x8C48,
+                                             0x9DC1,
+                                             0xAF5A,
+                                             0xBED3,
+                                             0xCA6C,
+                                             0xDBE5,
+                                             0xE97E,
+                                             0xF8F7
+                                            };
+
+unsigned short crc16(unsigned char *address, unsigned int size,
+                     unsigned short crc)
+{
+  for (; (size > 0); size--)
+  {
+    /* byte loop */
+    unsigned char data = *address++; /* fetch the next data byte */
+
+    data ^= crc; /* EOR data with current CRC value */
+    crc = ((crctableA[(data & 0xF0) >> 4] ^ crctableB[data & 0x0F]) ^
+           (crc >> 8));
+  }
+
+  return(crc);
+}
+
+/**********************************************************************/
+
+#if 0 /* not required at the moment */
+
+/*
+ * elf_hash
+ * --------
+ * This function is derived from the one on page 68 of chapter of the "Unix
+ * SVR4 Programmer's Guide". It is used to generate a hash-code from a
+ * symbol name.
+ */
+unsigned int elf_hash(const unsigned char *name)
+{
+  unsigned int h = 0;
+  unsigned int g;
+
+  /* NULL pointer returns a hash of zero */
+  while (name && (*name))
+  {
+    h = ((h << 4) + *name++);
+
+    if (g = (h & 0xF0000000))
+      h ^= (g >> 24);
+
+    h &= ~g;
+  }
+
+  return(h);
+}
+#endif
+
+/**********************************************************************/
+
+/* EOF crc.c */
diff --git a/gdb/rdi-share/crc.h b/gdb/rdi-share/crc.h
new file mode 100644 (file)
index 0000000..77ba23e
--- /dev/null
@@ -0,0 +1,90 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * crc.h - describes some "standard" CRC calculation routines.
+ */
+#ifndef angel_crc_h
+#define angel_crc_h
+
+/*
+ * manifests
+ */
+
+/*
+ * When using "crc32" or "crc16" these initial CRC values must be given to
+ * the respective function the first time it is called. The function can
+ * then be called with the return value from the last call of the function
+ * to generate a running CRC over multiple data blocks.
+ * When the last data block has been processed using the "crc32" algorithm
+ * the CRC value should be inverted to produce the final CRC value:
+ * e.g. CRC = ~CRC
+ */
+
+#define startCRC32  (0xFFFFFFFF)    /* CRC initialised to all 1s */
+#define startCRC16  (0x0000)        /* CRC initialised to all 0s */
+
+/*
+ * For the CRC-32 residual to be calculated correctly requires that the CRC
+ * value is in memory little-endian due to the byte read, bit-ordering
+ * nature of the algorithm.
+ */
+#define CRC32residual   (0xDEBB20E3)    /* good CRC-32 residual */
+
+
+/**********************************************************************/
+
+/*
+ * exported functions
+ */
+
+/*
+ *  Function: crc32
+ *   Purpose: Provides a table driven implementation of the IEEE-802.3
+ *            32-bit CRC algorithm for byte data.
+ *
+ *    Params:
+ *       Input: address     pointer to the byte data
+ *              size        number of bytes of data to be processed
+ *              crc         initial CRC value to be used (can be the output
+ *                          from a previous call to this function).
+ *   Returns:
+ *          OK: 32-bit CRC value for the specified data
+ */
+extern unsigned int crc32(unsigned char *address, unsigned int size,
+                          unsigned int crc);
+
+/**********************************************************************/
+
+/*
+ *
+ *  Function: crc16
+ *   Purpose: Generates a table driven 16-bit CRC-CCITT for byte data
+ *
+ *    Params:
+ *       Input: address     pointer to the byte data
+ *              size        number of bytes of data to be processed
+ *              crc         initial CRC value to be used (can be the output
+ *                          from a previous call to this function).
+ *
+ *   Returns:
+ *          OK: 16-bit CRC value for the specified data
+ */
+extern unsigned short crc16(unsigned char *address, unsigned int size,
+                            unsigned short crc);
+
+/**********************************************************************/
+
+#endif /* !defined(angel_crc_h) */
+
+/* EOF crc.h */
diff --git a/gdb/rdi-share/dbg_conf.h b/gdb/rdi-share/dbg_conf.h
new file mode 100644 (file)
index 0000000..bf79958
--- /dev/null
@@ -0,0 +1,54 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM symbolic debugger toolbox: dbg_conf.h
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef Dbg_Conf__h
+
+#define Dbg_Conf__h
+
+typedef struct Dbg_ConfigBlock {
+    int bytesex;
+    int fpe;               /* Target should initialise FPE */
+    long memorysize;
+    unsigned long cpu_speed;/* Cpu speed (HZ) */
+    int serialport;        /*) remote connection parameters */
+    int seriallinespeed;   /*) (serial connection) */
+    int parallelport;      /*) ditto */
+    int parallellinespeed; /*) (parallel connection) */
+    char *ethernettarget;  /* name of remote ethernet target */
+    int processor;         /* processor the armulator is to emulate (eg ARM60) */
+    int rditype;           /* armulator / remote processor */
+    int heartbeat_on;  /* angel heartbeat */
+    int drivertype;        /* parallel / serial / etc */
+    char const *configtoload;
+    char const *memconfigtoload;
+    int flags;
+} Dbg_ConfigBlock;
+
+#define Dbg_ConfigFlag_Reset 1
+#define Dbg_ConfigFlag_LLSymsNeedPrefix 2
+
+typedef struct Dbg_HostosInterface Dbg_HostosInterface;
+/* This structure allows access by the (host-independent) C-library support
+   module of armulator or pisd (armos.c) to host-dependent functions for
+   which there is no host-independent interface.  Its contents are unknown
+   to the debugger toolbox.
+   The assumption is that, in a windowed system, fputc(stderr) for example
+   may not achieve the desired effect of the character appearing in some
+   window.
+ */
+
+#endif
diff --git a/gdb/rdi-share/dbg_cp.h b/gdb/rdi-share/dbg_cp.h
new file mode 100644 (file)
index 0000000..8974f83
--- /dev/null
@@ -0,0 +1,62 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM symbolic debugger toolbox: dbg_cp.h
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef Dbg_CP__h
+
+#define Dbg_CP__h
+
+#define Dbg_Access_Readable  1
+#define Dbg_Access_Writable  2
+#define Dbg_Access_CPDT      4 /* else CPRT */
+
+typedef struct {
+    unsigned short rmin, rmax;
+    /* a single description can be used for a range of registers with
+       the same properties *accessed via CPDT instructions*
+     */
+    unsigned char nbytes;   /* size of register */
+    unsigned char access;   /* see above (Access_xxx) */
+    union {
+       struct { /* CPDT instructions do not allow the coprocessor much freedom:
+                   only bit 22 ('N') and 12-15 ('CRd') are free for the
+                   coprocessor to use as it sees fit.
+                 */
+                unsigned char nbit;
+                unsigned char rdbits;
+              } cpdt;
+       struct { /* CPRT instructions have much more latitude.  The bits fixed
+                   by the ARM are  24..31 (condition mask & opcode)
+                                   20 (direction)
+                                   8..15 (cpnum, arm register)
+                                   4 (CPRT not CPDO)
+                   leaving 14 bits free to the coprocessor (fortunately
+                   falling within two bytes).
+                 */
+                unsigned char read_b0, read_b1,
+                              write_b0, write_b1;
+              } cprt;
+    } accessinst;
+} Dbg_CoProRegDesc;
+
+struct Dbg_CoProDesc {
+    int entries;
+    Dbg_CoProRegDesc regdesc[1/* really nentries */];
+};
+
+#define Dbg_CoProDesc_Size(n) (sizeof(struct Dbg_CoProDesc) + ((n)-1)*sizeof(Dbg_CoProRegDesc))
+
+#endif
diff --git a/gdb/rdi-share/dbg_hif.h b/gdb/rdi-share/dbg_hif.h
new file mode 100644 (file)
index 0000000..3982d11
--- /dev/null
@@ -0,0 +1,56 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM debugger toolbox : dbg_hif.c
+ * Description of the Dbg_HostosInterface structure.  This is *NOT*
+ * part of the debugger toolbox, but it is required by 2 back ends
+ * (armul & pisd) and two front ends (armsd & wdbg), so putting it
+ * in the toolbox is the only way of avoiding multiple copies.
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef dbg_hif__h
+#define dbg_hif__h
+
+#if defined __STDC__ || defined ALMOST_STDC
+#  include <stdarg.h>
+#else
+#  include <varargs.h>
+#endif
+
+typedef void Hif_DbgPrint(void *arg, const char *format, va_list ap);
+typedef void Hif_DbgPause(void *arg);
+
+typedef void Hif_WriteC(void *arg, int c);
+typedef int Hif_ReadC(void *arg);
+typedef int Hif_Write(void *arg, char const *buffer, int len);
+typedef char *Hif_GetS(void *arg, char *buffer, int len);
+
+typedef void Hif_RDIResetProc(void *arg);
+
+struct Dbg_HostosInterface {
+    Hif_DbgPrint *dbgprint;
+    Hif_DbgPause *dbgpause;
+    void *dbgarg;
+
+    Hif_WriteC *writec;
+    Hif_ReadC *readc;
+    Hif_Write *write;
+    Hif_GetS *gets;
+    void *hostosarg;
+
+    Hif_RDIResetProc *reset;
+    void *resetarg;
+};
+
+#endif
diff --git a/gdb/rdi-share/dbg_rdi.h b/gdb/rdi-share/dbg_rdi.h
new file mode 100644 (file)
index 0000000..efda7bd
--- /dev/null
@@ -0,0 +1,511 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * ARM debugger toolbox : dbg_rdi.h
+ */
+
+/*
+ * RCS $Revision$
+ * Checkin $Date$
+ */
+
+#ifndef dbg_rdi__h
+#define dbg_rdi__h
+
+/***************************************************************************\
+*                            Other RDI values                               *
+\***************************************************************************/
+
+#define RDISex_Little           0 /* the byte sex of the debuggee       */
+#define RDISex_Big              1
+#define RDISex_DontCare         2
+
+#define RDIPoint_EQ             0 /* the different types of break/watchpoints */
+#define RDIPoint_GT             1
+#define RDIPoint_GE             2
+#define RDIPoint_LT             3
+#define RDIPoint_LE             4
+#define RDIPoint_IN             5
+#define RDIPoint_OUT            6
+#define RDIPoint_MASK           7
+
+#define RDIPoint_16Bit          16  /* 16-bit breakpoint                */
+#define RDIPoint_Conditional    32
+
+/* ORRed with point type in extended RDP break and watch messages       */
+#define RDIPoint_Inquiry        64
+#define RDIPoint_Handle         128 /* messages                         */
+
+#define RDIWatch_ByteRead       1 /* types of data accesses to watch for*/
+#define RDIWatch_HalfRead       2
+#define RDIWatch_WordRead       4
+#define RDIWatch_ByteWrite      8
+#define RDIWatch_HalfWrite      16
+#define RDIWatch_WordWrite      32
+
+#define RDIReg_R15              (1L << 15) /* mask values for CPU       */
+#define RDIReg_PC               (1L << 16)
+#define RDIReg_CPSR             (1L << 17)
+#define RDIReg_SPSR             (1L << 18)
+#define RDINumCPURegs           19
+
+#define RDINumCPRegs            10 /* current maximum                   */
+
+#define RDIMode_Curr            255
+
+/* RDI_Info subcodes */
+/* rdp in parameters are all preceded by                                */
+/*   in byte = RDP_Info, word = info subcode                            */
+/*     out parameters are all preceded by                               */
+/*   out byte = RDP_Return                                              */
+
+#define RDIInfo_Target          0
+/* rdi: out ARMword *targetflags, out ARMword *processor id             */
+/* rdp: in none, out word targetflags, word processorid, byte status    */
+/* the following bits are defined in targetflags                        */
+#  define RDITarget_LogSpeed                  0x0f
+#  define RDITarget_HW                        0x10    /* else emulator  */
+#  define RDITarget_AgentMaxLevel             0xe0
+#  define RDITarget_AgentLevelShift       5
+#  define RDITarget_DebuggerMinLevel         0x700
+#  define RDITarget_DebuggerLevelShift    8
+#  define RDITarget_CanReloadAgent           0x800
+#  define RDITarget_CanInquireLoadSize      0x1000
+#  define RDITarget_UnderstandsRDPInterrupt 0x2000
+#  define RDITarget_CanProfile              0x4000
+#  define RDITarget_Code16                  0x8000
+#  define RDITarget_HasCommsChannel        0x10000
+
+#define RDIInfo_Points          1
+/* rdi: out ARMword *pointcapabilities                                  */
+/* rdp: in none, out word pointcapabilities, byte status                */
+/* the following bits are defined in pointcapabilities                  */
+#  define RDIPointCapability_Comparison   1
+#  define RDIPointCapability_Range        2
+/* 4 to 128 are RDIWatch_xx{Read,Write} left-shifted by two */
+#  define RDIPointCapability_Mask         0x100
+#  define RDIPointCapability_ThreadBreak  0x200
+#  define RDIPointCapability_ThreadWatch  0x400
+#  define RDIPointCapability_CondBreak    0x800
+#  define RDIPointCapability_Status       0x1000 /* status enquiries available */
+
+#define RDIInfo_Step            2
+/* rdi: out ARMword *stepcapabilities                                   */
+/* rdp: in none, out word stepcapabilities, byte status                 */
+/* the following bits are defined in stepcapabilities                   */
+#  define RDIStep_Multiple      1
+#  define RDIStep_PCChange      2
+#  define RDIStep_Single        4
+
+#define RDIInfo_MMU             3
+/* rdi: out ARMword *mmuidentity                                        */
+/* rdp: in none, out word mmuidentity, byte status                      */
+
+#define RDIInfo_DownLoad        4
+/* Inquires whether configuration download and selection is available.  */
+/* rdp: in none, out byte status                                        */
+/* No argument, no return value. status == ok if available              */
+
+#define RDIInfo_SemiHosting     5
+/* Inquires whether RDISemiHosting_* RDI_Info calls are available.      */
+/* rdp: in none, out byte status                                        */
+/* No argument, no return value. status == ok if available              */
+
+#define RDIInfo_CoPro           6
+/* Inquires whether CoPro RDI_Info calls are available.                 */
+/* rdp: in none, out byte status                                        */
+/* No argument, no return value. status == ok if available              */
+
+#define RDIInfo_Icebreaker      7
+/* Inquires whether debuggee controlled by IceBreaker.                  */
+/* rdp: in none, out byte status                                        */
+/* No argument, no return value. status == ok if available              */
+
+#define RDIMemory_Access        8
+/* rdi: out RDI_MemAccessStats *p, in ARMword *handle                   */
+/* rdp: in word handle                                                  */
+/*      out word nreads, word nwrites, word sreads, word swrites,       */
+/*          word ns, word s, byte status                                */
+
+/* Get memory access information for memory block with specified handle */
+
+#define RDIMemory_Map           9
+/* rdi: in  RDI_MemDescr md[n], in ARMword *n                           */
+/* rdp: in word n, n * {                                                */
+/*           word handle, word start, word limit,                       */
+/*           byte width, byte access                                    */
+/*           word Nread_ns, word Nwrite_ns,                             */
+/*           word Sread_ns, word Swrite_ns}                             */
+/*      out byte status                                                 */
+/* Sets memory characteristics.                                         */
+
+#define RDISet_CPUSpeed         10
+/* rdi: in  ARMword *speed                                              */
+/* rdp: in word speed, out byte status                                  */
+/* Sets CPU speed (in ns)                                               */
+
+#define RDIRead_Clock           12
+/* rdi: out ARMword *ns, out ARMword *s                                 */
+/* rdp: in none, out word ns, word s, byte status                       */
+/* Reads simulated time                                                 */
+
+#define RDIInfo_Memory_Stats    13
+/* Inquires whether RDI_Info codes 8-10 are available                   */
+/* rdp: in none, out byte status                                        */
+/* No argument, no return value. status == ok if available              */
+
+/* The next two are only to be used if RDIInfo_DownLoad returned no     */
+/* error                                                                */
+#define RDIConfig_Count         14
+/* rdi: out ARMword *count                                              */
+/* rdp: out byte status, word count (if status == OK)                   */
+
+/* In addition, the next one is only to be used if RDIConfig_Count      */
+/* returned no error                                                    */
+typedef struct { unsigned32 version; char name[32]; } RDI_ConfigDesc;
+#define RDIConfig_Nth           15
+/* rdi: in ARMword *n, out RDI_ConfigDesc *                             */
+/* rdp: in word n                                                       */
+/*      out word version, byte namelen, bytes * bytelen name,           */
+/*          byte status                                                 */
+
+/* Set a front-end polling function to be used from within driver poll  */
+/* loops                                                                */
+typedef void RDI_PollProc(void *);
+typedef struct { RDI_PollProc *p; void *arg; } RDI_PollDesc;
+#define RDISet_PollProc         16
+/* rdi: in RDI_PollDesc const *from, RDI_PollDesc *to                   */
+/*      if from non-NULL, sets the polling function from it             */
+/*      if to non-NULL, returns the previous polling function to it     */
+/* No corresponding RDP operation                                       */
+
+/* Called on debugger startup to see if the target is ready to execute  */
+#define RDIInfo_CanTargetExecute 20
+/* rdi: in  void
+ *      out byte status (RDIError_NoError => Yes, Otherwise No)
+ */
+
+/* Called to set the top of target memory in an ICEman2 system
+ * This is then used by ICEman to tell the C Library via the INFOHEAP
+ * SWI where the stack should start.
+ * Note that only ICEman2 supports this call.  Other systems eg.
+ * Demon, Angel, will simply return an error, which means that setting
+ * the top of memory in this fashion is not supported.
+ */
+#define RDIInfo_SetTopMem        21
+/* rdi: in  word mem_top
+ *      out byte status (RDIError_NoError => Done, Other => Not supported
+ */
+
+/* Called before performing a loadagent to determine the endianess of
+ * the debug agent, so that images of the wrong bytesex can be
+ * complained about
+ */
+#define RDIInfo_AgentEndianess   22
+/* rdi: in void
+ *      out byte status
+ *      status should be RDIError_LittleEndian or RDIError_BigEndian
+ *      any other value indicates the target does not support this
+ *      request, so the debugger will have to make a best guess, which
+ *      probably means only allow little endian loadagenting.
+ */
+
+/* The next two are only to be used if the value returned by            */
+/* RDIInfo_Points has RDIPointCapability_Status set.                    */
+#define RDIPointStatus_Watch    0x80
+#define RDIPointStatus_Break    0x81
+/* rdi: inout ARMword * (in handle, out hwresource), out ARMword *type  */
+/* rdp: in word handle, out word hwresource, word type, byte status     */
+
+#define RDISignal_Stop          0x100
+/* Requests that the debuggee stop                                      */
+/* No arguments, no return value                                        */
+/* rdp: no reply (when the debuggee stops, there will be a reply to the */
+/*      step or execute request which started it)                       */
+
+#define RDIVector_Catch         0x180
+/* rdi: in ARMword *bitmap                                              */
+/* rdp: int word bitmap, out byte status                                */
+/* bit i in bitmap set to cause vector i to cause entry to debugger     */
+
+/* The next four are only to be used if RDIInfo_Semihosting returned    */
+/* no error                                                             */
+#define RDISemiHosting_SetState 0x181
+/* rdi: in ARMword *semihostingstate                                    */
+/* rdp: in word semihostingstate, out byte status                       */
+#define RDISemiHosting_GetState 0x182
+/* rdi: out ARMword *semihostingstate                                   */
+/* rdp: in none, out word semihostingstate, byte status                 */
+#define RDISemiHosting_SetVector 0x183
+/* rdi: in ARMword *semihostingvector                                   */
+/* rdp: in word semihostingvector, out byte status                      */
+#define RDISemiHosting_GetVector 0x184
+/* rdi: out ARMword *semihostingvector                                  */
+/* rdp: in none, out word semihostingvector, byte status                */
+
+/* The next two are only to be used if RDIInfo_Icebreaker returned      */
+/* no error                                                             */
+#define RDIIcebreaker_GetLocks  0x185
+/* rdi: out ARMword *lockedstate                                        */
+/* rdp: in none, out word lockedstate, byte status                      */
+
+#define RDIIcebreaker_SetLocks  0x186
+/* rdi: in ARMword *lockedstate                                         */
+/* rdp: in word lockedstate, out byte status                            */
+
+/* lockedstate is a bitmap of the icebreaker registers locked against   */
+/* use by IceMan (because explicitly written by the user)               */
+
+#define RDIInfo_GetLoadSize     0x187
+/* rdi: out ARMword *maxloadsize                                        */
+/* rdp: in none, out word maxloadsize, byte status                      */
+/* Inquires the maximum length of data transfer the agent is prepared   */
+/* to receive                                                           */
+/* Only usable if RDIInfo_Target returned RDITarget_CanInquireLoadSize  */
+/* rdi: out ARMword *size                                               */
+
+/* Only to be used if the value returned by RDIInfo_Target had          */
+/* RDITarget_HasCommsChannel set                                        */
+typedef void RDICCProc_ToHost(void *arg, ARMword data);
+typedef void RDICCProc_FromHost(void *arg, ARMword *data, int *valid);
+
+#define RDICommsChannel_ToHost  0x188
+/* rdi: in RDICCProc_ToHost *, in void *arg                             */
+/* rdp: in byte connect, out byte status                                */
+#define RDICommsChannel_FromHost 0x189
+/* rdi: in RDICCProc_FromHost *, in void *arg                           */
+/* rdp: in byte connect, out byte status                                */
+
+/* These 4 are only to be used if RDIInfo_Semihosting returns no error  */
+#define RDISemiHosting_SetARMSWI 0x190
+/* rdi: in ARMword ARM_SWI_number                                       */
+/* rdp: in ARMword ARM_SWI_number, out byte status                      */
+
+#define RDISemiHosting_GetARMSWI 0x191
+/* rdi: out ARMword ARM_SWI_number                                      */
+/* rdp: out ARMword ARM_SWI_number, byte status                         */
+
+#define RDISemiHosting_SetThumbSWI 0x192
+/* rdi: in ARMword Thumb_SWI_number                                     */
+/* rdp: in ARMword Thumb_SWI_number, out byte status                    */
+
+#define RDISemiHosting_GetThumbSWI 0x193
+/* rdi: out ARMword ARM_Thumb_number                                    */
+/* rdp: out ARMword ARM_Thumb_number, byte status                       */
+
+
+#define RDICycles               0x200
+/* rdi: out ARMword cycles[12]                                          */
+/* rdp: in none, out 6 words cycles, byte status                        */
+/* the rdi result represents 6 big-endian doublewords; the rdp results  */
+/* return values for the ls halves of these                             */
+#  define RDICycles_Size        48
+
+#define RDIErrorP               0x201
+/* rdi: out ARMaddress *errorp                                          */
+/* rdp: in none, out word errorp, byte status                           */
+/* Returns the error pointer associated with the last return from step  */
+/* or execute with status RDIError_Error.                               */
+
+#define RDISet_Cmdline          0x300
+/* rdi: in char *commandline (a null-terminated string)                 */
+/* No corresponding RDP operation (cmdline is sent to the agent in      */
+/* response to SWI_GetEnv)                                              */
+
+#define RDISet_RDILevel         0x301
+/* rdi: in ARMword *level                                               */
+/* rdp: in word level, out byte status                                  */
+/* Sets the RDI/RDP protocol level to be used (must lie between the     */
+/* limits returned by RDIInfo_Target).                                  */
+
+#define RDISet_Thread           0x302
+/* rdi: in ARMword *threadhandle                                        */
+/* rdp: in word threadhandle, out byte status                           */
+/* Sets the thread context for subsequent thread-sensitive operations   */
+/* (null value sets no thread)                                          */
+
+/* The next two are only to be used if RDI_read or RDI_write returned   */
+/* RDIError_LittleEndian or RDIError_BigEndian, to signify that the     */
+/* debugger has noticed.                                                */
+#define RDIInfo_AckByteSex  0x303
+/* rdi: in ARMword *sex (RDISex_Little or RDISex_Big)                   */
+
+/* The next two are only to be used if RDIInfo_CoPro returned no error  */
+#define RDIInfo_DescribeCoPro   0x400
+/* rdi: in int *cpno, Dbg_CoProDesc *cpd                                */
+/* rdp: in byte cpno,                                                   */
+/*         cpd->entries * {                                             */
+/*           byte rmin, byte rmax, byte nbytes, byte access,            */
+/*           byte cprt_r_b0, cprt_r_b1, cprt_w_b0, cprt_w_b1}           */
+/*         byte = 255                                                   */
+/*      out byte status                                                 */
+
+#define RDIInfo_RequestCoProDesc 0x401
+/* rdi: in int *cpno, out Dbg_CoProDesc *cpd                            */
+/* rpd: in byte cpno                                                    */
+/*      out nentries * {                                                */
+/*            byte rmin, byte rmax, byte nbytes, byte access,           */
+/*          }                                                           */
+/*          byte = 255, byte status                                     */
+
+#define RDIInfo_Log             0x800
+/* rdi: out ARMword *logsetting                                         */
+/* No corresponding RDP operation                                       */
+#define RDIInfo_SetLog          0x801
+/* rdi: in ARMword *logsetting                                          */
+/* No corresponding RDP operation                                       */
+
+#define RDIProfile_Stop         0x500
+/* No arguments, no return value                                        */
+/* rdp: in none, out byte status                                        */
+/* Requests that pc sampling stop                                       */
+
+#define RDIProfile_Start        0x501
+/* rdi: in ARMword *interval                                            */
+/* rdp: in word interval, out byte status                               */
+/* Requests that pc sampling start, with period <interval> usec         */
+
+#define RDIProfile_WriteMap     0x502
+/* rdi: in ARMword map[]                                                */
+/* map[0] is the length of the array, subsequent elements are sorted    */
+/* and are the base of ranges for pc sampling (so if the sampled pc     */
+/* lies between map[i] and map[i+1], count[i] is incremented).          */
+/* rdp: a number of messages, each of form:                             */
+/*        in word len, word size, word offset, <size> words map data    */
+/*        out status                                                    */
+/* len, size and offset are all word counts.                            */
+
+#define RDIProfile_ReadMap      0x503
+/* rdi: in ARMword *len, out ARMword counts[len]                        */
+/* Requests that the counts array be set to the accumulated pc sample   */
+/* counts                                                               */
+/* rdp: a number of messages, each of form:                             */
+/*        in word offset, word size                                     */
+/*        out <size> words, status                                      */
+/* len, size and offset are all word counts.                            */
+
+#define RDIProfile_ClearCounts  0x504
+/* No arguments, no return value                                        */
+/* rdp: in none, out byte status                                        */
+/* Requests that pc sample counts be set to zero                        */
+
+#define RDIInfo_RequestReset    0x900
+/* Request reset of the target environment                              */
+/* No arguments, no return value                                        */
+/* No RDP equivalent, sends an RDP reset                                */
+
+#define RDIInfo_CapabilityRequest 0x8000
+/* Request whether the interface supports the named capability. The     */
+/* capability is specified by or'ing the RDIInfo number with this, and  */
+/* sending that request                                                 */
+/* rdi: in none                                                         */
+/* rdp: in none, out byte status                                        */
+
+typedef struct {
+  ARMword len;
+  ARMword map[1];
+} RDI_ProfileMap;
+
+typedef unsigned32 PointHandle;
+typedef unsigned32 ThreadHandle;
+#define RDINoPointHandle        ((PointHandle)-1L)
+#define RDINoHandle             ((ThreadHandle)-1L)
+
+struct Dbg_ConfigBlock;
+struct Dbg_HostosInterface;
+struct Dbg_MCState;
+typedef int rdi_open_proc(unsigned type, struct Dbg_ConfigBlock const *config,
+                          struct Dbg_HostosInterface const *i,
+                          struct Dbg_MCState *dbg_state);
+typedef int rdi_close_proc(void);
+typedef int rdi_read_proc(ARMword source, void *dest, unsigned *nbytes);
+typedef int rdi_write_proc(const void *source, ARMword dest, unsigned *nbytes);
+typedef int rdi_CPUread_proc(unsigned mode, unsigned32 mask, ARMword *state);
+typedef int rdi_CPUwrite_proc(unsigned mode, unsigned32 mask, ARMword const *state);
+typedef int rdi_CPread_proc(unsigned CPnum, unsigned32 mask, ARMword *state);
+typedef int rdi_CPwrite_proc(unsigned CPnum, unsigned32 mask, ARMword const *state);
+typedef int rdi_setbreak_proc(ARMword address, unsigned type, ARMword bound,
+                              PointHandle *handle);
+typedef int rdi_clearbreak_proc(PointHandle handle);
+typedef int rdi_setwatch_proc(ARMword address, unsigned type, unsigned datatype,
+                              ARMword bound, PointHandle *handle);
+typedef int rdi_clearwatch_proc(PointHandle handle);
+typedef int rdi_execute_proc(PointHandle *handle);
+typedef int rdi_step_proc(unsigned ninstr, PointHandle *handle);
+typedef int rdi_info_proc(unsigned type, ARMword *arg1, ARMword *arg2);
+typedef int rdi_pointinq_proc(ARMword *address, unsigned type,
+                              unsigned datatype, ARMword *bound);
+
+typedef enum {
+    RDI_ConfigCPU,
+    RDI_ConfigSystem
+} RDI_ConfigAspect;
+
+typedef enum {
+    RDI_MatchAny,
+    RDI_MatchExactly,
+    RDI_MatchNoEarlier
+} RDI_ConfigMatchType;
+
+typedef int rdi_addconfig_proc(unsigned32 nbytes);
+typedef int rdi_loadconfigdata_proc(unsigned32 nbytes, char const *data);
+typedef int rdi_selectconfig_proc(RDI_ConfigAspect aspect, char const *name,
+                                  RDI_ConfigMatchType matchtype, unsigned versionreq,
+                                  unsigned *versionp);
+
+typedef char *getbufferproc(void *getbarg, unsigned32 *sizep);
+typedef int rdi_loadagentproc(ARMword dest, unsigned32 size, getbufferproc *getb, void *getbarg);
+typedef int rdi_targetisdead(void);
+
+typedef struct {
+    int itemmax;
+    char const * const *names;
+} RDI_NameList;
+
+typedef RDI_NameList const *rdi_namelistproc(void);
+
+typedef int rdi_errmessproc(char *buf, int buflen, int errnum);
+
+struct RDIProcVec {
+    char rditypename[12];
+
+    rdi_open_proc       *open;
+    rdi_close_proc      *close;
+    rdi_read_proc       *read;
+    rdi_write_proc      *write;
+    rdi_CPUread_proc    *CPUread;
+    rdi_CPUwrite_proc   *CPUwrite;
+    rdi_CPread_proc     *CPread;
+    rdi_CPwrite_proc    *CPwrite;
+    rdi_setbreak_proc   *setbreak;
+    rdi_clearbreak_proc *clearbreak;
+    rdi_setwatch_proc   *setwatch;
+    rdi_clearwatch_proc *clearwatch;
+    rdi_execute_proc    *execute;
+    rdi_step_proc       *step;
+    rdi_info_proc       *info;
+    /* V2 RDI */
+    rdi_pointinq_proc   *pointinquiry;
+
+    /* These three useable only if RDIInfo_DownLoad returns no error */
+    rdi_addconfig_proc  *addconfig;
+    rdi_loadconfigdata_proc *loadconfigdata;
+    rdi_selectconfig_proc *selectconfig;
+
+    rdi_namelistproc    *drivernames;
+    rdi_namelistproc    *cpunames;
+
+    rdi_errmessproc     *errmess;
+
+    /* Only if RDIInfo_Target returns a value with RDITarget_LoadAgent set */
+    rdi_loadagentproc   *loadagent;
+    rdi_targetisdead    *targetisdead;
+};
+
+#endif
diff --git a/gdb/rdi-share/devclnt.h b/gdb/rdi-share/devclnt.h
new file mode 100644 (file)
index 0000000..cb920f6
--- /dev/null
@@ -0,0 +1,260 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Public client interface to devices
+ */
+
+#ifndef angel_devclnt_h
+#define angel_devclnt_h
+
+/*
+ * This header exports the public interface to Angel-compliant device
+ * drivers.
+ *
+ * They are intended to be used solely by Angel, not by the User
+ * Application.  See devappl.h for the User Application interface to
+ * the device drivers.
+ */
+
+#include "devices.h"
+
+/* General purpose constants, macros, enums, typedefs */
+
+/*
+ * possible channels at device level
+ *
+ * XXX
+ *
+ * these are used as array indices, so be specific about their values
+ */
+typedef enum DevChanID {
+  DC_DBUG = 0,                  /* reliable debug packets
+                                 * containing SDBG, CLIB,UDBG, etc.) */
+  DC_APPL = 1,                  /* application packets */
+  DC_NUM_CHANNELS
+} DevChanID;
+
+/* Publically-accessible globals */
+/* none */
+
+/* Public functions */
+
+/*
+ * Function: angel_DeviceWrite
+ *  Purpose: The main entry point for asynchronous writes to a device.
+ *
+ *   Params:
+ *              Input: devID     index of the device to write to
+ *                     buff      data to write
+ *                     length    how much data to write
+ *                     callback  callback here when write finished
+ *                                or error
+ *                     cb_data   data to be passed to callback
+ *                     chanID    device channel to use
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: DE_OKAY     write request is underway           
+ *                     DE_NO_DEV   no such device                      
+ *                     DE_BAD_DEV  device does not support angel writes
+ *                     DE_BAD_CHAN no such device channel              
+ *                     DE_BUSY     device busy with another write      
+ *                     DE_INVAL    silly length                        
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Commence asynchronous transmission of a buffer on a device.  The
+ * callback will occur when the write completes or if there is an
+ * error.
+ *
+ * This must be called for each packet to be sent.
+ */
+
+DevError angel_DeviceWrite(DeviceID devID, p_Buffer buff,
+                           unsigned length, DevWrite_CB_Fn callback,
+                           void *cb_data, DevChanID chanID);
+
+
+/*
+ * Function: angel_DeviceRegisterRead
+ *  Purpose: The main entry point for asynchronous reads from a device.
+ *
+ *   Params:
+ *              Input: devID     index of the device to read from
+ *                     callback  callback here when read finished
+ *                                or error
+ *                     cb_data   data to be passed to callback
+ *                     get_buff  callback to be used to acquire buffer
+ *                                for incoming packets
+ *                     getb_data data to be passed to get_buff
+ *                     chanID    device channel to use
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns: DE_OKAY     read request is underway           
+ *                     DE_NO_DEV   no such device                      
+ *                     DE_BAD_DEV  device does not support angel reads
+ *                     DE_BAD_CHAN no such device channel              
+ *                     DE_BUSY     device busy with another read      
+ *                     DE_INVAL    silly length                        
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Register asynchronous packet read from a device.  The callback will
+ * occur when the read completes or if there is an error.
+ *
+ * This is persistent: the read remains registered for all incoming
+ * packets on the device channel.
+ */
+
+DevError angel_DeviceRegisterRead(DeviceID devID,
+                                  DevRead_CB_Fn callback, void *cb_data,
+                                  DevGetBuff_Fn get_buff, void *getb_data,
+                                  DevChanID chanID);
+
+
+/*
+ * Function: angel_DeviceControl
+ *  Purpose: Call a control function for a device
+ *
+ *   Params:
+ *              Input: devID     index of the device to control to
+ *                     op        operation to perform
+ *                     arg       parameter depending on op
+ *
+ *            Returns: DE_OKAY     control request is underway           
+ *                     DE_NO_DEV   no such device                      
+ *                     DE_BAD_OP   device does not support operation
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * Have a device perform a control operation.  Extra parameters vary 
+ * according to the operation requested.
+ */
+
+DevError angel_DeviceControl(DeviceID devID, DeviceControl op, void *arg);
+
+
+/*
+ * Function: angel_ReceiveMode
+ *  Purpose: enable or disable reception across all devices
+ *
+ *   Params:
+ *              Input: mode   choose enable or disable
+ *
+ * Pass the mode parameter to the receive_mode control method of each device
+ */
+
+void angel_ReceiveMode(DevRecvMode mode);
+
+
+/*
+ * Function: angel_ResetDevices
+ *  Purpose: reset all devices
+ *
+ *   Params: none
+ *
+ * Call the reset control method for each device
+ */
+
+void angel_ResetDevices(void);
+
+
+/*
+ * Function: angel_InitialiseDevices
+ *  Purpose: initialise the device driver layer
+ *
+ *   Params: none
+ *
+ * Set up the device driver layer and call the init method for each device
+ */
+
+void angel_InitialiseDevices(void);
+
+
+/*
+ * Function: angel_IsAngelDevice
+ *  Purpose: Find out if a device supports Angel packets
+ *
+ *   Params:
+ *              Input: devID     index of the device to control to
+ *
+ *            Returns: TRUE      supports Angel packets
+ *                     FALSE     raw device
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ */
+
+bool angel_IsAngelDevice(DeviceID devID);
+
+
+#if !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0
+
+/*
+ * Function: angel_ApplDeviceHandler
+ *  Purpose: The entry point for User Application Device Driver requests
+ *           in a full functiionality version of Angel.
+ *           It will never be called directly by the User Application,
+ *           but gets called indirectly, via the SWI handler.
+ *
+ *  Params:
+ *      Input: swi_r0    Argument to SWI indicating that 
+ *                       angel_ApplDeviceHandler was to be called.  This
+ *                       will not be used in this function, but is needed
+ *                       by the SWI handler.
+ *             arg_blk   pointer to block of arguments
+ *                       arg_blk[0] is one of
+ *                       angel_SWIreason_ApplDevice_{Read,Write,Yield}
+ *                       which indicates which angel_Device* fn is to
+ *                       be called.  arg_blk[1] - arg_blk[n] are the
+ *                       arguments to the corresponding
+ *                       angel_ApplDevice* function.
+ *             Output: -
+ *             In/Out: -
+ *
+ *            Returns:   whatever the specified angel_Device* function
+ *                       returns.
+ *
+ *      Reads globals: -
+ *   Modifies globals: -
+ *
+ * Other side effects: -
+ *
+ * This has the side effects of angel_Device{Read,Write,Yield}
+ * depending upon which is operation is specified as described above.
+ */
+
+DevError angel_ApplDeviceHandler(
+  unsigned swi_r0, unsigned *arg_blk
+);
+
+#endif /* ndef MINIMAL_ANGEL */
+
+#endif /* ndef angel_devclnt_h */
+
+/* EOF devclnt.h */
diff --git a/gdb/rdi-share/devices.h b/gdb/rdi-share/devices.h
new file mode 100644 (file)
index 0000000..eac6ee2
--- /dev/null
@@ -0,0 +1,104 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Devices header file
+ */
+
+#ifndef angel_devices_h
+#define angel_devices_h
+
+/*
+ * Provides common types for using devices, and provides access to the
+ * device table.
+ */
+
+#include "angel.h"
+#include "buffers.h"
+
+/* General purpose constants, macros, enums, typedefs */
+
+/* a non-enum holder for device IDs */
+typedef unsigned int DeviceID;
+
+/* device error codes */
+typedef enum DevError {
+  DE_OKAY,     /* no error */
+  DE_NO_DEV,   /* no such device */
+  DE_BAD_DEV,  /* device does not support angel */
+  DE_BAD_CHAN, /* no such device channel */
+  DE_BAD_OP,   /* operation not supported by this device */
+  DE_BUSY,     /* device already busy */
+  DE_INVAL,    /* length invalid */
+  DE_FAILED    /* something else went wrong */
+} DevError;
+
+/* return codes from asynchronous calls - primarily for channels' benefit */
+typedef enum DevStatus {
+  DS_DONE,                      /* operation succeeded */
+  DS_OVERFLOW,                  /* not enough buffer space */
+  DS_BAD_PACKET,                /* packet failed */
+  DS_DEV_ERROR,                 /* device error */
+  DS_INT_ERROR                  /* internal error */
+} DevStatus;
+
+/* Callback for async. writes */
+typedef void (*DevWrite_CB_Fn)(
+    void *buff,     /* pointer to data -- cast to p_Buffer  */
+    void *length,   /* how much done   -- cast to unsigned  */
+    void *status,   /* success code    -- cast to DevStatus */
+    void *cb_data   /* as supplied */
+    );
+
+/* Callback for async. reads */
+typedef void (*DevRead_CB_Fn)(
+    void *buff,     /* pointer to data -- cast to p_Buffer  */
+    void *length,   /* how much read   -- cast to unsigned  */
+    void *status,   /* success code    -- cast to DevStatus */
+    void *cb_data   /* as supplied */
+    );
+
+/* control operations */
+typedef enum DeviceControl {
+  DC_INIT,                      /* initialise device             */
+  DC_RESET,                     /* reset device                  */
+  DC_RECEIVE_MODE,              /* control reception             */
+  DC_SET_PARAMS,                /* set parameters of device      */
+#ifndef TARGET
+  DC_GET_USER_PARAMS,           /* params set by user at open    */
+  DC_GET_DEFAULT_PARAMS,        /* device default parameters     */
+  DC_RESYNC,                    /* resynchronise with new agent  */
+#endif
+  DC_PRIVATE                    /* start of private device codes */
+} DeviceControl;
+
+typedef enum DevRecvMode {
+  DR_DISABLE,
+  DR_ENABLE
+} DevRecvMode;
+
+/*
+ * callback to allow a device driver to request a buffer, to be filled
+ * with an incoming packet
+ */
+typedef p_Buffer (*DevGetBuff_Fn)(unsigned req_size, void *cb_data);
+
+
+/* Publically-accessible globals */
+/* none */
+
+#endif /* ndef angel_devices_h */
+
+/* EOF devices.h */
diff --git a/gdb/rdi-share/devsw.c b/gdb/rdi-share/devsw.c
new file mode 100644 (file)
index 0000000..590b812
--- /dev/null
@@ -0,0 +1,400 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "adp.h"
+#include "hsys.h"
+#include "rxtx.h"
+#include "drivers.h"
+#include "buffers.h"
+#include "devclnt.h"
+#include "adperr.h"
+#include "devsw.h"
+#include "hostchan.h"
+#include "logging.h"
+
+/*
+ * TODO: this should be adjustable - it could be done by defining
+ *       a reason code for DevSW_Ioctl.  It could even be a
+ *       per-devicechannel parameter.
+ */
+static const unsigned int allocsize = ADP_BUFFER_MIN_SIZE;
+
+#define illegalDevChanID(type)  ((type) >= DC_NUM_CHANNELS)
+
+/**********************************************************************/
+
+/*
+ *  Function: initialise_read
+ *   Purpose: Set up a read request for another packet
+ *
+ *    Params:
+ *      In/Out: ds      State structure to be initialised
+ *
+ *   Returns:
+ *          OK: 0
+ *       Error: -1
+ */
+static int initialise_read(DevSWState *ds)
+{
+    struct data_packet *dp;
+
+    /*
+     * try to claim the structure that will
+     * eventually hold the new packet.
+     */
+    if ((ds->ds_nextreadpacket = DevSW_AllocatePacket(allocsize)) == NULL)
+        return -1;
+
+    /*
+     * Calls into the device driver use the DriverCall structure: use
+     * the buffer we have just allocated, and declare its size.  We
+     * are also obliged to clear the driver's context pointer.
+     */
+    dp = &ds->ds_activeread.dc_packet;
+    dp->buf_len = allocsize;
+    dp->data = ds->ds_nextreadpacket->pk_buffer;
+
+    ds->ds_activeread.dc_context = NULL;
+
+    return 0;
+}
+
+/*
+ *  Function: initialise_write
+ *   Purpose: Set up a write request for another packet
+ *
+ *    Params:
+ *       Input: packet  The packet to be written
+ *
+ *              type    The type of the packet
+ *
+ *      In/Out: dc      The structure to be intialised
+ *
+ *   Returns: Nothing
+ */
+static void initialise_write(DriverCall *dc, Packet *packet, DevChanID type)
+{
+    struct data_packet *dp = &dc->dc_packet;
+
+    dp->len = packet->pk_length;
+    dp->data = packet->pk_buffer;
+    dp->type = type;
+
+    /*
+     * we are required to clear the state structure for the driver
+     */
+    dc->dc_context = NULL;
+}
+
+/*
+ *  Function: enqueue_packet
+ *   Purpose: move a newly read packet onto the appropriate queue
+ *              of read packets
+ *
+ *    Params:
+ *      In/Out: ds      State structure with new packet
+ *
+ *   Returns: Nothing
+ */
+static void enqueue_packet(DevSWState *ds)
+{
+    struct data_packet *dp = &ds->ds_activeread.dc_packet;
+    Packet *packet = ds->ds_nextreadpacket;
+
+    /*
+     * transfer the length
+     */
+    packet->pk_length = dp->len;
+
+    /*
+     * take this packet out of the incoming slot
+     */
+    ds->ds_nextreadpacket = NULL;
+
+    /*
+     * try to put it on the correct input queue
+     */
+    if (illegalDevChanID(dp->type))
+    {
+        /* this shouldn't happen */
+        WARN("Illegal type for Rx packet");
+        DevSW_FreePacket(packet);
+    }
+    else
+        Adp_addToQueue(&ds->ds_readqueue[dp->type], packet);
+}
+
+/*
+ *  Function: flush_packet
+ *   Purpose: Send a packet to the device driver
+ *
+ *    Params:
+ *       Input: device  The device to be written to
+ *
+ *      In/Out: dc      Describes the packet to be sent
+ *
+ *   Returns: Nothing
+ *
+ * Post-conditions: If the whole packet was accepted by the device
+ *                      driver, then dc->dc_packet.data will be
+ *                      set to NULL.
+ */
+static void flush_packet(const DeviceDescr *device, DriverCall *dc)
+{
+    if (device->DeviceWrite(dc) > 0)
+        /*
+         * the whole packet was swallowed
+         */
+        dc->dc_packet.data = NULL;
+}
+
+/**********************************************************************/
+
+/*
+ * These are the externally visible functions.  They are documented in
+ * devsw.h
+ */
+Packet *DevSW_AllocatePacket(const unsigned int length)
+{
+    Packet *pk;
+
+    if ((pk = malloc(sizeof(*pk))) == NULL)
+    {
+        WARN("malloc failure");
+        return NULL;
+    }
+
+    if ((pk->pk_buffer = malloc(length+CHAN_HEADER_SIZE)) == NULL)
+    {
+        WARN("malloc failure");
+        free(pk);
+        return NULL;
+    }
+
+    return pk;
+}
+
+void DevSW_FreePacket(Packet *pk)
+{
+    free(pk->pk_buffer);
+    free(pk);
+}
+
+AdpErrs DevSW_Open(DeviceDescr *device, const char *name, const char *arg,
+                   const DevChanID type)
+{
+    DevSWState *ds;
+
+    /*
+     * is this the very first open call for this driver?
+     */
+    if ((ds = (DevSWState *)(device->SwitcherState)) == NULL)
+    {
+        /*
+         * yes, it is: initialise state
+         */
+        if ((ds = malloc(sizeof(*ds))) == NULL)
+            /* give up */
+            return adp_malloc_failure;
+
+        (void)memset(ds, 0, sizeof(*ds));
+        device->SwitcherState = (void *)ds;
+    }
+
+    /*
+     * check that we haven't already been opened for this type
+     */
+    if ((ds->ds_opendevchans & (1 << type)) != 0)
+        return adp_device_already_open;
+
+    /*
+     * if no opens have been done for this device, then do it now
+     */
+    if (ds->ds_opendevchans == 0)
+        if (device->DeviceOpen(name, arg) < 0)
+            return adp_device_open_failed;
+
+    /*
+     * open has finished
+     */
+    ds->ds_opendevchans |= (1 << type);
+    return adp_ok;
+}
+
+AdpErrs DevSW_Match(const DeviceDescr *device, const char *name,
+                    const char *arg)
+{
+    return (device->DeviceMatch(name, arg) == -1) ? adp_failed : adp_ok;
+}
+
+AdpErrs DevSW_Close(const DeviceDescr *device, const DevChanID type)
+{
+    DevSWState *ds = (DevSWState *)(device->SwitcherState);
+    Packet *pk;
+
+    if ((ds->ds_opendevchans & (1 << type)) == 0)
+        return adp_device_not_open;
+
+    ds->ds_opendevchans &= ~(1 << type);
+
+    /*
+     * if this is the last close for this channel, then inform the driver
+     */
+    if (ds->ds_opendevchans == 0)
+        device->DeviceClose();
+
+    /*
+     * release all packets of the appropriate type
+     */
+    for (pk = Adp_removeFromQueue(&(ds->ds_readqueue[type]));
+         pk != NULL;
+         pk = Adp_removeFromQueue(&(ds->ds_readqueue[type])))
+        DevSW_FreePacket(pk);
+
+    /* that's all */
+    return adp_ok;
+}
+
+AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
+                   Packet **packet, bool block)
+{
+  int read_err;
+  DevSWState *ds = device->SwitcherState;
+
+    /*
+     * To try to get information out of the device driver as
+     * quickly as possible, we try and read more packets, even
+     * if a completed packet is already available.
+     */
+
+    /*
+     * have we got a packet currently pending?
+     */
+  if (ds->ds_nextreadpacket == NULL)
+    /*
+       * no - set things up
+       */
+    if (initialise_read(ds) < 0) {
+      /*
+       * we failed to initialise the next packet, but can
+       * still return a packet that has already arrived.
+       */
+      *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]); 
+      return adp_ok;
+    }
+  read_err = device->DeviceRead(&ds->ds_activeread, block);
+  switch (read_err) {
+  case 1:
+    /*
+     * driver has pulled in a complete packet, queue it up
+     */
+#ifdef RET_DEBUG
+    printf("got a complete packet\n");
+#endif
+    enqueue_packet(ds);
+    *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
+    return adp_ok;
+  case 0:
+    /*
+     * OK, return the head of the read queue for the given type
+     */
+    /*    enqueue_packet(ds); */
+    *packet = Adp_removeFromQueue(&ds->ds_readqueue[type]);
+    return adp_ok;
+  case -1:
+#ifdef RET_DEBUG
+    printf("got a bad packet\n");
+#endif
+    /* bad packet */
+    *packet = NULL;
+    return adp_bad_packet;
+  default:
+    panic("DevSW_Read: bad read status %d", read_err);
+  }
+  return 0; /* get rid of a potential compiler warning */
+}
+
+
+AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device)
+{
+    struct DriverCall *dc;
+    struct data_packet *dp;
+
+    dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
+    dp = &dc->dc_packet;
+
+    /*
+     * try to flush any packet that is still being written
+     */
+    if (dp->data != NULL)
+    {
+        flush_packet(device, dc);
+
+        /* see if it has gone */
+        if (dp->data != NULL)
+           return adp_write_busy;
+        else
+           return adp_ok;
+    }
+    else
+       return adp_ok;
+}
+
+
+AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type)
+{
+    struct DriverCall *dc;
+    struct data_packet *dp;
+
+    dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
+    dp = &dc->dc_packet;
+
+    if (illegalDevChanID(type))
+        return adp_illegal_args;
+
+    /*
+     * try to flush any packet that is still being written
+     */
+    if (DevSW_FlushPendingWrite(device) != adp_ok)
+       return adp_write_busy;
+
+    /*
+     * we can take this packet - set things up, then try to get rid of it
+     */
+    initialise_write(dc, packet, type);
+    flush_packet(device, dc);
+
+    return adp_ok;
+}
+
+AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args)
+{
+    return (device->DeviceIoctl(opcode, args) < 0) ? adp_failed : adp_ok;
+}
+
+bool DevSW_WriteFinished(const DeviceDescr *device)
+{
+    struct DriverCall *dc;
+    struct data_packet *dp;
+
+    dc = &((DevSWState *)(device->SwitcherState))->ds_activewrite;
+    dp = &dc->dc_packet;
+
+    return (dp == NULL || dp->data == NULL);
+}
+
+/* EOF devsw.c */
diff --git a/gdb/rdi-share/devsw.h b/gdb/rdi-share/devsw.h
new file mode 100644 (file)
index 0000000..f561768
--- /dev/null
@@ -0,0 +1,268 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ */
+#ifndef angsd_devsw_h
+#define angsd_devsw_h
+
+#include "devclnt.h"
+#include "adperr.h"
+#include "drivers.h"
+
+#ifndef __cplusplus
+typedef struct Packet Packet;
+typedef struct DevSWState DevSWState;
+#endif
+
+/*
+ * the basic structure used for passing packets around
+ */
+struct Packet
+{
+    struct Packet *pk_next;             /* XXX first field in struct */
+    unsigned int   pk_length;
+    unsigned char *pk_buffer;
+};
+
+/*
+ * control structure, used for maintaining device switcher state
+ */
+struct DevSWState
+{
+    unsigned int  ds_opendevchans;      /* bitmap of open device channels */
+
+    /*
+     * queue of packets read for the various device channels
+     */
+    Packet       *ds_readqueue[DC_NUM_CHANNELS];
+
+    /*
+     * structures for managing active read and write operations
+     */
+    Packet       *ds_nextreadpacket;
+    DriverCall    ds_activeread;
+    DriverCall    ds_activewrite;
+};
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/*
+ *  Function: DevSW_AllocatePacket
+ *   Purpose: Claim some memory to hold a struct Packet, and the buffer for
+ *              that packet.
+ *
+ *    Params:
+ *       Input: length  Size of the buffer in struct Packet.
+ *
+ *   Returns:
+ *          OK: Pointer to the newly malloc()ed Packet.
+ *       Error: NULL
+ */
+Packet *DevSW_AllocatePacket(const unsigned int length);
+
+/*
+ *  Function: DevSW_FreePacket
+ *   Purpose: Free the memory associated with a struct Packet.
+ *
+ *  Pre-conditions The structure must have been originally claimed
+ *                      via DevSW_AllocatePacket.
+ *
+ *    Params:
+ *       Input: pk      The packet to be freed.
+ *
+ *   Returns: Nothing
+ */
+void DevSW_FreePacket(Packet *pk);
+
+/*
+ *  Function: DevSW_Open
+ *   Purpose: Open the specified device driver
+ *
+ *    Params:
+ *       Input: name    Identifies which device to open.  This can either be
+ *                      a host specific identifier (e.g. "/dev/ttya",
+ *                      "COM1:"), or a number which is used to refer to
+ *                      `standard' interfaces, so "1" would be the first host
+ *                      interface, "2" the second, and so on.
+ *
+ *              arg     Driver specific arguments.  For example, some serial
+ *                      drivers accept speed and control arguments such as
+ *                      "9600" or "19200/NO_BREAK".  These arguments are
+ *                      completely free-form: it is the individual drivers
+ *                      which do the necessary interpretation.
+ *
+ *              type    The type of packet the caller is interested in.  Only
+ *                      one open is allowed for each type of packet.
+ *
+ *      In/Out: device  The device driver to open
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_open_failed
+ *              adp_device_already_open
+ *              adp_malloc_failure
+ */
+AdpErrs DevSW_Open(DeviceDescr *device, const char *name, const char *arg,
+                   const DevChanID type);
+
+/*
+ *  Function: DevSW_Match
+ *   Purpose: Minimal veneer for DeviceMatch
+ *
+ *    Params:
+ *       Input: device  The device driver to match.
+ *
+ *              name    Identifies which device to open.  This can either be
+ *                      a host specific identifier (e.g. "/dev/ttya",
+ *                      "COM1:"), or a number which is used to refer to
+ *                      `standard' interfaces, so "1" would be the first host
+ *                      interface, "2" the second, and so on.
+ *
+ *              arg     Driver specific arguments.  For example, some serial
+ *                      drivers accept speed and control arguments such as
+ *                      "9600" or "19200/NO_BREAK".  These arguments are
+ *                      completely free-form: it is the individual drivers
+ *                      which do the necessary interpretation.
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_failed
+ */
+AdpErrs DevSW_Match(const DeviceDescr *device, const char *name,
+                    const char *arg);
+
+/*
+ *  Function: DevSW_Close
+ *   Purpose: Close the specified device driver. All packets of the type
+ *              used by the caller held within the switching layer will
+ *              be discarded.
+ *
+ *  Pre-conditions: Device must have been previously opened.
+ *
+ *    Params:
+ *       Input: device  The device driver to close
+ *
+ *              type    The type of packet the caller was interested in.
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_not_open
+ */
+AdpErrs DevSW_Close(const DeviceDescr *device, const DevChanID type);
+
+/*
+ *  Function: DevSW_Read
+ *   Purpose: Read a packet of appropriate type from the device driver
+ *
+ *    Params:
+ *       Input: device  The device driver to read packet from.
+ *
+ *              type    The type of packet the caller is interested in.
+ *
+ *      Output: packet  Pointer to new packet (if one is available)
+ *              NULL (if no complete packet is available)
+ *
+ *       Input: block   If TRUE, read may safely block for a short period
+ *                      of time (say up to 20ms), to avoid high CPU load
+ *                      whilst waiting for a reply.
+ *                      If FALSE, read MUST NOT block.
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_bad_packet
+ *
+ * Post-conditions: The calling function is responsible for freeing the
+ *                      resources used by the packet when it is no longer
+ *                      needed.
+ */
+AdpErrs DevSW_Read(const DeviceDescr *device, const DevChanID type,
+                   Packet **packet, bool block);
+
+/*
+ *  Function: DevSW_Write
+ *   Purpose: Try to write a packet to the device driver.  The write will
+ *              be bounced if another write is still in progress.
+ *
+ *    Params:
+ *       Input: device  The device driver to write a packet to.
+ *
+ *              packet  The packet to be written.
+ *
+ *              type    The type to be assigned to the packet.
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_illegal_args
+ *              adp_write_busy
+ *
+ * Post-conditions: The calling function retains "ownership" of the packet,
+ *                      i.e. it is responsible for freeing the resources used
+ *                      by the packet when it is no longer needed.
+ */
+AdpErrs DevSW_Write(const DeviceDescr *device, Packet *packet, DevChanID type);
+
+/*
+ *  Function: DevSW_FlushPendingWrite
+ *   Purpose: If a write is in progress, give it a chance to finish.
+ *
+ *    Params:
+ *       Input: device  The device driver to flush.
+ *
+ *   Returns:
+ *              adp_ok           no pending write, or write flushed completely
+ *              adp_write_busy   pending write not flushed completely
+ */
+AdpErrs DevSW_FlushPendingWrite(const DeviceDescr *device);
+
+/*
+ *  Function: DevSW_Ioctl
+ *   Purpose: Perform miscellaneous control operations.  This is a minimal
+ *              veneer to DeviceIoctl.
+ *
+ *    Params:
+ *       Input: device  The device driver to control.
+ *
+ *              opcode  Reason code indicating the operation to perform.
+ *
+ *      In/Out: args    Pointer to opcode-sensitive arguments/result space.
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_failed
+ */
+AdpErrs DevSW_Ioctl(const DeviceDescr *device, const int opcode, void *args);
+
+/*
+ *  Function: DevSW_WriteFinished
+ *   Purpose: Return TRUE if the active device has finished writing
+ *              the last packet to be sent, or FALSE if a packet is still
+ *              being transmitted.
+ *
+ *    Params:
+ *       Input: device  The device driver to check.
+ *
+ *   Returns:
+ *        TRUE: write finished or inactive
+ *       FALSE: write in progress
+ */
+bool DevSW_WriteFinished(const DeviceDescr *device);
+
+#ifdef __cplusplus
+    }
+#endif
+
+#endif /* ndef angsd_devsw_h */
+
+/* EOF devsw.h */
diff --git a/gdb/rdi-share/drivers.c b/gdb/rdi-share/drivers.c
new file mode 100644 (file)
index 0000000..ba0eee5
--- /dev/null
@@ -0,0 +1,34 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * drivers.c - declares a NULL terminated list of device driver
+ *             descriptors supported by the host.
+ */
+#include <stdio.h>
+
+#include "drivers.h"
+
+extern DeviceDescr angel_SerialDevice;
+extern DeviceDescr angel_SerparDevice;
+extern DeviceDescr angel_EthernetDevice;
+
+DeviceDescr *devices[] =
+{
+    &angel_SerialDevice,
+    &angel_SerparDevice,
+    &angel_EthernetDevice,
+    NULL
+};
+
+/* EOF drivers.c */
diff --git a/gdb/rdi-share/drivers.h b/gdb/rdi-share/drivers.h
new file mode 100644 (file)
index 0000000..3655c18
--- /dev/null
@@ -0,0 +1,193 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Definitions for device driver interface.
+ */
+#ifndef angsd_drivers_h
+#define angsd_drivers_h
+
+#include "rxtx.h"
+
+#ifndef __cplusplus
+typedef struct DeviceDescr DeviceDescr;
+typedef struct DriverCall DriverCall;
+#endif
+
+/*
+ * used to pass packets across the driver interface
+ */
+struct DriverCall
+{
+    struct data_packet  dc_packet;
+    void               *dc_context;
+};
+
+/*
+ * used to describe a device driver
+ */
+struct DeviceDescr
+{
+    char  *DeviceName;
+    int  (*DeviceOpen)(const char *name, const char *arg);
+    int  (*DeviceMatch)(const char *name, const char *arg);
+    void (*DeviceClose)(void);
+    int  (*DeviceRead)(DriverCall *dc, bool block);
+    int  (*DeviceWrite)(DriverCall *dc);
+    int  (*DeviceIoctl)(const int opcode, void *args);
+    void  *SwitcherState;               /* used by switcher interface */
+};
+
+/*
+ *  Function: DeviceOpen
+ *
+ *   Purpose: Open a communications device
+ *
+ *  Pre-conditions: No previous open is still active
+ *
+ *    Params:
+ *       Input: name    Identifies which device to open.  This can either be
+ *                      a host specific identifier (e.g. "/dev/ttya",
+ *                      "COM1:"), or a number which is used to refer to
+ *                      `standard' interfaces, so "1" would be the first host
+ *                      interface, "2" the second, and so on.
+ *
+ *              arg     Driver specific arguments.  For example, some serial
+ *                      drivers accept speed and control arguments such as
+ *                      "9600" or "19200/NO_BREAK".  These arguments are
+ *                      completely free-form: it is the individual drivers
+ *                      which do the necessary interpretation.
+ *
+ *   Returns:
+ *          OK: 0
+ *       Error: -1
+ */
+extern int DeviceOpen(const char *name, const char *arg);
+
+/*
+ *  Function: DeviceMatch
+ *
+ *   Purpose: Check whether parameters are OK to be passed to DeviceOpen
+ *
+ *    Params:
+ *       Input: name    Identifies which device to open.  This can either be
+ *                      a host specific identifier (e.g. "/dev/ttya",
+ *                      "COM1:"), or a number which is used to refer to
+ *                      `standard' interfaces, so "1" would be the first host
+ *                      interface, "2" the second, and so on.
+ *
+ *              arg     Driver specific arguments.  For example, some serial
+ *                      drivers accept speed and control arguments such as
+ *                      "9600" or "19200/NO_BREAK".  These arguments are
+ *                      completely free-form: it is the individual drivers
+ *                      which do the necessary interpretation.
+ *
+ *   Returns:
+ *          OK: 0
+ *       Error: -1
+ */
+extern int DeviceMatch(const char *name, const char *arg);
+
+/*
+ *  Function: DeviceClose
+ *
+ *   Purpose: Close a communications device
+ *
+ *  Pre-conditions: Device must have been previously opened
+ *
+ *    Params: None
+ *
+ *   Returns: Nothing
+ */
+extern void DeviceClose(void);
+
+/*
+ *  Function: DeviceRead
+ *
+ *   Purpose: Try to read a complete packet from a communications device.
+ *              This read must usually be non-blocking, i.e. it should read as
+ *              many data from the device as needed to complete the packet,
+ *              but it should not wait if the packet is not complete, and no
+ *              more data are currently available from the device.
+ *            As an optimisation the read can optionally block when 'block'
+ *              is TRUE, but only for a short time.  It is acceptable for the
+ *              'block' parameter to be ignored in which case all reads
+ *              should be non-blocking.
+ *
+ *  Pre-conditions: Device has been opened via DeviceOpen()
+ *
+ *    Params:
+ *      In/Out: dc      Describes the packet being read (dc->dc_packet);
+ *                      dc->dc_context is for the driver to store private
+ *                      context, and is guaranteed to be NULL the first
+ *                      time DeviceRead is called for a given packet.
+ *
+ *          In: block   If TRUE, read may safely block for a short period
+ *                      of time (say up to 20ms), to avoid high CPU load
+ *                      whilst waiting for a reply.
+ *                      If FALSE, read MUST NOT block.
+ *
+ *   Returns:
+ *          OK:  1 (packet is complete)
+ *               0 (packet is not yet complete)
+ *       Error: -1 bad packet
+ *
+ *   Post-conditions: should a calamatous error occur panic() will be called
+ */
+extern int DeviceRead(DriverCall *dc, bool block);
+
+/*
+ *  Function: DeviceWrite
+ *
+ *   Purpose: Try to write a packet to a communications device.  This write
+ *              must be non-blocking, i.e. it should write as many data to
+ *              the device as is immediately possible, but should not wait
+ *              for space to send any more after that.
+ *
+ *  Pre-conditions: Device has been opened via DeviceOpen()
+ *
+ *    Params:
+ *      In/Out: dc      Describes the packet being written (dc->dc_packet);
+ *                      dc->dc_context is for the driver to store private
+ *                      context, and is guaranteed to be NULL the first
+ *                      time DeviceWrite is called for a given packet.
+ *
+ *   Returns:
+ *          OK:  1 (all of the packet has been written)
+ *               0 (some of the packet remains to be written)
+ *       Error: -1
+ */
+extern int DeviceWrite(DriverCall *dc);
+
+/*
+ *  Function: DeviceIoctl
+ *
+ *   Purpose: Perform miscellaneous driver operations
+ *
+ *  Pre-conditions: Device has been open via DeviceOpen()
+ *
+ *    Params:
+ *       Input: opcode  Reason code indicating the operation to perform
+ *      In/Out: args    Pointer to opcode-sensitive arguments/result space
+ *
+ *   Returns:
+ *          OK: 0
+ *       Error: -1
+ */
+extern int DeviceIoctl(const int opcode, void *args);
+
+#endif /* !defined(angsd_drivers_h) */
+
+/* EOF drivers.h */
diff --git a/gdb/rdi-share/endian.h b/gdb/rdi-share/endian.h
new file mode 100644 (file)
index 0000000..3d32d9a
--- /dev/null
@@ -0,0 +1,125 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * endian.h - target endianness independent read/write primitives.
+ */
+
+#ifndef angel_endian_h
+#define angel_endian_h
+
+/*
+ * The endianness of the data being processed needs to be known, but
+ * the host endianness is not required (since the data is constructed
+ * using bytes).  At the moment these are provided as macros. This
+ * gives the compiler freedom in optimising individual calls. However,
+ * if space is at a premium then functions should be provided.
+ *
+ * NOTE: These macros assume that the data has been packed in the same format
+ *       as the packing on the build host. If this is not the case then
+ *       the wrong addresses could be used when dealing with structures.
+ *
+ */
+
+/*
+ * For all the following routines the target endianness is defined by the
+ * following boolean definitions.
+ */
+#define BE (1 == 1) /* TRUE  : big-endian */
+#define LE (1 == 0) /* FALSE : little-endian */
+
+/*
+ * The following type definitions are used by the endianness converting
+ * macros.
+ */
+typedef unsigned char U8;
+typedef U8 *P_U8;
+typedef const U8 *CP_U8;
+
+typedef unsigned short U16;
+typedef U16 *P_U16;
+
+typedef unsigned int U32;
+typedef U32 *P_U32;
+
+/*
+ * If the endianness of the host and target are known (fixed) and the same
+ * then the following macro definitions can be used. These just directly copy
+ * the data.
+ *
+ * #define READ(e,a)       (a)
+ * #define WRITE(e,a,v)    ((a) = (v))
+ * #define PREAD(e,a)      (a)
+ * #define PWRITE(e,a,v)   (*(a) = (v))
+ */
+
+/*
+ * These macros assume that a byte (char) is 8bits in size, and that the
+ * endianness is not important when reading or writing bytes.
+ */
+#define PUT8(a,v)       (*((P_U8)(a)) = (U8)(v))
+#define PUT16LE(a,v)    (PUT8(a,((v) & 0xFF)), \
+                         PUT8((((P_U8)(a)) + sizeof(char)),((v) >> 8)))
+#define PUT16BE(a,v)    (PUT8(a,((v) >> 8)), \
+                         PUT8((((P_U8)(a)) + sizeof(char)),((v) & 0xFF)))
+#define PUT32LE(a,v)    (PUT16LE(a,v), \
+                         PUT16LE((((P_U8)(a)) + sizeof(short)),((v) >> 16)))
+#define PUT32BE(a,v)    (PUT16BE(a,((v) >> 16)), \
+                         PUT16BE((((P_U8)(a)) + sizeof(short)),v))
+
+#define GET8(a)     (*((CP_U8)(a)))
+#define GET16LE(a)  (GET8(a) | (((U16)GET8(((CP_U8)(a)) + sizeof(char))) << 8))
+#define GET16BE(a)  ((((U16)GET8(a)) << 8) | GET8(((CP_U8)(a)) + sizeof(char)))
+#define GET32LE(a)  (GET16LE(a) | \
+                     (((U32)GET16LE(((CP_U8)(a)) + sizeof(short))) << 16))
+#define GET32BE(a)  ((((U32)GET16BE(a)) << 16) | \
+                     GET16BE(((CP_U8)(a)) + sizeof(short)))
+
+/*
+ * These macros simplify the code in respect to reading and writing the
+ * correct size data when dealing with endianness. "e" is TRUE if we are
+ * dealing with big-endian data, FALSE if we are dealing with little-endian.
+ */
+
+/* void WRITE(int endianness, void *address, unsigned value); */
+
+#define WRITE16(e,a,v) ((e) ? PUT16BE(&(a),v) : PUT16LE(&(a),v))
+#define WRITE32(e,a,v) ((e) ? PUT32BE(&(a),v) : PUT32LE(&(a),v))
+#define WRITE(e,a,v)   ((sizeof(v) == sizeof(char)) ? \
+                        PUT8(&(a),v) : ((sizeof(v) == sizeof(short)) ? \
+                                        WRITE16(e,a,v) : WRITE32(e,a,v)))
+
+/* unsigned READ(int endianness, void *address) */
+#define READ16(e,a) ((e) ? GET16BE(&(a)) : GET16LE(&(a)))
+#define READ32(e,a) ((e) ? GET32BE(&(a)) : GET32LE(&(a)))
+#define READ(e,a) ((sizeof(a) == sizeof(char)) ? \
+                   GET8((CP_U8)&(a)) : ((sizeof(a) == sizeof(short)) ? \
+                                       READ16(e,a) : READ32(e,a)))
+
+/* void PWRITE(int endianness, void *address, unsigned value); */
+#define PWRITE16(e,a,v) ((e) ? PUT16BE(a,v) : PUT16LE(a,v))
+#define PWRITE32(e,a,v) ((e) ? PUT32BE(a,v) : PUT32LE(a,v))
+#define PWRITE(e,a,v)   ((sizeof(v) == sizeof(char)) ? \
+                         PUT8(a,v) : ((sizeof(v) == sizeof(short)) ? \
+                                      PWRITE16(e,a,v) : PWRITE32(e,a,v)))
+
+/* unsigned PREAD(int endianness, void *address) */
+#define PREAD16(e,a) ((e) ? GET16BE(a) : GET16LE(a))
+#define PREAD32(e,a) ((e) ? GET32BE(a) : GET32LE(a))
+#define PREAD(e,a) ((sizeof(*(a)) == sizeof(char)) ? \
+                    GET8((CP_U8)a) : ((sizeof(*(a)) == sizeof(short)) ? \
+                                     PREAD16(e,a) : PREAD32(e,a)))
+
+#endif /* !defined(angel_endian_h) */
+
+/* EOF endian.h */
diff --git a/gdb/rdi-share/etherdrv.c b/gdb/rdi-share/etherdrv.c
new file mode 100644 (file)
index 0000000..976b2f5
--- /dev/null
@@ -0,0 +1,725 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * etherdrv.c - Ethernet Driver for Angel.
+ */
+
+#ifdef __hpux
+# define _POSIX_SOURCE 1
+# define _HPUX_SOURCE 1
+# define _XOPEN_SOURCE 1
+#endif
+
+#include <stdio.h>
+#ifdef __hpux
+# define uint hide_HPs_uint
+#endif
+#ifdef __unix
+# include <unistd.h>
+# ifdef __hpux
+#   undef uint
+# endif
+#endif
+#include <stdlib.h>
+#include <string.h>
+#ifdef __hpux
+# define uint hide_HPs_uint
+#endif
+#include <fcntl.h>
+#ifdef __hpux
+# undef uint
+#endif
+#include <errno.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "host.h"
+
+#ifdef COMPILING_ON_WINDOWS
+  typedef char * caddr_t;
+# undef IGNORE
+# include <winsock.h>
+# include "angeldll.h"
+#else
+# ifdef __hpux
+#   define uint hide_HPs_uint
+# endif
+# include <sys/types.h>
+# include <sys/socket.h>
+# ifdef __hpux
+#   undef uint
+# endif
+# include <netdb.h>
+# include <sys/time.h>
+# include <sys/ioctl.h>
+# if !defined(__hpux) && !defined(__linux__) && !defined(_WIN32)
+#   include <sys/filio.h>
+# endif
+# include <netinet/in.h>
+# include <arpa/inet.h>
+#endif
+
+#include "hsys.h"
+#include "devices.h"
+#include "endian.h"
+#include "buffers.h"
+#include "hostchan.h"
+#include "params.h"
+#include "logging.h"
+#include "ethernet.h"
+
+
+#ifndef COMPILING_ON_WINDOWS
+/* these two might not work for windows */
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+#endif
+
+#ifndef UNUSED
+# define UNUSED(x) (x = x)      /* Silence compiler warnings */
+#endif
+
+/*
+ * forward declarations of static functions
+ */
+static int EthernetOpen(const char *name, const char *arg);
+static int EthernetMatch(const char *name, const char *arg);
+static void EthernetClose(void);
+static int EthernetRead(DriverCall *dc, bool block);
+static int EthernetWrite(DriverCall *dc);
+static int EthernetIoctl(const int opcode, void *args);
+
+/*
+ * the device descriptor for Ethernet
+ */
+DeviceDescr angel_EthernetDevice =
+{
+    "Ethernet",
+    EthernetOpen,
+    EthernetMatch,
+    EthernetClose,
+    EthernetRead,
+    EthernetWrite,
+    EthernetIoctl
+};
+
+/*
+ * descriptor for the socket that we talk down
+ */
+static int sock = -1;
+
+/*
+ * address of the remote target
+ */
+static struct sockaddr_in remote, *ia = &remote;
+
+/*
+ * array of dynamic port numbers on target
+ */
+static unsigned short int ports[2];
+
+/*
+ *  Function: set_address
+ *   Purpose: Try to get an address into an understandable form
+ *
+ *    Params:
+ *       Input: addr    The address to parse
+ *
+ *      Output: ia      Structure to hold the parsed address
+ *
+ *   Returns:
+ *          OK:  0
+ *       Error: -1
+ */
+static int set_address(const char *const addr, struct sockaddr_in *const ia)
+{
+    ia->sin_family = AF_INET;
+
+    /*
+     * Try address as a dotted decimal
+     */
+    ia->sin_addr.s_addr = inet_addr(addr);
+
+    /*
+     * If that failed, try it as a hostname
+     */
+    if (ia->sin_addr.s_addr == (u_int)-1)
+    {
+        struct hostent *hp = gethostbyname(addr);
+
+        if (hp == NULL)
+            return -1;
+
+        (void)memcpy((caddr_t)&ia->sin_addr, hp->h_addr, hp->h_length);
+    }
+
+    return 0;
+}
+
+/*
+ *  Function: open_socket
+ *   Purpose: Open a non-blocking UDP socket, and bind it to a port
+ *              assigned by the system.
+ *
+ *    Params: None
+ *
+ *   Returns:
+ *          OK: socket descriptor
+ *       Error: -1
+ */
+static int open_socket(void)
+{
+    int sfd;
+#if 0                           /* see #if 0 just below -VVV- */
+    int yesplease = 1;
+#endif
+    struct sockaddr_in local;
+
+    /*
+     * open the socket
+     */
+#ifdef COMPILING_ON_WINDOWS
+    if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
+        return -1;
+#else
+    if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+    {
+# ifdef DEBUG
+        perror("socket");
+# endif
+        return -1;
+    }
+#endif
+
+    /*
+     * 960731 KWelton
+     *
+     * I don't believe that this should be necessary - if we
+     * use select(), then non-blocking I/O is redundant.
+     * Unfortunately, select() appears to be broken (under
+     * Solaris, with a limited amount of time available for
+     * debug), so this code stays in for the time being
+     */
+#if 0
+    /*
+     * enable non-blocking I/O
+     */
+    if (ioctlsocket(sfd, FIONBIO, &yesplease) < 0)
+    {
+# ifdef DEBUG
+        perror("ioctl(FIONBIO)");
+# endif
+        closesocket(sfd);
+
+        return -1;
+    }
+#endif /* 0/1 */
+
+    /*
+     * bind local address to a system-assigned port
+     */
+    memset((char *)&local, 0, sizeof(local));
+    local.sin_family = AF_INET;
+    local.sin_port = htons(0);
+    local.sin_addr.s_addr = INADDR_ANY;
+    if (bind(sfd, (struct sockaddr *)&local, sizeof(local)) < 0)
+    {
+#ifdef DEBUG
+        perror("bind");
+#endif
+        closesocket(sfd);
+
+        return -1;
+    }
+
+    /*
+     * all done
+     */
+    return sfd;
+}
+
+/*
+ *  Function: fetch_ports
+ *   Purpose: Request assigned port numbers from remote target
+ *
+ *    Params: None
+ *
+ *   Returns: Nothing
+ *
+ * Post-conditions: This routine will *always* return something for the
+ *                      port numbers.  If the remote target does not
+ *                      respond, then it makes something up - this allows
+ *                      the standard error message (from ardi.c) to be
+ *                      generated when the target is dead for whatever
+ *                      reason.
+ */
+static void fetch_ports(void)
+{
+    int i;
+    const char ctrlpacket[] = CTRL_MAGIC;
+        CtrlResponse response;
+
+    /*
+     * we will try 3 times to elicit a response from the target
+     */
+    for (i = 0; i < 3; ++i)
+    {
+        struct timeval tv;
+        fd_set fdset;
+
+        /*
+         * send the magic string to the control
+         * port on the remote target
+         */
+        ia->sin_port = htons(CTRL_PORT);
+        if (sendto(sock, ctrlpacket, sizeof(ctrlpacket), 0,
+                       (struct sockaddr *)ia, sizeof(*ia)) < 0)
+        {
+#ifdef DEBUG
+            perror("fetch_ports: sendto");
+#endif
+            return;
+        }
+
+        FD_ZERO(&fdset);
+        FD_SET(sock, &fdset);
+        tv.tv_sec = 0;
+        tv.tv_usec = 250000;
+
+        if (select(sock + 1, &fdset, NULL, NULL, &tv) < 0)
+        {
+#ifdef DEBUG
+            perror("fetch_ports: select");
+#endif
+            return;
+        }
+
+        if (FD_ISSET(sock, &fdset))
+        {
+            /*
+             * there is something there - read it
+             */
+            if (recv(sock, (char *)&response, sizeof(response), 0) < 0)
+            {
+#ifdef COMPILING_ON_WINDOWS
+                unsigned int werrno = WSAGetLastError();
+
+                if (werrno == WSAEWOULDBLOCK || werrno == 0)
+#else
+                if (errno == EWOULDBLOCK)
+#endif
+                {
+                    --i;
+                    continue;
+                }
+                else
+                {
+#ifdef DEBUG
+                    perror("fetch_ports: recv");
+#endif
+                    return;
+                }
+            }
+            {
+                /*
+                 * XXX
+                 *
+                 * this is *very* unpleasant - try to match the structure
+                 * layout
+                 */
+                unsigned short *sptr = (unsigned short *)(response + RESP_DBUG);
+
+                if (strcmp(response, ctrlpacket) == 0)
+                {
+                    ports[DBUG_INDEX] = htons(*sptr);
+                    sptr++;
+                    ports[APPL_INDEX] = htons(*sptr);
+                }
+
+#ifdef DEBUG
+                printf("fetch_ports: got response, DBUG=%d, APPL=%d\n",
+                       ports[DBUG_INDEX], ports[APPL_INDEX]);
+#endif
+                return;
+            }
+        }
+    }
+
+    /*
+     * we failed to get a response
+     */
+#ifdef DEBUG
+    printf("fetch_ports: failed to get a real answer\n");
+#endif
+}
+
+/*
+ *  Function: read_packet
+ *   Purpose: read a packet, and pass it back to higher levels
+ *
+ *    Params:
+ *      In/Out: packet  Holder for the read packet
+ *
+ *   Returns:  1 - Packet is complete
+ *             0 - No complete packet read
+ *
+ * Post-conditions: Will call panic() if something goes wrong with the OS
+ */
+static int read_packet(struct data_packet *const packet)
+{
+    struct sockaddr_in from;
+    int nbytes, fromlen = sizeof(from);
+    DevChanID devchan;
+
+    /*
+     * try to get the packet
+     */
+    if ((nbytes = recvfrom(sock, (char *)(packet->data), packet->buf_len, 0,
+                           (struct sockaddr *)&from, &fromlen)) < 0)
+    {
+#ifdef COMPILING_ON_WINDOWS
+        if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
+            MessageBox(GetFocus(), "Error receiving packet\n", "Angel", MB_OK | MB_ICONSTOP);
+#else
+        if (errno != EWOULDBLOCK)
+        {
+# ifdef DEBUG
+            perror("recv");
+# endif
+            panic("ethernet recv failure");
+        }
+#endif
+        return 0;
+    }
+
+#ifdef COMPILING_ON_WINDOWS
+    if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
+    {
+        progressInfo.nRead += nbytes;
+        (*pfnProgressCallback)(&progressInfo);
+    }
+#endif
+
+    /*
+     * work out where the packet was from
+     */
+    if (from.sin_addr.s_addr != remote.sin_addr.s_addr)
+    {
+        /*
+         * not from our target - ignore it
+         */
+#ifdef DEBUG
+        printf("read_packet: ignoring packet from %s\n",
+               inet_ntoa(from.sin_addr));
+#endif
+
+        return 0;
+    }
+    else if (ntohs(from.sin_port) == ports[DBUG_INDEX])
+        devchan = DC_DBUG;
+    else if (ntohs(from.sin_port) == ports[APPL_INDEX])
+        devchan = DC_APPL;
+    else
+    {
+        /*
+         * unknown port number - ignore it
+         */
+#ifdef DEBUG
+        printf("read_packet: ignore packet from port %hd\n",
+               htons(from.sin_port));
+#endif
+
+        return 0;
+    }
+
+#if defined(DEBUG) && !defined(DO_TRACE)
+    printf("EthernetRead: %d bytes from %s channel\n",
+           nbytes, (devchan == DC_DBUG) ? "DBUG" : "APPL");
+#endif
+
+#ifdef DO_TRACE
+    printf("[%d on %d]\n", nbytes, devchan);
+    {
+        int i = 0;
+        unsigned char *cptr = packet->data;
+
+        while (i < nbytes)
+        {
+            printf("<%02X ", *(cptr++));
+
+            if (!(++i % 16))
+                printf("\n");
+        }
+
+        if (i % 16)
+            printf("\n");
+    }
+#endif
+
+    /*
+     * OK - fill in the details
+     */
+    packet->type = devchan;
+    packet->len = nbytes;
+    return 1;
+}
+
+/**********************************************************************/
+
+/*
+ *  Function: Ethernet_Open
+ *   Purpose: Open the Ethernet device.  See the documentation for
+ *              DeviceOpen in drivers.h
+ *
+ * Post-conditions: Will have updated struct sockaddr_in remote (*ia)
+ *                      with the address of the remote target.
+ */
+static int EthernetOpen(const char *name, const char *arg)
+{
+#ifdef COMPILING_ON_WINDOWS
+    WORD wVersionRequested;
+    WSADATA wsaData;
+#endif
+    /*
+     * name is passed as e=<blah>, so skip 1st two characters
+     */
+    const char *etheraddr = name + 2;
+
+#ifdef DEBUG
+    printf("EthernetOpen: name `%s'\n", name);
+#endif
+
+    /* Check that the name is a valid one */
+    if (EthernetMatch(name, arg) != 0)
+        return -1;
+
+#ifdef COMPILING_ON_WINDOWS
+    wVersionRequested = MAKEWORD(1, 1);
+    if (WSAStartup(wVersionRequested, &wsaData) != 0)
+        /*
+         * Couldn't find a useable winsock.dll.
+         */
+        return -1;
+
+    if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
+    {
+        WSACleanup();
+
+        /*
+         * Couldn't find a winsock.dll with supported version.
+         */
+        return -1;
+    }
+#endif
+
+    memset((char *)ia, 0, sizeof(*ia));
+    if (set_address(etheraddr, ia) < 0)
+    {
+#ifdef COMPILING_ON_WINDOWS
+        /*
+         * SJ - I'm not sure that this is the correct way to handle this
+         * as Fail calls remote_disable and exits, while panic just exits.
+         * However at the time of writing remote_disable does nothing!
+         */
+ /*     Panic("EthernetOpen: bad name `%s'\n", etheraddr); */
+#else
+        Fail("EthernetOpen: bad name `%s'\n", etheraddr);
+#endif
+        return -1;
+    }
+
+    if ((sock = open_socket()) < 0)
+        return -1;
+
+    /*
+     * fetch the port numbers assigned by the remote target
+     * to its Debug and Application sockets
+     */
+    fetch_ports();
+
+    return 0;
+}
+
+static int EthernetMatch(const char *name, const char *arg)
+{
+    /* IGNORE arg */
+    if (0)
+        arg = arg;
+
+    if (name == NULL)
+        return -1;
+
+    if (tolower(name[0]) != 'e' || name[1] != '=')
+        return -1;
+
+    return 0;
+}
+
+static void EthernetClose(void)
+{
+    if (sock >= 0)
+    {
+        closesocket(sock);
+        sock = -1;
+    }
+
+#ifdef COMPILING_ON_WINDOWS
+    WSACleanup();
+#endif
+}
+
+static int EthernetRead(DriverCall *dc, bool block)
+{
+    fd_set fdset;
+    struct timeval tv;
+    int err;
+
+    FD_ZERO(&fdset);
+    FD_SET(sock, &fdset);
+
+#ifdef COMPILING_ON_WINDOWS
+    UNUSED(block);
+    tv.tv_sec = tv.tv_usec = 0;
+#else
+    tv.tv_sec = 0;
+    tv.tv_usec = (block ? 10000 : 0);
+#endif
+
+    err = select(sock + 1, &fdset, NULL, NULL, &tv);
+
+    if (err < 0) {
+      if (errno == EINTR) {
+        return 0;
+      }
+      panic("ethernet select failure (errno=%i)",errno);
+      return 0;
+    }
+
+    if (FD_ISSET(sock, &fdset))
+      return read_packet(&dc->dc_packet);
+    else
+      return 0;
+}
+
+static int EthernetWrite(DriverCall *dc)
+{
+    int nbytes;
+    struct data_packet *packet = &dc->dc_packet;
+
+    if (packet->type == DC_DBUG)
+        ia->sin_port = htons(ports[DBUG_INDEX]);
+    else if (packet->type == DC_APPL)
+        ia->sin_port = htons(ports[APPL_INDEX]);
+    else
+    {
+        panic("EthernetWrite: unknown devchan");
+        return 0;
+    }
+
+#if defined(DEBUG) && !defined(DO_TRACE)
+    printf("EthernetWrite: %d bytes to %s channel\n",
+           packet->len, (packet->type == DC_DBUG) ? "DBUG" : "APPL");
+#endif
+
+#ifdef DO_TRACE
+    printf("[%d on %d]\n", packet->len, packet->type);
+    {
+        int i = 0;
+        unsigned char *cptr = packet->data;
+
+        while (i < packet->len)
+        {
+            printf(">%02X ", *(cptr++));
+
+            if (!(++i % 16))
+                printf("\n");
+        }
+
+        if (i % 16)
+            printf("\n");
+    }
+#endif
+
+    if ((nbytes = sendto(sock, (char *)(packet->data), packet->len, 0,
+                         (struct sockaddr *)ia, sizeof(*ia))) != packet->len)
+    {
+#ifdef COMPILING_ON_WINDOWS
+        if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
+#else
+        if (nbytes < 0 && errno != EWOULDBLOCK)
+#endif
+        {
+#ifdef DEBUG
+            perror("sendto");
+#endif
+#ifdef COMPILING_ON_WINDOWS
+            panic("ethernet send failure\n");
+#else
+            /* might not work for Windows */
+            panic("ethernet send failure [%s]\n",
+                  errno < sys_nerr ? sys_errlist[errno] : "unknown errno");
+#endif
+        }
+#ifdef DEBUG
+        else if (nbytes >= 0)
+            fprintf(stderr, "ethernet send: asked for %d, sent %d\n", packet->len, nbytes);
+#endif
+        return 0;
+    }
+
+#ifdef COMPILING_ON_WINDOWS
+    if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
+    {
+        progressInfo.nWritten += nbytes;
+        (*pfnProgressCallback)(&progressInfo);
+    }
+#endif
+
+    return 1;
+}
+
+static int EthernetIoctl(const int opcode, void *args)
+{
+#ifdef DEBUG
+    printf( "EthernetIoctl: op %d arg %x\n", opcode, args );
+#endif
+
+    /*
+     * IGNORE(opcode)
+     */
+    if (0)
+    {
+        int dummy = opcode;
+        UNUSED(dummy);
+    }
+    UNUSED(args);
+
+    switch ( opcode )
+    {
+        case DC_RESYNC:
+        {
+#ifdef DEBUG
+            printf( "EthernetIoctl: resync\n" );
+#endif
+            fetch_ports();
+            return 0;
+        }
+
+        default:
+        {
+            return -1;
+        }
+    }
+}
+
+/* EOF etherdrv.c */
diff --git a/gdb/rdi-share/ethernet.h b/gdb/rdi-share/ethernet.h
new file mode 100644 (file)
index 0000000..930aced
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * ethernet.h:  Angel drivers for Ethernet using Fusion UDP/IP stack
+ */
+#ifndef angel_ethernet_h
+#define angel_ethernet_h
+
+/*
+ * the UDP ports that Angel Ethernet uses
+ */
+#define CTRL_PORT       1913
+
+/*
+ * the size of the largest packet accepted on the control socket
+ */
+#define CTRL_MAXPACKET  6
+
+/*
+ * This is the "magic number" sent to the control port to
+ * request that the channel port numbers are returned
+ */
+#define CTRL_MAGIC      "Angel"
+
+/*
+ * Array used for responding to a request on the control port
+ */
+typedef unsigned char CtrlResponse[10];
+#define RESP_MAGIC 0
+#define RESP_DBUG  6
+#define RESP_APPL  8
+
+/*
+ * indices for accessing the array of port numbers sent
+ * over the control socket
+ */
+#define DBUG_INDEX      0
+#define APPL_INDEX      1
+
+#ifdef TARGET
+
+# include "devdriv.h"
+
+extern const struct angel_DeviceEntry angel_EthernetDevice;
+
+/*
+ *  Function: angel_EthernetPoll
+ *   Purpose: Poll Fusion for newly arrived packets
+ *
+ *  Pre-conditions: Called in SVC mode with the lock
+ *
+ *    Params:
+ *       Input: data    IGNORE'd
+ *
+ *   Returns: Nothing
+ *
+ * Post-conditions: Will have passed any packets received along to
+ *                      higher levels
+ */
+void angel_EthernetPoll(unsigned int data);
+
+void angel_EthernetNOP(unsigned int data);
+
+
+/*
+ *  Function: angel_FindEthernetConfigBlock
+ *   Purpose: Search the Flash for an ethernet config block and return
+ *            it if found.
+ *
+ *    Params: None
+ *
+ *   Returns: NULL if no config block found, the address if one is found.
+ *
+ */
+extern angel_EthernetConfigBlock *angel_FindEthernetConfigBlock(void);
+
+#else /* def TARGET */
+
+# ifndef COMPILING_ON_WINDOWS
+#  define ioctlsocket(x, y, z)  ioctl((x), (y), (z))
+#  define closesocket(x)        close(x)
+# endif
+
+#endif /* def TARGET */
+
+#endif /* ndef angel_ethernet_h */
+
+/* EOF ethernet.h */
diff --git a/gdb/rdi-share/host.h b/gdb/rdi-share/host.h
new file mode 100644 (file)
index 0000000..3ae8fc4
--- /dev/null
@@ -0,0 +1,222 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+
+#ifndef _host_LOADED
+#define _host_LOADED 1
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#ifndef SEEK_SET
+#  define SEEK_SET  0
+#endif
+#ifndef SEEK_CUR
+#  define SEEK_CUR  1
+#endif
+#ifndef SEEK_END
+#  define SEEK_END  2
+#endif
+
+/* The following for the benefit of compiling on SunOS */
+#ifndef offsetof
+#  define offsetof(T, member)  ((char *)&(((T *)0)->member) - (char *)0)
+#endif
+
+#ifdef unix                   /* A temporary sop to older compilers */
+#  ifndef __unix              /* (good for long-term portability?)  */
+#    define __unix    1
+#  endif
+#endif
+
+#ifdef __unix
+/* Generic unix -- hopefully a split into other variants will not be    */
+/* needed.  However, beware the 'bsd' test above and safe_toupper etc.  */
+/* which cope with backwards (pre-posix/X/open) unix compatility.       */
+#  define COMPILING_ON_UNIX     1
+#endif
+#if defined(_WIN32)
+#  define COMPILING_ON_WIN32    1
+#  if !defined(__CYGWIN32__)
+#    define COMPILING_ON_WINDOWS  1
+#  endif
+#endif
+#if defined(_CONSOLE)
+#  define COMPILING_ON_WINDOWS_CONSOLE 1
+#  define COMPILING_ON_WINDOWS 1
+#endif
+#ifdef _MSC_VER
+#  define COMPILING_ON_MSDOS    1
+#  define COMPILING_ON_WINDOWS  1
+#  if defined(__cplusplus)
+#    define IMPLEMENT_BOOL_AS_INT 1 /* VC++ doesn't have 'bool' (yet) */
+#  endif
+#endif
+/* The '(defined(__sparc) && defined(P_tmpdir)                     */
+/* && !defined(__svr4__))' is to detect gcc on SunOS.              */
+/* C++ compilers don't have to define __STDC__                     */
+#if (defined(__sparc) && defined(P_tmpdir))
+#  if defined(__svr4__)
+#    define COMPILING_ON_SOLARIS
+#  else
+#    define COMPILING_ON_SUNOS
+#  endif
+#endif
+#ifdef __hppa
+#  define COMPILING_ON_HPUX
+#endif
+
+/*
+ * The following typedefs may need alteration for obscure host machines.
+ */
+#if defined(__alpha) && defined(__osf__) /* =========================== */
+/* Under OSF the alpha has 64-bit pointers and 64-bit longs.            */
+typedef                int   int32;
+typedef unsigned       int   unsigned32;
+/* IPtr and UPtr are 'ints of same size as pointer'.  Do not use in     */
+/* new code.  Currently only used within 'ncc'.                         */
+typedef          long  int   IPtr;
+typedef unsigned long  int   UPtr;
+
+#else /* all hosts except alpha under OSF ============================= */
+
+typedef          long  int   int32;
+typedef unsigned long  int   unsigned32;
+/* IPtr and UPtr are 'ints of same size as pointer'.  Do not use in     */
+/* new code.  Currently only used within 'ncc'.                         */
+#define IPtr int32
+#define UPtr unsigned32
+#endif /* ============================================================= */
+
+typedef          short int   int16;
+typedef unsigned short int   unsigned16;
+typedef   signed       char  int8;
+typedef unsigned       char  unsigned8;
+
+/* The following code defines the 'bool' type to be 'int' under C       */
+/* and real 'bool' under C++.  It also avoids warnings such as          */
+/* C++ keyword 'bool' used as identifier.  It can be overridden by      */
+/* defining IMPLEMENT_BOOL_AS_ENUM or IMPLEMENT_BOOL_AS_INT.            */
+#undef _bool
+
+#ifdef IMPLEMENT_BOOL_AS_ENUM
+   enum _bool { _false, _true };
+#  define _bool enum _bool
+#elif defined(IMPLEMENT_BOOL_AS_INT) || !defined(__cplusplus)
+#  define _bool int
+#  define _false 0
+#  define _true 1
+#endif
+
+#ifdef _bool
+#  if defined(_MFC_VER) || defined(__CC_NORCROFT) /* When using MS Visual C/C++ v4.2 */
+#    define bool _bool /* avoids "'bool' is reserved word" warning      */
+#  else
+     typedef _bool bool;
+#  endif
+#  define true _true
+#  define false _false
+#endif
+
+#define YES   true
+#define NO    false
+#undef TRUE             /* some OSF headers define as 1                 */
+#define TRUE  true
+#undef FALSE            /* some OSF headers define as 1                 */
+#define FALSE false
+
+/* 'uint' conflicts with some Unixen sys/types.h, so we now don't define it */
+typedef unsigned8  uint8;
+typedef unsigned16 uint16;
+typedef unsigned32 uint32;
+
+typedef unsigned   Uint;
+typedef unsigned8  Uint8;
+typedef unsigned16 Uint16;
+typedef unsigned32 Uint32;
+
+#ifdef ALPHA_TASO_SHORT_ON_OSF /* was __alpha && __osf.                 */
+/* The following sets ArgvType for 64-bit pointers so that              */
+/* DEC Unix (OSF) cc can be used with the -xtaso_short compiler option  */
+/* to force pointers to be 32-bit.  Not currently used since most/all   */
+/* ARM tools accept 32 or 64 bit pointers transparently.  See IPtr.     */
+#pragma pointer_size (save)
+#pragma pointer_size (long)
+typedef char *ArgvType;
+#pragma pointer_size (restore)
+#else
+typedef char *ArgvType;
+#endif
+
+/*
+ * Rotate macros
+ */
+#define ROL_32(val, n) \
+((((unsigned32)(val) << (n)) | ((unsigned32)(val) >> (32-(n)))) & 0xFFFFFFFFL)
+#define ROR_32(val, n) \
+((((unsigned32)(val) >> (n)) | ((unsigned32)(val) << (32-(n)))) & 0xFFFFFFFFL)
+
+#ifdef COMPILING_ON_UNIX
+#  define FOPEN_WB     "w"
+#  define FOPEN_RB     "r"
+#  define FOPEN_RWB    "r+"
+#  ifndef __STDC__                     /* caveat RISCiX... */
+#    define remove(file) unlink(file)  /* a horrid hack, but probably best? */
+#  endif
+#else
+#  define FOPEN_WB     "wb"
+#  define FOPEN_RB     "rb"
+#  define FOPEN_RWB    "rb+"
+#endif
+
+#ifndef FILENAME_MAX
+#  define FILENAME_MAX 256
+#endif
+
+#if (!defined(__STDC__) && !defined(__cplusplus) && !defined(_MSC_VER)) || \
+    defined(COMPILING_ON_SUNOS)
+/* Use bcopy rather than memmove, as memmove is not available.     */
+/* There does not seem to be a header for bcopy.                   */
+void bcopy(const char *src, char *dst, int length);
+#  define memmove(d,s,l) bcopy(s,d,l)
+
+/* BSD/SUN don't have strtoul(), but then strtol() doesn't barf on */
+/* overflow as required by ANSI... This bodge is horrid.           */
+#  define strtoul(s, ptr, base) strtol(s, ptr, base)
+
+/* strtod is present in the C-library but is not in stdlib.h       */
+extern double strtod(const char *str, char **ptr);
+#endif
+
+/* For systems that do not define EXIT_SUCCESS and EXIT_FAILURE */
+#ifndef EXIT_SUCCESS
+#  define EXIT_SUCCESS           0
+#endif
+#ifndef EXIT_FAILURE
+#  define EXIT_FAILURE           1
+#endif
+
+#ifndef IGNORE
+#define IGNORE(x) (x = x)  /* Silence compiler warnings for unused arguments */
+#endif
+
+/* Define endian-ness of host */
+
+#if defined(__acorn) || defined(__mvs) || defined(_WIN32) || \
+  (defined(__alpha) && defined(__osf__))
+#  define HOST_ENDIAN_LITTLE
+#elif defined(__sparc) || defined(macintosh)
+#  define HOST_ENDIAN_BIG
+#else
+#  define HOST_ENDIAN_UNKNOWN
+#endif
+
+#endif
+
+/* end of host.h */
diff --git a/gdb/rdi-share/hostchan.c b/gdb/rdi-share/hostchan.c
new file mode 100644 (file)
index 0000000..b62fbe3
--- /dev/null
@@ -0,0 +1,1060 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * hostchan.c - Semi Synchronous Host side channel interface for Angel.
+ */
+
+#include <stdio.h>
+
+#if defined(__unix) || defined(__CYGWIN32__)
+#  include <sys/time.h>
+#  ifdef sun
+      int gettimeofday(struct timeval *tp, struct timezone *tzp);
+#  endif
+#else
+#  include "winsock.h"
+#  include "time.h"
+#endif
+#include "hsys.h"
+#include "host.h"
+#include "logging.h"
+#include "chandefs.h"
+#include "chanpriv.h"
+#include "devclnt.h"
+#include "buffers.h"
+#include "drivers.h"
+#include "adperr.h"
+#include "devsw.h"
+#include "hostchan.h"
+
+#ifndef UNUSED
+#define UNUSED(x) (x = x)  /* Silence compiler warnings for unused arguments */
+#endif
+
+#define HEARTRATE 5000000
+
+/*
+ * list of available drivers, declared in drivers.c
+ */
+extern DeviceDescr *devices[];
+
+static DeviceDescr *deviceToUse = NULL;
+
+static struct Channel {
+    ChannelCallback callback;
+    void *callback_state;
+} channels[CI_NUM_CHANNELS];
+
+static unsigned char HomeSeq;
+static unsigned char OppoSeq;
+
+/*
+ * Handler for DC_APPL packets
+ */
+static DC_Appl_Handler dc_appl_handler = NULL;
+
+/*
+ * slots for registered asynchronous processing callback procedures
+ */
+#define MAX_ASYNC_CALLBACKS 8
+static unsigned int             num_async_callbacks = 0;
+static Adp_Async_Callback       async_callbacks[MAX_ASYNC_CALLBACKS];
+
+/*
+ * writeQueueRoot is the queue of write requests pending acknowledgement
+ * writeQueueSend is the queue of pending write requests which will
+ * be a subset of the list writeQueueRoot
+ */
+static Packet *writeQueueRoot = NULL;
+static Packet *writeQueueSend = NULL;
+static Packet *resend_pkt = NULL;
+static int resending = FALSE;
+
+/* heartbeat_enabled is a flag used to indicate whether the heartbeat is
+ * currently turned on, heartbeat_enabled will be false in situations
+ * where even though a heartbeat is being used it is problematical or
+ * dis-advantageous to have it turned on, for instance during the 
+ * initial stages of boot up
+ */
+unsigned int heartbeat_enabled = FALSE;
+/* heartbeat_configured is set up by the device driver to indicate whether
+ * the heartbeat is being used during this debug session.  In contrast to
+ * heartbeat_enabled it must not be changed during a session.  The logic for
+ * deciding whether to send a heartbeat is: Is heartbeat_configured for this
+ * session? if and only if it is then if heartbeat[is currently]_enabled and
+ * we are due to send a pulse then send it 
+ */
+unsigned int heartbeat_configured = TRUE;
+
+void Adp_initSeq( void ) {
+  Packet *tmp_pkt = writeQueueSend;
+
+  HomeSeq = 0;
+  OppoSeq = 0;
+  if ( writeQueueSend != NULL) {
+    while (writeQueueSend->pk_next !=NULL) {
+      tmp_pkt = writeQueueSend;
+      writeQueueSend = tmp_pkt->pk_next;
+      DevSW_FreePacket(tmp_pkt);
+    }
+  }
+  tmp_pkt = writeQueueRoot;
+  if ( writeQueueRoot == NULL)
+    return;
+
+  while (writeQueueRoot->pk_next !=NULL) {
+    tmp_pkt = writeQueueRoot;
+    writeQueueRoot = tmp_pkt->pk_next;
+    DevSW_FreePacket(tmp_pkt);
+  }
+  return;
+}
+
+/**********************************************************************/
+
+/*
+ *  Function: DummyCallback
+ *   Purpose: Default callback routine to handle unexpected input
+ *              on a channel
+ *
+ *    Params:
+ *       Input: packet  The received packet
+ *
+ *              state   Contains nothing of significance
+ *
+ *   Returns: Nothing
+ */
+static void DummyCallback(Packet *packet, void *state)
+{
+    ChannelID chan;
+    const char fmt[] = "Unexpected read on channel %u, length %d\n";
+    char fmtbuf[sizeof(fmt) + 24];
+
+    UNUSED(state);
+
+    chan = *(packet->pk_buffer);
+    sprintf(fmtbuf, fmt, chan, packet->pk_length);
+    printf(fmtbuf);
+
+    /*
+     * junk this packet
+     */
+    DevSW_FreePacket(packet);
+}
+
+/*
+ *  Function: BlockingCallback
+ *   Purpose: Callback routine used to implement a blocking read call
+ *
+ *    Params:
+ *       Input: packet  The received packet.
+ *
+ *      Output: state   Address of higher level's pointer to the received
+ *                      packet.
+ *
+ *   Returns: Nothing
+ */
+static void BlockingCallback(Packet *packet, void *state)
+{
+    /*
+     * Pass the packet back to the caller which requested a packet
+     * from this channel.  This also flags the completion of the I/O
+     * request to the blocking read call.
+     */
+    *((Packet **)state) = packet;
+}
+
+/*
+ *  Function: FireCallback
+ *   Purpose: Pass received packet along to the callback routine for
+ *              the appropriate channel
+ *
+ *    Params:
+ *       Input: packet  The received packet.
+ *
+ *   Returns: Nothing
+ *
+ * Post-conditions: The Target-to-Host sequence number for the channel
+ *                      will have been incremented.
+ */
+static void FireCallback(Packet *packet)
+{
+    ChannelID chan;
+    struct Channel *ch;
+
+    /*
+     * is this a sensible channel number?
+     */
+    chan = *(packet->pk_buffer);
+    if (invalidChannelID(chan))
+    {
+        printf("ERROR: invalid ChannelID received from target\n");
+
+        /*
+         * free the packet's resources, 'cause no-one else will
+         */
+        DevSW_FreePacket(packet);
+        return;
+    }
+
+    /*
+     * looks OK - increment sequence number, and pass packet to callback
+     */
+    ch = channels + chan;
+    (ch->callback)(packet, ch->callback_state);
+}
+
+/**********************************************************************/
+
+/*
+ * These are the externally visible functions.  They are documented
+ * in hostchan.h
+ */
+void Adp_addToQueue(Packet **head, Packet *newpkt)
+{
+    /*
+     * this is a bit of a hack
+     */
+    Packet *pk;
+
+    /*
+     * make sure that the hack we are about to use will work as expected
+     */
+    ASSERT(&(((Packet *)0)->pk_next) == 0, "bad struct Packet layout");
+
+#if DEBUG && 0
+    printf("Adp_addToQueue(%p, %p)\n", head, newpkt);
+#endif
+
+    /*
+     * here's the hack - it relies upon the next
+     * pointer being at the start of Packet.
+     */
+    pk = (Packet *)(head);
+
+    /*
+     * skip to the end of the queue
+     */
+    while (pk->pk_next != NULL)
+        pk = pk->pk_next;
+
+    /*
+     * now add the new element
+     */
+    newpkt->pk_next = NULL;
+    pk->pk_next = newpkt;
+}
+
+Packet *Adp_removeFromQueue(Packet **head)
+{
+    struct Packet *pk;
+
+    pk = *head;
+
+    if (pk != NULL)
+        *head = pk->pk_next;
+
+    return pk;
+}
+
+AdpErrs Adp_OpenDevice(const char *name, const char *arg,
+                       unsigned int heartbeat_on)
+{
+    int i;
+    AdpErrs retc;
+    ChannelID chan;
+
+#ifdef DEBUG
+    printf("Adp_OpenDevice(%s, %s)\n", name, arg ? arg : "<NULL>");
+#endif
+
+    heartbeat_configured = heartbeat_on;
+    if (deviceToUse != NULL)
+        return adp_device_already_open;
+
+    for (i = 0; (deviceToUse = devices[i]) != NULL; ++i)
+        if (DevSW_Match(deviceToUse, name, arg) == adp_ok)
+            break;
+
+    if (deviceToUse == NULL)
+        return adp_device_not_found;
+
+    /*
+     * we seem to have found a suitable device driver, so try to open it
+     */
+    if ((retc = DevSW_Open(deviceToUse, name, arg, DC_DBUG)) != adp_ok)
+    {
+        /* we don't have a device to use */
+        deviceToUse = NULL;
+        return retc;
+    }
+
+    /*
+     * there is no explicit open on channels any more, so
+     * initialise state for all channels.
+     */
+    for (chan = 0; chan < CI_NUM_CHANNELS; ++chan)
+    {
+        struct Channel *ch = channels + chan;
+
+        ch->callback = DummyCallback;
+        ch->callback_state = NULL;
+        OppoSeq = 0;
+        HomeSeq = 0;
+    }
+
+    return adp_ok;
+}
+
+AdpErrs Adp_CloseDevice(void)
+{
+    AdpErrs retc;
+
+#ifdef DEBUG
+    printf("Adp_CloseDevice\n");
+#endif
+
+    if (deviceToUse == NULL)
+        return adp_device_not_open;
+
+    heartbeat_enabled = FALSE;
+
+    retc = DevSW_Close(deviceToUse, DC_DBUG);
+
+    /*
+     * we have to clear deviceToUse, even when the lower layers
+     * faulted the close, otherwise the condition will never clear
+     */
+    if (retc != adp_ok)
+        WARN("DevSW_Close faulted the call");
+
+    deviceToUse = NULL;
+    return retc;
+}
+
+AdpErrs Adp_Ioctl(int opcode, void *args)
+{
+#ifdef DEBUG
+    printf("Adp_Ioctl\n");
+#endif
+
+    if (deviceToUse == NULL)
+        return adp_device_not_open;
+
+    return DevSW_Ioctl(deviceToUse, opcode, args);
+}
+
+AdpErrs Adp_ChannelRegisterRead(const ChannelID chan,
+                                const ChannelCallback cbfunc,
+                                void *cbstate)
+{
+#ifdef DEBUG
+    printf("Adp_ChannelRegisterRead(%d, %p, %x)\n", chan, cbfunc, cbstate);
+#endif
+
+    if (deviceToUse == NULL)
+        return adp_device_not_open;
+
+    if (invalidChannelID(chan))
+        return adp_bad_channel_id;
+
+    if (cbfunc == NULL)
+    {
+        channels[chan].callback = DummyCallback;
+        channels[chan].callback_state = NULL;
+    }
+    else
+    {
+        channels[chan].callback = cbfunc;
+        channels[chan].callback_state = cbstate;
+    }
+
+    return adp_ok;
+}
+
+AdpErrs Adp_ChannelRead(const ChannelID chan, Packet **packet)
+{
+    struct Channel *ch;
+
+#ifdef DEBUG
+    printf("Adp_ChannelRead(%d, %x)\n", chan, *packet);
+#endif
+
+    if (deviceToUse == NULL)
+        return adp_device_not_open;
+
+    if (invalidChannelID(chan))
+        return adp_bad_channel_id;
+
+    /*
+     * if a callback has already been registered for this
+     * channel, then we do not allow this blocking read.
+     */
+    ch = channels + chan;
+    if (ch->callback != DummyCallback)
+        return adp_callback_already_registered;
+
+    /*
+     * OK, use our own callback to wait for a packet to arrive
+     * on this channel
+     */
+    ch->callback = BlockingCallback;
+    ch->callback_state = packet;
+    *packet = NULL;
+
+    /*
+     * keep polling until a packet appears for this channel
+     */
+    while (((volatile Packet *)(*packet)) == NULL)
+        /*
+         * this call will block until a packet is read on any channel
+         */
+        Adp_AsynchronousProcessing(async_block_on_read);
+
+    /*
+     * OK, the packet has arrived: clear the callback
+     */
+    ch->callback = DummyCallback;
+    ch->callback_state = NULL;
+
+    return adp_ok;
+}
+
+static AdpErrs ChannelWrite(
+    const ChannelID chan, Packet *packet, AsyncMode mode)
+{
+    struct Channel *ch;
+    unsigned char *cptr;
+
+#ifdef DEBUG
+    printf( "Adp_ChannelWrite(%d, %x)\n", chan, packet );
+#endif
+
+    if (deviceToUse == NULL)
+        return adp_device_not_open;
+
+    if (invalidChannelID(chan))
+        return adp_bad_channel_id;
+
+    /*
+     * fill in the channels header at the start of this buffer
+     */
+    ch = channels + chan;
+    cptr = packet->pk_buffer;
+    *cptr++ = chan;
+    *cptr = 0;
+    packet->pk_length += CHAN_HEADER_SIZE;
+
+    /*
+     * OK, add this packet to the write queue, and try to flush it out
+     */
+
+    Adp_addToQueue(&writeQueueSend, packet);
+    Adp_AsynchronousProcessing(mode);
+
+    return adp_ok;
+}
+
+AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet) {
+  return ChannelWrite(chan, packet, async_block_on_write);
+}
+
+AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet) {
+  return ChannelWrite(chan, packet, async_block_on_nothing);
+}
+
+static AdpErrs send_resend_msg(DeviceID devid) {
+
+  /*
+   * Send a resend message, usually in response to a bad packet or
+   * a resend request */
+  Packet * packet;
+  packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
+  packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
+  packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
+  packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
+  packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_RESEND;
+  packet->pk_length = CF_DATA_BYTE_POS;
+  return DevSW_Write(deviceToUse, packet, devid);
+}
+
+static AdpErrs check_seq(unsigned char msg_home, unsigned char msg_oppo) {
+  Packet *tmp_pkt;
+
+  UNUSED(msg_oppo);
+  /* 
+   * check if we have got an ack for anything and if so remove it from the
+   * queue
+   */
+  if (msg_home == (unsigned char)(OppoSeq+1)) {
+    /*
+     * arrived in sequence can increment our opposing seq number and remove
+     * the relevant packet from our queue
+     * check that the packet we're going to remove really is the right one
+     */
+    tmp_pkt = writeQueueRoot;
+    while ((tmp_pkt->pk_next != NULL) &&
+           (tmp_pkt->pk_next->pk_buffer[CF_HOME_SEQ_BYTE_POS]
+            != OppoSeq)){
+      tmp_pkt = tmp_pkt->pk_next;
+    }
+    OppoSeq++;
+    if (tmp_pkt->pk_next == NULL) {
+#ifdef DEBUG
+      printf("trying to remove a non existant packet\n");
+#endif
+      return adp_bad_packet;
+    }
+    else {
+      Packet *tmp = tmp_pkt->pk_next;
+#ifdef RET_DEBUG
+      printf("removing a packet from the root queue\n");
+#endif
+      tmp_pkt->pk_next = tmp_pkt->pk_next->pk_next;
+      /* remove the appropriate packet */
+      DevSW_FreePacket(tmp);
+    return adp_ok;
+    }
+  }
+  else if (msg_home < (unsigned char) (OppoSeq+1)){
+    /* already received this message */
+#ifdef RET_DEBUG
+    printf("sequence numbers low\n");
+#endif   
+    return adp_seq_low;
+  }
+  else {  /* we've missed something */
+#ifdef RET_DEBUG
+    printf("sequence numbers high\n");
+#endif   
+    return adp_seq_high;
+  }
+}
+
+static unsigned long tv_diff(const struct timeval *time_now, 
+                             const struct timeval *time_was)
+{
+    return (  ((time_now->tv_sec * 1000000) + time_now->tv_usec)
+            - ((time_was->tv_sec * 1000000) + time_was->tv_usec) );
+}
+
+#if !defined(__unix) && !defined(__CYGWIN32__)
+static void gettimeofday( struct timeval *time_now, void *dummy )
+{
+    time_t t = clock();
+    UNUSED(dummy);
+    time_now->tv_sec = t/CLOCKS_PER_SEC;
+    time_now->tv_usec = (t%CLOCKS_PER_SEC)*(1000000/CLOCKS_PER_SEC);
+}
+#endif
+
+static AdpErrs pacemaker(void)
+{
+  Packet *packet;
+
+  packet = DevSW_AllocatePacket(CF_DATA_BYTE_POS);
+  if (packet == NULL) {
+    printf("ERROR: could not allocate a packet in pacemaker()\n");
+    return adp_malloc_failure;
+  }
+  packet->pk_buffer[CF_CHANNEL_BYTE_POS] = CI_PRIVATE;
+  packet->pk_buffer[CF_HOME_SEQ_BYTE_POS] = HomeSeq;
+  packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS] = OppoSeq;
+  packet->pk_buffer[CF_FLAGS_BYTE_POS] = CF_RELIABLE | CF_HEARTBEAT;
+  packet->pk_length = CF_DATA_BYTE_POS;
+  return DevSW_Write(deviceToUse, packet, DC_DBUG);
+}  
+
+#ifdef FAKE_BAD_LINE_RX
+static AdpErrs fake_bad_line_rx( const Packet *const packet, AdpErrs adp_err )
+{
+    static unsigned int bl_num = 0;
+
+    if (     (packet != NULL)
+          && (bl_num++ >= 20 )
+          && ((bl_num % FAKE_BAD_LINE_RX) == 0))
+    {
+        printf("DEBUG: faking a bad packet\n");
+        return adp_bad_packet;
+    }
+    return adp_err;
+}
+#endif /* def FAKE_BAD_LINE_RX */
+
+#ifdef FAKE_BAD_LINE_TX
+static unsigned char tmp_ch;
+
+static void fake_bad_line_tx( void )
+{
+    static unsigned int bl_num = 0;
+
+    /* give the thing a chance to boot then try corrupting stuff */
+    if ( (bl_num++ >= 20) && ((bl_num % FAKE_BAD_LINE_TX) == 0)) 
+    {
+        printf("DEBUG: faking a bad packet for tx\n");
+        tmp_ch = writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS];
+        writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = 77;
+    }
+}
+
+static void unfake_bad_line_tx( void )
+{
+    static unsigned int bl_num = 0;
+
+    /*
+     * must reset the packet so that its not corrupted when we
+     *  resend it 
+     */   
+    if ( (bl_num >= 20) && ((bl_num % FAKE_BAD_LINE_TX) != 0))
+    {
+        writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS] = tmp_ch;
+    }
+}
+#endif /* def FAKE_BAD_LINE_TX */
+
+/*
+ * NOTE: we are assuming that a resolution of microseconds will
+ * be good enough for the purporses of the heartbeat.  If this proves
+ * not to be the case then we may need a rethink, possibly using
+ * [get,set]itimer
+ */
+static struct timeval time_now;
+static struct timeval time_lastalive;
+
+static void async_process_dbug_read( const AsyncMode mode,
+                                     bool *const finished  )
+{
+    Packet *packet;
+    unsigned int msg_home, msg_oppo;
+    AdpErrs adp_err;
+
+    adp_err = DevSW_Read(deviceToUse, DC_DBUG, &packet,
+                         mode == async_block_on_read    );
+
+#ifdef FAKE_BAD_LINE_RX
+    adp_err = fake_bad_line_rx( packet, adp_err );
+#endif
+
+    if (adp_err == adp_bad_packet) {
+        /* We got a bad packet, ask for a resend, send a resend message */
+#ifdef DEBUG
+        printf("received a bad packet\n");
+#endif
+        send_resend_msg(DC_DBUG);
+    }
+    else if (packet != NULL)
+    {
+        /* update the heartbeat clock */
+        gettimeofday(&time_lastalive, NULL);
+
+            /*
+             * we got a live one here - were we waiting for it?
+             */
+        if (mode == async_block_on_read)
+           /* not any more */
+           *finished = TRUE;
+#ifdef RETRANS
+
+        if (packet->pk_length < CF_DATA_BYTE_POS) {
+            /* we've got a packet with no header information! */
+            printf("ERROR: packet with no transport header\n");
+            send_resend_msg(DC_DBUG);
+        }
+        else {
+#ifdef RET_DEBUG
+            unsigned int c;
+#endif
+            /*
+             * TODO: Check to see if its acknowledgeing anything, remove
+             * those packets it is from the queue.  If its a retrans add the
+             * packets to the queue
+             */
+            msg_home = packet->pk_buffer[CF_HOME_SEQ_BYTE_POS];
+            msg_oppo = packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS];
+#ifdef RET_DEBUG
+            printf("msg seq numbers are hseq 0x%x oseq 0x%x\n",
+                   msg_home, msg_oppo);
+            for (c=0;c<packet->pk_length;c++)
+               printf("%02.2x", packet->pk_buffer[c]);
+            printf("\n");
+#endif
+            /* now was it a resend request? */
+            if ((packet->pk_buffer[CF_FLAGS_BYTE_POS]) 
+                & CF_RESEND) {
+                /* we've been asked for a resend so we had better resend */
+                /*
+                 * I don't think we can use a resend as acknowledgement for
+                 * anything so lets not do this for the moment
+                 * check_seq(msg_home, msg_oppo);
+                 */
+#ifdef RET_DEBUG
+                printf("received a resend request\n");
+#endif
+                if (HomeSeq != msg_oppo) {
+                    int found = FALSE;
+                    /* need to resend from msg_oppo +1 upwards */
+                    DevSW_FreePacket(packet);
+                    resending = TRUE;
+                    /* find the correct packet to resend from */
+                    packet = writeQueueRoot;
+                    while (((packet->pk_next) != NULL) && !found) {
+                        if ((packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
+                            != msg_oppo+1) {
+                            resend_pkt = packet;
+                            found = TRUE;
+                        }
+                        packet = packet->pk_next;
+                    }
+                    if (!found) {
+                        panic("trying to resend non-existent packets\n");
+                    }
+                }
+                else if (OppoSeq != msg_home) {
+                    /* 
+                     * send a resend request telling the target where we think
+                     * the world is at 
+                     */
+                    DevSW_FreePacket(packet);
+                    send_resend_msg(DC_DBUG);
+                }
+            }
+            else {
+                /* not a resend request, lets check the sequence numbers */
+                
+                if ((packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_HBOOT) &&
+                    (packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_TBOOT)) {
+                    adp_err = check_seq(msg_home, msg_oppo);
+                    if (adp_err == adp_seq_low) {
+                        /* we have already received this packet so discard */
+                        DevSW_FreePacket(packet);
+                    }
+                    else if (adp_err == adp_seq_high) {
+                        /*
+                         * we must have missed a packet somewhere, discard this 
+                         * packet and tell the target where we are
+                         */
+                        DevSW_FreePacket(packet);
+                        send_resend_msg(DC_DBUG);
+                    }
+                    else
+                       /*
+                        * now pass the packet to whoever is waiting for it
+                        */
+                       FireCallback(packet);
+                }
+                else
+                   FireCallback(packet);
+            }
+        }
+#else
+        /*
+             * now pass the packet to whoever is waiting for it
+             */
+        FireCallback(packet);
+#endif
+    }
+}
+
+static void async_process_appl_read(void)
+{
+    Packet *packet;
+    AdpErrs adp_err;
+
+    /* see if there is anything for the DC_APPL channel */
+    adp_err = DevSW_Read(deviceToUse, DC_APPL, &packet, FALSE);
+
+    if (adp_err == adp_ok && packet != NULL)
+    {
+        /* got an application packet on a shared device */
+
+#ifdef DEBUG
+        printf("GOT DC_APPL PACKET: len %d\nData: ", packet->pk_length);
+        {
+            unsigned int c;
+            for ( c = 0; c < packet->pk_length; ++c )
+               printf( "%02X ", packet->pk_buffer[c] );
+        }
+        printf("\n");
+#endif
+
+        if (dc_appl_handler != NULL)
+        {
+            dc_appl_handler( deviceToUse, packet );
+        }
+        else
+        {
+            /* for now, just free it!! */
+#ifdef DEBUG
+            printf("no handler - dropping DC_APPL packet\n");
+#endif
+            DevSW_FreePacket( packet );
+        }
+    }
+}
+
+static void async_process_write( const AsyncMode mode,
+                                 bool *const finished  )
+{
+    Packet *packet;
+
+#ifdef DEBUG
+    static unsigned int num_written = 0;
+#endif
+
+    /*
+     * NOTE: here we rely in the fact that any packet in the writeQueueSend
+     * section of the queue will need its sequence number setting up while
+     * and packet in the writeQueueRoot section will have its sequence
+     * numbers set up from when it was first sent so we can easily look
+     * up the packet numbers when(if) we want to resend the packet.
+     */
+
+#ifdef DEBUG
+    if (writeQueueSend!=NULL)
+       printf("written 0x%x\n",num_written += writeQueueSend->pk_length);
+#endif
+    /*
+     * give the switcher a chance to complete any partial writes
+     */
+    if (DevSW_FlushPendingWrite(deviceToUse) == adp_write_busy)
+    {
+        /* no point trying a new write */
+        return;
+    }
+      
+    /*
+     * now see whether there is anything to write
+     */
+    packet = NULL;
+    if (resending) {
+        packet = resend_pkt;
+#ifdef RET_DEBUG
+        printf("resending hseq 0x%x oseq 0x%x\n", 
+               packet->pk_buffer[CF_HOME_SEQ_BYTE_POS],
+               packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
+#endif
+    }
+    else if (writeQueueSend != NULL) {
+#ifdef RETRANS
+        /* set up the sequence number on the packet */
+        packet = writeQueueSend;
+        HomeSeq++;
+        (writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
+            = OppoSeq;
+        (writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS])
+            = HomeSeq;
+        (writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS])
+            = CF_RELIABLE;
+# ifdef RET_DEBUG
+        printf("sending packet with hseq 0x%x oseq 0x%x\n",
+               writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS],
+               writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
+# endif
+#endif /* RETRANS */
+    }
+
+    if (packet != NULL) {
+        AdpErrs dev_err;
+
+#ifdef FAKE_BAD_LINE_TX
+        fake_bad_line_tx();
+#endif
+
+        dev_err = DevSW_Write(deviceToUse, packet, DC_DBUG);
+        if (dev_err == adp_ok) {
+#ifdef RETRANS
+            if (resending) {
+                /* check to see if we've recovered yet */
+                if ((packet->pk_next) == NULL){
+# ifdef RET_DEBUG
+                    printf("we have recovered\n");
+# endif
+                    resending = FALSE;
+                }
+                else {
+                    resend_pkt = resend_pkt->pk_next;
+                }
+            }
+            else {
+                /* 
+                 * move the packet we just sent from the send queue to the root
+                 */
+                Packet *tmp_pkt, *tmp;
+
+# ifdef FAKE_BAD_LINE_TX
+                unfake_bad_line_tx();
+# endif
+
+                tmp_pkt = writeQueueSend;
+                writeQueueSend = writeQueueSend->pk_next;
+                tmp_pkt->pk_next = NULL;
+                if (writeQueueRoot == NULL)
+                   writeQueueRoot = tmp_pkt;
+                else {
+                    tmp = writeQueueRoot;
+                    while (tmp->pk_next != NULL) {
+                        tmp = tmp->pk_next;
+                    }
+                    tmp->pk_next = tmp_pkt;
+                }
+            }
+#else  /* not RETRANS */
+            /*
+             * switcher has taken the write, so remove it from the
+             * queue, and free its resources
+             */
+            DevSW_FreePacket(Adp_removeFromQueue(&writeQueueSend));
+#endif /* if RETRANS ... else ... */
+
+            if (mode == async_block_on_write)
+               *finished = DevSW_WriteFinished(deviceToUse);
+
+        } /* endif write ok */
+    }
+    else /* packet == NULL */
+    {
+        if (mode == async_block_on_write)
+           *finished = DevSW_WriteFinished(deviceToUse);
+    }
+}
+
+static void async_process_heartbeat( void )
+{
+    /* check to see whether we need to send a heartbeat */
+    gettimeofday(&time_now, NULL);
+
+    if (tv_diff(&time_now, &time_lastalive) >= HEARTRATE)
+    {
+        /*
+         * if we've not booted then don't do send a heartrate the link
+         * must be reliable enough for us to boot without any clever stuff,
+         * if we can't do this then theres little chance of the link staying
+         * together even with the resends etc
+         */
+        if (heartbeat_enabled) {
+            gettimeofday(&time_lastalive, NULL);
+            pacemaker();
+        }
+    }
+}
+
+static void async_process_callbacks( void )
+{
+    /* call any registered asynchronous callbacks */
+    unsigned int i;
+    for ( i = 0; i < num_async_callbacks; ++i )
+       async_callbacks[i]( deviceToUse, &time_now );
+}
+
+void Adp_AsynchronousProcessing(const AsyncMode mode)
+{
+    bool finished = FALSE;
+#ifdef DEBUG
+    unsigned int wc = 0, dc = 0, ac = 0, hc = 0;
+# define INC_COUNT(x) ((x)++)
+#else
+# define INC_COUNT(x)
+#endif
+
+    if ((time_lastalive.tv_sec == 0) && (time_lastalive.tv_usec == 0)) {
+      /* first time through, needs initing */
+      gettimeofday(&time_lastalive, NULL);
+    }
+
+    /* main loop */
+    do
+    {
+        async_process_write( mode, &finished );
+        INC_COUNT(wc);
+
+        if ( ! finished && mode != async_block_on_write )
+        {
+            async_process_dbug_read( mode, &finished );
+            INC_COUNT(dc);
+        }
+
+        if ( ! finished && mode != async_block_on_write )
+        {
+           async_process_appl_read();
+           INC_COUNT(ac);
+        }
+
+        if ( ! finished )
+        {
+          if (heartbeat_configured)
+            async_process_heartbeat();
+          async_process_callbacks();
+          INC_COUNT(hc);
+        }
+
+    } while (!finished && mode != async_block_on_nothing);
+
+#ifdef DEBUG
+    if ( mode != async_block_on_nothing )
+       printf( "Async: %s - w %d, d %d, a %d, h %d\n",
+               mode == async_block_on_write ? "blk_write" : "blk_read",
+               wc, dc, ac, hc );
+#endif
+}
+
+/*
+ * install a handler for DC_APPL packets (can be NULL), returning old one.
+ */
+DC_Appl_Handler Adp_Install_DC_Appl_Handler(const DC_Appl_Handler handler)
+{
+    DC_Appl_Handler old_handler = dc_appl_handler;
+
+#ifdef DEBUG
+    printf( "Installing DC_APPL handler %x (old %x)\n", handler, old_handler );
+#endif
+
+    dc_appl_handler = handler;
+    return old_handler;
+}
+
+
+/*
+ * add an asynchronous processing callback to the list
+ * TRUE == okay, FALSE == no more async processing slots
+ */
+bool Adp_Install_Async_Callback( const Adp_Async_Callback callback_proc )
+{
+    if ( num_async_callbacks < MAX_ASYNC_CALLBACKS && callback_proc != NULL )
+    {
+        async_callbacks[num_async_callbacks] = callback_proc;
+        ++num_async_callbacks;
+        return TRUE;
+    }
+    else
+       return FALSE;
+}
+
+
+/*
+ * delay for a given period (in microseconds)
+ */
+void Adp_delay(unsigned int period)
+{
+    struct timeval tv;
+
+#ifdef DEBUG
+    printf("delaying for %d microseconds\n", period);
+#endif
+    tv.tv_sec = (period / 1000000);
+    tv.tv_usec = (period % 1000000);
+
+    (void)select(0, NULL, NULL, NULL, &tv);
+}
+
+/* EOF hostchan.c */
diff --git a/gdb/rdi-share/hostchan.h b/gdb/rdi-share/hostchan.h
new file mode 100644 (file)
index 0000000..db313dc
--- /dev/null
@@ -0,0 +1,300 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ */
+#ifndef angsd_hostchan_h
+#define angsd_hostchan_h
+
+/* struct timeval */
+#if defined(__unix) || defined(__CYGWIN32__)
+#  include <sys/time.h>
+#else
+#  include "winsock.h"
+#  include "time.h"
+#endif
+
+#include "chandefs.h"
+#include "adperr.h"
+#include "devsw.h"
+
+/*
+ * asynchronous processing modes
+ */
+enum AsyncMode
+{
+    async_block_on_nothing,
+    async_block_on_read,
+    async_block_on_write
+};
+
+#ifndef __cplusplus
+typedef enum AsyncMode AsyncMode;
+#endif
+
+/*
+ * prototype for channels callback function
+ */
+typedef void (*ChannelCallback)(Packet *packet, void *state);
+
+/*
+ *  Function: Adp_initSeq
+ *   Purpose: initialise the channel protocol and sequence numbers
+ *
+ *    Params: none
+ *
+ *   Returns: Nothing
+ */
+extern void Adp_initSeq(void);
+
+/*
+ *  Function: Adp_addToQueue
+ *   Purpose: chain a Packet to the end of a linked list of such structures
+ *
+ *    Params:
+ *      In/Out: head    Head of the linked list
+ *
+ *              newpkt  Packet to be chained onto the list
+ *
+ *   Returns: Nothing
+ */
+extern void Adp_addToQueue(Packet **head, Packet *newpkt);
+
+/*
+ *  Function: removeFromQueue
+ *   Purpose: remove a Packet from the head of a linked list of such structures
+ *
+ *    Params:
+ *      In/Out: head    Head of the linked list
+ *
+ *   Returns: Old head from the linked list
+ *
+ * Post-conditions: Second element in the list will be the new head.
+ */
+
+extern Packet *Adp_removeFromQueue(Packet **head);
+
+/*
+ *  Function: Adp_OpenDevice
+ *   Purpose: Open a device to use for channels communication.  This is a
+ *              very thin veneer to the device drivers: what hostchan.c
+ *              will do is call DeviceMatch for each device driver until it
+ *              finds a driver that will accept name and arg, then call
+ *              DeviceOpen for that device.
+ *
+ *  Pre-conditions: No previous open is still active
+ *
+ *    Params:
+ *       Input: name    Identifies which device to open.  This can either be
+ *                      a host specific identifier (e.g. "/dev/ttya",
+ *                      "COM1:"), or a number which is used to refer to
+ *                      `standard' interfaces, so "1" would be the first host
+ *                      interface, "2" the second, and so on.
+ *
+ *              arg     Driver specific arguments.  For example, some serial
+ *                      drivers accept speed and control arguments such as
+ *                      "9600" or "19200/NO_BREAK".  These arguments are
+ *                      completely free-form: it is the individual drivers
+ *                      which do the necessary interpretation.
+ *
+ *              heartbeat_on  Incicates if the heartbeat is configured to be 
+ *                      used or not, true if it is, false otherwise
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_not_known,
+ *              adp_device_open_failed
+ *              adp_device_already_open
+ */
+AdpErrs Adp_OpenDevice(const char *name, const char *arg,
+                       unsigned int heartbeat_on);
+
+/*
+ *  Function: Adp_CloseDevice
+ *   Purpose: Close the device used for channels communication.
+ *
+ *    Params: None
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_not_open
+ */
+AdpErrs Adp_CloseDevice(void);
+
+/*
+ *  Function: Adp_Ioctl
+ *   Purpose: Perform miscellaneous control operations on
+ *              the device used for channels communication.
+ *              This is a minimal veneer to DevSW_Ioctl.
+ *
+ *    Params:
+ *       Input: opcode  Reason code indicating the operation to perform.
+ *      In/Out: args    Pointer to opcode-sensitive arguments/result space.
+ *
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_not_open, adp_failed
+ */
+AdpErrs Adp_Ioctl(int opcode, void *args);
+
+/*
+ *  Function: Adp_ChannelRegisterRead
+ *   Purpose: Register a callback function for received packets on a given
+ *              channel
+ *
+ *    Params:
+ *       Input: chan    The channel the callback function is for.
+ *
+ *              cbfunc  The callback function.  If NULL, then the current
+ *                      callback is removed.
+ *
+ *              cbstate State pointer to pass into the callback function
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_not_open
+ *              adp_bad_channel_id
+ *
+ * Post-conditions: The callback function is responsible for freeing the
+ *                      packet that is passed to it, when that packet is
+ *                      no longer needed.
+ */
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+    
+extern AdpErrs Adp_ChannelRegisterRead(const ChannelID chan,
+                               const ChannelCallback cbfunc,
+                                void *cbstate);
+
+#ifdef __cplusplus
+    }
+#endif
+/*
+ *  Function: Adp_ChannelRead
+ *   Purpose: Wait until a packet has been read for a given channel, and
+ *              then return it.  Callbacks for other channels are still
+ *              active while this read is blocking.
+ *
+ *  Pre-conditions: No callback has been already been registered for
+ *                      the channel.
+ *
+ *    Params:
+ *       Input: chan    The channel to read.
+ *
+ *      Output: packet  The received packet.
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_not_open
+ *              adp_bad_channel_id
+ *              adp_callback_already_registered
+ *
+ * Post-conditions: The calling function is responsible for freeing the
+ *                      received packet, when that packet is no longer
+ *                      needed.
+ */
+AdpErrs Adp_ChannelRead(const ChannelID chan, Packet **packet);
+
+/*
+ *  Function: Adp_ChannelWrite
+ *   Purpose: Write a packet to the given channel
+ *
+ *  Pre-conditions: Channel must have been previously opened.
+ *
+ *    Params:
+ *       Input: chan    The channel to write.
+ *
+ *              packet  The packet to write.
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_not_open
+ *              adp_bad_channel_id
+ *
+ * Post-conditions: The packet being written becomes the "property" of
+ *                      Adp_ChannelWrite, which is responsible for freeing
+ *                      the packet when it is no longer needed.
+ */
+AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet);
+
+/*
+ *  Function: Adp_ChannelWriteAsync
+ *   Purpose: Write a packet to the given channel, but don't wait
+ *            for the write to complete before returning.
+ *
+ *  Pre-conditions: Channel must have been previously opened.
+ *
+ *    Params:
+ *       Input: chan    The channel to write.
+ *
+ *              packet  The packet to write.
+ *
+ *   Returns:
+ *          OK: adp_ok
+ *       Error: adp_device_not_open
+ *              adp_bad_channel_id
+ *
+ * Post-conditions: The packet being written becomes the "property" of
+ *                      Adp_ChannelWrite, which is responsible for freeing
+ *                      the packet when it is no longer needed.
+ */
+AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet);
+
+/*
+ *  Function: Adp_AsynchronousProcessing
+ *   Purpose: This routine should be called from persistent any idle loop
+ *              to give the data I/O routines a chance to poll for packet
+ *              activity.  Depending upon the requested mode, this routine
+ *              may, or may not, block.
+ *
+ *    Params:
+ *       Input: mode    Specifies whether to block until a complete packet
+ *                      has been read, all pending writes have completed,
+ *                      or not to block at all.
+ *
+ *   Returns: Nothing.
+ */
+void Adp_AsynchronousProcessing(const AsyncMode mode);
+
+/*
+ * prototype for DC_APPL packet handler
+ */
+typedef void (*DC_Appl_Handler)(const DeviceDescr *device, Packet *packet);
+
+/*
+ * install a handler for DC_APPL packets (can be NULL), returning old one.
+ */
+DC_Appl_Handler Adp_Install_DC_Appl_Handler(const DC_Appl_Handler handler);
+
+/*
+ * prototype for asynchronous processing callback
+ */
+typedef void (*Adp_Async_Callback)(const DeviceDescr *device,
+                                   const struct timeval *const time_now);
+
+/*
+ * add an asynchronous processing callback to the list
+ * TRUE == okay, FALSE == no more async processing slots
+ */
+bool Adp_Install_Async_Callback( const Adp_Async_Callback callback_proc );
+
+/*
+ * delay for a given period (in microseconds)
+ */
+void Adp_delay(unsigned int period);
+
+#endif /* ndef angsd_hostchan_h */
+
+/* EOF hostchan.h */
diff --git a/gdb/rdi-share/hsys.c b/gdb/rdi-share/hsys.c
new file mode 100644 (file)
index 0000000..ef42a30
--- /dev/null
@@ -0,0 +1,915 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * Host C Library support functions.
+ *
+ * $Revision$
+ *     $Date$
+ */
+
+#ifdef DEBUG
+#  include <ctype.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <time.h>
+
+#include "adp.h"
+#include "host.h"
+#include "ardi.h"
+#include "buffers.h"
+#include "channels.h"        /* Channel interface. */
+#include "endian.h"
+#include "logging.h"         /* Angel support functions. */
+#include "msgbuild.h"
+#include "sys.h"    
+#include "hsys.h"      /* Function and structure declarations. */
+#include "hostchan.h"
+
+#define FILEHANDLE int
+
+/* Note: no statics allowed.  All globals must be malloc()ed on the heap.
+   The state struct is used for this purpose.  See 'hsys.h'.                */
+/* This is the message handler function passed to the channel manager in
+   HostSysInit.  It is called whenever a message is received. 'buffptr'
+   points to the message body.  Functionality is provided by the debugger
+   toolkit.  The routine is very loosely based on the HandleSWI routine from
+   armos.c in the armulator source.                                         */
+/* These routines could be tested by providing a simple interface to armsd, 
+   and running them in that.   */
+
+
+/* taken staight from armulator source */
+#ifdef __riscos
+  extern int _fisatty(FILE *);
+# define isatty_(f) _fisatty(f)
+# define EMFILE -1
+# define EBADF -1
+  int _kernel_escape_seen(void) { return 0 ;}
+#else
+# if defined(_WINDOWS) || defined(_CONSOLE)
+#   define isatty_(f) (f == stdin || f == stdout)
+# else
+#   ifdef __ZTC__
+#     include <io.h>
+#     define isatty_(f) isatty((f)->_file)
+#   else
+#     ifdef macintosh
+#       include <ioctl.h>
+#       define isatty_(f) (~ioctl((f)->_file,FIOINTERACTIVE,NULL))
+#     else
+#       define isatty_(f) isatty(fileno(f))
+#     endif
+#   endif
+# endif
+#endif
+
+/* Set up the state block, filetable and register the C lib callback fn */
+int HostSysInit(const struct Dbg_HostosInterface *hostif, char **cmdline,
+                hsys_state **stateptr)
+{
+  ChannelCallback HandleMessageFPtr = (ChannelCallback) HandleSysMessage;
+  int i;
+  *stateptr = (hsys_state *)malloc(sizeof(hsys_state));
+
+  if (*stateptr == NULL) return RDIError_OutOfStore;
+
+  (*stateptr)->hostif=hostif;
+  (*stateptr)->last_errno=0;
+  (*stateptr)->OSptr=(OSblock *)malloc(sizeof(OSblock));
+  if ((*stateptr)->OSptr == NULL) return RDIError_OutOfStore;
+  for (i=0; i<UNIQUETEMPS; i++) (*stateptr)->OSptr->TempNames[i]=NULL;
+  for (i=0; i<HSYS_FOPEN_MAX; i++) {
+       (*stateptr)->OSptr->FileTable[i]=NULL;
+       (*stateptr)->OSptr->FileFlags[i]=0;
+  }
+  (*stateptr)->CommandLine=cmdline;
+
+  return Adp_ChannelRegisterRead(CI_CLIB, (ChannelCallback)HandleMessageFPtr,
+                                 *stateptr);
+}
+
+/* Shut down the Clib support, this will probably never get called though */
+int HostSysExit(hsys_state *stateptr)
+{
+  free(stateptr->OSptr);
+  free(stateptr);
+  return RDIError_NoError;
+}
+
+#ifdef DEBUG
+static void DebugCheckNullTermString(char *prefix, bool nl,
+                                     unsigned int len, unsigned char *strp)
+{
+    printf("%s: %d: ", prefix, len);
+    if (strp[len]=='\0')
+       printf("\"%s\"", strp);
+    else
+       printf("NOT NULL TERMINATED");
+    if (nl)
+       printf("\n");
+    else
+    {
+        printf(" ");
+        fflush(stdout);
+    }
+}
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+static char *DebugStrError(int last_errno)
+{
+    if (last_errno < sys_nerr)
+       return sys_errlist[last_errno];
+    else
+       return "NO MSG (errno>sys_nerr)";
+}
+
+static void DebugCheckErr(char *prefix, bool nl, int err, int last_errno)
+{
+    printf("\t%s: returned ", prefix);
+    if (err == 0)
+       printf("okay");
+    else
+       printf("%d, errno = %d \"%s\"", err, last_errno,
+              DebugStrError(last_errno));
+    if (nl)
+       printf("\n");
+    else
+    {
+        printf(" ");
+        fflush(stdout);
+    }
+}
+
+static void DebugCheckNonNull(char *prefix, bool nl,
+                              void *handle, int last_errno)
+{
+    printf("\t%s: returned ", prefix);
+    if (handle != NULL)
+       printf("okay [%08x]", (unsigned int)handle);
+    else
+       printf("NULL, errno = %d \"%s\"", last_errno,
+              DebugStrError(last_errno));
+    if (nl)
+       printf("\n");
+    else
+    {
+        printf(" ");
+        fflush(stdout);
+    }
+}
+
+#define DebugPrintF(c) printf c;
+
+#else
+
+#define DebugCheckNullTermString(p, n, l, s)    ((void)(0))
+#define DebugCheckErr(p, n, e, l)               ((void)(0))
+#define DebugCheckNonNull(p, n, h, l)           ((void)(0))
+#define DebugPrintF(c)                          ((void)(0))
+
+#endif /* ifdef DEBUG ... else */
+
+static FILE *hsysGetRealFileHandle(hsys_state *stateptr, int fh, char *flags)
+{
+    FILE *file_p = NULL;
+
+    if (fh < 0 || fh >= HSYS_FOPEN_MAX)
+    {
+        stateptr->last_errno = EBADF;
+        DebugPrintF(("\tfh %d out-of-bounds!\n", fh));
+        return NULL;
+    }
+    else
+    {
+        file_p = stateptr->OSptr->FileTable[fh];
+        if (file_p != NULL) {
+            if (flags != NULL)
+               *flags = stateptr->OSptr->FileFlags[fh];
+        }
+        else {
+          stateptr->last_errno = EBADF;
+          DebugPrintF(("\tFileTable[%d] is NULL\n", fh));
+        }
+
+        return file_p;
+    }
+}
+
+int HandleSysMessage(Packet *packet, hsys_state *stateptr)
+{
+  unsigned int reason_code, mode, len, c, nbytes, nbtotal, nbtogo = 0;
+  long posn, fl;
+  char character;
+  int err;
+
+  /* Note: We must not free the buffer passed in as the callback handler */
+  /* expects to do this.  Freeing any other buffers we have malloced */
+  /* ourselves is acceptable */
+
+  unsigned char *buffp = ((unsigned char *)BUFFERDATA(packet->pk_buffer))+16;
+                                          /* buffp points to the parameters*/
+                                          /* the invidual messages, excluding*/
+                                          /* standard SYS fields (debugID, */
+                                          /* osinfo and reasoncode) */
+  unsigned char *buffhead = (unsigned char *)(packet->pk_buffer);
+
+  int DebugID, OSInfo1, OSInfo2, count;
+
+  const char* fmode[] = {"r","rb","r+","r+b",
+                               "w","wb","w+","w+b",
+                               "a","ab","a+","a+b",
+                               "r","r","r","r"} /* last 4 are illegal */ ;
+
+  FILEHANDLE fh;  /* fh is used as an index to the real file handle
+                         * in OSptr */  
+  FILE *fhreal;
+  unpack_message(BUFFERDATA(buffhead), "%w%w%w%w", &reason_code,
+                 &DebugID, &OSInfo1, &OSInfo2);
+                                        /* Extract reason code from buffer. */
+  reason_code &= 0xFFFF;        /* Strip away direction bit, OSInfo and     */
+                                /* DebugInfo fields.  Will want to do some  */
+                                /* sort of validation on this later.        */
+  
+  switch(reason_code)
+  {
+
+  case CL_WriteC:   /* Write a character to the terminal. */
+                    /* byte data -> word status           */
+    {
+#ifdef DEBUG
+      int c = (int)(*buffp);
+      printf("CL_WriteC: [%02x]>%c<", c, isprint(c) ? c : '.');
+#endif
+      stateptr->hostif->writec(stateptr->hostif->hostosarg, (int)(*buffp));
+      DevSW_FreePacket(packet);
+      return msgsend(CI_CLIB,"%w%w%w%w%w", CL_WriteC|HtoT,
+                    DebugID, OSInfo1, OSInfo2, NoError);
+    }
+
+  case CL_Write0:  /* Write a null terminated string to the terminal. */
+    {
+      unpack_message(buffp, "%w", &len);
+      DebugCheckNullTermString("CL_Write0", TRUE, len, buffp+4);
+      stateptr->hostif->write(stateptr->hostif->hostosarg,
+                              (char *) buffp+4, len);
+      DevSW_FreePacket(packet);
+      return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Write0|HtoT, DebugID, 
+                    OSInfo1, OSInfo2, NoError);
+    }
+
+  case CL_ReadC:   /* Read a byte from the terminal */
+    {
+      DebugPrintF(("CL_ReadC: "));
+      DevSW_FreePacket(packet);
+
+      character = stateptr->hostif->readc(stateptr->hostif->hostosarg);
+      DebugPrintF(("\nCL_ReadC returning [%02x]>%c<\n", character,
+                   isprint(character) ? character : '.'));
+
+      return msgsend(CI_CLIB, "%w%w%w%w%w%b", CL_ReadC|HtoT,
+                    DebugID, OSInfo1, OSInfo2, NoError, character);
+    }
+
+  case CL_System:  /* Pass NULL terminated string to the hosts command 
+                    * interpreter. As it is nULL terminated we dont need
+                    * the length
+                    */
+    {
+      unpack_message(buffp, "%w", &len);
+      DebugCheckNullTermString("CL_System", TRUE, len, buffp+4);
+
+      err = system((char *)buffp+4); /* Use the string in the buffer */
+      stateptr->last_errno = errno;
+      DebugCheckErr("system", TRUE, err, stateptr->last_errno);
+
+      err = msgsend(CI_CLIB, "%w%w%w%w%w%w", CL_System|HtoT,
+                    DebugID, OSInfo1, OSInfo2, NoError, err);
+      DevSW_FreePacket(packet);
+      return err;
+    }
+
+  case CL_GetCmdLine:  /* Returns the command line used to call the program */
+    {
+      /* Note: we reuse the packet here, this may not always be desirable */
+      /* /* TODO: Use long buffers if possible */
+      DebugPrintF(("CL_GetCmdLine: \"%s\"\n", *(stateptr->CommandLine)));
+
+      if (buffhead!=NULL) {
+        len = strlen(*(stateptr->CommandLine));
+        if (len > Armsd_BufferSize-24) len = Armsd_BufferSize-24; 
+        packet->pk_length = len + msgbuild(BUFFERDATA(buffhead),
+                                           "%w%w%w%w%w%w", CL_GetCmdLine|HtoT,
+                                           DebugID, OSInfo1, OSInfo2,
+                                           NoError, len);
+        strncpy((char *) BUFFERDATA(buffhead)+24,*(stateptr->CommandLine),
+                len);
+        
+        Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
+        return 0;
+      }
+      else return -1;
+    }
+
+  case CL_Clock:   /* Return the number of centiseconds since the support */
+                   /* code started executing */
+    {
+      time_t retTime = time(NULL);
+      if (retTime == (time_t)-1)
+             stateptr->last_errno = errno;
+      else
+             retTime *=100;
+
+      DebugPrintF(("CL_Clock: %lu\n", retTime));
+      DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
+                    stateptr->last_errno);
+
+      DevSW_FreePacket(packet);
+      return msgsend(CI_CLIB, "%w%w%w%w%w%w",CL_Clock|HtoT,
+                         DebugID, OSInfo1, OSInfo2, NoError, retTime);
+    }
+
+  case CL_Time:    /* return time, in seconds since the start of 1970 */
+    {
+      time_t retTime = time(NULL);
+      if (retTime == (time_t)-1)
+              stateptr->last_errno = errno;
+
+      DebugPrintF(("CL_Time: %lu\n", retTime));
+      DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
+                    stateptr->last_errno);
+
+      DevSW_FreePacket(packet);
+      return msgsend(CI_CLIB,"%w%w%w%w%w%w",CL_Time|HtoT,
+                         DebugID, OSInfo1, OSInfo2, NoError, retTime);
+    }
+
+  case CL_Remove:  /* delete named in the null terminated string */
+    {
+      /* Removing an open file will cause problems but once again
+       * its not our problem, likely result is a tangled FileTable */
+      /* As the filename is passed with a null terminator we can use it
+       * straight out of the buffer without copying it.*/
+
+      unpack_message(buffp, "%w", &len);
+      DebugCheckNullTermString("CL_Remove", TRUE, len, buffp+4);
+
+      err=remove((char *)buffp+4);
+      stateptr->last_errno = errno;
+      DevSW_FreePacket(packet);
+      DebugCheckErr("remove", TRUE, err, stateptr->last_errno);
+
+      return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Remove|HtoT,
+                     DebugID, OSInfo1, OSInfo2, err?-1:NoError);
+    }
+
+  case CL_Rename:  /* rename file */
+    {
+      /* Rename(word nbytes, bytes oname, word nbytes, bytes nname)
+      * return(byte status)
+      */
+      unsigned int len2;
+
+      unpack_message(buffp, "%w", &len);
+      DebugCheckNullTermString("CL_Rename", FALSE, len, buffp+4);
+      unpack_message(buffp+5+len, "%w", &len2);
+      DebugCheckNullTermString("to", TRUE, len2, buffp+9+len);
+
+      /* Both names are passed with null terminators so we can use them
+       * directly from the buffer. */
+      err = rename((char *)buffp+4, (char *)buffp+9+len);
+      stateptr->last_errno = errno;
+      DebugCheckErr("rename", TRUE, err, stateptr->last_errno);
+      DevSW_FreePacket(packet);
+
+      return msgsend(CI_CLIB, "%w%w%w%w%w",  CL_Rename|HtoT,
+                     DebugID, OSInfo1, OSInfo2, (err==0)? NoError : -1);
+    }
+  
+  case CL_Open:    /* open the file */
+    {
+      /* Open(word nbytes, bytes name, byte mode)
+      * return(word handle)
+      */
+      unpack_message(buffp, "%w", &len);
+      /* get the open mode */
+      unpack_message((buffp)+4+len+1, "%w", &mode);
+      DebugCheckNullTermString("CL_Open", FALSE, len, buffp+4);
+      DebugPrintF(("mode: %d\n", mode));
+
+      /* do some checking on the file first? */
+      /* check if its a tty */
+      if (strcmp((char *)buffp+4, ":tt")==0 && (mode==0||mode==1)) {
+        /* opening tty "r" */
+        fhreal = stdin;
+        stateptr->last_errno = errno;
+        DebugPrintF(("\tstdin "));
+      }
+      else if (strcmp((char *)buffp+4, ":tt")== 0 && (mode==4||mode==5)) {
+        /* opening tty "w" */
+        fhreal = stdout;
+        stateptr->last_errno = errno;
+        DebugPrintF(("\tstdout "));
+      }
+      else
+      {
+        fhreal = fopen((char *)buffp+4, fmode[mode&0xFF]);
+        stateptr->last_errno = errno;
+        DebugCheckNonNull("fopen", FALSE, fhreal, stateptr->last_errno);
+      }
+      DevSW_FreePacket(packet);
+
+      c = NONHANDLE;
+      if (fhreal != NULL) {
+        /* update filetable */
+        for (c=3; c < HSYS_FOPEN_MAX; c++) {
+          /* allow for stdin, stdout, stderr (!!! WHY? MJG) */
+          if (stateptr->OSptr->FileTable[c] == NULL) {
+            stateptr->OSptr->FileTable[c]= fhreal;
+            stateptr->OSptr->FileFlags[c]= mode & 1;
+            DebugPrintF(("fh: %d\n", c));
+            break;
+          }
+          else if (c == HSYS_FOPEN_MAX) {
+          /* no filehandles free */
+          DebugPrintF(("no free fh: %d\n", c));
+          stateptr->last_errno = EMFILE;
+          }
+        }
+      }
+      else {
+        /*        c = NULL;*/
+        DebugPrintF(("error fh: %d\n", c));
+      }
+      (void) msgsend(CI_CLIB, "%w%w%w%w%w",  CL_Open|HtoT,
+                     DebugID, OSInfo1, OSInfo2, c);
+      return 0;
+    }
+
+  case CL_Close:   /* close the file pointed to by the filehandle */
+    {
+      unpack_message(buffp, "%w", &fh);
+      DebugPrintF(("CL_Close: fh %d\n", fh));
+      DevSW_FreePacket(packet);
+
+      fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
+      if (fhreal == NULL)
+         err = -1;
+      else {
+          if (fhreal == stdin || fhreal == stdout || fhreal == stderr) {
+              stateptr->last_errno = errno;
+              DebugPrintF(("\tskipping close of std*\n"));
+              err = 0;
+          }
+          else {
+              err = fclose(fhreal);
+              if (err == 0)
+                 stateptr->OSptr->FileTable[fh]=NULL;
+              stateptr->last_errno = errno;
+              DebugCheckErr("fclose", TRUE, err, stateptr->last_errno);
+          }
+      }
+      return msgsend(CI_CLIB,"%w%w%w%w%w",  CL_Close|HtoT, DebugID,
+                     OSInfo1, OSInfo2, err);
+    }
+
+  case CL_Write:
+    {
+        /* Write(word handle, word nbtotal, word nbytes, bytes data)
+         * return(word nbytes)
+         * WriteX(word nbytes, bytes data)
+         * return(word nbytes)
+         */
+      unsigned char *rwdata = NULL, *rwhead = NULL;
+      unsigned char *write_source = NULL;
+      char flags;
+      FILE *fhreal;
+      unsigned int ack_reason = CL_Write; /* first ack is for CL_Write */
+
+      err = -1;                 /* err == 0 is fwrite() error indication */
+      unpack_message(buffp, "%w%w%w", &fh, &nbtotal, &nbytes); 
+      DebugPrintF(("CL_Write: fh %d nbtotal %u nbytes %u\n",
+                   fh, nbtotal, nbytes));
+
+      fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
+      nbtogo = nbtotal;
+
+      /* deal with the file handle */
+      if (fhreal == NULL)
+         err = 0;
+      else {
+        if (flags & READOP)
+           fseek(fhreal,0,SEEK_CUR);
+        stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
+
+        nbtogo -= nbytes;
+
+        if (nbtogo > 0) {
+          write_source = rwdata = rwhead = (unsigned char *)malloc(nbtotal);
+          if (rwhead == NULL) {
+            fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
+                    __LINE__, __FILE__);
+            return -1;
+          }
+          memcpy(rwdata, buffp+12, nbytes);
+          rwdata += nbytes;
+        }
+        else
+           write_source = buffp+12;
+      }
+
+      do {
+        /* at least once!! */
+
+        if (nbtogo == 0 && err != 0) {
+          /* Do the actual write! */
+          if (fhreal == stdout || fhreal == stderr) {
+            stateptr->hostif->write(stateptr->hostif->hostosarg,
+                                    (char *)write_source, nbtotal);
+          }
+          else 
+             err = fwrite(write_source, 1, nbtotal, fhreal);
+          stateptr->last_errno = errno;
+          DebugCheckErr("fwrite", TRUE, (err == 0), stateptr->last_errno);
+        }
+
+        DevSW_FreePacket(packet);
+        if (msgsend(CI_CLIB,"%w%w%w%w%w%w", ack_reason|HtoT,
+                    DebugID, OSInfo1, OSInfo2, (err == 0), nbtogo))
+        {
+            fprintf(stderr, "COULD NOT REPLY at line %d in %s\n",
+                    __LINE__, __FILE__);
+            if (rwhead != NULL)
+               free(rwhead);
+            return -1;
+        }
+
+        if (nbtogo == 0 || err == 0) {
+          DebugPrintF(("\twrite complete - returning\n"));
+          if (rwhead != NULL)
+             free(rwhead);
+          return 0;
+        }
+        else {
+          /* await extension */
+          ack_reason = CL_WriteX;
+
+          packet = DevSW_AllocatePacket(Armsd_BufferSize);
+          if (packet == NULL)
+          {
+            fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
+                    __LINE__, __FILE__);
+            if (rwhead != NULL)
+               free(rwhead);
+            return -1;
+          }
+          Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
+          Adp_ChannelRead(CI_CLIB, &packet);
+          Adp_ChannelRegisterRead(CI_CLIB,
+                                  (ChannelCallback)HandleSysMessage,
+                                  stateptr);
+
+          buffhead = packet->pk_buffer;
+          unpack_message(BUFFERDATA(buffhead), "%w%w%w%w%w", &reason_code,
+                         &DebugID, &OSInfo1, &OSInfo2, &nbytes); 
+          if (reason_code != (CL_WriteX|TtoH)) {
+            DevSW_FreePacket(packet);
+            free(rwhead);
+            fprintf(stderr, "EXPECTING CL_WriteX GOT %u at line %d in %s\n",
+                    reason_code, __LINE__, __FILE__);
+            return -1;
+          }
+
+          DebugPrintF(("CL_WriteX: nbytes %u\n", nbytes));
+          memcpy(rwdata, BUFFERDATA(buffhead)+20, nbytes);
+          rwdata += nbytes;
+          nbtogo -= nbytes;
+        }
+
+      } while (TRUE);           /* will return when done */
+    }
+
+  case CL_WriteX:     /*
+                       * NOTE: if we've got here something has gone wrong
+                       * CL_WriteX's should all be picked up within the
+                       * CL_Write loop, probably best to return an error here
+                       * do this for the moment just so we do actually return
+                       */
+    fprintf(stderr, "ERROR: unexpected CL_WriteX message received\n");
+    return -1; 
+
+  case CL_Read:
+    {
+                   /* Read(word handle, word nbtotal)
+                    * return(word nbytes, word nbmore, bytes data)
+                    */
+                   /* ReadX()
+                    * return(word nbytes, word nbmore, bytes data) */
+      unsigned char *rwdata, *rwhead;
+      int gotlen;
+      unsigned int max_data_in_buffer=Armsd_BufferSize-28;
+      char flags;
+      FILE *fhreal;
+      unsigned int nbleft = 0, reason = CL_Read;
+
+      err = NoError;
+
+      unpack_message(buffp, "%w%w", &fh, &nbtotal);
+      DebugPrintF(("CL_Read: fh %d, nbtotal %d: ", fh, nbtotal));
+
+      rwdata = rwhead = (unsigned char *)malloc(nbtotal);
+      if (rwdata == NULL) {
+        fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
+                __LINE__, __FILE__);
+        DevSW_FreePacket(packet);
+        return -1;
+      }
+
+      /* perform the actual read */
+      fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
+      if (fhreal == NULL)
+      {
+        /* bad file handle */
+        err = -1;
+        nbytes = 0;
+        gotlen = 0;
+      }
+      else
+      {
+        if (flags & WRITEOP)
+          fseek(fhreal,0,SEEK_CUR);
+        stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
+        if (isatty_(fhreal)) {
+          /* reading from a tty, so do some nasty stuff, reading into rwdata */
+          if (angel_hostif->gets(stateptr->hostif->hostosarg, (char *)rwdata,
+                                 nbtotal) != 0)
+             gotlen = strlen((char *)rwdata);
+          else
+             gotlen = 0;
+          stateptr->last_errno = errno;
+          DebugPrintF(("ttyread %d\n", gotlen));
+        }
+        else {
+          /* not a tty, reading from a real file */
+          gotlen = fread(rwdata, 1, nbtotal, fhreal);
+          stateptr->last_errno = errno;
+          DebugCheckErr("fread", FALSE, (gotlen == 0), stateptr->last_errno);
+          DebugPrintF(("(%d)\n", gotlen));
+        }
+      }
+
+      nbtogo = gotlen;
+
+      do {
+        /* at least once */
+
+        if ((unsigned int) nbtogo <= max_data_in_buffer)
+           nbytes = nbtogo;
+        else
+           nbytes = max_data_in_buffer;
+        nbtogo -= nbytes;
+
+        /* last ReadX needs subtle adjustment to returned nbtogo */
+        if (nbtogo == 0 && err == NoError && reason == CL_ReadX)
+           nbleft = nbtotal - gotlen;
+        else
+           nbleft = nbtogo;
+
+        count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w%w",
+                         reason|HtoT, 0, ADP_HandleUnknown,
+                         ADP_HandleUnknown, err, nbytes, nbleft);
+
+        if (err == NoError) {
+          /* copy data into buffptr */   
+          memcpy(BUFFERDATA(buffhead)+28, rwdata, nbytes);
+          rwdata += nbytes;
+          count += nbytes;
+        }
+
+        DebugPrintF(("\treplying err %d, nbytes %d, nbtogo %d\n",
+                     err, nbytes, nbtogo));
+
+        packet->pk_length = count;
+        Adp_ChannelWrite(CI_CLIB, packet);
+
+        if (nbtogo == 0 || err != NoError) {
+          /* done */
+          free(rwhead);
+          return 0;
+        }
+        else {
+          /* await extension */
+          reason = CL_ReadX;
+
+          packet = DevSW_AllocatePacket(Armsd_BufferSize);
+          if (packet == NULL) {
+            fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
+                    __LINE__, __FILE__);
+            free(rwhead);
+            return -1;
+          }
+          Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
+          Adp_ChannelRead(CI_CLIB, &packet);
+          Adp_ChannelRegisterRead(CI_CLIB,
+                                  (ChannelCallback)HandleSysMessage,
+                                  stateptr);
+          buffhead = packet->pk_buffer;
+          unpack_message(BUFFERDATA(buffhead),"%w", &reason_code);
+          if (reason_code != (CL_ReadX|TtoH)) {
+            fprintf(stderr, "EXPECTING CL_ReadX GOT %u at line %d in %s\n",
+                    reason_code, __LINE__, __FILE__);
+            DevSW_FreePacket(packet);
+            free(rwdata);
+            return -1;
+          }
+        }
+
+      } while (TRUE);           /* will return above on error or when done */
+    }
+
+  case CL_ReadX:      /* If we're here something has probably gone wrong */
+    fprintf(stderr, "ERROR: Got unexpected CL_ReadX message\n");
+    return -1;
+
+  case CL_Seek:
+    {
+      unpack_message(buffp, "%w%w", &fh, &posn);
+      DebugPrintF(("CL_Seek: fh %d, posn %ld\n", fh, posn));
+      DevSW_FreePacket(packet);
+
+      fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
+      if (fhreal == NULL)
+         err = -1;
+      else {
+        err = fseek(fhreal, posn, SEEK_SET); 
+        stateptr->last_errno = errno;
+        DebugCheckErr("fseek", TRUE, err, stateptr->last_errno);
+      }
+
+      return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Seek|HtoT, 
+                         DebugID, OSInfo1, OSInfo2, err);
+    }
+
+  case CL_Flen:
+    {
+      unpack_message(buffp, "%w", &fh);
+      DebugPrintF(("CL_Flen: fh %d ", fh));
+      DevSW_FreePacket(packet);
+
+      fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
+      if (fhreal == NULL)
+        fl = -1;
+      else {
+        posn = ftell(fhreal);
+        if (fseek(fhreal, 0L, SEEK_END) < 0) {
+          fl=-1;
+        }
+        else {
+          fl = ftell(fhreal);
+          fseek(fhreal, posn, SEEK_SET);
+        }
+        stateptr->last_errno = errno;
+      }
+      DebugPrintF(("returning len %ld\n", fl));
+      return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Flen|HtoT, DebugID, OSInfo1,
+                     OSInfo2, fl);
+    } 
+
+  case CL_IsTTY:
+    {
+      int  ttyOrNot;
+      unpack_message(buffp, "%w", &fh);
+      DebugPrintF(("CL_IsTTY: fh %d ", fh));
+      DevSW_FreePacket(packet);
+
+      fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
+      if (fhreal == NULL)
+         ttyOrNot = FALSE;
+      else {
+        ttyOrNot = isatty_(fhreal);
+        stateptr->last_errno = errno;
+      }
+      DebugPrintF(("returning %s\n", ttyOrNot ? "tty (1)" : "not (0)"));
+
+      return msgsend(CI_CLIB, "%w%w%w%w%w",CL_IsTTY|HtoT, 
+                         DebugID, OSInfo1, OSInfo2, ttyOrNot);
+    }
+
+  case CL_TmpNam:
+    {
+      char *name;
+      unsigned int tnamelen, TargetID;
+      unpack_message(buffp, "%w%w", &tnamelen, &TargetID); 
+      DebugPrintF(("CL_TmpNam: tnamelen %d TargetID %d: ",
+                   tnamelen, TargetID));
+      DevSW_FreePacket(packet);
+
+      TargetID = TargetID & 0xFF;
+      if (stateptr->OSptr->TempNames[TargetID] == NULL) {
+        if ((stateptr->OSptr->TempNames[TargetID] =
+             (char *)malloc(L_tmpnam)) == NULL)
+        {
+          fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
+                  __LINE__, __FILE__);
+          return -1;
+        }
+        tmpnam(stateptr->OSptr->TempNames[TargetID]);
+      }
+      name = stateptr->OSptr->TempNames[TargetID];
+      len = strlen(name) + 1;
+      packet = DevSW_AllocatePacket(Armsd_BufferSize);
+      if (packet == NULL)
+      {
+          fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
+                  __LINE__, __FILE__);
+          return -1;
+      }
+      buffhead = packet->pk_buffer;
+      if (len > tnamelen) {
+        DebugPrintF(("TMPNAME TOO LONG!\n"));
+        count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w",
+                           CL_TmpNam|HtoT, DebugID, OSInfo1, OSInfo2, -1);
+      }
+      else {
+        DebugPrintF(("returning \"%s\"\n", name));
+        count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w", CL_TmpNam|HtoT,
+                         DebugID, OSInfo1, OSInfo2, 0, len);
+        strcpy((char *)BUFFERDATA(buffhead)+count, name);
+        count +=len+1;
+      }
+      packet->pk_length = count;
+      Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
+      return 0;
+    }
+
+  case CL_Unrecognised:
+    DebugPrintF(("CL_Unrecognised!!\n"));
+    return 0;
+
+  default:
+    fprintf(stderr, "UNRECOGNISED CL code %08x\n", reason_code);
+    break;
+/* Need some sort of error handling here. */
+/* A call to CL_Unrecognised should suffice */
+  }
+  return -1;  /* Stop a potential compiler warning */
+}
+
+#ifdef COMPILING_ON_WINDOWS
+
+#include <windows.h>
+
+extern HWND hwndParent;
+
+void panic(const char *format, ...)
+{
+    char buf[2048];
+    va_list args;
+
+    Adp_CloseDevice();
+
+    va_start(args, format);
+    vsprintf(buf, format, args);
+
+    MessageBox(hwndParent, (LPCTSTR)buf, (LPCTSTR)"Fatal Error:", MB_OK);
+
+    /* SJ - Not the proper way to shutdown the app */
+    exit(EXIT_FAILURE);
+
+/*
+    if (hwndParent != NULL)
+        SendMessage(hwndParent, WM_QUIT, 0, 0);
+*/
+
+    va_end(args);
+}
+
+#else
+
+void panic(const char *format, ...)
+{
+    va_list args;
+
+    va_start(args, format);
+    fprintf(stderr, "Fatal error: ");
+    vfprintf(stderr, format, args);
+    fprintf(stderr,"\n");
+
+    exit(EXIT_FAILURE);
+}
+
+#endif
+
+/* EOF hsys.c */
diff --git a/gdb/rdi-share/hsys.h b/gdb/rdi-share/hsys.h
new file mode 100644 (file)
index 0000000..7f63d01
--- /dev/null
@@ -0,0 +1,101 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*
+ * Host C library support header file.
+ *
+ * $Revision$
+ *     $Date$
+ *
+ */
+
+#ifndef angsd_hsys_h
+#define angsd_hsys_h
+
+#define HSYS_FOPEN_MAX 256
+#define NONHANDLE -1
+#define UNIQUETEMPS 256
+
+#include "dbg_hif.h"
+#include "hostchan.h"
+
+typedef struct {
+  FILE *FileTable[HSYS_FOPEN_MAX] ;
+  char FileFlags[HSYS_FOPEN_MAX] ;
+  char *TempNames[UNIQUETEMPS];
+} OSblock;
+
+#define NOOP 0
+#define BINARY 1
+#define READOP 2
+#define WRITEOP 4
+
+typedef struct {
+  const struct Dbg_HostosInterface *hostif;  /* Interface to debug toolkit. */
+  int last_errno;                              /* Number of the last error. */
+  OSblock *OSptr;
+  char **CommandLine ;           /* Ptr to cmd line d`string held by ardi.c */
+} hsys_state;
+
+/*
+ *  Function: HostSysInit
+ *   Purpose: Set up the state block, filetable and register the and C lib
+ *            callback fn 
+ *
+ *    Params:
+ *       Input: hostif, the host interface from the debug toolbox
+ *              cmdline, the command line used to call the image
+ *              state, the status block for the C lib 
+ *
+ *   Returns:
+ *          OK: an RDIError_* valuee
+ */
+extern int HostSysInit(
+  const struct Dbg_HostosInterface *hostif, char **cmdline, hsys_state **state
+);
+
+/*
+ *  Function: HostSysExit
+ *   Purpose: Close down the host side C library support
+ *
+ *    Params:
+ *       Input: hstate, the status block for the C lib 
+ *
+ *    Returns:  an RDIError_* valuee
+ */
+extern int HostSysExit(hsys_state *hstate);
+
+/*
+ *  Function: HandleSysMessage
+ *   Purpose: Handle an incoming C library message as a callback
+ *
+ *    Params:
+ *       Input: packet is the incoming data packet as described in devsw.h
+ *       hstate, the status block for the C lib
+ *
+ *    Returns:  an RDIError_* valuee
+ */
+extern int HandleSysMessage(Packet *packet, hsys_state* stateptr);
+
+/*
+ *  Function: panic
+ *   Purpose: Print a fatal error message
+ *
+ *    Params:
+ *       Input: format  printf() style message describing the problem
+ *              ...     extra arguments for printf().
+ *
+ *   Returns: This routine does not return
+ *
+ * Post-conditions: Will have called exit(1);
+ */
+extern void panic(const char *format, ...);
+
+#endif /* ndef angsd_hsys_h */
+
+/* EOF hsys.h */
diff --git a/gdb/rdi-share/logging.c b/gdb/rdi-share/logging.c
new file mode 100644 (file)
index 0000000..79b70ef
--- /dev/null
@@ -0,0 +1,369 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * logging.c - methods for logging warnings, errors and trace info
+ *
+ */
+
+#include <stdarg.h>     /* ANSI varargs support */
+
+#ifdef TARGET
+# include "angel.h"
+# include "devconf.h"
+#else
+# include "host.h"
+#endif
+
+#include "logging.h"    /* Header file for this source code */
+
+#ifndef UNUSED
+# define UNUSED(x) ((x)=(x))
+#endif
+
+/*
+ * __rt_warning
+ * ------------
+ * This routine is provided as a standard method of generating
+ * run-time system warnings. The actual action taken by this code can
+ * be board or target application specific, e.g. internal logging,
+ * debug message, etc.
+ */
+
+#ifdef DEBUG
+
+# ifdef DEBUG_METHOD
+
+#  define  STRINGIFY2(x) #x
+#  define  STRINGIFY(x)  STRINGIFY2(x)
+#  define  DEBUG_METHOD_HEADER        STRINGIFY(DEBUG_METHOD##.h)
+
+#  include DEBUG_METHOD_HEADER
+
+#  define  METHOD_EXPAND_2(m, p, c) m##p(c)
+#  define  METHOD_EXPAND(m, p, c)   METHOD_EXPAND_2(m, p, c)
+
+#  define  CHAROUT(c)    METHOD_EXPAND(DEBUG_METHOD, _PutChar,  (c))
+#  define  PRE_DEBUG(l)  METHOD_EXPAND(DEBUG_METHOD, _PreWarn,  (l))
+#  define  POST_DEBUG(n) METHOD_EXPAND(DEBUG_METHOD, _PostWarn, (n))
+
+# else
+#  error Must define DEBUG_METHOD
+# endif
+
+#endif /* def DEBUG */
+
+/*
+ * the guts of __rt_warning
+ */
+
+#pragma no_check_stack
+#ifdef DEBUG
+
+static const char hextab[] = "0123456789ABCDEF";
+
+/*
+ * If debugging, then we break va_warn into sub-functions which
+ * allow us to get an easy breakpoint on the formatted string
+ */
+static int va_warn0(char *format, va_list args)
+{
+    int len = 0;
+
+    while ((format != NULL) && (*format != '\0'))
+    {
+        if (*format == '%')
+        {
+            char fch = *(++format); /* get format character (skipping '%') */
+            int ival; /* holder for integer arguments */
+            char *string; /* holder for string arguments */
+            int width = 0; /* No field width by default */
+            int padzero = FALSE; /* By default we pad with spaces */
+
+            /*
+             * Check if the format has a width specified. NOTE: We do
+             * not use the "isdigit" function here, since it will
+             * require run-time support. The current ARM Ltd header
+             * defines "isdigit" as a macro, that uses a fixed
+             * character description table.
+             */
+            if ((fch >= '0') && (fch <= '9'))
+            {
+                if (fch == '0')
+                {
+                    /* Leading zeroes padding */
+                    padzero = TRUE;
+                    fch = *(++format);
+                }
+
+                while ((fch >= '0') && (fch <= '9'))
+                {
+                    width = ((width * 10) + (fch - '0'));
+                    fch = *(++format);
+                }
+            }
+
+            if (fch == 'l')
+                /* skip 'l' in "%lx", etc. */
+                fch = *(++format);
+
+            switch (fch)
+            {
+              case 'c':
+                  /* char */
+                  ival = va_arg(args, int);
+                  CHAROUT((char)ival);
+                  len++;
+                  break;
+
+              case 'x':
+              case 'X':
+              {
+                  /* hexadecimal */
+                  unsigned int uval = va_arg(args, unsigned int);
+                  int loop;
+
+                  UNUSED(uval);
+
+                  if ((width == 0) || (width > 8))
+                      width = 8;
+
+                  for(loop = (width * 4); (loop != 0); loop -= 4)
+                  {
+                      CHAROUT(hextab[(uval >> (loop - 4)) & 0xF]);
+                      len++;
+                  }
+              }
+
+              break;
+
+              case 'd':
+                  /* decimal */
+                  ival = va_arg(args, int);
+
+                  if (ival < 0)
+                  {
+                      ival = -ival;
+                      CHAROUT('-');
+                      len++;
+                  }
+
+                  if (ival == 0)
+                  {
+                      CHAROUT('0');
+                      len++;
+                  }
+                  else
+                  {
+                      /*
+                       * The simplest method of displaying numbers is
+                       * to provide a small recursive routine, that
+                       * nests until the most-significant digit is
+                       * reached, and then falls back out displaying
+                       * individual digits. However, we want to avoid
+                       * using recursive code within the lo-level
+                       * parts of Angel (to minimise the stack
+                       * usage). The following number conversion is a
+                       * non-recursive solution.
+                       */
+                      char buffer[16]; /* stack space used to hold number */
+                      int count = 0; /* pointer into buffer */
+
+                      /*
+                       * Place the conversion into the buffer in
+                       * reverse order:
+                       */
+                      while (ival != 0)
+                      {
+                          buffer[count++] = ('0' + ((unsigned int)ival % 10));
+                          ival = ((unsigned int)ival / 10);
+                      }
+
+                      /*
+                       * Check if we are placing the data in a
+                       * fixed width field:
+                       */
+                      if (width != 0)
+                      {
+                          width -= count;
+
+                          for (; (width != 0); width--)
+                          {
+                              CHAROUT(padzero ? '0': ' ');
+                              len++;
+                          }
+                      }
+
+                      /* then display the buffer in reverse order */
+                      for (; (count != 0); count--)
+                      {
+                          CHAROUT(buffer[count - 1]);
+                          len++;
+                      }
+                  }
+
+                  break;
+
+              case 's':
+                  /* string */
+                  string = va_arg(args, char *);
+
+                  /* we only need this test once */
+                  if (string != NULL)
+                      /* whilst we check this for every character */
+                      while (*string)
+                      {
+                          CHAROUT(*string);
+                          len++;
+                          string++;
+
+                          /*
+                           * NOTE: We do not use "*string++" as the macro
+                           * parameter, since we do not know how many times
+                           *the parameter may be expanded within the macro.
+                           */
+                      }
+
+                  break;
+
+              case '\0':
+                  /*
+                   * string terminated by '%' character, bodge things
+                   * to prepare for default "format++" below
+                   */
+                  format--;
+
+                  break;
+
+              default:
+                  /* just display the character */
+                  CHAROUT(*format);
+                  len++;
+
+                  break;
+            }
+
+            format++; /* step over format character */
+        }
+        else
+        {
+            CHAROUT(*format);
+            len++;
+            format++;
+        }
+    }
+    return len;
+}
+
+/*
+ * this routine is simply here as a good breakpoint for dumping msg -
+ * can be used by DEBUG_METHOD macros or functions, if required.
+ */
+# ifdef DEBUG_NEED_VA_WARN1
+static void va_warn1(int len, char *msg)
+{
+    UNUSED(len); UNUSED(msg);
+}
+# endif
+
+void va_warn(WarnLevel level, char *format, va_list args)
+{
+    int len;
+
+    if ( PRE_DEBUG( level ) )
+    {
+        len = va_warn0(format, args);
+        POST_DEBUG( len );
+    }
+}
+
+#else /* ndef DEBUG */
+
+void va_warn(WarnLevel level, char *format, va_list args)
+{
+    UNUSED(level); UNUSED(format); UNUSED(args);
+}
+
+#endif /* ... else ndef(DEBUG) ... */
+#pragma check_stack
+
+#pragma no_check_stack
+void __rt_warning(char *format, ...)
+{
+    va_list args;
+
+    /*
+     * For a multi-threaded system we should provide a lock at this point
+     * to ensure that the warning messages are sequenced properly.
+     */
+
+    va_start(args, format);
+    va_warn(WL_WARN, format, args);
+    va_end(args);
+
+    return;
+}
+#pragma check_stack
+
+#ifdef TARGET
+
+#pragma no_check_stack
+void __rt_uninterruptable_loop( void ); /* in suppasm.s */
+
+void __rt_error(char *format, ...)
+{
+    va_list args;
+
+    va_start(args, format);
+
+    /* Display warning message */
+    va_warn(WL_ERROR, format, args);
+
+    __rt_uninterruptable_loop();
+
+    va_end(args);
+    return;
+}
+#pragma check_stack
+
+#endif /* def TARGET */
+
+#ifdef DO_TRACE
+
+static bool trace_on = FALSE; /* must be set true in debugger if req'd */
+
+#pragma no_check_stack
+void __rt_trace(char *format, ...)
+{
+    va_list args;
+
+    /*
+     * For a multi-threaded system we should provide a lock at this point
+     * to ensure that the warning messages are sequenced properly.
+     */
+
+    if (trace_on)
+    {
+        va_start(args, format);
+        va_warn(WL_TRACE, format, args);
+        va_end(args);
+    }
+
+    return;
+}
+#pragma check_stack
+
+#endif /* def DO_TRACE */
+
+
+/* EOF logging.c */
diff --git a/gdb/rdi-share/logging.h b/gdb/rdi-share/logging.h
new file mode 100644 (file)
index 0000000..97bf902
--- /dev/null
@@ -0,0 +1,121 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * logging.h - methods for logging warnings, errors and trace info
+ */
+
+#ifndef angel_logging_h
+#define angel_logging_h
+
+#include <stdarg.h>
+
+/*
+ * __rt_warning
+ * ------------
+ * Provides a standard method of generating run-time system
+ * warnings. The actual action taken by this code can be board or
+ * target application specific, e.g. internal logging, debug message,
+ * etc.
+ */
+extern void __rt_warning(char *format, ...);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * __rt_error
+ * ----------
+ * Raise an internal Angel error. The parameters are passed directly
+ * to "__rt_warning" for display, and the code then raises a debugger
+ * event and stops the target processing.
+ */
+extern void __rt_error(char *format, ...);
+
+/*
+ * Some macros for debugging and warning messages
+ */
+
+typedef enum WarnLevel {
+    WL_TRACE,
+    WL_WARN,
+    WL_ERROR
+} WarnLevel;
+
+void va_warn(WarnLevel level, char *format, va_list args);
+
+#ifdef _WINGDI_
+/* stupidity in MSVC <wingdi.h> (in <windows.h> in <winsock.h>) */
+# undef ERROR
+#endif
+
+#ifndef ERROR
+# define ERROR_FORMAT "Error \"%s\" in %s at line %d\n"
+# define ERROR(e) __rt_error(ERROR_FORMAT, (e), __FILE__, __LINE__)
+#endif
+
+#ifndef ASSERT
+# ifdef ASSERTIONS_ENABLED
+#   define ASSERT(x, y) ((x) ? (void)(0) : ERROR((y)))
+# else
+#   define ASSERT(x, y) ((void)(0))
+# endif
+#endif
+
+#ifndef WARN
+# ifdef ASSERTIONS_ENABLED
+#   define WARN_FORMAT "Warning \"%s\" in %s at line %d\n"
+#   define WARN(w) __rt_warning(WARN_FORMAT, (w), __FILE__, __LINE__)
+# else
+#   define WARN(w) ((void)(0))
+# endif
+#endif
+
+
+#ifdef NO_INFO_MESSAGES
+# define __rt_info (void)
+# ifndef INFO
+#   define INFO(w)
+# endif
+#else
+# define __rt_info __rt_warning
+# ifndef INFO
+#  ifdef DEBUG
+#   define INFO(w) __rt_warning("%s\n", (w))
+#  else
+#   define INFO(w) ((void)(0))
+#  endif
+# endif
+#endif
+
+
+#if defined(DEBUG) && !defined(NO_IDLE_CHITCHAT)
+# ifndef DO_TRACE
+#   define DO_TRACE (1)
+# endif
+#endif
+
+#ifdef DO_TRACE
+extern void __rt_trace(char *format, ...);
+#endif
+
+#ifndef TRACE
+# ifdef DO_TRACE
+#   define TRACE(w) __rt_trace("%s ", (w))
+# else
+#   define TRACE(w) ((void)(0))
+# endif
+#endif
+
+#endif /* ndef angel_logging_h */
+
+/* EOF logging.h */
diff --git a/gdb/rdi-share/msgbuild.c b/gdb/rdi-share/msgbuild.c
new file mode 100644 (file)
index 0000000..e2db2cc
--- /dev/null
@@ -0,0 +1,282 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * msgbuild.c - utilities for assembling and interpreting ADP messages
+ *
+ */
+
+#include <stdarg.h>     /* ANSI varargs support */
+
+#ifdef TARGET
+# include "angel.h"
+# include "devconf.h"
+#else
+# include "host.h"
+# include "hostchan.h"
+#endif
+
+#include "channels.h"
+#include "buffers.h"
+#include "endian.h"     /* Endianness support macros */
+#include "msgbuild.h"   /* Header file for this source code */
+
+#ifndef UNUSED
+# define UNUSED(x) ((x)=(x))
+#endif
+
+#ifndef TARGET
+
+extern unsigned int Armsd_BufferSize;
+
+#endif /* ndef TARGET */
+
+
+unsigned int vmsgbuild(unsigned char *buffer, const char *format, va_list args)
+{
+    unsigned int blen = 0;
+    int ch;
+
+    /* Step through the format string */
+    while ((ch = *format++) != '\0')
+    {
+        if (ch != '%')
+        {
+            if (buffer != NULL)
+                *buffer++ = (unsigned char)ch;
+
+            blen++;
+        }
+        else
+        {
+            switch (ch = *format++)
+            {
+              case 'w':
+              case 'W':
+              /* 32bit pointer */
+              case 'p':
+              case 'P':
+              {
+                  /* 32bit word / 32bit pointer */
+                  unsigned int na = va_arg(args, unsigned int);
+
+                  if (buffer != NULL)
+                  {
+                      PUT32LE(buffer, na);
+                      buffer += sizeof(unsigned int);
+                  }
+
+                  blen += sizeof(unsigned int);
+
+                  break;
+              }
+
+              case 'h':
+              case 'H':
+              {
+                  /* 16bit value */
+                  unsigned int na = va_arg(args, unsigned int);
+
+                  if (buffer != NULL)
+                  {
+                      PUT16LE(buffer, na);
+                      buffer += sizeof(unsigned short);
+                  }
+
+                  blen += sizeof(unsigned short);
+
+                  break;
+              }
+
+              case 'c':
+              case 'C':
+              case 'b':
+              case 'B':
+                  /* 8bit character / 8bit byte */
+                  ch = va_arg(args, int);
+
+                  /*
+                   * XXX
+                   *
+                   * fall through to the normal character processing
+                   */
+
+              case '%':
+              default:
+                  /* normal '%' character, or a different normal character */
+                  if (buffer != NULL)
+                      *buffer++ = (unsigned char)ch;
+
+                  blen++;
+                  break;
+            }
+        }
+    }
+
+    return blen;
+}
+
+/*
+ * msgbuild
+ * --------
+ * Simple routine to aid in construction of Angel messages. See the
+ * "msgbuild.h" header file for a detailed description of the operation
+ * of this routine.
+ */
+unsigned int msgbuild(unsigned char *buffer, const char *format, ...)
+{
+    va_list args;
+    unsigned int blen;
+
+    va_start(args, format);
+    blen = vmsgbuild(buffer, format, args);
+    va_end(args);
+
+    return blen;
+}
+
+#if !defined(JTAG_ADP_SUPPORTED) && !defined(MSG_UTILS_ONLY)
+/*
+ * This routine allocates a buffer, puts the data supplied as
+ * parameters into the buffer and sends the message. It does *NOT*
+ * wait for a reply.
+ */
+extern int msgsend(ChannelID chan, const char *format,...)
+{
+    unsigned int length;
+    p_Buffer buffer;
+    va_list args;
+# ifndef TARGET
+    Packet *packet;
+
+    packet = DevSW_AllocatePacket(Armsd_BufferSize);
+    buffer = packet->pk_buffer;
+# else
+    buffer = angel_ChannelAllocBuffer(Angel_ChanBuffSize);
+# endif
+
+    if (buffer != NULL)
+    {
+        va_start(args, format);
+
+        length = vmsgbuild(BUFFERDATA(buffer), format, args);
+
+# ifdef TARGET
+        angel_ChannelSend(CH_DEFAULT_DEV, chan, buffer, length);
+# else
+        packet->pk_length = length;
+        Adp_ChannelWrite(chan, packet);
+# endif
+
+        va_end(args);
+        return 0;
+    }
+    else
+        return -1;
+}
+
+#endif /* ndef JTAG_ADP_SUPPORTED && ndef MSG_UTILS_ONLY */
+
+/*
+ * unpack_message
+ * --------------
+ */
+extern unsigned int unpack_message(unsigned char *buffer, const char *format, ...)
+{
+    va_list args;
+    unsigned int blen = 0;
+    int ch;
+    char *chp = NULL;
+
+    va_start(args, format);
+
+    /* Step through the format string. */
+    while ((ch = *format++) != '\0')
+    {
+        if (ch != '%')
+        {
+            if (buffer != NULL)
+                ch = (unsigned char)*buffer++;
+
+            blen++;
+        }
+        else
+        {
+            switch (ch = *format++)
+            {
+              case 'w':
+              case 'W':
+              {
+                  /* 32bit word. */
+                  unsigned int *nap = va_arg(args, unsigned int*);
+
+                  if (buffer != NULL)
+                  {
+                      *nap = PREAD32(LE, buffer);
+                      buffer += sizeof(unsigned int);
+                  }
+
+                  blen += sizeof(unsigned int);
+
+                  break;
+              }
+
+              case 'h':
+              case 'H':
+              {
+                  /* 16bit value. */
+                  unsigned int *nap = va_arg(args, unsigned int*);
+
+                  if (buffer != NULL)
+                  {
+                      *nap = PREAD16(LE,buffer);
+                      buffer += sizeof(unsigned short);
+                  }
+
+                  blen += sizeof(unsigned short);
+
+                  break;
+              }
+
+              case 'c':
+              case 'C':
+              case 'b':
+              case 'B':
+                  /* 8-bit character, or 8-bit byte */
+                  chp = va_arg(args, char*);
+
+                  /*
+                   * XXX
+                   *
+                   * fall through to the normal character processing.
+                   */
+
+              case '%':
+              default:
+                  /* normal '%' character, or a different normal character */
+                  if (buffer != NULL)
+                      *chp = (unsigned char)*buffer++;
+
+                  blen++;
+
+                  break;
+            }
+        }
+    }
+
+    va_end(args);
+    return(blen);
+}
+
+
+/* EOF msgbuild.c */
diff --git a/gdb/rdi-share/msgbuild.h b/gdb/rdi-share/msgbuild.h
new file mode 100644 (file)
index 0000000..ac2436c
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * msgbuild.h - utilities for assembling and interpreting ADP messages
+ */
+
+#ifndef angel_msgbuild_h
+#define angel_msgbuild_h
+#include <stdarg.h>
+#include "channels.h"
+
+/*
+ * msgbuild
+ * --------
+ * We use a "varargs" function to enable a description of how the
+ * final message should look to be provided. We use a function rather
+ * than in-line macros to keep the size of Angel small.
+ *
+ * The "buffer" pointer is the starting point from where the data will
+ * be written. Note: If a NULL pointer is passed then no data will be
+ * written, but the size information will be returned. This allows
+ * code to call this routine with a NULL "buffer" pointer to ascertain
+ * whether the pointer they are passing contains enough space for the
+ * message being constructed.
+ *
+ * The "format" string should contain sequences of the following
+ * tokens:
+ *      %w - insert 32bit word value
+ *      %p - insert 32bit target pointer value
+ *      %h - insert 16bit value
+ *      %b - insert 8bit byte value
+ *
+ * The return parameter is the final byte length of the data written.
+ */
+unsigned int msgbuild(unsigned char *buffer, const char *format, ...);
+unsigned int vmsgbuild(unsigned char *buffer, const char *format,
+                       va_list args);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * msgsend
+ * -------
+ * As for msgbuild except that it allocates a buffer, formats the data as
+ * for msgbuild and transmits the packet. Returns 0 if successful non 0 if ot
+ * fails.
+ * Not for use on cooked channels e.g. debug channels only.
+ */
+extern int msgsend(ChannelID chan, const char *format, ...);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Unpack_message
+ * --------------
+ *    This basically does the opposite of msg_build, it takes a message, and
+ * a scanf type format string (but much cut down functionality) and returns
+ * the arguments in the message.
+ */
+extern unsigned int unpack_message(unsigned char *buffer, const char *format, ...);
+
+#endif /* ndef angel_msgbuild_h */
+
+/* EOF msgbuild.h */
diff --git a/gdb/rdi-share/params.c b/gdb/rdi-share/params.c
new file mode 100644 (file)
index 0000000..2c78188
--- /dev/null
@@ -0,0 +1,325 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Parameter negotiation utility functions
+ */
+
+#include "params.h"
+
+#include "endian.h"
+#include "logging.h"
+
+
+/*
+ * Function: Angel_FindParam
+ *  Purpose: find the value of a given parameter from a config.
+ *
+ * see params.h for details
+ */
+bool Angel_FindParam( ADP_Parameter          type,
+                      const ParameterConfig *config,
+                      unsigned int          *value )
+{
+    unsigned int i;
+
+    for ( i = 0; i < config->num_parameters; ++i )
+       if ( config->param[i].type == type )
+       {
+           *value = config->param[i].value;
+           return TRUE;
+       }
+
+    return FALSE;
+}
+
+
+#if !defined(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0
+
+ParameterList *Angel_FindParamList( const ParameterOptions *options,
+                                    ADP_Parameter           type )
+{
+    unsigned int i;
+
+    for ( i = 0; i < options->num_param_lists; ++i )
+       if ( options->param_list[i].type == type )
+          return &options->param_list[i];
+
+    return NULL;
+}
+
+
+#if defined(TARGET) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_MatchParams
+ *  Purpose: find a configuration from the requested options which is
+ *           the best match from the supported options.
+ *
+ * see params.h for details
+ */
+const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested,
+                                          const ParameterOptions *supported )
+{
+    static Parameter        chosen_params[AP_NUM_PARAMS];
+    static ParameterConfig  chosen_config = {
+        AP_NUM_PARAMS,
+        chosen_params
+    };
+    unsigned int i;
+
+    ASSERT( requested != NULL, "requested is NULL" );
+    ASSERT( requested != NULL, "requested is NULL" );
+    ASSERT( supported->num_param_lists <= AP_NUM_PARAMS, "supp_num too big" );
+
+    if ( requested->num_param_lists > supported->num_param_lists )
+    {
+        WARN( "req_num exceeds supp_num" );
+        return NULL;
+    }
+
+    for ( i = 0; i < requested->num_param_lists; ++i )
+    {
+        bool           match;
+        unsigned int   j;
+
+        const ParameterList *req_list = &requested->param_list[i];
+        ADP_Parameter        req_type = req_list->type;
+        const ParameterList *sup_list = Angel_FindParamList(
+                                            supported, req_type );
+
+        if ( sup_list == NULL )
+        {
+#ifdef ASSERTIONS_ENABLED
+            __rt_warning( "option %x not supported\n", req_type );
+#endif
+            return NULL;
+        }
+
+        for ( j = 0, match = FALSE;
+              (j < req_list->num_options) && !match;
+              ++j
+            )
+        {
+            unsigned int k;
+
+            for ( k = 0;
+                  (k < sup_list->num_options) && !match;
+                  ++k
+                )
+            {
+                if ( req_list->option[j] == sup_list->option[k] )
+                {
+#ifdef DEBUG
+                    __rt_info( "chose value %d for option %x\n",
+                               req_list->option[j], req_type );
+#endif
+                    match = TRUE;
+                    chosen_config.param[i].type = req_type;
+                    chosen_config.param[i].value = req_list->option[j];
+                }
+            }
+        }
+
+        if ( !match )
+        {
+#ifdef ASSERTIONS_ENABLED
+            __rt_warning( "no match found for option %x\n", req_type );
+#endif
+            return NULL;
+        }
+    }
+
+    chosen_config.num_parameters = i;
+    INFO( "match succeeded" );
+    return &chosen_config;
+}
+#endif /* defined(TARGET) || defined(TEST_PARAMS) */
+
+
+#if !defined(TARGET) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_StoreParam
+ *  Purpose: store the value of a given parameter to a config.
+ *
+ * see params.h for details
+ */
+bool Angel_StoreParam( ParameterConfig *config,
+                       ADP_Parameter    type,
+                       unsigned int     value )
+{
+    unsigned int i;
+
+    for ( i = 0; i < config->num_parameters; ++i )
+       if ( config->param[i].type == type )
+       {
+           config->param[i].value = value;
+           return TRUE;
+       }
+
+    return FALSE;
+}
+#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
+
+
+#if defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_BuildParamConfigMessage
+ *  Purpose: write a parameter config to a buffer in ADP format.
+ *
+ * see params.h for details
+ */
+unsigned int Angel_BuildParamConfigMessage( unsigned char         *buffer,
+                                            const ParameterConfig *config )
+{
+    unsigned char *start = buffer;
+    unsigned int i;
+
+    PUT32LE( buffer, config->num_parameters );
+    buffer += sizeof( word );
+
+    for ( i = 0; i < config->num_parameters; ++i )
+    {
+        PUT32LE( buffer, config->param[i].type );
+        buffer += sizeof( word );
+        PUT32LE( buffer, config->param[i].value );
+        buffer += sizeof( word );
+    }
+
+    return (buffer - start);
+}
+#endif /* defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
+
+
+#if !defined(TARGET) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_BuildParamOptionsMessage
+ *  Purpose: write a parameter Options to a buffer in ADP format.
+ *
+ * see params.h for details
+ */
+unsigned int Angel_BuildParamOptionsMessage( unsigned char          *buffer,
+                                             const ParameterOptions *options )
+{
+    unsigned char *start = buffer;
+    unsigned int i, j;
+
+    PUT32LE( buffer, options->num_param_lists );
+    buffer += sizeof( word );
+
+    for ( i = 0; i < options->num_param_lists; ++i )
+    {
+        PUT32LE( buffer, options->param_list[i].type );
+        buffer += sizeof( word );
+        PUT32LE( buffer, options->param_list[i].num_options );
+        buffer += sizeof( word );
+        for ( j = 0; j < options->param_list[i].num_options; ++j )
+        {
+            PUT32LE( buffer, options->param_list[i].option[j] );
+            buffer += sizeof( word );
+        }
+    }
+
+    return (buffer - start);
+}
+#endif /* !defined(TARGET) || defined(TEST_PARAMS) */
+
+
+#if !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_ReadParamConfigMessage
+ *  Purpose: read a parameter config from a buffer where it is in ADP format.
+ *
+ * see params.h for details
+ */
+bool Angel_ReadParamConfigMessage( const unsigned char *buffer,
+                                   ParameterConfig     *config )
+{
+    unsigned int word;
+    unsigned int i;
+
+    word = GET32LE( buffer );
+    buffer += sizeof( word );
+    if ( word > config->num_parameters )
+    {
+        WARN( "not enough space" );
+        return FALSE;
+    }
+    config->num_parameters = word;
+
+    for ( i = 0; i < config->num_parameters; ++i )
+    {
+        config->param[i].type = (ADP_Parameter)GET32LE( buffer );
+        buffer += sizeof( word );
+        config->param[i].value = GET32LE( buffer );
+        buffer += sizeof( word );
+    }
+
+    return TRUE;
+}
+#endif /* !defined(TARGET) || defined(LINK_RECOVERY) || defined(TEST_PARAMS) */
+
+
+#if defined(TARGET) || defined(TEST_PARAMS)
+/*
+ * Function: Angel_ReadParamOptionsMessage
+ *  Purpose: read a parameter options block from a buffer
+ *             where it is in ADP format.
+ *
+ * see params.h for details
+ */
+bool Angel_ReadParamOptionsMessage( const unsigned char *buffer,
+                                    ParameterOptions    *options )
+{
+    unsigned int word;
+    unsigned int i, j;
+
+    word = GET32LE( buffer );
+    buffer += sizeof( word );
+    if ( word > options->num_param_lists )
+    {
+        WARN( "not enough space" );
+        return FALSE;
+    }
+    options->num_param_lists = word;
+
+    for ( i = 0; i < options->num_param_lists; ++i )
+    {
+        ParameterList *list = &options->param_list[i];
+
+        list->type = (ADP_Parameter)GET32LE( buffer );
+        buffer += sizeof( word );
+        word = GET32LE( buffer );
+        buffer += sizeof( word );
+        if ( word > list->num_options )
+        {
+            WARN( "not enough list space" );
+            return FALSE;
+        }
+        list->num_options = word;
+
+        for ( j = 0; j < list->num_options; ++j )
+        {
+            list->option[j] = GET32LE( buffer );
+            buffer += sizeof( word );
+        }
+    }
+
+    return TRUE;
+}
+#endif /* defined(TARGET) || defined(TEST_PARAMS) */
+
+#endif /* !define(TARGET) || !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0 */
+
+/* EOF params.c */
diff --git a/gdb/rdi-share/params.h b/gdb/rdi-share/params.h
new file mode 100644 (file)
index 0000000..5b0757b
--- /dev/null
@@ -0,0 +1,181 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Parameter negotiation structures and utilities
+ */
+
+#ifndef angel_params_h
+#define angel_params_h
+
+#include "angel.h"
+#include "adp.h"
+
+#ifndef TARGET
+# include "host.h"
+#endif
+
+/* A single parameter, with tag */
+typedef struct Parameter {
+      ADP_Parameter     type;
+      unsigned int      value;
+} Parameter;
+
+/* A list of parameter values, with tag */
+typedef struct ParameterList {
+      ADP_Parameter     type;
+      unsigned int      num_options;
+      unsigned int     *option; /* points to array of values */
+} ParameterList;
+
+/* A configuration of one or more parameters */
+typedef struct ParameterConfig {
+      unsigned int      num_parameters;
+      Parameter        *param;  /* pointer to array of Parameters */
+} ParameterConfig;
+
+/* A set of parameter options */
+typedef struct ParameterOptions {
+      unsigned int      num_param_lists;
+      ParameterList    *param_list; /* pointer to array of ParamLists */
+} ParameterOptions;
+
+/*
+ * Function: Angel_MatchParams
+ *  Purpose: find a configuration from the requested options which is
+ *           the best match from the supported options.
+ *
+ *   Params:
+ *              Input: requested      The offered set of parameters.
+ *                     supported      The supported set of parameters.
+ *
+ *            Returns: ptr to config  A match has been made, ptr to result
+ *                                      will remain valid until next call to
+ *                                      this function.
+ *                     NULL           Match not possible
+ */
+const ParameterConfig *Angel_MatchParams( const ParameterOptions *requested,
+                                          const ParameterOptions *supported );
+
+/*
+ * Function: Angel_FindParam
+ *  Purpose: find the value of a given parameter from a config.
+ *
+ *   Params:
+ *              Input: type     parameter type to find
+ *                     config   config to search
+ *             Output: value    parameter value if found
+ *
+ *            Returns: TRUE     parameter found
+ *                     FALSE    parameter not found
+ */
+bool Angel_FindParam( ADP_Parameter          type,
+                      const ParameterConfig *config,
+                      unsigned int          *value );
+
+/*
+ * Function: Angel_StoreParam
+ *  Purpose: store the value of a given parameter in a config.
+ *
+ *   Params:
+ *             In/Out: config   config to store in
+ *              Input: type     parameter type to store
+ *                     value    parameter value if found
+ *
+ *            Returns: TRUE     parameter found and new value stored
+ *                     FALSE    parameter not found
+ */
+bool Angel_StoreParam( ParameterConfig *config,
+                       ADP_Parameter    type,
+                       unsigned int     value );
+
+/*
+ * Function: Angel_FindParamList
+ *  Purpose: find the parameter list of a given parameter from an options.
+ *
+ *   Params:
+ *              Input: type     parameter type to find
+ *                     options  options block to search
+ *
+ *            Returns: pointer to list
+ *                     NULL     parameter not found
+ */
+ParameterList *Angel_FindParamList( const ParameterOptions *options,
+                                    ADP_Parameter           type );
+
+/*
+ * Function: Angel_BuildParamConfigMessage
+ *  Purpose: write a parameter config to a buffer in ADP format.
+ *
+ *   Params:
+ *              Input: buffer   where to write to
+ *                     config   the parameter config to write
+ *
+ *            Returns: number of characters written to buffer
+ */
+unsigned int Angel_BuildParamConfigMessage( unsigned char         *buffer,
+                                            const ParameterConfig *config );
+
+/*
+ * Function: Angel_BuildParamOptionsMessage
+ *  Purpose: write a parameter Options to a buffer in ADP format.
+ *
+ *   Params:
+ *              Input: buffer   where to write to
+ *                     options  the options block to write
+ *
+ *            Returns: number of characters written to buffer
+ */
+unsigned int Angel_BuildParamOptionsMessage( unsigned char          *buffer,
+                                             const ParameterOptions *options );
+
+/*
+ * Function: Angel_ReadParamConfigMessage
+ *  Purpose: read a parameter config from a buffer where it is in ADP format.
+ *
+ *   Params:
+ *              Input: buffer   where to read from
+ *             In/Out: config   the parameter config to read to, which must
+ *                              be set up on entry with a valid array, and
+ *                              the size of the array in num_parameters.
+ *
+ *            Returns: TRUE     okay
+ *                     FALSE    not enough space in config
+ */
+bool Angel_ReadParamConfigMessage( const unsigned char *buffer,
+                                   ParameterConfig     *config );
+
+/*
+ * Function: Angel_ReadParamOptionsMessage
+ *  Purpose: read a parameter options from a buffer
+ *             where it is in ADP format.
+ *
+ *   Params:
+ *              Input: buffer   where to read from
+ *             In/Out: options  the parameter options block to read to, 
+ *                                which must be set up on entry with a valid
+ *                                array, and the size of the array in
+ *                                num_parameters.  Each param_list must
+ *                                also be set up in the same way.
+ *
+ *            Returns: TRUE     okay
+ *                     FALSE    not enough space in options
+ */
+bool Angel_ReadParamOptionsMessage( const unsigned char *buffer,
+                                    ParameterOptions    *options );
+
+#endif /* ndef angel_params_h */
+
+/* EOF params.h */
diff --git a/gdb/rdi-share/rx.c b/gdb/rdi-share/rx.c
new file mode 100644 (file)
index 0000000..4f434f0
--- /dev/null
@@ -0,0 +1,361 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*-*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title:  Character reception engine
+ */
+
+#include <stdarg.h>    /* ANSI varargs support */
+#include "angel.h"     /* Angel system definitions */
+#include "endian.h"    /* Endian independant memory access macros */
+#include "crc.h"       /* crc generation definitions and headers */
+#include "rxtx.h"
+#include "channels.h"
+#include "buffers.h"
+#ifdef TARGET
+#  include "devdriv.h"
+#endif
+#include "logging.h"
+
+static re_status unexp_stx(struct re_state *rxstate);
+static re_status unexp_etx(struct re_state *rxstate);
+
+/* bitfield for the rx_engine state */
+typedef enum rx_state_flag{
+  RST_STX,
+  RST_TYP,
+  RST_LEN,
+  RST_DAT,
+  RST_CRC,
+  RST_ETX,
+  RST_ESC = (0x1 << 0x3)
+} rx_state_flag;
+
+void Angel_RxEngineInit(const struct re_config *rxconfig,
+                        struct re_state *rxstate)
+{
+  rxstate->rx_state = RST_STX;
+  rxstate->field_c = 0;
+  rxstate->index = 0;
+  rxstate->crc = 0;
+  rxstate->error = RE_OKAY;
+  rxstate->config = rxconfig;
+}
+
+re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
+                         struct re_state *rxstate)
+{
+  /*
+   * TODO: add the flow control bits in
+   * Note: We test for the data field in a seperate case so we can
+   * completely avoid entering the switch for most chars
+   */
+
+  /* see if we're expecting a escaped char */
+  if ((rxstate->rx_state & RST_ESC) == RST_ESC)
+  {
+    /* unescape the char and unset the flag*/
+    new_ch &= ~serial_ESCAPE;
+#ifdef DO_TRACE
+    __rt_trace("rxe-echar-%2x ", new_ch);
+#endif
+    rxstate->rx_state &= ~RST_ESC;
+  }
+  else if ( (1 << new_ch) & rxstate->config->esc_set )
+  {
+    /* see if the incoming char is a special one */
+    if (new_ch == rxstate->config->esc)
+    {
+#ifdef DO_TRACE
+      __rt_trace("rxe-esc ");
+#endif
+      rxstate->rx_state |= RST_ESC;
+      return RS_IN_PKT;
+    }
+    else
+    {
+      /*
+       * must be a normal packet so do some unexpected etx/stx checking
+       * we haven't been told to escape or received an escape so unless
+       * we are expecting an stx or etx then we can take the unexpected 
+       * stx/etx trap
+       */
+      if ((new_ch == (rxstate->config->stx)) && (rxstate->rx_state != RST_STX))
+        return unexp_stx(rxstate);
+      if ((new_ch == (rxstate->config->etx)) && (rxstate->rx_state != RST_ETX))
+        return unexp_etx(rxstate);
+    }
+  }
+
+  if (rxstate->rx_state == RST_DAT)
+  {
+    /*
+     * do this to speed up the common case, no real penalty for
+     * other cases 
+     */
+#ifdef DO_TRACE
+    __rt_trace("rxe-dat ");
+#endif
+
+    rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
+    (packet->data)[rxstate->index++] = (unsigned int)new_ch & 0xff;
+
+    if (rxstate->index == packet->len)
+      rxstate->rx_state = RST_CRC;
+
+    return RS_IN_PKT;
+  }
+
+  /*
+   * Now that the common case is out of the way we can test for everything
+   * else without worrying quite so much about the speed, changing the
+   * order to len,crc,stx,etx,typ might gain a tiny bit of speed but lets
+   * leave that for the moment
+   */
+  switch (rxstate->rx_state)
+  {
+    case RST_STX:
+      if (new_ch == rxstate->config->stx)
+      {
+        rxstate->rx_state = RST_TYP;
+        rxstate->error = RE_OKAY;
+        rxstate->crc = startCRC32;
+        rxstate->index = 0;
+        return RS_IN_PKT;
+      }
+      else
+      {
+        rxstate->error = RE_OKAY;
+        return RS_WAIT_PKT;
+      }
+
+    case RST_TYP:
+      packet->type = (DevChanID)new_ch;
+      rxstate->rx_state = RST_LEN;
+      rxstate->error = RE_OKAY;
+      rxstate->field_c = 0; /* set up here for the length that follows */
+#ifdef DO_TRACE 
+      __rt_trace("rxe-type-%2x ", packet->type);
+#endif
+      rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
+
+      return RS_IN_PKT;
+
+    case RST_LEN:
+      rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
+
+      if (rxstate->field_c++ == 0)
+      {
+        /* first length byte */
+        packet->len = ((unsigned int)new_ch) << 8;
+        return RS_IN_PKT;
+      }
+      else
+      {
+        /* got the whole legth */
+        packet->len |= new_ch;
+#ifdef DO_TRACE
+        __rt_trace("rxe-len-%4x\n", packet->len);
+#endif
+
+        /* check that the length is ok */
+        if (packet->len == 0)
+        {
+          /* empty pkt */
+          rxstate->field_c = 0;
+          rxstate->rx_state = RST_CRC;
+          return RS_IN_PKT;
+        }
+        else
+        {
+          if (packet->data == NULL)
+          {
+            /* need to alloc the data buffer */
+            if (!rxstate->config->ba_callback(
+                packet, rxstate->config->ba_data)) {
+              rxstate->rx_state = RST_STX;
+              rxstate->error = RE_INTERNAL;
+              return RS_BAD_PKT;
+            }
+          }
+
+          if (packet->len > packet->buf_len)
+          {
+            /* pkt bigger than buffer */
+            rxstate->field_c = 0;
+            rxstate->rx_state = RST_STX;
+            rxstate->error = RE_LEN;
+            return RS_BAD_PKT;
+          }
+          else
+          {
+            /* packet ok */
+            rxstate->field_c = 0;
+            rxstate->rx_state = RST_DAT;
+            return RS_IN_PKT;
+          }
+        }
+      }
+
+    case RST_DAT:
+      /* dummy case (dealt with earlier) */
+#ifdef ASSERTIONS_ENABLED
+      __rt_warning("ERROR: hit RST_dat in switch\n");
+#endif
+      rxstate->rx_state = RST_STX;
+      rxstate->error = RE_INTERNAL;
+      return RS_BAD_PKT;
+
+    case RST_CRC:
+      if (rxstate->field_c == 0)
+        packet->crc = 0;
+
+      packet->crc |= (new_ch & 0xFF) << ((3 - rxstate->field_c) * 8);
+      rxstate->field_c++;
+
+      if (rxstate->field_c == 4)
+      {
+        /* last crc field */
+        rxstate->field_c = 0;
+        rxstate->rx_state = RST_ETX;
+#ifdef DO_TRACE
+        __rt_trace("rxe-rcrc-%8x ", packet->crc);
+#endif
+      }
+
+      return RS_IN_PKT;
+
+    case RST_ETX:
+      if (new_ch == rxstate->config->etx)
+      {
+#if defined(DEBUG) && !defined(NO_PKT_DATA)
+        {
+          int c;
+# ifdef DO_TRACE
+          __rt_trace("\n");
+# endif
+          __rt_info("RXE Data =");
+          for (c=0; c < packet->len; c++)
+            __rt_info("%02x", packet->data[c]);
+          __rt_info("\n"); 
+        }
+#endif
+
+        /* check crc */
+        if (rxstate->crc == packet->crc)
+        {
+          /* crc ok */
+          rxstate->rx_state = RST_STX;
+          rxstate->field_c = 0;
+          return RS_GOOD_PKT;
+        }
+        else
+        {
+#ifdef ASSERTIONS_ENABLED
+          __rt_warning("Bad crc, rx calculates it should be 0x%x\n", rxstate->crc);
+#endif
+          rxstate->rx_state = RST_STX;
+          rxstate->error = RE_CRC;
+          return RS_BAD_PKT;
+        }
+      }
+      else if (new_ch == rxstate->config->stx)
+        return unexp_stx(rxstate);
+      else
+      {
+        rxstate->rx_state = RST_STX;
+        rxstate->error = RE_NETX;
+        return RS_BAD_PKT;
+      }
+
+    default:
+#ifdef ASSERTIONS_ENABLED
+      __rt_warning("ERROR fell through rxengine\n");
+#endif
+      rxstate->rx_state = RST_STX;
+      rxstate->error = RE_INTERNAL;
+      return RS_BAD_PKT;
+  }
+}
+
+static re_status unexp_stx(struct re_state *rxstate)
+{
+#ifdef ASSERTIONS_ENABLED
+  __rt_warning("Unexpected stx\n");
+#endif
+  rxstate->crc = startCRC32;
+  rxstate->index = 0;
+  rxstate->rx_state = RST_TYP;
+  rxstate->error = RE_U_STX;
+  rxstate->field_c = 0;
+  return RS_BAD_PKT;
+}
+
+static re_status unexp_etx(struct re_state *rxstate)
+{
+#ifdef ASSERTIONS_ENABLED
+  __rt_warning("Unexpected etx, rxstate: index= 0x%2x, field_c=0x%2x, state=0x%2x\n", rxstate->index, rxstate->field_c, rxstate->rx_state);
+#endif
+  rxstate->crc = 0;
+  rxstate->index = 0;
+  rxstate->rx_state = RST_STX;
+  rxstate->error = RE_U_ETX;
+  rxstate->field_c = 0;
+  return RS_BAD_PKT;
+}
+
+/*
+ * This can be used as the buffer allocation callback for the rx engine,
+ * and makes use of angel_DD_GetBuffer() [in devdrv.h]. 
+ *
+ * Saves duplicating this callback function in every device driver that
+ * uses the rx engine.
+ *
+ * Note that this REQUIRES that the device id is installed as ba_data
+ * in the rx engine config structure for the driver.
+ */
+bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data )
+{
+#ifdef TARGET
+    DeviceID devid = (DeviceID)cb_data;
+#else
+    IGNORE(cb_data);
+#endif
+
+    if ( packet->type < DC_NUM_CHANNELS )
+    {
+        /* request a buffer down from the channels layer */
+#ifdef TARGET
+        packet->data = angel_DD_GetBuffer( devid, packet->type,
+                                           packet->len              );
+#else
+        packet->data = malloc(packet->len);
+#endif
+        if ( packet->data == NULL )
+           return FALSE;
+        else
+        {
+            packet->buf_len = packet->len;
+            return TRUE;
+        }
+    }
+    else
+    {
+        /* bad type field */
+        return FALSE;
+    }
+}
+
+/* EOF rx.c */
diff --git a/gdb/rdi-share/rxtx.h b/gdb/rdi-share/rxtx.h
new file mode 100644 (file)
index 0000000..204e998
--- /dev/null
@@ -0,0 +1,263 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*-*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *   Project: ANGEL
+ *
+ *     Title:  Definitions required for the rx and tx engines
+ */
+
+#ifndef angel_rxtx_h
+#define angel_rxtx_h
+
+
+/*
+ * we need a definition for bool, which is "system" dependent
+ */
+#ifdef TARGET
+# include "angel.h"
+#else
+# include "host.h"
+#endif
+
+#include "devclnt.h"
+
+/* return status codes for the rx engine */
+typedef enum re_status {
+  RS_WAIT_PKT,
+  RS_IN_PKT,
+  RS_BAD_PKT,
+  RS_GOOD_PKT
+} re_status;
+
+/* return status codes for the tx engine */
+typedef enum te_status {
+  TS_IDLE,
+  TS_IN_PKT,
+  TS_DONE_PKT
+} te_status;
+
+
+/*
+ * required serial definitions, they should all be <32, refer to the
+ * re_config struct comments for more details
+ */
+#define serial_STX    (0x1c) /* data packet start */
+#define serial_ETX    (0x1d) /* packet end */
+#define serial_ESC    (0x1b) /* standard escape character */
+#define serial_XON    (0x11) /* software flow control - enable transmission */
+#define serial_XOFF   (0x13) /* software flow control - disable transmission */
+
+/*
+ * All other characters are transmitted clean. If any of the above
+ * characters need to be transmitted as part of the serial data stream
+ * then the character will be preceded by the "serial_ESC" character,
+ * and then the required character transmitted (OR-ed with the
+ * "serial_ESCAPE" value, to ensure that the serial stream never has
+ * any of the exceptional characters generated by data transfers).
+ */
+
+#define serial_ESCAPE   (0x40)  /* OR-ed with escaped characters */
+
+/* bad packet error codes */
+typedef enum re_error {
+  RE_OKAY,
+  RE_U_STX,
+  RE_U_ETX,
+  RE_LEN,
+  RE_CRC,
+  RE_NETX,
+  RE_INTERNAL
+} re_error;
+
+/* a decoded packet */
+struct data_packet {
+  unsigned short  buf_len;      /* should be set by caller */
+  DevChanID       type;         /* valid when status is RS_GOOD_PKT */
+  unsigned short  len;          /* --"--                            */
+  unsigned int    crc;          /* crc for the unescaped pkt */
+  unsigned char   *data;        /* should be set by caller */
+};
+
+/*
+ * Purpose: typedef for flow control function
+ *
+ *  Params:
+ *          Input:  fc_char  the flow control character in question
+ *          In/Out: cb_data  callback data as set in the fc_data
+ *                             field of re_config, typically device id
+ *
+ * This callback would tpyically respond to received XON and XOFF
+ * characters by controlling the transmit side of the device.
+ */
+typedef void (*fc_cb_func)(char fc_char, void *cb_data);
+
+
+/*
+ * Purpose: typedef for the function to alloc the data buffer 
+ *
+ *  Params:
+ *          In/Out: packet    the data packet: len and type will be set on
+ *                              entry, and buf_len and data should
+ *                              be set by this routine if successful.
+ *                  cb_data   callback data as set in the ba_data
+ *                              field of re_config, typically device id
+ *
+ *         Returns: TRUE      buffer allocated okay
+ *                  FALSE     couldn't allocate buffer of required size
+ *                              for given type
+ *
+ * This callback should attempt to acquire a buffer for the data portion
+ * of the packet which is currently being received, based on the len and 
+ * type fields supplied in packet.
+ *
+ * angel_DD_RxEng_BufferAlloc() is supplied for use as this callback,
+ * and will be sufficient for most devices.
+ */
+typedef bool (*BufferAlloc_CB_Fn)(struct data_packet *packet, void *cb_data);
+
+
+/*
+ * The static info needed by the engine, may vary per device.
+ *
+ * fc_set and esc_set are bitmaps, e.g. bit 3 == charcode 3 == ASCII ETX.
+ * Thus any of the first 32 charcodes can be set for flow control or to
+ * be escaped.
+ * 
+ * Note that esc_set should include all of fc_set, and should have bits
+ * set for stx, etx and esc, as a minimum.
+ *
+ * If character codes > 31 need to be used then fc_set and esc_set
+ * and their handling can be extended to use arrays and bit manipulation
+ * macros, potentially up to the full 256 possible chars.
+ *
+ * Note too that this could/should be shared with the tx engine.
+ */
+
+struct re_config {
+  unsigned char     stx;                  /* the STX char for this device */
+  unsigned char     etx;                  /* the ETX --"--                */
+  unsigned char     esc;                  /* the ESC --"--                */
+  unsigned int      fc_set;               /* bitmap of flow control chars */
+  unsigned int      esc_set;              /* bitmap of special chars      */
+  fc_cb_func        fc_callback;          /* flow control callback func   */
+  void              *fc_data;             /* data to pass to fc_callback  */
+  BufferAlloc_CB_Fn ba_callback;          /* buffer alloc callback        */
+  void              *ba_data;             /* data to pass to ba_calback   */
+};
+
+/* the dynamic info needed by the rx engine */
+struct re_state {
+  unsigned char          rx_state; /* 3 bits pkt state, 1 prepro state */
+  unsigned short         field_c;  /* chars left in current field */
+  unsigned short         index;    /* index into buffer */
+  unsigned int           crc;      /* crc accumulator */
+  re_error               error;    /* valid only if status is RS_BAD_PKT */
+  const struct re_config *config;  /* pointer to static config */
+};
+
+/* dynamic state info needed by the tx engine */
+struct te_state {
+  unsigned short         field_c;  /* position in current field */
+  unsigned char          tx_state; /* encodes n,e, and f (2+1+2=5 bits) */
+  unsigned char          encoded;  /* escape-encoded char for transmission */
+  const struct re_config *config;  /* pointer to static config */
+  unsigned int           crc;      /* space for CRC (before escaping) */
+};
+
+/*
+ * Function: Angel_RxEngineInit
+ *  Purpose: Initialise state (during device init) for engine.
+ *
+ *   Params:
+ *              Input: config   static config info
+ *             In/Out: state    internal state
+ */
+
+void Angel_RxEngineInit(const struct re_config *config,
+                        struct re_state *state);
+
+/*
+ * Function: Angel_RxEngine
+ *  Purpose: Rx Engine for character-based devices
+ *
+ *   Params:
+ *              Input: new_ch       the latest character
+ *
+ *             In/Out: packet       details of packet
+ *                                   packet.buf_len and packet.data must
+ *                                   be set on entry!
+ *                     state        internal state, intially set by
+ *                                   angel_RxEngineInit()
+ *
+ *            Returns: re_status (see above)
+ *
+ */
+
+re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
+                         struct re_state *state);
+
+/*
+ * This can be used as the buffer allocation callback for the rx engine,
+ * and will make use of angel_DD_GetBuffer() [in devdrv.h]. 
+ *
+ * Saves duplicating this callback function in every device driver that
+ * uses the rx engine.
+ *
+ * Note that this REQUIRES that the device id is installed as ba_data
+ * in the rx engine config structure for the driver.
+ */
+bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data );
+
+/*
+ * Function: Angel_TxEngineInit
+ *  Purpose: Set up tx engine at start of new packet, calculate CRC etc.
+ *           (This should perform the actions described under
+ *             "Initialisation" above)
+ *
+ *   Params:
+ *              Input: config   static config info
+ *                     packet   the packet to transmit
+ *             In/Out: state    internal state
+ */
+
+void Angel_TxEngineInit(const struct re_config   *config,
+                        const struct data_packet *packet, 
+                        struct te_state    *state);
+
+/*
+ * Function: Angel_TxEngine
+ *  Purpose: Tx Engine for character-based devices
+ *
+ *   Params:
+ *              Input: packet       details of packet
+ *                                   packet.len, packet.data and
+ *                                   packet.type must
+ *                                   be set on entry!
+ *             In/Out: state        internal state, intially set by
+ *                                   angel_TxEngineStart()
+ *             Output: tx_ch        the character to be transmitted 
+ *                                   (NOT SET if return code is TS_IDLE)
+ *
+ *            Returns: te_status (see above)
+ */
+
+te_status Angel_TxEngine(const struct data_packet  *packet,
+                         struct te_state *state,
+                         unsigned char *tx_ch);
+
+
+
+#endif /* !defined(angel_rxtx_h) */
+
+/*  EOF rxtx.h */
diff --git a/gdb/rdi-share/serdrv.c b/gdb/rdi-share/serdrv.c
new file mode 100644 (file)
index 0000000..43fd5a0
--- /dev/null
@@ -0,0 +1,649 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * serdrv.c - Synchronous Serial Driver for Angel.
+ *            This is nice and simple just to get something going.
+ */
+
+#ifdef __hpux
+#  define _POSIX_SOURCE 1
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crc.h"
+#include "devices.h"
+#include "buffers.h"
+#include "rxtx.h"
+#include "hostchan.h"
+#include "params.h"
+#include "logging.h"
+
+#ifdef COMPILING_ON_WINDOWS
+#  undef   ERROR
+#  undef   IGNORE
+#  include <windows.h>
+#  include "angeldll.h"
+#  include "comb_api.h"
+#else
+#  ifdef __hpux
+#    define _TERMIOS_INCLUDED
+#    include <sys/termio.h>
+#    undef _TERMIOS_INCLUDED
+#  else
+#    include <termios.h>
+#  endif
+#  include "unixcomm.h"
+#endif
+
+#ifndef UNUSED
+#  define UNUSED(x) (x = x)      /* Silence compiler warnings */
+#endif
+#define MAXREADSIZE 512
+#define MAXWRITESIZE 512
+
+#define SERIAL_FC_SET  ((1<<serial_XON)|(1<<serial_XOFF))
+#define SERIAL_CTL_SET ((1<<serial_STX)|(1<<serial_ETX)|(1<<serial_ESC))
+#define SERIAL_ESC_SET (SERIAL_FC_SET|SERIAL_CTL_SET)
+
+static const struct re_config config = {
+    serial_STX, serial_ETX, serial_ESC, /* self-explanatory?               */
+    SERIAL_FC_SET,                      /* set of flow-control characters  */
+    SERIAL_ESC_SET,                     /* set of characters to be escaped */
+    NULL /* serial_flow_control */, NULL  ,    /* what to do with FC chars */
+    angel_DD_RxEng_BufferAlloc, NULL                /* how to get a buffer */
+};
+
+static struct re_state rxstate;
+
+typedef struct writestate {
+  unsigned int wbindex;
+  /*  static te_status testatus;*/
+  unsigned char writebuf[MAXWRITESIZE];
+  struct te_state txstate;
+} writestate;
+
+static struct writestate wstate;
+
+/*
+ * The set of parameter options supported by the device
+ */
+static unsigned int baud_options[] = {
+#ifdef __hpux
+    115200, 57600, 
+#endif
+    38400, 19200, 9600
+};
+
+static ParameterList param_list[] = {
+    { AP_BAUD_RATE,
+      sizeof(baud_options)/sizeof(unsigned int),
+      baud_options }
+};
+
+static const ParameterOptions serial_options = {
+    sizeof(param_list)/sizeof(ParameterList), param_list };
+
+/* 
+ * The default parameter config for the device
+ */
+static Parameter param_default[] = {
+    { AP_BAUD_RATE, 9600 }
+};
+
+static ParameterConfig serial_defaults = {
+    sizeof(param_default)/sizeof(Parameter), param_default };
+
+/*
+ * The user-modified options for the device
+ */
+static unsigned int user_baud_options[sizeof(baud_options)/sizeof(unsigned)];
+
+static ParameterList param_user_list[] = {
+    { AP_BAUD_RATE,
+      sizeof(user_baud_options)/sizeof(unsigned),
+      user_baud_options }
+};
+
+static ParameterOptions user_options = {
+    sizeof(param_user_list)/sizeof(ParameterList), param_user_list };
+
+static bool user_options_set;
+
+/* forward declarations */
+static int serial_reset( void );
+static int serial_set_params( const ParameterConfig *config );
+static int SerialMatch(const char *name, const char *arg);
+
+static void process_baud_rate( unsigned int target_baud_rate )
+{
+    const ParameterList *full_list;
+    ParameterList       *user_list;
+
+    /* create subset of full options */
+    full_list = Angel_FindParamList( &serial_options, AP_BAUD_RATE );
+    user_list = Angel_FindParamList( &user_options,   AP_BAUD_RATE );
+
+    if ( full_list != NULL && user_list != NULL )
+    {
+        unsigned int i, j;
+        unsigned int def_baud = 0;
+
+        /* find lower or equal to */
+        for ( i = 0; i < full_list->num_options; ++i )
+           if ( target_baud_rate >= full_list->option[i] )
+           {
+               /* copy remaining */
+               for ( j = 0; j < (full_list->num_options - i); ++j )
+                  user_list->option[j] = full_list->option[i+j];
+               user_list->num_options = j;
+
+               /* check this is not the default */
+               Angel_FindParam( AP_BAUD_RATE, &serial_defaults, &def_baud );
+               if ( (j == 1) && (user_list->option[0] == def_baud) )
+               {
+#ifdef DEBUG
+                   printf( "user selected default\n" );
+#endif
+               }
+               else
+               {
+                   user_options_set = TRUE;
+#ifdef DEBUG
+                   printf( "user options are: " );
+                   for ( j = 0; j < user_list->num_options; ++j )
+                      printf( "%u ", user_list->option[j] );
+                   printf( "\n" );
+#endif
+               }
+
+               break;   /* out of i loop */
+           }
+                
+#ifdef DEBUG
+        if ( i >= full_list->num_options )
+           printf( "couldn't match baud rate %u\n", target_baud_rate );
+#endif
+    }
+#ifdef DEBUG
+    else
+       printf( "failed to find lists\n" );
+#endif
+}
+
+static int SerialOpen(const char *name, const char *arg)
+{
+    const char *port_name = name;
+
+#ifdef DEBUG
+    printf("SerialOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+    if (IsOpenSerial()) return -1;
+#else
+    if (Unix_IsSerialInUse()) return -1;
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+    if (SerialMatch(name, arg) != adp_ok)
+        return adp_failed;
+#else
+    port_name = Unix_MatchValidSerialDevice(port_name);
+# ifdef DEBUG
+    printf("translated port to %s\n", port_name == 0 ? "NULL" : port_name);
+# endif
+    if (port_name == 0) return adp_failed;
+#endif
+
+    user_options_set = FALSE;
+
+    /* interpret and store the arguments */
+    if ( arg != NULL )
+    {
+        unsigned int target_baud_rate;
+        target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
+        if (target_baud_rate > 0)
+        {
+#ifdef DEBUG
+            printf( "user selected baud rate %u\n", target_baud_rate );
+#endif
+            process_baud_rate( target_baud_rate );
+        }
+#ifdef DEBUG
+        else
+           printf( "could not understand baud rate %s\n", arg );
+#endif
+    }
+
+#ifdef COMPILING_ON_WINDOWS
+    {
+        int port = IsValidDevice(name);
+        if (OpenSerial(port, FALSE) != COM_OK)
+            return -1;
+    }
+#else
+    if (Unix_OpenSerial(port_name) < 0)
+      return -1;
+#endif
+
+    serial_reset();
+
+#if defined(__unix) || defined(__CYGWIN32__)
+    Unix_ioctlNonBlocking();
+#endif
+
+    Angel_RxEngineInit(&config, &rxstate);
+    /*
+     * DANGER!: passing in NULL as the packet is ok for now as it is just
+     * IGNOREd but this may well change
+     */
+    Angel_TxEngineInit(&config, NULL, &wstate.txstate); 
+    return 0;
+}
+
+static int SerialMatch(const char *name, const char *arg)
+{
+    UNUSED(arg);
+#ifdef COMPILING_ON_WINDOWS
+    if (IsValidDevice(name) == COM_DEVICENOTVALID)
+        return -1;
+    else
+        return 0;
+#else
+    return Unix_MatchValidSerialDevice(name) == 0 ? -1 : 0;
+#endif
+}
+
+static void SerialClose(void)
+{
+#ifdef DO_TRACE
+    printf("SerialClose()\n");
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+    CloseSerial();
+#else
+    Unix_CloseSerial();
+#endif
+}
+
+static int SerialRead(DriverCall *dc, bool block) {
+  static unsigned char readbuf[MAXREADSIZE];
+  static int rbindex=0;
+
+  int nread;
+  int read_errno;
+  int c=0;
+  re_status restatus;
+  int ret_code = -1;            /* assume bad packet or error */
+
+  /* must not overflow buffer and must start after the existing data */
+#ifdef COMPILING_ON_WINDOWS
+  {
+    BOOL dummy = FALSE;
+    nread = BytesInRXBufferSerial();
+
+    if (nread > MAXREADSIZE - rbindex)
+      nread = MAXREADSIZE - rbindex;
+
+    if ((read_errno = ReadSerial(readbuf+rbindex, nread, &dummy)) == COM_READFAIL)
+    {
+        MessageBox(GetFocus(), "Read error\n", "Angel", MB_OK | MB_ICONSTOP);
+        return -1;   /* SJ - This really needs to return a value, which is picked up in */
+                     /*      DevSW_Read as meaning stop debugger but don't kill. */
+    }
+    else if (pfnProgressCallback != NULL && read_errno == COM_OK)
+    {
+      progressInfo.nRead += nread;
+      (*pfnProgressCallback)(&progressInfo);
+    }
+  }
+#else
+  nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
+  read_errno = errno;
+#endif
+
+  if ((nread > 0) || (rbindex > 0)) {
+
+#ifdef DO_TRACE
+    printf("[%d@%d] ", nread, rbindex);
+#endif
+
+    if (nread>0)
+       rbindex = rbindex+nread;
+
+    do {
+      restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
+#ifdef DO_TRACE
+      printf("<%02X ",readbuf[c]);
+      if (!(++c % 16))
+          printf("\n");
+#else
+      c++;
+#endif
+    } while (c<rbindex &&
+             ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
+
+#ifdef DO_TRACE
+   if (c % 16)
+        printf("\n");
+#endif
+
+    switch(restatus) {
+      
+      case RS_GOOD_PKT:
+        ret_code = 1;
+        /* fall through to: */
+
+      case RS_BAD_PKT:
+        /*
+         * We now need to shuffle any left over data down to the
+         * beginning of our private buffer ready to be used 
+         *for the next packet 
+         */
+#ifdef DO_TRACE
+        printf("SerialRead() processed %d, moving down %d\n", c, rbindex-c);
+#endif
+        if (c != rbindex) memmove((char *) readbuf, (char *) (readbuf+c),
+                                  rbindex-c);
+        rbindex -= c;
+        break;
+
+      case RS_IN_PKT:
+      case RS_WAIT_PKT:
+        rbindex = 0;            /* will have processed all we had */
+        ret_code = 0;
+        break;
+
+      default:
+#ifdef DEBUG
+        printf("Bad re_status in serialRead()\n");
+#endif
+        break;
+    }
+  } else if (nread == 0)
+    ret_code = 0;               /* nothing to read */
+  else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
+    ret_code = 0;
+
+#ifdef DEBUG
+  if ((nread<0) && (read_errno!=ERRNO_FOR_BLOCKED_IO))
+    perror("read() error in serialRead()");
+#endif
+
+  return ret_code;
+}
+
+
+static int SerialWrite(DriverCall *dc) {
+  int nwritten = 0;
+  te_status testatus = TS_IN_PKT;
+
+  if (dc->dc_context == NULL) {
+    Angel_TxEngineInit(&config, &(dc->dc_packet), &(wstate.txstate));
+    wstate.wbindex = 0;
+    dc->dc_context = &wstate;
+  }
+
+  while ((testatus == TS_IN_PKT) && (wstate.wbindex < MAXWRITESIZE))
+  {
+    /* send the raw data through the tx engine to escape and encapsulate */
+    testatus = Angel_TxEngine(&(dc->dc_packet), &(wstate.txstate),
+                              &(wstate.writebuf)[wstate.wbindex]);
+    if (testatus != TS_IDLE) wstate.wbindex++;
+  }
+
+  if (testatus == TS_IDLE) {
+#ifdef DEBUG
+    printf("SerialWrite: testatus is TS_IDLE during preprocessing\n");
+#endif
+  }
+
+#ifdef DO_TRACE
+  { 
+    int i = 0;
+
+    while (i<wstate.wbindex)
+    {
+        printf(">%02X ",wstate.writebuf[i]);
+
+        if (!(++i % 16))
+            printf("\n");
+    }
+    if (i % 16)
+        printf("\n");
+  }
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+  if (WriteSerial(wstate.writebuf, wstate.wbindex) == COM_OK)
+  {
+    nwritten = wstate.wbindex;
+    if (pfnProgressCallback != NULL)
+    {
+      progressInfo.nWritten += nwritten;
+      (*pfnProgressCallback)(&progressInfo);
+    }
+  }
+  else
+  {
+      MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
+      return -1;   /* SJ - This really needs to return a value, which is picked up in */
+                   /*      DevSW_Read as meaning stop debugger but don't kill. */
+  }
+#else
+  nwritten = Unix_WriteSerial(wstate.writebuf, wstate.wbindex);
+
+  if (nwritten < 0) {
+    nwritten=0;
+  }
+#endif
+
+#ifdef DEBUG
+  if (nwritten > 0)
+    printf("Wrote %#04x bytes\n", nwritten);
+#endif
+
+  if ((unsigned) nwritten == wstate.wbindex && 
+      (testatus == TS_DONE_PKT || testatus == TS_IDLE)) {
+
+    /* finished sending the packet */
+
+#ifdef DEBUG
+    printf("SerialWrite: calling Angel_TxEngineInit after sending packet (len=%i)\n",wstate.wbindex);
+#endif
+    testatus = TS_IN_PKT;
+    wstate.wbindex = 0;
+    return 1;
+  }
+  else {
+#ifdef DEBUG
+    printf("SerialWrite: Wrote part of packet wbindex=%i, nwritten=%i\n",
+           wstate.wbindex, nwritten);
+#endif
+   
+    /*
+     *  still some data left to send shuffle whats left down and reset
+     * the ptr
+     */
+    memmove((char *) wstate.writebuf, (char *) (wstate.writebuf+nwritten),
+            wstate.wbindex-nwritten);
+    wstate.wbindex -= nwritten;
+    return 0;
+  }
+  return -1;
+}
+
+
+static int serial_reset( void )
+{
+#ifdef DEBUG
+    printf( "serial_reset\n" );
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+    FlushSerial();
+#else
+    Unix_ResetSerial();
+#endif
+
+    return serial_set_params( &serial_defaults );
+}
+
+
+static int find_baud_rate( unsigned int *speed )
+{
+    static struct {
+          unsigned int baud;
+          int termiosValue;
+    } possibleBaudRates[] = {
+#if defined(__hpux)
+        {115200,_B115200}, {57600,_B57600},
+#endif
+#ifdef COMPILING_ON_WINDOWS
+        {38400,CBR_38400}, {19200,CBR_19200}, {9600, CBR_9600}, {0,0}
+#else
+        {38400,B38400}, {19200,B19200}, {9600, B9600}, {0,0}
+#endif
+    };
+    unsigned int i;
+
+    /* look for lower or matching -- will always terminate at 0 end marker */
+    for ( i = 0; possibleBaudRates[i].baud > *speed; ++i )
+       /* do nothing */ ;
+
+    if ( possibleBaudRates[i].baud > 0 )
+       *speed = possibleBaudRates[i].baud;
+
+    return possibleBaudRates[i].termiosValue;
+}
+
+
+static int serial_set_params( const ParameterConfig *config )
+{
+    unsigned int speed;
+    int termios_value;
+
+#ifdef DEBUG
+    printf( "serial_set_params\n" );
+#endif
+
+    if ( ! Angel_FindParam( AP_BAUD_RATE, config, &speed ) )
+    {
+#ifdef DEBUG
+        printf( "speed not found in config\n" );
+#endif
+        return DE_OKAY;
+    }
+
+    termios_value = find_baud_rate( &speed );
+    if ( termios_value == 0 )
+    {
+#ifdef DEBUG
+        printf( "speed not valid: %u\n", speed );
+#endif
+        return DE_OKAY;
+    }
+
+#ifdef DEBUG
+    printf( "setting speed to %u\n", speed );
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+    SetBaudRate((WORD)termios_value);
+#else
+    Unix_SetSerialBaudRate(termios_value);
+#endif
+
+    return DE_OKAY;
+}
+
+
+static int serial_get_user_params( ParameterOptions **p_options )
+{
+#ifdef DEBUG
+    printf( "serial_get_user_params\n" );
+#endif
+
+    if ( user_options_set )
+    {
+        *p_options = &user_options;
+    }
+    else
+    {
+        *p_options = NULL;
+    }
+
+    return DE_OKAY;
+}
+
+
+static int serial_get_default_params( ParameterConfig **p_config )
+{
+#ifdef DEBUG
+    printf( "serial_get_default_params\n" );
+#endif
+
+    *p_config = (ParameterConfig *) &serial_defaults;
+    return DE_OKAY;
+}
+
+
+static int SerialIoctl(const int opcode, void *args) {
+
+    int ret_code;
+
+#ifdef DEBUG
+    printf( "SerialIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
+#endif
+
+    switch (opcode)
+    {
+       case DC_RESET:         
+           ret_code = serial_reset();
+           break;
+
+       case DC_SET_PARAMS:     
+           ret_code = serial_set_params((const ParameterConfig *)args);
+           break;
+
+       case DC_GET_USER_PARAMS:     
+           ret_code = serial_get_user_params((ParameterOptions **)args);
+           break;
+
+       case DC_GET_DEFAULT_PARAMS:
+           ret_code = serial_get_default_params((ParameterConfig **)args);
+           break;
+
+       default:               
+           ret_code = DE_BAD_OP;
+           break;
+    }
+
+  return ret_code;
+}
+
+DeviceDescr angel_SerialDevice = {
+    "SERIAL",
+    SerialOpen,
+    SerialMatch,
+    SerialClose,
+    SerialRead,
+    SerialWrite,
+    SerialIoctl
+};
diff --git a/gdb/rdi-share/serpardr.c b/gdb/rdi-share/serpardr.c
new file mode 100644 (file)
index 0000000..604d048
--- /dev/null
@@ -0,0 +1,730 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ * serpardv.c - Serial/Parallel Driver for Angel.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crc.h"
+#include "devices.h"
+#include "buffers.h"
+#include "rxtx.h"
+#include "hostchan.h"
+#include "params.h"
+#include "logging.h"
+#include "hsys.h"
+
+#ifdef COMPILING_ON_WINDOWS
+#  undef   ERROR
+#  undef   IGNORE
+#  include <windows.h>
+#  include "angeldll.h"
+#  include "comb_api.h"
+#else
+#  ifdef __hpux
+#    define _TERMIOS_INCLUDED
+#    include <sys/termio.h>
+#    undef _TERMIOS_INCLUDED
+#  else
+#    include <termios.h>
+#  endif
+#  include "unixcomm.h"
+#endif
+
+#ifndef UNUSED
+#  define UNUSED(x) (x = x)     /* Silence compiler warnings */
+#endif
+
+#define MAXREADSIZE     512
+#define MAXWRITESIZE    512
+
+#define SERPAR_FC_SET  ((1 << serial_XON) | (1 << serial_XOFF))
+#define SERPAR_CTL_SET ((1 << serial_STX) | (1 << serial_ETX) | \
+                        (1 << serial_ESC))
+#define SERPAR_ESC_SET (SERPAR_FC_SET | SERPAR_CTL_SET)
+
+static const struct re_config config = {
+    serial_STX, serial_ETX, serial_ESC, /* self-explanatory?               */
+    SERPAR_FC_SET,                      /* set of flow-control characters  */
+    SERPAR_ESC_SET,                     /* set of characters to be escaped */
+    NULL,                               /* serial_flow_control */
+    NULL,                               /* what to do with FC chars */
+    angel_DD_RxEng_BufferAlloc, NULL    /* how to get a buffer */
+};
+
+static struct re_state rxstate;
+
+/*
+ * structure used for manipulating transmit data
+ */
+typedef struct TxState
+{
+    struct te_state state;
+    unsigned int    index;
+    unsigned char   writebuf[MAXWRITESIZE];
+} TxState;
+
+/*
+ * The set of parameter options supported by the device
+ */
+static unsigned int baud_options[] =
+{
+#ifdef __hpux
+    115200, 57600,
+#endif
+    38400, 19200, 9600
+};
+
+static ParameterList param_list[] =
+{
+    {
+        AP_BAUD_RATE,
+        sizeof(baud_options) / sizeof(unsigned int),
+        baud_options
+    }
+};
+
+static const ParameterOptions serpar_options =
+{
+    sizeof(param_list) / sizeof(ParameterList),
+    param_list
+};
+
+/*
+ * The default parameter config for the device
+ */
+static Parameter param_default[] =
+{
+    { AP_BAUD_RATE, 9600 }
+};
+
+static const ParameterConfig serpar_defaults =
+{
+    sizeof(param_default)/sizeof(Parameter),
+    param_default
+};
+
+/*
+ * The user-modified options for the device
+ */
+static unsigned int user_baud_options[sizeof(baud_options) /
+                                     sizeof(unsigned int)];
+
+static ParameterList param_user_list[] =
+{
+    {
+        AP_BAUD_RATE,
+        sizeof(user_baud_options) / sizeof(unsigned),
+        user_baud_options
+    }
+};
+
+static ParameterOptions user_options =
+{
+    sizeof(param_user_list) / sizeof(ParameterList),
+    param_user_list
+};
+
+static bool user_options_set;
+
+/* forward declarations */
+static int serpar_reset(void);
+static int serpar_set_params(const ParameterConfig *config);
+static int SerparMatch(const char *name, const char *arg);
+
+static void process_baud_rate(unsigned int target_baud_rate)
+{
+    const ParameterList *full_list;
+    ParameterList       *user_list;
+
+    /* create subset of full options */
+    full_list = Angel_FindParamList(&serpar_options, AP_BAUD_RATE);
+    user_list = Angel_FindParamList(&user_options,   AP_BAUD_RATE);
+
+    if (full_list != NULL && user_list != NULL)
+    {
+        unsigned int i, j;
+        unsigned int def_baud = 0;
+
+        /* find lower or equal to */
+        for (i = 0; i < full_list->num_options; ++i)
+           if (target_baud_rate >= full_list->option[i])
+           {
+               /* copy remaining */
+               for (j = 0; j < (full_list->num_options - i); ++j)
+                  user_list->option[j] = full_list->option[i+j];
+               user_list->num_options = j;
+
+               /* check this is not the default */
+               Angel_FindParam(AP_BAUD_RATE, &serpar_defaults, &def_baud);
+               if ((j == 1) && (user_list->option[0] == def_baud))
+               {
+#ifdef DEBUG
+                   printf("user selected default\n");
+#endif
+               }
+               else
+               {
+                   user_options_set = TRUE;
+#ifdef DEBUG
+                   printf("user options are: ");
+                   for (j = 0; j < user_list->num_options; ++j)
+                      printf("%u ", user_list->option[j]);
+                   printf("\n");
+#endif
+               }
+
+               break;   /* out of i loop */
+           }
+
+#ifdef DEBUG
+        if (i >= full_list->num_options)
+           printf("couldn't match baud rate %u\n", target_baud_rate);
+#endif
+    }
+#ifdef DEBUG
+    else
+       printf("failed to find lists\n");
+#endif
+}
+
+static int SerparOpen(const char *name, const char *arg)
+{
+    char *sername = NULL;
+    char *parname = NULL;
+
+#ifdef DEBUG
+    printf("SerparOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+    if (IsOpenSerial() || IsOpenParallel()) return -1;
+#else
+    if (Unix_IsSerialInUse() || Unix_IsParallelInUse()) return -1;
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+    if (SerparMatch(name, arg) == -1)
+        return -1;
+#else
+    Unix_IsValidParallelDevice(name,&sername,&parname);
+# ifdef DEBUG
+    printf("translated %s to serial %s and parallel %s\n",
+           name==0 ? "NULL" : name,
+           sername==0 ? "NULL" : sername,
+           parname==0 ? "NULL" : parname);
+# endif
+    if (sername==NULL || parname==NULL) return -1;
+#endif
+
+    user_options_set = FALSE;
+
+    /* interpret and store the arguments */
+    if (arg != NULL)
+    {
+        unsigned int target_baud_rate;
+
+        target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
+
+        if (target_baud_rate > 0)
+        {
+#ifdef DEBUG
+            printf("user selected baud rate %u\n", target_baud_rate);
+#endif
+            process_baud_rate(target_baud_rate);
+        }
+#ifdef DEBUG
+        else
+            printf("could not understand baud rate %s\n", arg);
+#endif
+    }
+
+#ifdef COMPILING_ON_WINDOWS
+    {
+        /*
+         * The serial port number is in name[0] followed by
+         * the parallel port number in name[1]
+         */
+
+        int sport = name[0] - '0';
+        int pport = name[1] - '0';
+
+        if (OpenParallel(pport) != COM_OK)
+            return -1;
+
+        if (OpenSerial(sport, FALSE) != COM_OK)
+        {
+            CloseParallel();
+            return -1;
+        }
+    }
+#else
+    Unix_OpenParallel(parname);
+    Unix_OpenSerial(sername);
+#endif
+
+    serpar_reset();
+
+#if defined(__unix) || defined(__CYGWIN32__)
+    Unix_ioctlNonBlocking();
+#endif
+
+    Angel_RxEngineInit(&config, &rxstate);
+
+    return 0;
+}
+
+#ifdef COMPILING_ON_WINDOWS
+static int SerparMatch(const char *name, const char *arg)
+{
+    char sername[2];
+    char parname[2];
+
+    UNUSED(arg);
+
+    sername[0] = name[0];
+    parname[0] = name[1];
+    sername[1] = parname[1] = 0;
+
+    if (IsValidDevice(sername) == COM_DEVICENOTVALID ||
+        IsValidDevice(parname) == COM_DEVICENOTVALID)
+        return -1;
+    else
+        return 0;
+}
+#else
+static int SerparMatch(const char *portstring, const char *arg)
+{
+    char *sername=NULL, *parname=NULL;
+    UNUSED(arg);
+
+    Unix_IsValidParallelDevice(portstring,&sername,&parname);
+
+      /* Match failed if either sername or parname are still NULL */
+    if (sername==NULL || parname==NULL) return -1;
+    return 0;
+}
+#endif
+
+static void SerparClose(void)
+{
+#ifdef COMPILING_ON_WINDOWS
+    CloseParallel();
+    CloseSerial();
+#else
+    Unix_CloseParallel();
+    Unix_CloseSerial();
+#endif
+}
+
+static int SerparRead(DriverCall *dc, bool block)
+{
+    static unsigned char readbuf[MAXREADSIZE];
+    static int rbindex = 0;
+
+    int nread;
+    int read_errno;
+    int c = 0;
+    re_status restatus;
+    int ret_code = -1;            /* assume bad packet or error */
+
+    /*
+     * we must not overflow buffer, and must start after
+     * the existing data
+     */
+#ifdef COMPILING_ON_WINDOWS
+    {
+        BOOL dummy = FALSE;
+        nread = BytesInRXBufferSerial();
+
+        if (nread > MAXREADSIZE - rbindex)
+            nread = MAXREADSIZE - rbindex;
+        read_errno = ReadSerial(readbuf+rbindex, nread, &dummy);
+        if (pfnProgressCallback != NULL && read_errno == COM_OK)
+        {
+            progressInfo.nRead += nread;
+            (*pfnProgressCallback)(&progressInfo);
+        }
+    }
+#else
+    nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
+    read_errno = errno;
+#endif
+
+    if ((nread > 0) || (rbindex > 0))
+    {
+#ifdef DO_TRACE
+        printf("[%d@%d] ", nread, rbindex);
+#endif
+
+        if (nread > 0)
+            rbindex = rbindex + nread;
+
+        do
+        {
+            restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
+
+#ifdef DO_TRACE
+            printf("<%02X ",readbuf[c]);
+#endif
+            c++;
+        } while (c < rbindex &&
+                 ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
+
+#ifdef DO_TRACE
+        printf("\n");
+#endif
+
+        switch(restatus)
+        {
+          case RS_GOOD_PKT:
+              ret_code = 1;
+              /* fall through to: */
+
+          case RS_BAD_PKT:
+              /*
+               * We now need to shuffle any left over data down to the
+               * beginning of our private buffer ready to be used
+               *for the next packet
+               */
+#ifdef DO_TRACE
+              printf("SerparRead() processed %d, moving down %d\n",
+                     c, rbindex - c);
+#endif
+
+              if (c != rbindex)
+                  memmove((char *) readbuf, (char *) (readbuf + c), rbindex - c);
+
+              rbindex -= c;
+
+              break;
+
+          case RS_IN_PKT:
+          case RS_WAIT_PKT:
+              rbindex = 0;            /* will have processed all we had */
+              ret_code = 0;
+              break;
+
+          default:
+#ifdef DEBUG
+              printf("Bad re_status in SerparRead()\n");
+#endif
+              break;
+        }
+    }
+    else if (nread == 0)
+        /* nothing to read */
+        ret_code = 0;
+    else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
+        ret_code = 0;
+
+#ifdef DEBUG
+    if ((nread < 0) && (read_errno != ERRNO_FOR_BLOCKED_IO))
+        perror("read() error in SerparRead()");
+#endif
+
+    return ret_code;
+}
+
+/*
+ *  Function: send_packet
+ *   Purpose: Send a stream of bytes to Angel through the parallel port
+ *
+ * Algorithm: We need to present the data in a form that all boards can
+ *            swallow.  With the PID board, this is a problem: for reasons
+ *            described in the driver (angel/pid/st16c552.c), data are
+ *            sent a nybble at a time on D0-D2 and D4; D3 is wired to ACK,
+ *            which generates an interrupt when it goes low.  This routine
+ *            fills in an array of nybbles, with ACK clear in all but the
+ *            last one.  If, for whatever reason, the write fails, then
+ *            ACK is forced high (thereby enabling the next write a chance
+ *            to be noticed when the falling edge of ACK generates an
+ *            interrupt (hopefully).
+ *
+ *    Params:
+ *       Input: txstate Contains the packet to be sent
+ *
+ *   Returns: Number of *complete* bytes written
+ */
+
+static int SerparWrite(DriverCall *dc)
+{
+    te_status status;
+    int nwritten = 0;
+    static TxState txstate;
+
+    /*
+     * is this a new packet?
+     */
+    if (dc->dc_context == NULL)
+    {
+        /*
+         * yes - initialise TxEngine
+         */
+        Angel_TxEngineInit(&config, &dc->dc_packet, &txstate.state);
+
+        txstate.index = 0;
+        dc->dc_context = &txstate;
+    }
+
+    /*
+     * fill the buffer using the Tx Engine
+     */
+    do
+    {
+        status = Angel_TxEngine(&dc->dc_packet, &txstate.state,
+                                &txstate.writebuf[txstate.index]);
+        if (status != TS_IDLE) txstate.index++;
+
+    } while (status == TS_IN_PKT && txstate.index < MAXWRITESIZE);
+
+#ifdef DO_TRACE
+    {
+        unsigned int i = 0;
+
+        while (i < txstate.index)
+        {
+            printf(">%02X ", txstate.writebuf[i]);
+
+            if (!(++i % 16))
+                putc('\n', stdout);
+        }
+
+        if (i % 16)
+            putc('\n', stdout);
+    }
+#endif
+
+    /*
+     * the data are ready, all we need now is to send them out
+     * in a form that Angel can swallow.
+     */
+#ifdef COMPILING_ON_WINDOWS
+  if (WriteParallel(txstate.writebuf, txstate.index) == COM_OK)
+  {
+    nwritten = txstate.index;
+    if (pfnProgressCallback != NULL)
+    {
+      progressInfo.nWritten += nwritten;
+      (*pfnProgressCallback)(&progressInfo);
+    }
+  }
+  else
+  {
+      MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
+      return -1;   /* SJ - This really needs to return a value, which is picked up in */
+                   /*      DevSW_Read as meaning stop debugger but don't kill. */
+  }
+#else
+    nwritten = Unix_WriteParallel(txstate.writebuf, txstate.index);
+#endif
+
+    if (nwritten < 0) nwritten = 0;
+
+#ifdef DO_TRACE
+    printf("SerparWrite: wrote %d out of %d bytes\n",
+           nwritten, txstate.index);
+#endif
+
+    /*
+     * has the whole packet gone?
+     */
+    if (nwritten == (int)txstate.index &&
+        (status == TS_DONE_PKT || status == TS_IDLE))
+        /*
+         * yes it has
+         */
+        return 1;
+    else
+    {
+        /*
+         * if some data are left, shuffle them
+         * to the start of the buffer
+         */
+        if (nwritten != (int)txstate.index && nwritten != 0)
+        {
+            txstate.index -= nwritten;
+            (void)memmove((char *) txstate.writebuf,
+                          (char *) (txstate.writebuf + nwritten),
+                          txstate.index);
+        }
+        else if (nwritten == (int)txstate.index)
+            txstate.index = 0;
+
+        return 0;
+    }
+}
+
+static int serpar_reset(void)
+{
+#ifdef COMPILING_ON_WINDOWS
+    FlushParallel();
+    FlushSerial();
+#else
+    Unix_ResetParallel();
+    Unix_ResetSerial();
+#endif
+
+    return serpar_set_params(&serpar_defaults);
+}
+
+static int find_baud_rate(unsigned int *speed)
+{
+    static struct
+    {
+        unsigned int baud;
+        int termiosValue;
+    } possibleBaudRates[] =
+      {
+#if defined(__hpux)
+          {115200, _B115200}, {57600, _B57600},
+#endif
+#ifdef COMPILING_ON_WINDOWS
+        {38400, CBR_38400}, {19200, CBR_19200}, {9600, CBR_9600}, {0, 0}
+#else
+        {38400, B38400}, {19200, B19200}, {9600, B9600}, {0, 0}
+#endif
+    };
+    unsigned int i;
+
+    /* look for lower or matching -- will always terminate at 0 end marker */
+    for (i = 0; possibleBaudRates[i].baud > *speed; ++i)
+        /* do nothing */
+        ;
+
+    if (possibleBaudRates[i].baud > 0)
+       *speed = possibleBaudRates[i].baud;
+
+    return possibleBaudRates[i].termiosValue;
+}
+
+static int serpar_set_params(const ParameterConfig *config)
+{
+    unsigned int speed;
+    int termios_value;
+
+#ifdef DEBUG
+    printf("serpar_set_params\n");
+#endif
+
+    if (!Angel_FindParam(AP_BAUD_RATE, config, &speed))
+    {
+#ifdef DEBUG
+        printf("speed not found in config\n");
+#endif
+        return DE_OKAY;
+    }
+
+    termios_value = find_baud_rate(&speed);
+    if (termios_value == 0)
+    {
+#ifdef DEBUG
+        printf("speed not valid: %u\n", speed);
+#endif
+        return DE_OKAY;
+    }
+
+#ifdef DEBUG
+    printf("setting speed to %u\n", speed);
+#endif
+
+#ifdef COMPILING_ON_WINDOWS
+    SetBaudRate((WORD)termios_value);
+#else
+    Unix_SetSerialBaudRate(termios_value);
+#endif
+
+    return DE_OKAY;
+}
+
+
+static int serpar_get_user_params(ParameterOptions **p_options)
+{
+#ifdef DEBUG
+    printf("serpar_get_user_params\n");
+#endif
+
+    if (user_options_set)
+    {
+        *p_options = &user_options;
+    }
+    else
+    {
+        *p_options = NULL;
+    }
+
+    return DE_OKAY;
+}
+
+
+static int serial_get_default_params( const ParameterConfig **p_config )
+{
+#ifdef DEBUG
+    printf( "serial_get_default_params\n" );
+#endif
+
+    *p_config = &serpar_defaults;
+    return DE_OKAY;
+}
+
+
+static int SerparIoctl(const int opcode, void *args)
+{
+    int ret_code;
+
+#ifdef DEBUG
+    printf("SerparIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
+#endif
+
+    switch (opcode)
+    {
+       case DC_RESET:
+           ret_code = serpar_reset();
+           break;
+
+       case DC_SET_PARAMS:
+           ret_code = serpar_set_params((const ParameterConfig *)args);
+           break;
+
+       case DC_GET_USER_PARAMS:
+           ret_code = serpar_get_user_params((ParameterOptions **)args);
+           break;
+
+       case DC_GET_DEFAULT_PARAMS:
+           ret_code =
+               serial_get_default_params((const ParameterConfig **)args);
+           break;
+
+       default:
+           ret_code = DE_BAD_OP;
+           break;
+    }
+
+  return ret_code;
+}
+
+DeviceDescr angel_SerparDevice =
+{
+    "SERPAR",
+    SerparOpen,
+    SerparMatch,
+    SerparClose,
+    SerparRead,
+    SerparWrite,
+    SerparIoctl
+};
+
+/* EOF serpardr.c */
diff --git a/gdb/rdi-share/sys.h b/gdb/rdi-share/sys.h
new file mode 100644 (file)
index 0000000..b68ac78
--- /dev/null
@@ -0,0 +1,319 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* sys.h 
+ ***********************************************************************
+ * Angel C Libary support channel protocol definitions
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *
+ *
+ *
+ * MESSAGE FORMAT
+ * --------------
+ * Format of the "data" section of C Lib Support Channel Messages.
+ * You will notice that the format is much the same as the format
+ * of ADP messages - this is so that multi-threaded C Libraries can
+ * be supported.
+ *
+ *  unsigned32 reason     - Main C Library reason code.
+ *  unsigned32 debugID    - Info. describing host debug world;
+ *                          private to host and used in any target
+ *                          initiated messages.
+ *  unsigned32 OSinfo1    \ Target OS information to identify process/thread
+ *  unsigned32 OSinfo2    / world, etc. These two fields are target defined.
+ *  byte       args[n]    - Data for message "reason" code.
+ *
+ * The "debugID" is defined by the host-end of the protocol, and is used
+ * by the host to ensure that messages are routed to the correct handler
+ * program/veneer (eg. imagine several threads having opened stdout and
+ * each writing to a different window in a windowed debugger).
+ *
+ * NOTE: The reason that there is no "size" information, is that the
+ * message IDs themselves encode the format of any arguments.
+ *
+ * For further discussion of the format see adp.h
+ *
+ * N.B. All streams are little endian.
+ *
+ * CLIB REASON CODE
+ * ----------------
+ * The message reason codes contain some information that ties them to
+ * the channel and direction that the message will be used with. This
+ * will ensure that even if the message "#define name" is not
+ * completely descriptive, the message reason code is.
+ *
+ *      b31    = direction. 0=Host-to-Target; 1=Target-to-Host;
+ *      b30-16 = reserved. should be zero
+ *      b15-0  = message reason code.
+ *
+ * Note that typically a request will be initiated by the target side, and
+ * that the host will then respond with either an acknowledgement or some
+ * data.  In either case the same reason code will be used, but the direction
+ * bit will be reveresed.
+ */
+
+#ifndef __sys_h
+#define __sys_h
+
+#ifndef HtoT
+#define HtoT    ((unsigned)0 << 31)     /* Host-to-Target message */
+#define TtoH    ((unsigned)1 << 31)     /* Target-to-Host message */
+#endif
+
+/*
+ * The following are error codes used in the status field returned on
+ * sending a message. 0 represents no error having occurred, non-zero
+ * represents a general error.  More codes should be added as required.
+ */
+#ifndef ErrCode
+#define NoError  0x0
+#endif
+
+/*************************************************************************/
+/* The following are direct conversions of the DeMon SWI's               */
+/* NB: nbytes is the number of bytes INCLUDING THE NULL character where  */
+/*     applicable.                                                       */
+
+/* This message is used as a  response to a packet whose message
+ * was not understood.  The return parameter, code is the reason
+ * code which was not understood. Although intended for use as a
+ * default case on a received message switch it can also be used
+ * as a  proper message*/
+#define CL_Unrecognised          0x00
+    /* Unrecognised()
+     * return(word code)
+     */
+
+/* Write a character to the terminal.
+ */
+#define CL_WriteC       0x01
+   /* WriteC(byte data)
+    * return(word status)
+    */
+
+/* Write a NULL terminated string of characters to the terminal.  The length
+ * of the string excluding the NULL terminating character is passed in 
+ * 'nbytes'.
+ */
+#define CL_Write0       0x02
+   /* Write0(word nbytes, bytes data)
+    * return(word status)
+    */
+
+/* Read a character from the terminal - probably the keyboard.
+ */
+#define CL_ReadC        0x04
+   /* ReadC(void)
+    * return(word status, byte data)
+    */
+
+/* Perform system call, pass NULL terminated string to host's command
+ * line interpreter(NOT AVAILABLE IN PC/DOS RELEASE).  The data byte
+ * returned holds the return code from the system call.
+ */ 
+#define CL_System       0x05
+   /* CLI(word nbytes, bytes data)
+    * return(word status, word data)
+    */
+
+/* It returns the address of the null terminated command line string used to
+ * invoke the program. status will be set to NoError if the command line
+ * can be returned. Other status values will be treated as error conditions.
+ */
+#define CL_GetCmdLine   0x10
+   /* GetCmdLine(void)
+    * return(word status, word nbytes, bytes argline)
+    */
+
+/* Return the number of centi-seconds since the support code began 
+ * execution.  Only the difference between successive calls can be
+ * meaningful.
+ */
+#define CL_Clock        0x61
+   /* Clock(void)
+    * return(word status, word clks)
+    */
+
+/* Return the number of seconds since the beginning of 1970.
+ */
+#define CL_Time         0x63
+   /* Time(void)
+    * return(word status, word time)
+    */
+
+/* Delete(remove, un-link, wipe, destroy) the file named by the
+ * NULL-terminated string 'name'.
+ */
+#define CL_Remove       0x64
+   /* Remove(word nbytes, bytes name)
+    * return(word status)
+    */
+
+/* Rename the file specified by the NULL-terminated string 'oname'
+ * to 'nname'.
+ */   
+#define CL_Rename       0x65
+   /* Rename(word nbytes, bytes oname, word nbytes, bytes nname)
+    * return(word status)
+    */
+
+/* 'name' specifies a NULL-terminated string containing a file name or a
+ * device name.  Opens the file/device and returns a non-zero handle on
+ * success that can be quoted to CL_Close, CL_Read, CL_Write, CL_Seek,
+ * CL_Flen or CL_IsTTY.  The mode is an integer in the range 0-11:-
+ *
+ * Mode:              0   1   2   3   4   5   6   7   8   9   10   11
+ * ANSI C fopen mode: r   rb  r+  r+b w   wb  w+  w+b a   ab  a+   a+b
+ *
+ * Values 12-15 are illegal.  If 'name' is ":tt" the stdin/stdout is
+ * opened depending on whether 'mode' is read or write.
+ */ 
+#define CL_Open         0x66
+   /* Open(word nbytes, bytes name, word mode)
+    * return(word handle)
+    */
+
+/* 'handle' is a file handle previously returned by CL_Open.  CL_Close
+ * closes the file.
+ */ 
+#define CL_Close        0x68
+   /* Close(word handle)
+    * return(word status)
+    */
+
+/* Writes data of length nbytes to the file/device specified by
+ * handle.  nbtotal represents the total number of bytes to be
+ * written, whereas nbytes is the number of bytes in this packet
+ *
+ * If nbtotal is <= DATASIZE - CL_Write message header size in the
+ * packet then nbytes = nbtotal and the number of bytes not written
+ * is returned.  If nbtotal is > the packet size then the CL_Write
+ * must be followed by a number of CL_WriteX's to complete the write,
+ * the nbytes returned by CL_Write can be ignored
+ * If the status word returned is non zero, an error has occurred and
+ * the write request has been aborted.
+ * 
+ */
+#define CL_Write        0x69
+   /* Write(word handle, word nbtotal, word nbytes, bytes data)
+    * return(word status, word nbytes)
+    */
+
+/* Write Extension is a reads a continuation of data from a CL_Write 
+ * which was too big to fit in a single packet.
+ * nbytes is the number of bytes of data in this packet, the 
+ * returned value of nbytes can be ignored except if it is the 
+ * last packet, in which case it is the number of bytes that were NOT
+ * written 
+ */
+#define CL_WriteX       0x6A
+   /* WriteX(word nbytes, bytes data)
+    * return(word status, word nbytes)
+    */
+
+/* Reads 'nbytes' from the file/device specified by 'handle'.
+ *
+ * If nbytes <= DATASIZE then the read will occur in a single packet
+ * and the returned value of nbytes will be the number of bytes actually
+ * read and nbmore will be 0. If nbytes> DATASIZE then multiple packets
+ * will have to be used ie CL_Read followed by 1 or more CL_ReadX
+ * packets. In this case CL_Read will return nbytes read in the current
+ * packet and nbmore representing how many more bytes are expected to be
+ * read
+ * If the status word is non zero then the request has completed with an
+ * error. If the status word is 0xFFFFFFFF (-1) then an EOF condition
+ * has been reached.
+ */
+#define CL_Read         0x6B
+   /* Read(word handle, word nbytes)
+    * return(word status, word nbytes, word nbmore, bytes data)
+    */
+
+/* Read eXtension returns a continuation of the data that was opened for
+ * read in the earlier CL_Read. The return value nbytes is the number of
+ * data bytes in the packet, nbmore is the number of bytes more that are
+ * expected to be read in subsequent packets.
+ */
+#define CL_ReadX        0x6C
+  /* ReadX()
+   * return(word status, word nbytes, word nbmore, bytes data)
+   */
+
+/* Seeks to byte position 'posn' in the file/device specified by 'handle'.
+ */
+#define CL_Seek         0x6D
+   /* Seek(word handle, word posn)
+    * return(word status)
+    */
+
+/* Returns the current length of the file specified by 'handle' in 'len'.
+ * If an error occurs 'len' is set to -1. 
+ */ 
+#define CL_Flen         0x6E
+   /* Flen(word handle)
+    * return(word len)
+    */
+
+/* Returns NoError if 'handle' specifies an interactive device, otherwise
+ * returns GenError
+ */ 
+#define CL_IsTTY        0x6F
+   /* IsTTY(word handle)
+    * return(word status)
+    */
+
+/* Returns a temporary host file name. The maximum length of a file name
+ * is passed to the host. The TargetID is some identifier from the target
+ * for this particular temporary filename. This value is could be used
+ * directly in the generation of the filename. 
+ *
+ * If the host cannot create a suitable name or the generated name is too
+ * long then status is non zero. status will be NoError if the host can create
+ * a name. 
+ */
+#define CL_TmpNam       0x70
+   /* TmpNam(word maxlength, word TargetID)
+    * return(word status, word nbytes, bytes fname)
+    */
+
+/* Note there is no message for Exit, EnterOS, InstallHandler or
+ * GenerateError as these will be supported entirely at the host end,
+ * or by the underlying Operating system.
+ */
+
+#define CL_UnknownReason (-1)
+
+extern unsigned int GetRaiseHandler( void );
+extern unsigned int SysLibraryHandler(unsigned int sysCode, unsigned int *args);
+extern void angel_SysLibraryInit(void);
+
+/*
+ * Function: Angel_IsSysHandlerRunning
+ *  Purpose: return whether or not SysLibraryHandler is running
+ *
+ *   No paramaters
+ *             
+ *   Returns 1 if SysLibraryHandler is running
+ *           0 otherwise
+ */
+extern int Angel_IsSysHandlerRunning(void);
+
+#ifdef ICEMAN2
+/* This function exists in an ICEman2 system only, and can be called by
+ * debug support code when the debugger tells it how much memory the
+ * target has.  This will then be used to deal with the HEAPINFO SWI
+ */
+extern void angel_SetTopMem(unsigned addr);
+#endif
+
+#endif
+
diff --git a/gdb/rdi-share/tx.c b/gdb/rdi-share/tx.c
new file mode 100644 (file)
index 0000000..a52286c
--- /dev/null
@@ -0,0 +1,176 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*-*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ *   Project: ANGEL
+ *
+ *     Title: Character based packet transmission engine
+ */
+
+#include <stdarg.h>    /* ANSI varargs support */
+#include "angel.h"     /* Angel system definitions */
+#include "endian.h"    /* Endian independant memory access macros */
+#include "crc.h"       /* crc generation definitions and headers */
+#include "rxtx.h"
+#include "channels.h"
+#include "buffers.h"
+#include "logging.h"
+
+/* definitions to describe the engines state */
+#define N_STX           0x0  /* first 2 bits for N_ */
+#define N_BODY          0x1
+#define N_ETX           0x2
+#define N_IDLE          0x3
+#define N_MASK          0x3 /* mask for the Encapsulator state */
+
+#define E_PLAIN         (0x0 << 2) /* 3rd bit for E_ */
+#define E_ESC           (0x1 << 2) /* 3rd bit for E_ */
+#define E_MASK          (0x1 << 2) /* mask for the Escaper state */
+
+#define F_HEAD          (0x0 << 3) /* 4th and 5th bits for F_ */
+#define F_DATA          (0x1 << 3) 
+#define F_CRC           (0x1 << 4)
+#define F_MASK          (0x3 << 3) /* mask for the Escaper state */
+
+static unsigned char escape(unsigned char ch_in, struct te_state *txstate);
+
+void Angel_TxEngineInit(const struct re_config *txconfig,
+                        const struct data_packet *packet, 
+                        struct te_state *txstate){
+  IGNORE(packet);
+  txstate->tx_state = N_STX | E_PLAIN | F_HEAD;
+  txstate->field_c = 0;
+  txstate->encoded = 0;
+  txstate->config = txconfig;
+  txstate->crc = 0;
+}
+
+te_status Angel_TxEngine(const struct data_packet *packet,
+                         struct te_state *txstate,
+                         unsigned char *tx_ch){
+  /* TODO: gaurd on long/bad packets */
+  /*
+   * encapsulate the packet, framing has been moved from a seperate
+   * function into the encapsulation routine as it needed too much
+   * inherited state for it to be sensibly located elsewhere
+   */
+  switch ((txstate->tx_state) & N_MASK){
+  case N_STX:
+#ifdef DO_TRACE
+    __rt_trace("txe-stx ");
+#endif
+    txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_BODY;
+    *tx_ch = txstate->config->stx;
+    txstate->field_c = 3; /* set up for the header */
+    txstate->crc = startCRC32; /* set up basic crc */
+    return TS_IN_PKT;
+  case N_BODY:{
+    switch (txstate->tx_state & F_MASK) {
+    case F_HEAD:
+#ifdef DO_TRACE
+    __rt_trace("txe-head ");
+#endif
+      if (txstate->field_c == 3) {
+        /* send type */
+        *tx_ch = escape(packet->type, txstate);
+        return TS_IN_PKT;
+      }
+      else {
+        *tx_ch = escape((packet->len >> (txstate->field_c - 1) * 8) & 0xff,
+                      txstate);
+          if (txstate->field_c == 0) {
+            /* move on to the next state */
+            txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_DATA;
+            txstate->field_c = packet->len;
+          }
+        return TS_IN_PKT;
+      }
+    case F_DATA:
+#ifdef DO_TRACE
+    __rt_trace("txe-data ");
+#endif
+      *tx_ch = escape(packet->data[packet->len - txstate->field_c], txstate);
+      if (txstate->field_c == 0) {
+        /* move on to the next state */
+        txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_CRC;
+        txstate->field_c = 4;
+      }      
+      return TS_IN_PKT;
+    case F_CRC:
+#ifdef DO_TRACE
+    __rt_trace("txe-crc ");
+#endif
+     *tx_ch = escape((txstate->crc >> ((txstate->field_c - 1) * 8)) & 0xff,
+                      txstate);
+
+      if (txstate->field_c == 0) {
+#ifdef DO_TRACE
+        __rt_trace("txe crc = 0x%x\n", txstate->crc);
+#endif
+        /* move on to the next state */
+        txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_ETX;
+      }
+      return TS_IN_PKT;     
+    }
+  }
+  case N_ETX:
+#ifdef DO_TRACE
+    __rt_trace("txe-etx\n");
+#endif
+    txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
+    *tx_ch = txstate->config->etx;
+    return TS_DONE_PKT;
+  default:
+#ifdef DEBUG
+    __rt_info("tx default\n");
+#endif
+    txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
+    return TS_IDLE;
+  }
+  /* stop a silly -Wall warning */
+  return (te_status)-1;
+}
+
+/*
+ * crc generation occurs in the escape function because it is the only
+ * place where we know that we're putting a real char into the buffer
+ * rather than an escaped one.
+ * We must be careful here not to update the crc when we're sending it
+ */
+static unsigned char escape(unsigned char ch_in, struct te_state *txstate) {
+   if (((txstate->tx_state) & E_MASK) == E_ESC) {
+      /* char has been escaped so send the real char */
+#ifdef DO_TRACE
+     __rt_trace("txe-echar ");
+#endif
+      txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_PLAIN;
+      txstate->field_c--;
+      if ((txstate->tx_state & F_MASK) != F_CRC)
+        txstate->crc = crc32( &ch_in, 1, txstate->crc);
+      return ch_in | serial_ESCAPE;
+   }
+   if ((ch_in < 32) && ((txstate->config->esc_set & (1 << ch_in)) != 0)) {
+     /* char needs escaping */
+#ifdef DO_TRACE
+     __rt_trace("txe-esc ");
+#endif
+     txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_ESC;
+     return txstate->config->esc;
+   }
+   /* must be a char that can be sent plain */
+   txstate->field_c--;
+   if ((txstate->tx_state & F_MASK) != F_CRC)
+     txstate->crc = crc32(&ch_in, 1, txstate->crc);
+   return ch_in;
+}
+
+/* EOF tx.c */
diff --git a/gdb/rdi-share/unixcomm.c b/gdb/rdi-share/unixcomm.c
new file mode 100644 (file)
index 0000000..7cb55e6
--- /dev/null
@@ -0,0 +1,535 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ */
+
+#ifdef __hpux
+#  define _POSIX_SOURCE 1
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#ifdef __hpux
+#  define _TERMIOS_INCLUDED
+#  include <sys/termio.h>
+#  undef _TERMIOS_INCLUDED
+#else
+#  include <termios.h>
+#endif
+
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#ifdef sun
+# include <sys/ioccom.h>
+# ifdef __svr4__
+#  include <sys/bpp_io.h>
+# else
+#  include <sbusdev/bpp_io.h>
+# endif
+#endif
+
+#ifdef BSD
+# ifdef sun
+#  include <sys/ttydev.h>
+# endif
+# ifdef __alpha 
+#  include <sys/ioctl.h>
+# else
+#  include <sys/filio.h>
+# endif
+#endif
+
+#ifdef __hpux
+#  define _INCLUDE_HPUX_SOURCE
+#  include <sys/ioctl.h>
+#  undef _INCLUDE_HPUX_SOURCE
+#endif
+
+#include "host.h"
+#include "unixcomm.h"
+
+#define PP_TIMEOUT      1              /* seconds */
+
+#ifdef sun
+#define SERPORT1   "/dev/ttya"
+#define SERPORT2   "/dev/ttyb"
+#define PARPORT1   "/dev/bpp0"
+#define PARPORT2   "/dev/bpp1"
+#endif
+
+#ifdef __hpux
+#define SERPORT1   "/dev/tty00"
+#define SERPORT2   "/dev/tty01"
+#define PARPORT1   "/dev/ptr_parallel"
+#define PARPORT2   "/dev/ptr_parallel"
+#endif
+
+#ifdef __linux__
+#define SERPORT1   "/dev/cua0"
+#define SERPORT2   "/dev/cua1"
+#define PARPORT1   "/dev/par0"
+#define PARPORT2   "/dev/par1"
+#endif
+
+#ifdef _WIN32
+#define SERPORT1   "com1"
+#define SERPORT2   "com2"
+#define PARPORT1   "lpt1"
+#define PARPORT2   "lpt2"
+#endif
+
+/*
+ * Parallel port output pins, used for signalling to target
+ */
+
+#ifdef sun
+struct bpp_pins bp;
+#endif
+
+static int serpfd = -1;
+static int parpfd = -1;
+
+extern const char *Unix_MatchValidSerialDevice(const char *name)
+{
+  int i=0;
+  char *sername=NULL;
+
+  /* Accept no name as the default serial port */
+  if (name == NULL) {
+    return SERPORT1;
+  }
+
+  /* Look for the simple cases - 1,2,s,S,/dev/... first, and
+   * afterwards look for S=... clauses, which need parsing properly.
+   */
+
+  /* Accept /dev/tty* where * is limited */
+  if (strlen(name) == strlen(SERPORT1) && strncmp(name, "/dev/tty", 8) == 0) return name;
+
+  /* Accept "1" or "2" or "S" - S is equivalent to "1" */
+  if (strcmp(name, "1") == 0 ||
+      strcmp(name, "S") == 0 || strcmp(name, "s") == 0) {
+    return SERPORT1;
+  }
+  if (strcmp(name, "2") == 0) return SERPORT2;
+
+  /* It wasn't one of the simple cases, so now we have to parse it
+   * properly
+   */
+
+  do {
+    switch (name[i]) {
+      case ',':
+        /* Skip over commas */
+        i++;
+        break;
+      
+      default:
+        return 0;
+        /* Unexpected character => error - not matched */
+
+      case 0:
+        /* End of string means return whatever we have matched */
+        return sername;
+
+      case 's':
+      case 'S':
+      case 'h':
+      case 'H': {
+        char ch = tolower(name[i]);
+        int j, continue_from, len;
+        
+        /* If the next character is a comma or a NULL then this is
+         * a request for the default Serial port
+         */
+        if (name[++i] == 0 || name[i] == ',') {
+          if (ch=='s') 
+              sername=SERPORT1;
+          break;
+        }
+
+        /* Next character must be an = */
+        if (name[i] != '=') return 0;
+        /* Search for the end of the port spec. (ends in NULL or ,) */
+        for (j= ++i; name[j] != 0 && name[j] != ','; j++)
+          ; /* Do nothing */
+        /* Notice whether this is the last thing to parse or not
+         * and also calaculate the length of the string
+         */
+        if (name[j] == '0') continue_from = -1;
+        else continue_from = j;
+        len=(j-i);
+
+        /* And now try to match the serial / parallel port */
+        switch (ch) {
+          case 's': {
+            /* Match serial port */
+            if (len==1) {
+              if (name[i]=='1') 
+                  sername=SERPORT1;
+              else if (name[i]=='2') 
+                  sername=SERPORT2;
+            } else if (len==strlen(SERPORT1)) {
+              if (strncmp(name+i,SERPORT1,strlen(SERPORT1)) == 0)
+                sername=SERPORT1;
+              else if (strncmp(name+i,SERPORT2,strlen(SERPORT2)) == 0)
+                sername=SERPORT2;
+            }
+
+            break;
+          }
+
+          case 'h': 
+            /* We don't actually deal with the H case here, we just
+             * match it and allow it through.
+             */
+            break;
+        }
+
+        if (continue_from == -1) return sername;
+        i = continue_from;
+        break;
+      }
+    }
+  } while (1);
+
+  return 0;
+}
+
+
+extern int Unix_IsSerialInUse(void)
+{
+    if (serpfd >= 0)
+        return -1;
+
+    return 0;
+}
+
+extern int Unix_OpenSerial(const char *name)
+{
+#if defined(BSD)
+    serpfd = open(name, O_RDWR);
+#else
+    serpfd = open(name, O_RDWR | O_NONBLOCK);
+#endif
+
+    if (serpfd < 0) {
+        perror("open");
+        return -1;
+    }
+
+    return 0;
+}
+
+extern void Unix_CloseSerial(void)
+{
+    if (serpfd >= 0)
+    {
+        (void)close(serpfd);
+        serpfd = -1;
+    }
+}
+
+extern int Unix_ReadSerial(unsigned char *buf, int n, bool block)
+{
+    fd_set fdset;
+    struct timeval tv;
+    int err;
+
+    FD_ZERO(&fdset);
+    FD_SET(serpfd, &fdset);
+
+    tv.tv_sec = 0;
+    tv.tv_usec = (block ? 10000 : 0);
+
+    err = select(serpfd + 1, &fdset, NULL, NULL, &tv);
+
+    if (err < 0 && errno != EINTR)
+    {
+#ifdef DEBUG
+        perror("select");
+#endif
+        panic("select failure");
+        return -1;
+    }
+    else if (err > 0 && FD_ISSET(serpfd, &fdset))
+        return read(serpfd, buf, n);
+    else /* err == 0 || FD_CLR(serpfd, &fdset) */
+    {
+        errno = ERRNO_FOR_BLOCKED_IO;
+        return -1;
+    }
+}
+
+extern int Unix_WriteSerial(unsigned char *buf, int n)
+{
+    return write(serpfd, buf, n);
+}
+
+extern void Unix_ResetSerial(void)
+{
+    struct termios terminfo;
+
+    tcgetattr(serpfd, &terminfo);
+#ifdef __CYGWIN32__
+    /* Expedient, but it works.  */
+    terminfo.c_iflag = 0;
+    terminfo.c_oflag = 0;
+    terminfo.c_cflag = 48;
+    terminfo.c_lflag = 0;
+    terminfo.c_cc[VMIN] = 0;
+    terminfo.c_cc[VTIME] = 1;
+#else
+    terminfo.c_lflag &= ~(ICANON | ISIG | ECHO | IEXTEN);
+    terminfo.c_iflag &= ~(IGNCR | INPCK | ISTRIP | ICRNL | BRKINT);
+    terminfo.c_iflag |= (IXON | IXOFF | IGNBRK);
+    terminfo.c_cflag = (terminfo.c_cflag & ~CSIZE) | CS8 | CREAD;
+    terminfo.c_cflag &= ~PARENB;
+    terminfo.c_cc[VMIN] = 1;
+    terminfo.c_cc[VTIME] = 0;
+    terminfo.c_oflag &= ~OPOST;
+#endif
+    tcsetattr(serpfd, TCSAFLUSH, &terminfo);
+}
+
+extern void Unix_SetSerialBaudRate(int baudrate)
+{
+    struct termios terminfo;
+
+    tcgetattr(serpfd, &terminfo);
+    cfsetospeed(&terminfo, baudrate);
+    cfsetispeed(&terminfo, baudrate);
+    tcsetattr(serpfd, TCSAFLUSH, &terminfo);
+}
+
+extern void Unix_ioctlNonBlocking(void)
+{
+#if defined(BSD)
+    int nonblockingIO = 1;
+    (void)ioctl(serpfd, FIONBIO, &nonblockingIO);
+
+    if (parpfd != -1)
+        (void)ioctl(parpfd, FIONBIO, &nonblockingIO);
+#endif
+}
+
+extern void Unix_IsValidParallelDevice(
+  const char *portstring, char **sername, char **parname)
+{
+  int i=0;
+  *sername=NULL;
+  *parname=NULL;
+
+  /* Do not recognise a NULL portstring */
+  if (portstring==NULL) return;
+
+  do {
+    switch (portstring[i]) {
+      case ',':
+        /* Skip over commas */
+        i++;
+        break;
+      
+      default:
+      case 0:
+        /* End of string or bad characcter means we have finished */
+        return;
+
+      case 's':
+      case 'S':
+      case 'p':
+      case 'P':
+      case 'h':
+      case 'H': {
+        char ch = tolower(portstring[i]);
+        int j, continue_from, len;
+        
+        /* If the next character is a comma or a NULL then this is
+         * a request for the default Serial or Parallel port
+         */
+        if (portstring[++i] == 0 || portstring[i] == ',') {
+          if (ch=='s') *sername=SERPORT1;
+          else if (ch=='p') *parname=PARPORT1;
+          break;
+        }
+
+        /* Next character must be an = */
+        if (portstring[i] != '=') return;
+        /* Search for the end of the port spec. (ends in NULL or ,) */
+        for (j= ++i; portstring[j] != 0 && portstring[j] != ','; j++)
+          ; /* Do nothing */
+        /* Notice whether this is the last thing to parse or not
+         * and also calaculate the length of the string
+         */
+        if (portstring[j] == '0') continue_from = -1;
+        else continue_from = j;
+        len=(j-i);
+
+        /* And now try to match the serial / parallel port */
+        switch (ch) {
+          case 's': {
+            /* Match serial port */
+            if (len==1) {
+              if (portstring[i]=='1') *sername=SERPORT1;
+              else if (portstring[i]=='2') *sername=SERPORT2;
+            } else if (len==strlen(SERPORT1)) {
+              if (strncmp(portstring+i,SERPORT1,strlen(SERPORT1)) == 0)
+                *sername=SERPORT1;
+              else if (strncmp(portstring+i,SERPORT2,strlen(SERPORT2)) == 0)
+                *sername=SERPORT2;
+            }
+            break;
+          }
+
+          case 'p': {
+            /* Match parallel port */
+            if (len==1) {
+              if (portstring[i]=='1') *parname=PARPORT1;
+              else if (portstring[i]=='2') *parname=PARPORT2;
+            } else if (len==strlen(PARPORT1)) {
+              if (strncmp(portstring+i,PARPORT1,strlen(PARPORT1)) == 0)
+                *parname=PARPORT1;
+              else if (strncmp(portstring+i,PARPORT2,strlen(PARPORT2)) == 0)
+                *parname=PARPORT2;
+            }
+            break;
+          }
+
+          case 'h': 
+            /* We don't actually deal with the H case here, we just
+             * match it and allow it through.
+             */
+            break;
+        }
+
+        if (continue_from == -1) return;
+        i = continue_from;
+        break;
+      }
+    }
+  } while (1);
+  return;  /* Will never get here */
+}
+
+extern int Unix_IsParallelInUse(void)
+{
+    if (parpfd >= 0)
+        return -1;
+
+    return 0;
+}
+
+extern int Unix_OpenParallel(const char *name)
+{
+#if defined(BSD)
+    parpfd = open(name, O_RDWR);
+#else
+    parpfd = open(name, O_RDWR | O_NONBLOCK);
+#endif
+
+    if (parpfd < 0)
+    {
+        char errbuf[256];
+
+        sprintf(errbuf, "open %s", name);
+        perror(errbuf);
+
+        return -1;
+    }
+
+    return 0;
+}
+
+extern void Unix_CloseParallel(void)
+{
+    if (parpfd >= 0)
+    {
+        (void)close(parpfd);
+        parpfd = -1;
+    }
+}
+
+
+extern unsigned int Unix_WriteParallel(unsigned char *buf, int n)
+{
+    int ngone;
+
+    if ((ngone = write(parpfd, buf, n)) < 0)
+    {
+        /*
+         * we ignore errors (except for debug purposes)
+         */
+#ifdef DEBUG
+        char errbuf[256];
+
+        sprintf(errbuf, "send_packet: write");
+        perror(errbuf);
+#endif
+        ngone = 0;
+    }
+
+    /* finished */
+    return (unsigned int)ngone;
+}
+
+
+#ifdef sun
+extern void Unix_ResetParallel(void)
+{
+    struct bpp_transfer_parms tp;
+
+#ifdef DEBUG
+    printf("serpar_reset\n");
+#endif
+
+    /*
+     * we need to set the parallel port up for BUSY handshaking,
+     * and select the timeout
+     */
+    if (ioctl(parpfd, BPPIOC_GETPARMS, &tp) < 0)
+    {
+#ifdef DEBUG
+        perror("ioctl(BPPIOCGETPARMS)");
+#endif
+        panic("serpar_reset: cannot get BPP parameters");
+    }
+
+    tp.write_handshake = BPP_BUSY_HS;
+    tp.write_timeout = PP_TIMEOUT;
+
+    if (ioctl(parpfd, BPPIOC_SETPARMS, &tp) < 0)
+    {
+#ifdef DEBUG
+        perror("ioctl(BPPIOC_SETPARMS)");
+#endif
+        panic("serpar_reset: cannot set BPP parameters");
+    }
+}
+
+#else
+
+/* Parallel not supported on HP */
+
+extern void Unix_ResetParallel(void)
+{
+}
+
+#endif
+
diff --git a/gdb/rdi-share/unixcomm.h b/gdb/rdi-share/unixcomm.h
new file mode 100644 (file)
index 0000000..baa6552
--- /dev/null
@@ -0,0 +1,212 @@
+/* 
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ * 
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/* -*-C-*-
+ *
+ * $Revision$
+ *     $Date$
+ *
+ */
+#ifndef angsd_unixcomm_h
+#define angsd_unixcomm_h
+
+#include <errno.h>
+
+#if defined(BSD)
+#  define ERRNO_FOR_BLOCKED_IO EWOULDBLOCK
+#else
+#  define ERRNO_FOR_BLOCKED_IO EAGAIN
+#endif
+
+/*
+ *  Function: Unix_MatchValidSerialDevice
+ *   Purpose: check that the serial driver/port name is valid
+ *            and return the actual device name if it is.
+ *
+ *    Params:
+ *       Input: name    Name of device going to be used
+ *
+ *   Returns: 
+ *          OK: Pointer to name of the device matched
+ *       Error or unrecognised deivce: 0
+ */
+extern const char *Unix_MatchValidSerialDevice(const char *name);
+
+/*
+ *  Function: Unix_IsSerialInUse
+ *   Purpose: check whether the serial port is in use
+ *
+ *    Params:
+ *       Input: Nothing
+ *
+ *   Returns: 
+ *          OK: 0       Serial device not in use
+ *       Error: -1      Serial device in use
+ */
+extern int Unix_IsSerialInUse(void);
+
+/*
+ *  Function: Unix_OpenSerial
+ *   Purpose: open the serial port
+ *
+ *    Params:
+ *       Input: name    Name of device to open
+ *
+ *   Returns: Unix 'open' returns
+ */
+extern int Unix_OpenSerial(const char *name);
+
+/*
+ *  Function: Unix_CloseSerial
+ *   Purpose: close the serial port
+ *
+ *    Params:
+ *       Input: Nothing
+ *
+ *   Returns: Nothing
+ */
+extern void Unix_CloseSerial(void);
+
+/*
+ *  Function: Unix_ReadSerial
+ *   Purpose: reads a specified number of bytes (or less) from the serial port
+ *
+ *    Params:
+ *       Input: buf     Buffer to store read bytes
+ *              n       Maximum number of bytes to read
+ *
+ *   Returns: Unix 'read' returns
+ */
+extern int Unix_ReadSerial(unsigned char *buf, int n, bool block);
+
+/*
+ *  Function: Unix_WriteSerial
+ *   Purpose: writes a specified number of bytes (or less) to the serial port
+ *
+ *    Params:
+ *       Input: buf     Buffer to write bytes from
+ *              n       Maximum number of bytes to write
+ *
+ *   Returns: Unix 'write' returns
+ */
+extern int Unix_WriteSerial(unsigned char *buf, int n);
+
+/*
+ *  Function: Unix_ResetSerial
+ *   Purpose: resets the serial port for another operation
+ *
+ *    Params:
+ *       Input: Nothing
+ *
+ *   Returns: Nothing
+ */
+extern void Unix_ResetSerial(void);
+
+/*
+ *  Function: Unix_SetSerialBaudRate
+ *   Purpose: check that the serial driver/port name is valid
+ *
+ *    Params:
+ *       Input: baudrate    termios value for baud rate
+ *
+ *   Returns: Nothing
+ */
+extern void Unix_SetSerialBaudRate(int baudrate);
+
+/*
+ *  Function: Unix_ioctlNonBlocking
+ *   Purpose: sets the serial port to non-blocking IO
+ *
+ *    Params:
+ *       Input: Nothing
+ *
+ *   Returns: Nothing
+ */
+extern void Unix_ioctlNonBlocking(void);
+
+/*
+ *  Function: Unix_IsValidParallelDevice
+ *   Purpose: check whether the combined serial and parallel device specification
+ *            is ok, and return the ports selected
+ *
+ *    Params:
+ *       Input: portstring - is a string which specifies which serial
+ *                           and parallel ports are to be used. Can
+ *                           include s=<val> and p=<val> separated by a
+ *                           comma.
+ *
+ *   Returns: 
+ *       Output: *sername  - returns the device name of the chosen serial port
+ *               *parname  - returns the device name of the chosen parallel port
+ *               If either of these is NULL on return then the match failed.
+ */
+extern void Unix_IsValidParallelDevice(
+  const char *portstring, char **sername, char **parname
+);
+
+/*
+ *  Function: Unix_IsParallelInUse
+ *   Purpose: check whether the parallel port is in use
+ *
+ *    Params:
+ *       Input: Nothing
+ *
+ *   Returns: 
+ *          OK: 0       Parallel device not in use
+ *       Error: -1      Parallel device in use
+ */
+extern int Unix_IsParallelInUse(void);
+
+/*
+ *  Function: Unix_OpenParallel
+ *   Purpose: open the parallel port
+ *
+ *    Params:
+ *       Input: name    Name of device to open
+ *
+ *   Returns: Unix 'open' returns
+ */
+extern int Unix_OpenParallel(const char *name);
+
+/*
+ *  Function: Unix_CloseParallel
+ *   Purpose: close the parallel port
+ *
+ *    Params:
+ *       Input: Nothing
+ *
+ *   Returns: Nothing
+ */
+extern void Unix_CloseParallel(void);
+
+/*
+ *  Function: Unix_WriteParallel
+ *   Purpose: writes a specified number of bytes (or less) to the parallel port
+ *
+ *    Params:
+ *       Input: buf     Buffer to write bytes from
+ *              n       Maximum number of bytes to write
+ *
+ *   Returns: Unix 'write' returns
+ */
+extern unsigned int Unix_WriteParallel(unsigned char *buf, int n);
+
+/*
+ *  Function: Unix_ResetParallel
+ *   Purpose: resets the parallel port for another operation
+ *
+ *    Params:
+ *       Input: Nothing
+ *
+ *   Returns: Nothing
+ */
+extern void Unix_ResetParallel(void);
+
+#endif /* ndef angsd_unixcomm_h */
+
+/* EOF unixcomm.h */
diff --git a/gdb/remote-rdi.c b/gdb/remote-rdi.c
new file mode 100644 (file)
index 0000000..19cedd3
--- /dev/null
@@ -0,0 +1,966 @@
+/* GDB interface to ARM RDI library.
+   Copyright 1997 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <fcntl.h>
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "gdbthread.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <signal.h>
+
+#include "rdi-share/ardi.h"
+#include "rdi-share/adp.h"
+#include "rdi-share/hsys.h"
+
+/* Prototypes for local functions */
+
+static void arm_rdi_files_info PARAMS ((struct target_ops *ignore));
+
+static int arm_rdi_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+                                      int len, int should_write,
+                                      struct target_ops *target));
+
+static void arm_rdi_prepare_to_store PARAMS ((void));
+
+static void arm_rdi_fetch_registers PARAMS ((int regno));
+
+static void arm_rdi_resume PARAMS ((int pid, int step,
+                                  enum target_signal siggnal));
+
+static int arm_rdi_start_remote PARAMS ((char *dummy));
+
+static void arm_rdi_open PARAMS ((char *name, int from_tty));
+
+static void arm_rdi_create_inferior PARAMS ((char *exec_file, char *args,
+                                            char **env));
+
+static void arm_rdi_close PARAMS ((int quitting));
+
+static void arm_rdi_store_registers PARAMS ((int regno));
+
+static void arm_rdi_mourn PARAMS ((void));
+
+static void arm_rdi_send PARAMS ((char *buf));
+
+static int arm_rdi_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+static void arm_rdi_kill PARAMS ((void));
+
+static void arm_rdi_detach PARAMS ((char *args, int from_tty));
+
+static void arm_rdi_interrupt PARAMS ((int signo));
+
+static void arm_rdi_interrupt_twice PARAMS ((int signo));
+
+static void interrupt_query PARAMS ((void));
+
+static int arm_rdi_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int arm_rdi_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static char *rdi_error_message PARAMS ((int err));
+
+static enum target_signal rdi_error_signal PARAMS ((int err));
+
+extern struct target_ops arm_rdi_ops;  /* Forward decl */
+
+static struct Dbg_ConfigBlock gdb_config;
+
+static struct Dbg_HostosInterface gdb_hostif;
+
+static int max_load_size;
+
+static int execute_status;
+
+/* A little list of breakpoints that have been set.  */
+
+static struct local_bp_list_entry {
+  CORE_ADDR addr;
+  PointHandle point;
+  struct local_bp_list_entry *next;
+} *local_bp_list;
+
+\f
+/* Stub for catch_errors.  */
+
+static int
+arm_rdi_start_remote (dummy)
+     char *dummy;
+{
+  return 1;
+}
+
+/* Helper callbacks for the "host interface" structure.  RDI functions call
+   these to forward output from the target system and so forth.  */
+
+void
+voiddummy()
+{
+  printf("void dummy\n");
+}
+
+static void
+myprint (arg, format, ap)
+     PTR arg;
+     const char *format;
+     va_list ap;
+{
+  vfprintf (stdout, format, ap);
+}
+
+static void
+mywritec (arg, c)
+     PTR arg;
+     int c;
+{
+  fputc (c, (FILE *) arg);
+}
+
+static int
+mywrite (arg, buffer, len)
+     PTR arg;
+     char const *buffer;
+     int len;
+{
+  return fwrite (buffer, 1, len, stdout);
+}
+
+static void
+mypause (arg)
+     PTR arg;
+{
+}
+
+/* These last two are tricky as we have to handle the special case of
+   being interrupted more carefully */
+
+static int
+myreadc (arg)
+     PTR arg;
+{ 
+  return fgetc (stdin);
+}
+
+static char *
+mygets (arg, buffer, len)
+     PTR arg;
+     char *buffer;
+     int len;
+{
+  return fgets(buffer, len, stdin);
+}
+
+/* Open a connection to a remote debugger.  NAME is the filename used
+   for communication.  */
+
+static void
+arm_rdi_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  int rslt, i;
+  unsigned long arg1, arg2;
+
+  if (name == NULL)
+    error ("To open an RDI connection, you need to specify what serial\n\
+device is attached to the remote system (e.g. /dev/ttya).");
+
+  /* Make the basic low-level connection.  */
+
+  rslt = Adp_OpenDevice (NULL, NULL, 1);
+
+  if (rslt != adp_ok)
+    error ("Could not open port");
+
+  gdb_config.bytesex = 2 | (target_byte_order == BIG_ENDIAN ? 1 : 0);
+  gdb_config.fpe = 1;
+  gdb_config.rditype = 2;
+  gdb_config.heartbeat_on = 1;
+  gdb_config.flags = 2;
+
+  gdb_hostif.dbgprint = myprint;
+  gdb_hostif.dbgpause = mypause;
+  gdb_hostif.dbgarg = stdout;
+  gdb_hostif.writec = mywritec;
+  gdb_hostif.readc = myreadc;
+  gdb_hostif.write = mywrite;
+  gdb_hostif.gets = mygets;
+  gdb_hostif.hostosarg = stdout;
+  gdb_hostif.reset = voiddummy;
+
+  rslt = angel_RDI_open (10, &gdb_config, &gdb_hostif, NULL);
+  if (rslt == RDIError_BigEndian || rslt == RDIError_LittleEndian)
+    ;  /* do nothing, this is the expected return */
+  else if (rslt)
+    {
+      printf_filtered ("RDI_open: %s\n", rdi_error_message (rslt));
+    }
+
+  rslt = angel_RDI_info (RDIInfo_Target, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  rslt = angel_RDI_info (RDIInfo_Points, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  rslt = angel_RDI_info (RDIInfo_Step, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  rslt = angel_RDI_info (RDIInfo_CoPro, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  rslt = angel_RDI_info (RDIInfo_SemiHosting, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  rslt = angel_RDI_info (RDIInfo_Icebreaker, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  rslt = angel_RDI_info (RDIInfo_DownLoad, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  rslt = angel_RDI_info (RDIInfo_GetLoadSize, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  max_load_size = arg1;
+
+  push_target (&arm_rdi_ops);
+
+  target_fetch_registers (-1);
+
+  rslt = angel_RDI_open (1, &gdb_config, NULL, NULL);
+  if (rslt)
+    {
+      printf_filtered ("RDI_open: %s\n", rdi_error_message (rslt));
+    }
+
+  arg1 = 0x13b;
+  rslt = angel_RDI_info (RDIVector_Catch, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+
+  arg1 = (unsigned long) "";
+  rslt = angel_RDI_info (RDISet_Cmdline, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+
+  /* Clear out any existing records of breakpoints.  */
+  {
+    struct local_bp_list_entry *entry, *preventry = NULL;
+
+    for (entry = local_bp_list; entry != NULL; entry = entry->next)
+      {
+       if (preventry)
+         free (preventry);
+      }
+  }
+
+  printf_filtered ("Connected to ARM RDI target.\n");
+}
+
+/* Start an inferior process and set inferior_pid to its pid.
+   EXEC_FILE is the file to run.
+   ARGS is a string containing the arguments to the program.
+   ENV is the environment vector to pass.  Errors reported with error().
+   On VxWorks and various standalone systems, we ignore exec_file.  */
+/* This is called not only when we first attach, but also when the
+   user types "run" after having attached.  */
+
+static void
+arm_rdi_create_inferior (exec_file, args, env)
+     char *exec_file;
+     char *args;
+     char **env;
+{
+  int len, rslt;
+  unsigned long arg1, arg2;
+  char *arg_buf;
+  CORE_ADDR entry_point;
+
+  if (exec_file == 0 || exec_bfd == 0)
+   error ("No exec file specified.");
+
+  entry_point = (CORE_ADDR) bfd_get_start_address (exec_bfd);
+
+  arm_rdi_kill ();      
+  remove_breakpoints ();
+  init_wait_for_inferior ();
+
+  len = strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10;
+  arg_buf = (char *) alloca (len);
+  arg_buf[0] = '\0';
+  strcat (arg_buf, exec_file);
+  strcat (arg_buf, " ");
+  strcat (arg_buf, args);
+
+  inferior_pid = 42;
+  insert_breakpoints ();  /* Needed to get correct instruction in cache */
+
+  if ( env != NULL)
+    {
+      while (*env)
+       {
+         if (strncmp(*env, "MEMSIZE=", sizeof("MEMSIZE=")-1)==0)
+           {
+             unsigned long top_of_memory;
+             char *end_of_num;
+
+             /* Set up memory limit */
+             top_of_memory = strtoul(*env + sizeof("MEMSIZE=")-1,
+                                     &end_of_num, 0);
+             printf_filtered ("Setting top-of-memory to 0x%x\n",
+                              top_of_memory);
+         
+             rslt=angel_RDI_info (RDIInfo_SetTopMem, &top_of_memory, &arg2);
+             if (rslt)
+               {
+                 printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+               }
+           }
+         env++;
+       }
+    }
+
+  arg1 = (unsigned long) arg_buf;
+  rslt = angel_RDI_info (RDISet_Cmdline, /* &arg1 */ (unsigned long *)arg_buf, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+
+  proceed (entry_point, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* This takes a program previously attached to and detaches it.  After
+   this is done, GDB can be used to debug some other program.  We
+   better not have left any breakpoints in the target program or it'll
+   die when it hits one.  */
+
+static void
+arm_rdi_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  /* (anything to do?) */
+}
+
+/* Clean up connection to a remote debugger.  */
+
+static void
+arm_rdi_close (quitting)
+     int quitting;
+{
+  int rslt;
+
+  rslt = angel_RDI_close ();
+  if (rslt)
+    {
+      printf_filtered ("RDI_close: %s\n", rdi_error_message (rslt));
+    }
+}
+\f
+/* Tell the remote machine to resume.  */
+
+static void
+arm_rdi_resume (pid, step, siggnal)
+     int pid, step;
+     enum target_signal siggnal;
+{
+  int rslt;
+  PointHandle point;
+
+  if (0 /* turn on when hardware supports single-stepping */)
+    {
+      rslt = angel_RDI_step (1, &point);
+      if (rslt)
+       {
+         printf_filtered ("RDI_step: %s\n", rdi_error_message (rslt));
+       }
+    }
+  else
+    {
+      char handle[4];
+      CORE_ADDR pc;
+
+      if (step)
+       {
+         pc = read_register (PC_REGNUM);
+         pc = arm_get_next_pc (pc);
+         arm_rdi_insert_breakpoint (pc, handle);
+       }
+      execute_status = rslt = angel_RDI_execute (&point);
+      if (rslt == RDIError_BreakpointReached)
+       ;
+      else if (rslt)
+       {
+         printf_filtered ("RDI_execute: %s\n", rdi_error_message (rslt));
+       }
+      if (step)
+       {
+         arm_rdi_remove_breakpoint (pc, handle);
+       }
+    }
+}
+\f
+/* Send ^C to target to halt it.  Target will respond, and send us a
+   packet.  */
+
+static void
+arm_rdi_interrupt (signo)
+     int signo;
+{
+}
+
+static void (*ofunc)();
+
+/* The user typed ^C twice.  */
+static void
+arm_rdi_interrupt_twice (signo)
+     int signo;
+{
+}
+
+/* Ask the user what to do when an interrupt is received.  */
+
+static void
+interrupt_query ()
+{
+}
+
+/* Wait until the remote machine stops, then return, storing status in
+   STATUS just as `wait' would.  Returns "pid" (though it's not clear
+   what, if anything, that means in the case of this target).  */
+
+static int
+arm_rdi_wait (pid, status)
+     int pid;
+     struct target_waitstatus *status;
+{
+  status->kind = execute_status == RDIError_NoError ?
+    TARGET_WAITKIND_EXITED : TARGET_WAITKIND_STOPPED;
+
+  /* convert stopped code from target into right signal */
+  status->value.sig = rdi_error_signal ( execute_status );
+
+  return inferior_pid;
+}
+
+/* Read the remote registers into the block REGS.  */
+
+/* ARGSUSED */
+static void
+arm_rdi_fetch_registers (regno)
+     int regno;
+{
+  int rslt, rdi_regmask;
+  unsigned long rawreg, rawregs[32];
+  char cookedreg[4];
+
+  if (regno == -1) 
+    {
+      rslt = angel_RDI_CPUread (255, 0x27fff, rawregs);
+      if (rslt)
+       {
+         printf_filtered ("RDI_CPUread: %s\n", rdi_error_message (rslt));
+       }
+
+      for (regno = 0; regno < 15; regno++)
+       {
+         store_unsigned_integer (cookedreg, 4, rawregs[regno]);
+         supply_register (regno, (char *) cookedreg);
+       }
+      store_unsigned_integer (cookedreg, 4, rawregs[15]);
+      supply_register (PS_REGNUM, (char *) cookedreg);
+      arm_rdi_fetch_registers (PC_REGNUM);
+    }
+  else
+    {
+      if (regno == PC_REGNUM)
+       rdi_regmask = RDIReg_PC;
+      else if (regno == PS_REGNUM)
+       rdi_regmask = RDIReg_CPSR;
+      else if (regno < 0 || regno > 15)
+       {
+         rawreg = 0;
+         supply_register (regno, (char *) &rawreg);
+         return;
+       }
+      else
+       rdi_regmask = 1 << regno;
+
+      rslt = angel_RDI_CPUread (255, rdi_regmask, &rawreg);
+      if (rslt)
+       {
+         printf_filtered ("RDI_CPUread: %s\n", rdi_error_message (rslt));
+       }
+      store_unsigned_integer (cookedreg, 4, rawreg);
+      supply_register (regno, (char *) cookedreg);
+    }
+}
+
+static void 
+arm_rdi_prepare_to_store ()
+{
+  /* Nothing to do.  */
+}
+
+/* Store register REGNO, or all registers if REGNO == -1, from the contents
+   of REGISTERS.  FIXME: ignores errors.  */
+
+static void
+arm_rdi_store_registers (regno)
+     int regno;
+{
+  int rslt, rdi_regmask;
+
+  /* These need to be able to take 'floating point register' contents */
+  unsigned long rawreg[3], rawerreg[3];
+
+  if (regno  == -1) 
+    {
+      for (regno = 0; regno < NUM_REGS; regno++)
+       arm_rdi_store_registers (regno);
+    }
+  else
+    {
+      read_register_gen (regno, (char *) rawreg);
+      /* RDI manipulates data in host byte order, so convert now. */
+      store_unsigned_integer (rawerreg, 4, rawreg[0]);
+
+      if (regno == PC_REGNUM)
+       rdi_regmask = RDIReg_PC;
+      else if (regno == PS_REGNUM)
+       rdi_regmask = RDIReg_CPSR;
+      else if (regno < 0 || regno > 15)
+       return;
+      else
+       rdi_regmask = 1 << regno;
+
+      rslt = angel_RDI_CPUwrite (255, rdi_regmask, rawerreg);
+      if (rslt)
+       {
+         printf_filtered ("RDI_CPUwrite: %s\n", rdi_error_message (rslt));
+       }
+    }
+}
+\f
+/* Read or write LEN bytes from inferior memory at MEMADDR,
+   transferring to or from debugger address MYADDR.  Write to inferior
+   if SHOULD_WRITE is nonzero.  Returns length of data written or
+   read; 0 for error.  */
+
+/* ARGSUSED */
+static int
+arm_rdi_xfer_memory(memaddr, myaddr, len, should_write, target)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int should_write;
+     struct target_ops *target;                        /* ignored */
+{
+  int rslt, i;
+
+  if (should_write)
+    {
+      rslt = angel_RDI_write (myaddr, memaddr, &len);
+      if (rslt)
+       {
+         printf_filtered ("RDI_write: %s\n", rdi_error_message (rslt));
+       }
+    }
+  else 
+    {
+      rslt = angel_RDI_read (memaddr, myaddr, &len);
+      if (rslt)
+       {
+         printf_filtered ("RDI_read: %s\n", rdi_error_message (rslt));
+         len = 0;
+       }
+    }
+  return len;
+}
+\f
+/* Display random info collected from the target.  */
+
+static void
+arm_rdi_files_info (ignore)
+     struct target_ops *ignore;
+{
+  char *file = "nothing";
+  int rslt;
+  unsigned long arg1, arg2;
+
+  rslt = angel_RDI_info (RDIInfo_Target, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  if (arg1 & (1 << 15))
+    printf_filtered ("Target supports Thumb code.\n");
+  if (arg1 & (1 << 14))
+    printf_filtered ("Target can do profiling.\n");
+  if (arg1 & (1 << 4))
+    printf_filtered ("Target is real hardware.\n");
+  
+  rslt = angel_RDI_info (RDIInfo_Step, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  printf_filtered ("Target can%s single-step.\n", (arg1 & 0x4 ? "" : "not"));
+
+  rslt = angel_RDI_info (RDIInfo_Icebreaker, &arg1, &arg2);
+  if (rslt)
+    {
+      printf_filtered ("RDI_info: %s\n", rdi_error_message (rslt));
+    }
+  else
+    printf_filtered ("Target includes an EmbeddedICE.\n");
+}
+\f
+static void
+arm_rdi_kill ()
+{
+  int rslt;
+
+  rslt = angel_RDI_open (1, &gdb_config, NULL, NULL);
+  if (rslt)
+    {
+      printf_filtered ("RDI_open: %s\n", rdi_error_message (rslt));
+    }
+}
+
+static void
+arm_rdi_mourn_inferior ()
+{
+  unpush_target (&arm_rdi_ops);
+  generic_mourn_inferior ();
+}
+\f
+/* While the RDI library keeps track of its own breakpoints, we need
+   to remember "handles" so that we can delete them later.  Since
+   breakpoints get used for stepping, be careful not to leak memory
+   here.  */
+
+static int
+arm_rdi_insert_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  int rslt;
+  PointHandle point;
+  struct local_bp_list_entry *entry;
+  int type = RDIPoint_EQ;
+
+  if (arm_pc_is_thumb (addr) || arm_pc_is_thumb_dummy (addr))
+    type |= RDIPoint_16Bit;
+  rslt = angel_RDI_setbreak (addr, type, 0, &point);
+  if (rslt)
+    {
+      printf_filtered ("RDI_setbreak: %s\n", rdi_error_message (rslt));
+    }
+  entry =
+    (struct local_bp_list_entry *) xmalloc (sizeof (struct local_bp_list_entry));
+  entry->addr = addr;
+  entry->point = point;
+  entry->next = local_bp_list;
+  local_bp_list = entry;
+  return rslt;
+}
+
+static int
+arm_rdi_remove_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  int rslt;
+  PointHandle point;
+  struct local_bp_list_entry *entry, *preventry;
+
+  for (entry = local_bp_list; entry != NULL; entry = entry->next)
+    {
+      if (entry->addr == addr)
+       {
+         break;
+       }
+      preventry = entry;
+    }
+  if (entry)
+    {
+      rslt = angel_RDI_clearbreak (entry->point);
+      if (rslt)
+       {
+         printf_filtered ("RDI_clearbreak: %s\n", rdi_error_message (rslt));
+       }
+      /* Delete the breakpoint entry locally.  */
+      if (entry == local_bp_list)
+       {
+         local_bp_list = entry->next;
+       }
+      else
+       {
+         preventry->next = entry->next;
+       }
+      free (entry);
+    }
+  return 0;
+}
+\f
+static char *
+rdi_error_message (err)
+     int err;
+{
+  switch (err)
+    {
+    case RDIError_NoError: 
+      return "no error";
+    case RDIError_Reset:
+      return "debuggee reset";
+    case RDIError_UndefinedInstruction:
+      return "undefined instruction";
+    case RDIError_SoftwareInterrupt:
+      return "SWI trapped";
+    case RDIError_PrefetchAbort:
+      return "prefetch abort, execution ran into unmapped memory?";
+    case RDIError_DataAbort:
+      return "data abort, no memory at specified address?";
+    case RDIError_AddressException:
+      return "address exception, access >26bit in 26bit mode";
+    case RDIError_IRQ:
+      return "IRQ, interrupt trapped";
+    case RDIError_FIQ:
+      return "FIQ, fast interrupt trapped";
+    case RDIError_Error:
+      return "a miscellaneous type of error";
+    case RDIError_BranchThrough0:
+      return "branch through location 0";
+    case RDIError_NotInitialised:
+      return "internal error, RDI_open not called first";
+    case RDIError_UnableToInitialise:
+      return "internal error, target world is broken";
+    case RDIError_WrongByteSex:
+      return "See Operator: WrongByteSex";
+    case RDIError_UnableToTerminate:
+      return "See Operator: Unable to Terminate";
+    case RDIError_BadInstruction:
+      return "bad instruction, illegal to execute this instruction";
+    case RDIError_IllegalInstruction:
+      return "illegal instruction, the effect of executing it is undefined";
+    case RDIError_BadCPUStateSetting:
+      return "internal error, tried to set SPSR of user mode";
+    case RDIError_UnknownCoPro:
+      return "unknown co-processor";
+    case RDIError_UnknownCoProState:
+      return "cannot execute co-processor request";
+    case RDIError_BadCoProState:
+      return "recognizably broken co-processor request";
+    case RDIError_BadPointType:
+      return "internal error, bad point yype";
+    case RDIError_UnimplementedType:
+      return "internal error, unimplemented type";
+    case RDIError_BadPointSize:
+      return "internal error, bad point size";
+    case RDIError_UnimplementedSize:
+      return "internal error, unimplemented size";
+    case RDIError_NoMorePoints:
+      return "last break/watch point was used";
+    case RDIError_BreakpointReached:
+      return "breakpoint reached";
+    case RDIError_WatchpointAccessed:
+      return "watchpoint accessed";
+    case RDIError_NoSuchPoint:
+      return "attempted to clear non-existent break/watch point";
+    case RDIError_ProgramFinishedInStep:
+      return "end of the program reached while stepping";
+    case RDIError_UserInterrupt:
+      return "you pressed Escape";
+    case RDIError_CantSetPoint:
+      return "no more break/watch points available";
+    case RDIError_IncompatibleRDILevels:
+      return "incompatible RDI levels";
+    case RDIError_LittleEndian:
+      return "debuggee is little endian";
+    case RDIError_BigEndian:
+      return "debuggee is big endian";
+    case RDIError_SoftInitialiseError:
+      return "recoverable error in RDI initialization";
+    case RDIError_InsufficientPrivilege:
+      return "internal error, supervisor state not accessible to monitor";
+    case RDIError_UnimplementedMessage:
+      return "internal error, unimplemented message";
+    case RDIError_UndefinedMessage:
+      return "internal error, undefined message";
+    default:
+      return "undefined error message, should reset target"; 
+    }
+}
+
+/* Convert the ARM error messages to signals that GDB knows about.  */
+
+static enum target_signal
+rdi_error_signal (err)
+     int err;
+{
+  switch (err)
+    {
+    case RDIError_NoError:
+      return 0;
+    case RDIError_Reset:
+      return TARGET_SIGNAL_TERM; /* ??? */
+    case RDIError_UndefinedInstruction:
+      return TARGET_SIGNAL_ILL;
+    case RDIError_SoftwareInterrupt:
+    case RDIError_PrefetchAbort:
+    case RDIError_DataAbort:
+      return TARGET_SIGNAL_TRAP;
+    case RDIError_AddressException:
+      return TARGET_SIGNAL_SEGV;
+    case RDIError_IRQ:
+    case RDIError_FIQ:
+      return TARGET_SIGNAL_TRAP;
+    case RDIError_Error:
+      return TARGET_SIGNAL_TERM;
+    case RDIError_BranchThrough0:
+      return TARGET_SIGNAL_TRAP;
+    case RDIError_NotInitialised:
+    case RDIError_UnableToInitialise:
+    case RDIError_WrongByteSex:
+    case RDIError_UnableToTerminate:
+      return TARGET_SIGNAL_UNKNOWN;
+    case RDIError_BadInstruction:
+    case RDIError_IllegalInstruction:
+      return TARGET_SIGNAL_ILL;
+    case RDIError_BadCPUStateSetting:
+    case RDIError_UnknownCoPro:
+    case RDIError_UnknownCoProState:
+    case RDIError_BadCoProState:
+    case RDIError_BadPointType:
+    case RDIError_UnimplementedType:
+    case RDIError_BadPointSize:
+    case RDIError_UnimplementedSize:
+    case RDIError_NoMorePoints:
+      return TARGET_SIGNAL_UNKNOWN;
+    case RDIError_BreakpointReached:
+    case RDIError_WatchpointAccessed:
+      return TARGET_SIGNAL_TRAP;
+    case RDIError_NoSuchPoint:
+    case RDIError_ProgramFinishedInStep:
+      return TARGET_SIGNAL_UNKNOWN;
+    case RDIError_UserInterrupt:
+      return TARGET_SIGNAL_INT;
+    case RDIError_IncompatibleRDILevels:
+    case RDIError_LittleEndian:
+    case RDIError_BigEndian:
+    case RDIError_SoftInitialiseError:
+    case RDIError_InsufficientPrivilege:
+    case RDIError_UnimplementedMessage:
+    case RDIError_UndefinedMessage:
+    default:
+      return TARGET_SIGNAL_UNKNOWN; 
+    }
+}
+\f
+/* Define the target operations structure.  */
+
+struct target_ops arm_rdi_ops = {
+  "rdi",                       /* to_shortname */
+  "ARM RDI",                   /* to_longname */
+  "Use a remote ARM-based computer, via the RDI library.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
+  arm_rdi_open,                        /* to_open */
+  arm_rdi_close,               /* to_close */
+  NULL,                                /* to_attach */
+  arm_rdi_detach,              /* to_detach */
+  arm_rdi_resume,              /* to_resume */
+  arm_rdi_wait,                        /* to_wait */
+  arm_rdi_fetch_registers,     /* to_fetch_registers */
+  arm_rdi_store_registers,     /* to_store_registers */
+  arm_rdi_prepare_to_store,    /* to_prepare_to_store */
+  arm_rdi_xfer_memory,         /* to_xfer_memory */
+  arm_rdi_files_info,          /* to_files_info */
+  arm_rdi_insert_breakpoint,   /* to_insert_breakpoint */
+  arm_rdi_remove_breakpoint,   /* to_remove_breakpoint */
+  NULL,                                /* to_terminal_init */
+  NULL,                                /* to_terminal_inferior */
+  NULL,                                /* to_terminal_ours_for_output */
+  NULL,                                /* to_terminal_ours */
+  NULL,                                /* to_terminal_info */
+  arm_rdi_kill,                        /* to_kill */
+  generic_load,                        /* to_load */
+  NULL,                                /* to_lookup_symbol */
+  arm_rdi_create_inferior,     /* to_create_inferior */
+  arm_rdi_mourn_inferior,      /* to_mourn_inferior */
+  0,                           /* to_can_run */
+  0,                           /* to_notice_signals */
+  0,                           /* to_thread_alive */
+  0,                           /* to_stop */
+  process_stratum,             /* to_stratum */
+  NULL,                                /* to_next */
+  1,                           /* to_has_all_memory */
+  1,                           /* to_has_memory */
+  1,                           /* to_has_stack */
+  1,                           /* to_has_registers */
+  1,                           /* to_has_execution */
+  NULL,                                /* sections */
+  NULL,                                /* sections_end */
+  OPS_MAGIC                    /* to_magic */
+};
+
+void
+_initialize_remote_rdi ()
+{
+  add_target (&arm_rdi_ops);
+}
+
+/* A little dummy to make linking with the library succeed. */
+
+Fail() {}
index 3cc4c4eed2d3a4d779e5bed5d63d1b82609a785d..04a9473b0a7a149898be3100d6f35c595ba8ae90 100644 (file)
@@ -54,6 +54,7 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#include "gdbcore.h"
 
 
 extern struct target_ops remote_rdp_ops;
@@ -138,6 +139,16 @@ ds;
 #define RDP_INFO_ABOUT_BREAK_THREAD_BREAK (1<<9)
 #define RDP_INFO_ABOUT_BREAK_THREAD_WATCH (1<<10)
 #define RDP_INFO_ABOUT_BREAK_COND      (1<<11)
+#define RDP_INFO_VECTOR_CATCH          (0x180)
+#define RDP_INFO_ICEBREAKER            (7)
+#define RDP_INFO_SET_CMDLINE            (0x300)
+
+#define RDP_SELECT_CONFIG              (0x16)
+#define RDI_ConfigCPU                  0
+#define RDI_ConfigSystem               1
+#define RDI_MatchAny                   0
+#define RDI_MatchExactly               1
+#define RDI_MatchNoEarlier             2
 
 #define RDP_RESET                      0x7f
 
@@ -157,6 +168,8 @@ ds;
 
 static int timeout = 2;
 
+static char * commandline = NULL;
+
 static int
 remote_rdp_xfer_inferior_memory PARAMS ((CORE_ADDR memaddr,
                                         char *myaddr,
@@ -263,9 +276,39 @@ rdp_init (cold, tty)
 
       if (tty)
        printf_unfiltered ("Trying to connect at %d baud.\n", baudtry);
+
+      /*
+      ** It seems necessary to reset an EmbeddedICE to get it going.
+      ** This has the side benefit of displaying the startup banner.
+      */
+      if (cold)
+       {
+         put_byte (RDP_RESET);
+         while ((restype = SERIAL_READCHAR (io, 1)) > 0)
+           {
+             switch (restype)
+               {
+               case SERIAL_TIMEOUT:
+                 break;
+               case RDP_RESET:
+                 /* Sent at start of reset process: ignore */
+                 break;
+               default:
+                 printf_unfiltered ("%c", isgraph (restype) ? restype : ' ');
+                 break;
+               }
+           }
+
+         if (restype == 0)
+           {
+             /* Got end-of-banner mark */
+             printf_filtered ("\n");
+           }
+       }
+
       put_byte (RDP_OPEN);
 
-      put_byte (type | RDP_OPEN_TYPE_RETURN_SEX);
+      put_byte (type | RDP_OPEN_TYPE_RETURN_SEX );
       put_word (0);
 
       while (!sync && (restype = SERIAL_READCHAR (io, 1)) > 0)
@@ -300,6 +343,10 @@ rdp_init (cold, tty)
            case RDP_RES_VALUE:
              {
                int resval = SERIAL_READCHAR (io, 1);
+
+               if (remote_debug)
+                 printf_unfiltered ("[%02x]\n", resval);
+
                switch (resval)
                  {
                  case SERIAL_TIMEOUT:
@@ -384,9 +431,27 @@ send_rdp (char *template, va_alist)
            }
          break;
        case 'Z':
-         /* Check the result code, error if not zero */
-         if (get_byte ())
-           error ("Command garbled");
+         /* Check the result code */
+         switch (get_byte ())
+           {
+           case 0:
+             /* Success */
+             break;
+           case 253:
+             /* Target can't do it; never mind */
+             printf_unfiltered ("RDP: Insufficient privilege\n");
+             return;
+           case 254:
+             /* Target can't do it; never mind */
+             printf_unfiltered ("RDP: Unimplemented message\n");
+             return;
+           case 255:
+             error ("Command garbled");
+             break;
+           default:
+             error ("Corrupt reply from target");
+             break;
+           }
          break;
        case 'W':
          /* Read a word from the target */
@@ -652,6 +717,50 @@ rdp_execute_start ()
 }
 
 
+static void
+rdp_set_command_line (command, args)
+     char * command;
+     char * args;
+{
+  /*
+  ** We could use RDP_INFO_SET_CMDLINE to send this, but EmbeddedICE systems
+  ** don't implement that, and get all confused at the unexpected text.
+  ** Instead, just keep a copy, and send it when the target does a SWI_GetEnv
+  */
+
+  if (commandline != NULL)
+    free (commandline);
+
+  commandline = malloc (strlen (command) + strlen (args) + 2);
+  if (commandline != NULL)
+    {
+      strcpy (commandline, command);
+      strcat (commandline, " ");
+      strcat (commandline, args);
+    }
+}
+
+static void
+rdp_catch_vectors ()
+{
+  /*
+  ** We want the target monitor to intercept the abort vectors
+  ** i.e. stop the program if any of these are used.
+  */
+  send_rdp ("bww-SZ", RDP_INFO, RDP_INFO_VECTOR_CATCH,
+           /*
+           ** Specify a bitmask including
+           **  the reset vector
+           **  the undefined instruction vector
+           **  the prefetch abort vector
+           **  the data abort vector
+           **  the address exception vector
+           */
+           (1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)
+           );
+}
+  
+
 
 #define a_byte 1
 #define a_word 2
@@ -786,6 +895,22 @@ exec_swi (swi, args)
       args->n = callback->isatty (callback, args->n);
       return 1;
 
+    case SWI_GetEnv:
+      if (commandline != NULL)
+       {
+         int len = strlen (commandline);
+         if (len > 255)
+           {
+             len = 255;
+             commandline [255]='\0';
+           }
+         remote_rdp_xfer_inferior_memory (args[0].n,
+                                          commandline, len+1, 1, 0);
+       }
+      else
+       remote_rdp_xfer_inferior_memory (args[0].n, "", 1, 1, 0);
+      return 1;
+      
     default:
       return 0;
     }
@@ -986,6 +1111,8 @@ remote_rdp_open (args, from_tty)
      char *args;
      int from_tty;
 {
+  int not_icebreaker;
+
   if (!args)
     error_no_arg ("serial port device name");
 
@@ -1010,7 +1137,33 @@ remote_rdp_open (args, from_tty)
 
   rdp_info ();
 
-  push_target (&remote_rdp_ops);
+  /* Need to set up the vector interception state */
+  rdp_catch_vectors();
+
+  /*
+  ** If it's an EmbeddedICE, we need to set the processor config.
+  ** Assume we can always have ARM7TDI...
+  */
+  send_rdp ("bw-SB", RDP_INFO, RDP_INFO_ICEBREAKER, & not_icebreaker);
+  if (!not_icebreaker)
+    {
+      const char * CPU = "ARM7TDI";
+      int ICEversion;
+      int len = strlen (CPU);
+      
+      send_rdp ("bbbbw-p-SWZ",
+               RDP_SELECT_CONFIG,
+               RDI_ConfigCPU,  /* Aspect: set the CPU */
+               len,            /* The number of bytes in the name */
+               RDI_MatchAny,   /* We'll take whatever we get */
+               0,              /* We'll take whatever version's there */
+               CPU,len,
+               & ICEversion);
+    }
+
+  /* command line initialised on 'run'*/
+
+  push_target (& remote_rdp_ops);
 
   callback->init (callback);
   flush_cached_frames ();
@@ -1192,6 +1345,54 @@ remote_rdp_files_info (target)
 }
 
 
+static void
+remote_rdp_create_inferior (exec_file, allargs, env)
+     char *  exec_file;
+     char *  allargs;
+     char ** env;
+{
+  CORE_ADDR entry_point;
+
+  if (exec_file == 0 || exec_bfd == 0)
+   error ("No exec file specified.");
+
+  entry_point = (CORE_ADDR) bfd_get_start_address (exec_bfd);
+
+  remote_rdp_kill ();   
+  remove_breakpoints ();
+  init_wait_for_inferior ();
+
+  /* This gives us a chance to set up the command line */
+  rdp_set_command_line (exec_file, allargs);
+
+  inferior_pid = 42;
+  insert_breakpoints ();  /* Needed to get correct instruction in cache */
+
+  /*
+  ** RDP targets don't provide any facility to set the top of memory,
+  ** so we don't bother to look for MEMSIZE in the environment.
+  */
+
+  /* Let's go! */
+  proceed (entry_point, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Accept any stray run/attach commands */
+static int
+remote_rdp_can_run()
+{
+  return 1;
+}
+
+/* Attach doesn't need to do anything */
+static void
+remote_rdp_attach(args, from_tty)
+     char * args;
+     int from_tty;
+{
+  return;
+}
+  
 /* Define the target subroutine names */
 
 struct target_ops remote_rdp_ops =
@@ -1203,7 +1404,7 @@ struct target_ops remote_rdp_ops =
   "Use a remote ARM system which uses the ARM Remote Debugging Protocol",
   remote_rdp_open,             /* to_open */
   remote_rdp_close,            /* to_close */
-  NULL,                                /* to_attach */
+  remote_rdp_attach,           /* to_attach */
   NULL,                                /* to_detach */
   remote_rdp_resume,           /* to_resume */
   remote_rdp_wait,             /* to_wait */
@@ -1222,9 +1423,9 @@ struct target_ops remote_rdp_ops =
   remote_rdp_kill,             /* to_kill */
   generic_load,                        /* to_load */
   NULL,                                /* to_lookup_symbol */
-  NULL,                                /* to_create_inferior */
+  remote_rdp_create_inferior,  /* to_create_inferior */
   generic_mourn_inferior,      /* to_mourn_inferior */
-  0,                           /* to_can_run */
+  remote_rdp_can_run,          /* to_can_run */
   0,                           /* to_notice_signals */
   0,                           /* to_thread_alive */
   0,                           /* to_stop */