Initial revision
diff --git a/tools/gdb/remote.c b/tools/gdb/remote.c
new file mode 100644
index 0000000..b8b2470
--- /dev/null
+++ b/tools/gdb/remote.c
@@ -0,0 +1,928 @@
+/*
+ * taken from gdb/remote.c
+ *
+ * I am only interested in the write to memory stuff - everything else
+ * has been ripped out
+ *
+ * all the copyright notices etc have been left in
+ */
+
+/* enough so that it will compile */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*nicked from gcc..*/
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc.  */
+#endif /* not GNU C.  */
+#ifdef __cplusplus
+extern "C" {
+#endif
+    void* alloca(size_t);
+#ifdef __cplusplus
+}
+#endif
+#endif /* alloca not defined.  */
+
+
+#include "serial.h"
+#include "error.h"
+#include "remote.h"
+#define REGISTER_BYTES 0
+#define fprintf_unfiltered fprintf
+#define fprintf_filtered fprintf
+#define fputs_unfiltered fputs
+#define fputs_filtered fputs
+#define fputc_unfiltered fputc
+#define fputc_filtered fputc
+#define printf_unfiltered printf
+#define printf_filtered printf
+#define puts_unfiltered puts
+#define puts_filtered puts
+#define putchar_unfiltered putchar
+#define putchar_filtered putchar
+#define fputstr_unfiltered(a,b,c) fputs((a), (c))
+#define gdb_stdlog stderr
+#define SERIAL_READCHAR(fd,timo)	serialreadchar((fd), (timo))
+#define SERIAL_WRITE(fd, addr, len)	serialwrite((fd), (addr), (len))
+#define error Error
+#define perror_with_name Perror
+#define gdb_flush fflush
+#define max(a,b) (((a)>(b))?(a):(b))
+#define min(a,b) (((a)<(b))?(a):(b))
+#define target_mourn_inferior() {}
+#define ULONGEST unsigned long
+#define CORE_ADDR unsigned long
+
+static int putpkt (char *);
+static int putpkt_binary(char *, int);
+static void getpkt (char *, int);
+
+static int remote_debug = 0, remote_register_buf_size = 0, watchdog = 0;
+
+int remote_desc = -1, remote_timeout = 10;
+
+static void
+fputstrn_unfiltered(char *s, int n, int x, FILE *fp)
+{
+    while (n-- > 0)
+	fputc(*s++, fp);
+}
+
+void
+remote_reset(void)
+{
+    SERIAL_WRITE(remote_desc, "+", 1);
+}
+
+void
+remote_continue(void)
+{
+    putpkt("c");
+}
+
+/* Remote target communications for serial-line targets in custom GDB protocol
+   Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+   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.  */
+/* *INDENT-OFF* */
+/* Remote communication protocol.
+
+   A debug packet whose contents are <data>
+   is encapsulated for transmission in the form:
+
+	$ <data> # CSUM1 CSUM2
+
+	<data> must be ASCII alphanumeric and cannot include characters
+	'$' or '#'.  If <data> starts with two characters followed by
+	':', then the existing stubs interpret this as a sequence number.
+
+	CSUM1 and CSUM2 are ascii hex representation of an 8-bit
+	checksum of <data>, the most significant nibble is sent first.
+	the hex digits 0-9,a-f are used.
+
+   Receiver responds with:
+
+	+	- if CSUM is correct and ready for next packet
+	-	- if CSUM is incorrect
+
+   <data> is as follows:
+   Most values are encoded in ascii hex digits.  Signal numbers are according
+   to the numbering in target.h.
+
+	Request		Packet
+
+	set thread	Hct...		Set thread for subsequent operations.
+					c = 'c' for thread used in step and
+					continue; t... can be -1 for all
+					threads.
+					c = 'g' for thread used in other
+					operations.  If zero, pick a thread,
+					any thread.
+	reply		OK		for success
+			ENN		for an error.
+
+	read registers  g
+	reply		XX....X		Each byte of register data
+					is described by two hex digits.
+					Registers are in the internal order
+					for GDB, and the bytes in a register
+					are in the same order the machine uses.
+			or ENN		for an error.
+
+	write regs	GXX..XX		Each byte of register data
+					is described by two hex digits.
+	reply		OK		for success
+			ENN		for an error
+
+        write reg	Pn...=r...	Write register n... with value r...,
+					which contains two hex digits for each
+					byte in the register (target byte
+					order).
+	reply		OK		for success
+			ENN		for an error
+	(not supported by all stubs).
+
+	read mem	mAA..AA,LLLL	AA..AA is address, LLLL is length.
+	reply		XX..XX		XX..XX is mem contents
+					Can be fewer bytes than requested
+					if able to read only part of the data.
+			or ENN		NN is errno
+
+	write mem	MAA..AA,LLLL:XX..XX
+					AA..AA is address,
+					LLLL is number of bytes,
+					XX..XX is data
+	reply		OK		for success
+			ENN		for an error (this includes the case
+					where only part of the data was
+					written).
+
+        write mem       XAA..AA,LLLL:XX..XX
+         (binary)                       AA..AA is address,
+                                        LLLL is number of bytes,
+                                        XX..XX is binary data
+        reply           OK              for success
+                        ENN             for an error
+
+	continue	cAA..AA		AA..AA is address to resume
+					If AA..AA is omitted,
+					resume at same address.
+
+	step		sAA..AA		AA..AA is address to resume
+					If AA..AA is omitted,
+					resume at same address.
+
+	continue with	Csig;AA..AA	Continue with signal sig (hex signal
+	signal				number).  If ;AA..AA is omitted,
+					resume at same address.
+
+	step with	Ssig;AA..AA	Like 'C' but step not continue.
+	signal
+
+	last signal     ?               Reply the current reason for stopping.
+                                        This is the same reply as is generated
+					for step or cont : SAA where AA is the
+					signal number.
+
+	detach          D               Reply OK.
+
+	There is no immediate reply to step or cont.
+	The reply comes when the machine stops.
+	It is		SAA		AA is the signal number.
+
+	or...		TAAn...:r...;n...:r...;n...:r...;
+					AA = signal number
+					n... = register number (hex)
+					  r... = register contents
+					n... = `thread'
+					  r... = thread process ID.  This is
+						 a hex integer.
+					n... = other string not starting
+					    with valid hex digit.
+					  gdb should ignore this n,r pair
+					  and go on to the next.  This way
+					  we can extend the protocol.
+	or...		WAA		The process exited, and AA is
+					the exit status.  This is only
+					applicable for certains sorts of
+					targets.
+	or...		XAA		The process terminated with signal
+					AA.
+	or (obsolete)	NAA;tttttttt;dddddddd;bbbbbbbb
+					AA = signal number
+					tttttttt = address of symbol "_start"
+					dddddddd = base of data section
+					bbbbbbbb = base of bss  section.
+					Note: only used by Cisco Systems
+					targets.  The difference between this
+					reply and the "qOffsets" query is that
+					the 'N' packet may arrive spontaneously
+					whereas the 'qOffsets' is a query
+					initiated by the host debugger.
+        or...           OXX..XX	XX..XX  is hex encoding of ASCII data. This
+					can happen at any time while the
+					program is running and the debugger
+					should continue to wait for
+					'W', 'T', etc.
+
+	thread alive	TXX		Find out if the thread XX is alive.
+	reply		OK		thread is still alive
+			ENN		thread is dead
+
+	remote restart	RXX		Restart the remote server
+
+	extended ops 	!		Use the extended remote protocol.
+					Sticky -- only needs to be set once.
+
+	kill request	k
+
+	toggle debug	d		toggle debug flag (see 386 & 68k stubs)
+	reset		r		reset -- see sparc stub.
+	reserved	<other>		On other requests, the stub should
+					ignore the request and send an empty
+					response ($#<checksum>).  This way
+					we can extend the protocol and GDB
+					can tell whether the stub it is
+					talking to uses the old or the new.
+	search		tAA:PP,MM	Search backwards starting at address
+					AA for a match with pattern PP and
+					mask MM.  PP and MM are 4 bytes.
+					Not supported by all stubs.
+
+	general query	qXXXX		Request info about XXXX.
+	general set	QXXXX=yyyy	Set value of XXXX to yyyy.
+	query sect offs	qOffsets	Get section offsets.  Reply is
+					Text=xxx;Data=yyy;Bss=zzz
+
+	Responses can be run-length encoded to save space.  A '*' means that
+	the next character is an ASCII encoding giving a repeat count which
+	stands for that many repititions of the character preceding the '*'.
+	The encoding is n+29, yielding a printable character where n >=3
+	(which is where rle starts to win).  Don't use an n > 126.
+
+	So
+	"0* " means the same as "0000".  */
+/* *INDENT-ON* */
+
+/* This variable (available to the user via "set remotebinarydownload")
+   dictates whether downloads are sent in binary (via the 'X' packet).
+   We assume that the stub can, and attempt to do it. This will be cleared if
+   the stub does not understand it. This switch is still needed, though
+   in cases when the packet is supported in the stub, but the connection
+   does not allow it (i.e., 7-bit serial connection only). */
+static int remote_binary_download = 1;
+
+/* Have we already checked whether binary downloads work? */
+static int remote_binary_checked;
+
+/* Maximum number of bytes to read/write at once.  The value here
+   is chosen to fill up a packet (the headers account for the 32).  */
+#define MAXBUFBYTES(N) (((N)-32)/2)
+
+/* Having this larger than 400 causes us to be incompatible with m68k-stub.c
+   and i386-stub.c.  Normally, no one would notice because it only matters
+   for writing large chunks of memory (e.g. in downloads).  Also, this needs
+   to be more than 400 if required to hold the registers (see below, where
+   we round it up based on REGISTER_BYTES).  */
+/* Round up PBUFSIZ to hold all the registers, at least.  */
+#define	PBUFSIZ ((REGISTER_BYTES > MAXBUFBYTES (400)) \
+		 ? (REGISTER_BYTES * 2 + 32) \
+		 : 400)
+
+
+/* This variable sets the number of bytes to be written to the target
+   in a single packet.  Normally PBUFSIZ is satisfactory, but some
+   targets need smaller values (perhaps because the receiving end
+   is slow).  */
+
+static int remote_write_size = 0x7fffffff;
+
+/* This variable sets the number of bits in an address that are to be
+   sent in a memory ("M" or "m") packet.  Normally, after stripping
+   leading zeros, the entire address would be sent. This variable
+   restricts the address to REMOTE_ADDRESS_SIZE bits.  HISTORY: The
+   initial implementation of remote.c restricted the address sent in
+   memory packets to ``host::sizeof long'' bytes - (typically 32
+   bits).  Consequently, for 64 bit targets, the upper 32 bits of an
+   address was never sent.  Since fixing this bug may cause a break in
+   some remote targets this variable is principly provided to
+   facilitate backward compatibility. */
+
+static int remote_address_size;
+
+/* Convert hex digit A to a number.  */
+
+static int
+fromhex (int a)
+{
+  if (a >= '0' && a <= '9')
+    return a - '0';
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else if (a >= 'A' && a <= 'F')
+    return a - 'A' + 10;
+  else {
+    error ("Reply contains invalid hex digit %d", a);
+    return -1;
+  }
+}
+
+/* Convert number NIB to a hex digit.  */
+
+static int
+tohex (int nib)
+{
+  if (nib < 10)
+    return '0' + nib;
+  else
+    return 'a' + nib - 10;
+}
+
+/* Return the number of hex digits in num.  */
+
+static int
+hexnumlen (ULONGEST num)
+{
+  int i;
+
+  for (i = 0; num != 0; i++)
+    num >>= 4;
+
+  return max (i, 1);
+}
+
+/* Set BUF to the hex digits representing NUM.  */
+
+static int
+hexnumstr (char *buf, ULONGEST num)
+{
+  int i;
+  int len = hexnumlen (num);
+
+  buf[len] = '\0';
+
+  for (i = len - 1; i >= 0; i--)
+    {
+      buf[i] = "0123456789abcdef"[(num & 0xf)];
+      num >>= 4;
+    }
+
+  return len;
+}
+
+/* Mask all but the least significant REMOTE_ADDRESS_SIZE bits. */
+
+static CORE_ADDR
+remote_address_masked (CORE_ADDR addr)
+{
+  if (remote_address_size > 0
+      && remote_address_size < (sizeof (ULONGEST) * 8))
+    {
+      /* Only create a mask when that mask can safely be constructed
+         in a ULONGEST variable. */
+      ULONGEST mask = 1;
+      mask = (mask << remote_address_size) - 1;
+      addr &= mask;
+    }
+  return addr;
+}
+
+/* Determine whether the remote target supports binary downloading.
+   This is accomplished by sending a no-op memory write of zero length
+   to the target at the specified address. It does not suffice to send
+   the whole packet, since many stubs strip the eighth bit and subsequently
+   compute a wrong checksum, which causes real havoc with remote_write_bytes.
+
+   NOTE: This can still lose if the serial line is not eight-bit clean. In
+   cases like this, the user should clear "remotebinarydownload". */
+static void
+check_binary_download (CORE_ADDR addr)
+{
+  if (remote_binary_download && !remote_binary_checked)
+    {
+      char *buf = alloca (PBUFSIZ);
+      char *p;
+      remote_binary_checked = 1;
+
+      p = buf;
+      *p++ = 'X';
+      p += hexnumstr (p, (ULONGEST) addr);
+      *p++ = ',';
+      p += hexnumstr (p, (ULONGEST) 0);
+      *p++ = ':';
+      *p = '\0';
+
+      putpkt_binary (buf, (int) (p - buf));
+      getpkt (buf, 0);
+
+      if (buf[0] == '\0')
+	remote_binary_download = 0;
+    }
+
+  if (remote_debug)
+    {
+      if (remote_binary_download)
+	fprintf_unfiltered (gdb_stdlog,
+			    "binary downloading suppported by target\n");
+      else
+	fprintf_unfiltered (gdb_stdlog,
+			    "binary downloading NOT suppported by target\n");
+    }
+}
+
+/* Write memory data directly to the remote machine.
+   This does not inform the data cache; the data cache uses this.
+   MEMADDR is the address in the remote memory space.
+   MYADDR is the address of the buffer in our space.
+   LEN is the number of bytes.
+
+   Returns number of bytes transferred, or 0 for error.  */
+
+int
+remote_write_bytes (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  unsigned char *buf = alloca (PBUFSIZ);
+  int max_buf_size;		/* Max size of packet output buffer */
+  int origlen;
+  extern int verbose;
+
+  /* Verify that the target can support a binary download */
+  check_binary_download (memaddr);
+
+  /* Chop the transfer down if necessary */
+
+  max_buf_size = min (remote_write_size, PBUFSIZ);
+  if (remote_register_buf_size != 0)
+    max_buf_size = min (max_buf_size, remote_register_buf_size);
+
+  /* Subtract header overhead from max payload size -  $M<memaddr>,<len>:#nn */
+  max_buf_size -= 2 + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 4;
+
+  origlen = len;
+  while (len > 0)
+    {
+      unsigned char *p, *plen;
+      int todo;
+      int i;
+
+      /* construct "M"<memaddr>","<len>":" */
+      /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */
+      memaddr = remote_address_masked (memaddr);
+      p = buf;
+      if (remote_binary_download)
+	{
+	  *p++ = 'X';
+	  todo = min (len, max_buf_size);
+	}
+      else
+	{
+	  *p++ = 'M';
+	  todo = min (len, max_buf_size / 2);	/* num bytes that will fit */
+	}
+
+      p += hexnumstr ((char *)p, (ULONGEST) memaddr);
+      *p++ = ',';
+
+      plen = p;			/* remember where len field goes */
+      p += hexnumstr ((char *)p, (ULONGEST) todo);
+      *p++ = ':';
+      *p = '\0';
+
+      /* We send target system values byte by byte, in increasing byte
+         addresses, each byte encoded as two hex characters (or one
+         binary character).  */
+      if (remote_binary_download)
+	{
+	  int escaped = 0;
+	  for (i = 0;
+	       (i < todo) && (i + escaped) < (max_buf_size - 2);
+	       i++)
+	    {
+	      switch (myaddr[i] & 0xff)
+		{
+		case '$':
+		case '#':
+		case 0x7d:
+		  /* These must be escaped */
+		  escaped++;
+		  *p++ = 0x7d;
+		  *p++ = (myaddr[i] & 0xff) ^ 0x20;
+		  break;
+		default:
+		  *p++ = myaddr[i] & 0xff;
+		  break;
+		}
+	    }
+
+	  if (i < todo)
+	    {
+	      /* Escape chars have filled up the buffer prematurely,
+	         and we have actually sent fewer bytes than planned.
+	         Fix-up the length field of the packet.  */
+
+	      /* FIXME: will fail if new len is a shorter string than
+	         old len.  */
+
+	      plen += hexnumstr ((char *)plen, (ULONGEST) i);
+	      *plen++ = ':';
+	    }
+	}
+      else
+	{
+	  for (i = 0; i < todo; i++)
+	    {
+	      *p++ = tohex ((myaddr[i] >> 4) & 0xf);
+	      *p++ = tohex (myaddr[i] & 0xf);
+	    }
+	  *p = '\0';
+	}
+
+      putpkt_binary ((char *)buf, (int) (p - buf));
+      getpkt ((char *)buf, 0);
+
+      if (buf[0] == 'E')
+	{
+	  /* There is no correspondance between what the remote protocol uses
+	     for errors and errno codes.  We would like a cleaner way of
+	     representing errors (big enough to include errno codes, bfd_error
+	     codes, and others).  But for now just return EIO.  */
+	  errno = EIO;
+	  return 0;
+	}
+
+      /* Increment by i, not by todo, in case escape chars
+         caused us to send fewer bytes than we'd planned.  */
+      myaddr += i;
+      memaddr += i;
+      len -= i;
+
+      if (verbose)
+	putc('.', stderr);
+    }
+  return origlen;
+}
+
+/* Stuff for dealing with the packets which are part of this protocol.
+   See comment at top of file for details.  */
+
+/* Read a single character from the remote end, masking it down to 7 bits. */
+
+static int
+readchar (int timeout)
+{
+  int ch;
+
+  ch = SERIAL_READCHAR (remote_desc, timeout);
+
+  switch (ch)
+    {
+    case SERIAL_EOF:
+      error ("Remote connection closed");
+    case SERIAL_ERROR:
+      perror_with_name ("Remote communication error");
+    case SERIAL_TIMEOUT:
+      return ch;
+    default:
+      return ch & 0x7f;
+    }
+}
+
+static int
+putpkt (buf)
+     char *buf;
+{
+  return putpkt_binary (buf, strlen (buf));
+}
+
+/* Send a packet to the remote machine, with error checking.  The data
+   of the packet is in BUF.  The string in BUF can be at most  PBUFSIZ - 5
+   to account for the $, # and checksum, and for a possible /0 if we are
+   debugging (remote_debug) and want to print the sent packet as a string */
+
+static int
+putpkt_binary (buf, cnt)
+     char *buf;
+     int cnt;
+{
+  int i;
+  unsigned char csum = 0;
+  char *buf2 = alloca (PBUFSIZ);
+  char *junkbuf = alloca (PBUFSIZ);
+
+  int ch;
+  int tcount = 0;
+  char *p;
+
+  /* Copy the packet into buffer BUF2, encapsulating it
+     and giving it a checksum.  */
+
+  if (cnt > BUFSIZ - 5)		/* Prosanity check */
+    abort ();
+
+  p = buf2;
+  *p++ = '$';
+
+  for (i = 0; i < cnt; i++)
+    {
+      csum += buf[i];
+      *p++ = buf[i];
+    }
+  *p++ = '#';
+  *p++ = tohex ((csum >> 4) & 0xf);
+  *p++ = tohex (csum & 0xf);
+
+  /* Send it over and over until we get a positive ack.  */
+
+  while (1)
+    {
+      int started_error_output = 0;
+
+      if (remote_debug)
+	{
+	  *p = '\0';
+	  fprintf_unfiltered (gdb_stdlog, "Sending packet: ");
+	  fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog);
+	  fprintf_unfiltered (gdb_stdlog, "...");
+	  gdb_flush (gdb_stdlog);
+	}
+      if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
+	perror_with_name ("putpkt: write failed");
+
+      /* read until either a timeout occurs (-2) or '+' is read */
+      while (1)
+	{
+	  ch = readchar (remote_timeout);
+
+	  if (remote_debug)
+	    {
+	      switch (ch)
+		{
+		case '+':
+		case SERIAL_TIMEOUT:
+		case '$':
+		  if (started_error_output)
+		    {
+		      putchar_unfiltered ('\n');
+		      started_error_output = 0;
+		    }
+		}
+	    }
+
+	  switch (ch)
+	    {
+	    case '+':
+	      if (remote_debug)
+		fprintf_unfiltered (gdb_stdlog, "Ack\n");
+	      return 1;
+	    case SERIAL_TIMEOUT:
+	      tcount++;
+	      if (tcount > 3)
+		return 0;
+	      break;		/* Retransmit buffer */
+	    case '$':
+	      {
+		/* It's probably an old response, and we're out of sync.
+		   Just gobble up the packet and ignore it.  */
+		getpkt (junkbuf, 0);
+		continue;	/* Now, go look for + */
+	      }
+	    default:
+	      if (remote_debug)
+		{
+		  if (!started_error_output)
+		    {
+		      started_error_output = 1;
+		      fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
+		    }
+		  fputc_unfiltered (ch & 0177, gdb_stdlog);
+		}
+	      continue;
+	    }
+	  break;		/* Here to retransmit */
+	}
+
+#if 0
+      /* This is wrong.  If doing a long backtrace, the user should be
+         able to get out next time we call QUIT, without anything as
+         violent as interrupt_query.  If we want to provide a way out of
+         here without getting to the next QUIT, it should be based on
+         hitting ^C twice as in remote_wait.  */
+      if (quit_flag)
+	{
+	  quit_flag = 0;
+	  interrupt_query ();
+	}
+#endif
+    }
+}
+
+/* Come here after finding the start of the frame.  Collect the rest
+   into BUF, verifying the checksum, length, and handling run-length
+   compression.  Returns 0 on any error, 1 on success.  */
+
+static int
+read_frame (char *buf)
+{
+  unsigned char csum;
+  char *bp;
+  int c;
+
+  csum = 0;
+  bp = buf;
+
+  while (1)
+    {
+      c = readchar (remote_timeout);
+
+      switch (c)
+	{
+	case SERIAL_TIMEOUT:
+	  if (remote_debug)
+	    fputs_filtered ("Timeout in mid-packet, retrying\n", gdb_stdlog);
+	  return 0;
+	case '$':
+	  if (remote_debug)
+	    fputs_filtered ("Saw new packet start in middle of old one\n",
+			    gdb_stdlog);
+	  return 0;		/* Start a new packet, count retries */
+	case '#':
+	  {
+	    unsigned char pktcsum;
+
+	    *bp = '\000';
+
+	    pktcsum = fromhex (readchar (remote_timeout)) << 4;
+	    pktcsum |= fromhex (readchar (remote_timeout));
+
+	    if (csum == pktcsum)
+	      {
+		return 1;
+	      }
+
+	    if (remote_debug)
+	      {
+		fprintf_filtered (gdb_stdlog,
+			      "Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
+				  pktcsum, csum);
+		fputs_filtered (buf, gdb_stdlog);
+		fputs_filtered ("\n", gdb_stdlog);
+	      }
+	    return 0;
+	  }
+	case '*':		/* Run length encoding */
+	  csum += c;
+	  c = readchar (remote_timeout);
+	  csum += c;
+	  c = c - ' ' + 3;	/* Compute repeat count */
+
+	  if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1)
+	    {
+	      memset (bp, *(bp - 1), c);
+	      bp += c;
+	      continue;
+	    }
+
+	  *bp = '\0';
+	  printf_filtered ("Repeat count %d too large for buffer: ", c);
+	  puts_filtered (buf);
+	  puts_filtered ("\n");
+	  return 0;
+	default:
+	  if (bp < buf + PBUFSIZ - 1)
+	    {
+	      *bp++ = c;
+	      csum += c;
+	      continue;
+	    }
+
+	  *bp = '\0';
+	  puts_filtered ("Remote packet too long: ");
+	  puts_filtered (buf);
+	  puts_filtered ("\n");
+
+	  return 0;
+	}
+    }
+}
+
+/* Read a packet from the remote machine, with error checking, and
+   store it in BUF.  BUF is expected to be of size PBUFSIZ.  If
+   FOREVER, wait forever rather than timing out; this is used while
+   the target is executing user code.  */
+
+static void
+getpkt (buf, forever)
+     char *buf;
+     int forever;
+{
+  int c;
+  int tries;
+  int timeout;
+  int val;
+
+  strcpy (buf, "timeout");
+
+  if (forever)
+    {
+      timeout = watchdog > 0 ? watchdog : -1;
+    }
+
+  else
+    timeout = remote_timeout;
+
+#define MAX_TRIES 3
+
+  for (tries = 1; tries <= MAX_TRIES; tries++)
+    {
+      /* This can loop forever if the remote side sends us characters
+         continuously, but if it pauses, we'll get a zero from readchar
+         because of timeout.  Then we'll count that as a retry.  */
+
+      /* Note that we will only wait forever prior to the start of a packet.
+         After that, we expect characters to arrive at a brisk pace.  They
+         should show up within remote_timeout intervals.  */
+
+      do
+	{
+	  c = readchar (timeout);
+
+	  if (c == SERIAL_TIMEOUT)
+	    {
+	      if (forever)	/* Watchdog went off.  Kill the target. */
+		{
+		  target_mourn_inferior ();
+		  error ("Watchdog has expired.  Target detached.\n");
+		}
+	      if (remote_debug)
+		fputs_filtered ("Timed out.\n", gdb_stdlog);
+	      goto retry;
+	    }
+	}
+      while (c != '$');
+
+      /* We've found the start of a packet, now collect the data.  */
+
+      val = read_frame (buf);
+
+      if (val == 1)
+	{
+	  if (remote_debug)
+	    {
+	      fprintf_unfiltered (gdb_stdlog, "Packet received: ");
+	      fputstr_unfiltered (buf, 0, gdb_stdlog);
+	      fprintf_unfiltered (gdb_stdlog, "\n");
+	    }
+	  SERIAL_WRITE (remote_desc, "+", 1);
+	  return;
+	}
+
+      /* Try the whole thing again.  */
+    retry:
+      SERIAL_WRITE (remote_desc, "-", 1);
+    }
+
+  /* We have tried hard enough, and just can't receive the packet.  Give up. */
+
+  printf_unfiltered ("Ignoring packet error, continuing...\n");
+  SERIAL_WRITE (remote_desc, "+", 1);
+}