* config/monitor.exp: Detect the "Couldn't establish connection"
[deliverable/binutils-gdb.git] / gdb / remote-mips.c
index 32655996fd1964bfb1d81bcf449865af4261fb72..26ed258a3201ddb7f44e1077b49c54fa3f71ffaf 100644 (file)
@@ -29,15 +29,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "serial.h"
 #include "target.h"
 #include "remote-utils.h"
+#include "gdb_string.h"
 
 #include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #ifdef ANSI_PROTOTYPES
 #include <stdarg.h>
 #else
 #include <varargs.h>
 #endif
 
-extern char *mips_read_processor_type PARAMS ((void));
+/* Microsoft C's stat.h doesn't define all the POSIX file modes.  */
+#ifndef S_IROTH
+#define S_IROTH S_IREAD
+#endif
 
 extern void mips_set_processor_type_command PARAMS ((char *, int));
 
@@ -58,17 +64,25 @@ static int mips_cksum PARAMS ((const unsigned char *hdr,
 
 static void mips_send_packet PARAMS ((const char *s, int get_ack));
 
+static void mips_send_command PARAMS ((const char *cmd, int prompt));
+
 static int mips_receive_packet PARAMS ((char *buff, int throw_error,
                                        int timeout));
 
-static int mips_request PARAMS ((int cmd, unsigned int addr,
-                                unsigned int data, int *perr, int timeout,
+static CORE_ADDR mips_request PARAMS ((int cmd, CORE_ADDR addr,
+                                CORE_ADDR data, int *perr, int timeout,
                                 char *buff));
 
 static void mips_initialize PARAMS ((void));
 
 static void mips_open PARAMS ((char *name, int from_tty));
 
+static void pmon_open PARAMS ((char *name, int from_tty));
+
+static void ddb_open PARAMS ((char *name, int from_tty));
+
+static void lsi_open PARAMS ((char *name, int from_tty));
+
 static void mips_close PARAMS ((int quitting));
 
 static void mips_detach PARAMS ((char *args, int from_tty));
@@ -78,6 +92,8 @@ static void mips_resume PARAMS ((int pid, int step,
 
 static int mips_wait PARAMS ((int pid, struct target_waitstatus *status));
 
+static int pmon_wait PARAMS ((int pid, struct target_waitstatus *status));
+
 static int mips_map_regno PARAMS ((int regno));
 
 static void mips_fetch_registers PARAMS ((int regno));
@@ -86,9 +102,9 @@ static void mips_prepare_to_store PARAMS ((void));
 
 static void mips_store_registers PARAMS ((int regno));
 
-static int mips_fetch_word PARAMS ((CORE_ADDR addr));
+static unsigned int mips_fetch_word PARAMS ((CORE_ADDR addr));
 
-static int mips_store_word PARAMS ((CORE_ADDR addr, int value,
+static int mips_store_word PARAMS ((CORE_ADDR addr, unsigned int value,
                                    char *old_contents));
 
 static int mips_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
@@ -101,6 +117,27 @@ static void mips_create_inferior PARAMS ((char *execfile, char *args,
 
 static void mips_mourn_inferior PARAMS ((void));
 
+static int pmon_makeb64 PARAMS ((unsigned long v, char *p, int n, int *chksum));
+
+static int pmon_zeroset PARAMS ((int recsize, char **buff, int *amount,
+                                 unsigned int *chksum));
+
+static int pmon_checkset PARAMS ((int recsize, char **buff, int *value));
+
+static void pmon_make_fastrec PARAMS ((char **outbuf, unsigned char *inbuf,
+                                       int *inptr, int inamount, int *recsize,
+                                       unsigned int *csum, unsigned int *zerofill));
+
+static int pmon_check_ack PARAMS ((char *mesg));
+
+static void pmon_start_download PARAMS ((void));
+
+static void pmon_end_download PARAMS ((int final, int bintotal));
+
+static void pmon_download PARAMS ((char *buffer, int length));
+
+static void pmon_load_fast PARAMS ((char *file));
+
 static void mips_load PARAMS ((char *file, int from_tty));
 
 static int mips_make_srec PARAMS ((char *buffer, int type, CORE_ADDR memaddr,
@@ -108,8 +145,13 @@ static int mips_make_srec PARAMS ((char *buffer, int type, CORE_ADDR memaddr,
 
 static int common_breakpoint PARAMS ((int cmd, CORE_ADDR addr, CORE_ADDR mask,
                                      char *flags));
-/* A forward declaration.  */
+
+static void common_open PARAMS ((struct target_ops *ops, char *name,
+                                 int from_tty));
+/* Forward declarations.  */
 extern struct target_ops mips_ops;
+extern struct target_ops pmon_ops;
+extern struct target_ops ddb_ops;
 \f
 /* The MIPS remote debugging interface is built on top of a simple
    packet protocol.  Each packet is organized as follows:
@@ -213,7 +255,7 @@ extern struct target_ops mips_ops;
   (((hdr)[HDR_INDX_TYPE_LEN] & TYPE_LEN_DA_BIT) == TYPE_LEN_DATA)
 #define HDR_GET_LEN(hdr) \
   ((((hdr)[HDR_INDX_TYPE_LEN] & 0x1f) << 6) + (((hdr)[HDR_INDX_LEN1] & 0x3f)))
-#define HDR_GET_SEQ(hdr) ((hdr)[HDR_INDX_SEQ] & 0x3f)
+#define HDR_GET_SEQ(hdr) ((unsigned int)(hdr)[HDR_INDX_SEQ] & 0x3f)
 
 /* The maximum data length.  */
 #define DATA_MAXLEN 1023
@@ -245,17 +287,51 @@ extern struct target_ops mips_ops;
 /* The sequence number modulos.  */
 #define SEQ_MODULOS (64)
 
+/* PMON commands to load from the serial port or UDP socket.  */
+#define LOAD_CMD       "load -b -s tty0\r"
+#define LOAD_CMD_UDP   "load -b -s udp\r"
+
+enum mips_monitor_type {
+  /* IDT/SIM monitor being used: */
+  MON_IDT,
+  /* PMON monitor being used: */
+  MON_PMON, /* 3.0.83 [COGENT,EB,FP,NET] Algorithmics Ltd. Nov  9 1995 17:19:50 */
+  MON_DDB,  /* 2.7.473 [DDBVR4300,EL,FP,NET] Risq Modular Systems,  Thu Jun 6 09:28:40 PDT 1996 */
+  MON_LSI,  /* 4.3.12 [EB,FP], LSI LOGIC Corp. Tue Feb 25 13:22:14 1997 */
+  /* Last and unused value, for sizing vectors, etc. */
+  MON_LAST
+};
+static enum mips_monitor_type mips_monitor = MON_LAST;
+
+/* The default monitor prompt text: */
+static char *mips_monitor_prompt = TARGET_MONITOR_PROMPT;
+/* For the Cogent PMON world this is still not ideal. The default
+   prompt is "PMON> ", unfortunately the user can change the prompt
+   and the new prompt will survive over a power-cycle (EEPROM). This
+   means that the code should really force the monitor prompt to a
+   known value as the very first action, and that the
+   "mips_monitor_prompt" support is not needed... since the prompt
+   could be explicitly set to TARGET_MONITOR_PROMPT (even though it
+   may be the prompt for a different monitor). However, this will
+   require changing the mips_initialize reset sequence. (TODO) */
+
 /* Set to 1 if the target is open.  */
 static int mips_is_open;
 
+/* Currently active target description (if mips_is_open == 1) */
+static struct target_ops *current_ops;
+
 /* Set to 1 while the connection is being initialized.  */
 static int mips_initializing;
 
+/* Set to 1 while the connection is being brought down.  */
+static int mips_exiting;
+
 /* The next sequence number to send.  */
-static int mips_send_seq;
+static unsigned int mips_send_seq;
 
 /* The next sequence number we expect to receive.  */
-static int mips_receive_seq;
+static unsigned int mips_receive_seq;
 
 /* The time to wait before retransmitting a packet, in seconds.  */
 static int mips_retransmit_wait = 3;
@@ -277,6 +353,17 @@ static int mips_need_reply = 0;
 /* Handle used to access serial I/O stream.  */
 static serial_t mips_desc;
 
+/* UDP handle used to download files to target.  */
+static serial_t udp_desc;
+static int udp_in_use;
+
+/* TFTP filename used to download files to DDB board, in the form
+   host:filename.  */
+static char *tftp_name;                /* host:filename */
+static char *tftp_localname;   /* filename portion of above */
+static int tftp_in_use;
+static FILE *tftp_file;
+
 /* Counts the number of times the user tried to interrupt the target (usually
    via ^C.  */
 static int interrupt_count;
@@ -289,11 +376,27 @@ static monitor_supports_breakpoints = 0;
 
 /* Data cache header.  */
 
+#if 0  /* not used (yet?) */
 static DCACHE *mips_dcache;
+#endif
 
 /* Non-zero means that we've just hit a read or write watchpoint */
 static int hit_watchpoint;
 
+static void
+close_ports()
+{
+  mips_is_open = 0;
+  SERIAL_CLOSE (mips_desc);
+
+  if (udp_in_use)
+    {
+      SERIAL_CLOSE (udp_desc);
+      udp_in_use = 0;
+    }
+  tftp_in_use = 0;
+}
+    
 /* Handle low-level error that we can't recover from.  Note that just
    error()ing out from target_wait or some such low-level place will cause
    all hell to break loose--the rest of GDB will tend to get left in an
@@ -330,8 +433,7 @@ mips_error (va_alist)
   /* Clean up in such a way that mips_close won't try to talk to the
      board (it almost surely won't work since we weren't able to talk to
      it).  */
-  mips_is_open = 0;
-  SERIAL_CLOSE (mips_desc);
+  close_ports ();
 
   printf_unfiltered ("Ending remote MIPS debugging.\n");
   target_mourn_inferior ();
@@ -339,34 +441,85 @@ mips_error (va_alist)
   return_to_top_level (RETURN_ERROR);
 }
 
+/* putc_readable - print a character, displaying non-printable chars in
+   ^x notation or in hex.  */
+
+static void
+putc_readable (ch)
+     int ch;
+{
+  if (ch == '\n')
+    putchar_unfiltered ('\n');
+  else if (ch == '\r')
+    printf_unfiltered ("\\r");
+  else if (ch < 0x20)  /* ASCII control character */
+    printf_unfiltered ("^%c", ch + '@');
+  else if (ch >= 0x7f) /* non-ASCII characters (rubout or greater) */
+    printf_unfiltered ("[%02x]", ch & 0xff);
+  else
+    putchar_unfiltered (ch);
+}
+
+
+/* puts_readable - print a string, displaying non-printable chars in
+   ^x notation or in hex.  */
+
+static void
+puts_readable (string)
+     char *string;
+{
+  int c;
+
+  while ((c = *string++) != '\0')
+    putc_readable (c);
+}
+
+
 /* Wait until STRING shows up in mips_desc.  Returns 1 if successful, else 0 if
-   timed out.  */
+   timed out.  TIMEOUT specifies timeout value in seconds.
+*/
 
 int
-mips_expect (string)
+mips_expect_timeout (string, timeout)
      char *string;
+     int timeout;
 {
   char *p = string;
-  int c;
+
+  if (remote_debug)
+    {
+      printf_unfiltered ("Expected \"");
+      puts_readable (string);
+      printf_unfiltered ("\", got \"");
+    }
 
   immediate_quit = 1;
   while (1)
     {
+      int c;
 
 /* Must use SERIAL_READCHAR here cuz mips_readchar would get confused if we
-   were waiting for the TARGET_MONITOR_PROMPT... */
+   were waiting for the mips_monitor_prompt... */
 
-      c = SERIAL_READCHAR (mips_desc, 2);
+      c = SERIAL_READCHAR (mips_desc, timeout);
 
       if (c == SERIAL_TIMEOUT)
-       return 0;
+       {
+         if (remote_debug)
+           printf_unfiltered ("\": FAIL\n");
+         return 0;
+       }
+
+      if (remote_debug)
+       putc_readable (c);
 
       if (c == *p++)
        {       
          if (*p == '\0')
            {
              immediate_quit = 0;
-
+             if (remote_debug)
+             printf_unfiltered ("\": OK\n");
              return 1;
            }
        }
@@ -379,9 +532,48 @@ mips_expect (string)
     }
 }
 
+/* Wait until STRING shows up in mips_desc.  Returns 1 if successful, else 0 if
+   timed out.  The timeout value is hard-coded to 2 seconds.  Use
+   mips_expect_timeout if a different timeout value is needed.
+*/
+
+int
+mips_expect (string)
+     char *string;
+{
+    return mips_expect_timeout (string, 2);
+}
+
+/* Read the required number of characters into the given buffer (which
+   is assumed to be large enough). The only failure is a timeout. */
+int
+mips_getstring (string, n)
+     char *string;
+     int n;
+{
+  char *p = string;
+  int c;
+
+  immediate_quit = 1;
+  while (n > 0)
+    {
+      c = SERIAL_READCHAR (mips_desc, 2);
+
+      if (c == SERIAL_TIMEOUT) {
+        fprintf_unfiltered (stderr, "Failed to read %d characters from target (TIMEOUT)\n", n);
+       return 0;
+      }
+
+      *p++ = c;
+      n--;
+    }
+
+  return 1;
+}
+
 /* Read a character from the remote, aborting on error.  Returns
    SERIAL_TIMEOUT on timeout (since that's what SERIAL_READCHAR
-   returns).  FIXME: If we see the string TARGET_MONITOR_PROMPT from
+   returns).  FIXME: If we see the string mips_monitor_prompt from
    the board, then we are debugging on the main console port, and we
    have somehow dropped out of remote debugging mode.  In this case,
    we automatically go back in to remote debugging mode.  This is a
@@ -399,16 +591,24 @@ mips_readchar (timeout)
 {
   int ch;
   static int state = 0;
-  static char nextstate[] = TARGET_MONITOR_PROMPT;
+  static int mips_monitor_prompt_len = -1;
+
+  /* NASTY, since we assume that the prompt does not change after the
+     first mips_readchar call: */
+  if (mips_monitor_prompt_len == -1)
+   mips_monitor_prompt_len = strlen(mips_monitor_prompt);
+
 #ifdef MAINTENANCE_CMDS
-  int i;
+  {
+    int i;
 
-  i = timeout;
-  if (i == -1 && watchdog > 0)
-    i = watchdog;
+    i = timeout;
+    if (i == -1 && watchdog > 0)
+     i = watchdog;
+  }
 #endif
 
-  if (state == (sizeof(nextstate) / sizeof(char)))
+  if (state == mips_monitor_prompt_len)
     timeout = 1;
   ch = SERIAL_READCHAR (mips_desc, timeout);
 #ifdef MAINTENANCE_CMDS
@@ -432,14 +632,15 @@ mips_readchar (timeout)
        printf_unfiltered ("Timed out in read\n");
     }
 
-  /* If we have seen TARGET_MONITOR_PROMPT and we either time out, or
+  /* If we have seen mips_monitor_prompt and we either time out, or
      we see a @ (which was echoed from a packet we sent), reset the
      board as described above.  The first character in a packet after
      the SYN (which is not echoed) is always an @ unless the packet is
      more than 64 characters long, which ours never are.  */
   if ((ch == SERIAL_TIMEOUT || ch == '@')
-      && state == (sizeof(nextstate) / sizeof(char))
-      && ! mips_initializing)
+      && state == mips_monitor_prompt_len
+      && ! mips_initializing
+      && ! mips_exiting)
     {
       if (remote_debug > 0)
        /* Don't use _filtered; we can't deal with a QUIT out of
@@ -457,7 +658,7 @@ mips_readchar (timeout)
       error ("Remote board reset, debug protocol re-initialized.");
     }
 
-  if (ch == nextstate[state])
+  if (ch == mips_monitor_prompt[state])
     ++state;
   else
     state = 0;
@@ -489,7 +690,7 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
        {
          ch = mips_readchar (timeout);
          if (ch == SERIAL_TIMEOUT)
-           return -1;
+           return -1;
          if (ch != SYN)
            {
              /* Printing the character here lets the user of gdb see
@@ -498,18 +699,13 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
                 we can't deal with a QUIT out of target_wait.  */
              if (! mips_initializing || remote_debug > 0)
                {
-                 if (ch < 0x20 && ch != '\n')
-                   {
-                     putchar_unfiltered ('^');
-                     putchar_unfiltered (ch + 0x40);
-                   }
-                 else
-                   putchar_unfiltered (ch);
+                 putc_readable (ch);
                  gdb_flush (gdb_stdout);
                }
 
              ++*pgarbage;
-             if (*pgarbage > mips_syn_garbage)
+             if (mips_syn_garbage > 0
+                 && *pgarbage > mips_syn_garbage)
                mips_error ("Debug protocol failure:  more than %d characters before a sync.", 
                            mips_syn_garbage);
            }
@@ -520,8 +716,7 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
        {
          ch = mips_readchar (timeout);
          if (ch == SERIAL_TIMEOUT)
-           return -1;
-
+            return -1;
          /* Make sure this is a header byte.  */
          if (ch == SYN || ! HDR_CHECK (ch))
            break;
@@ -532,7 +727,7 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
       /* If we got the complete header, we can return.  Otherwise we
         loop around and keep looking for SYN.  */
       if (i >= HDR_LENGTH)
-       return 0;
+        return 0;
     }
 }
 
@@ -600,7 +795,7 @@ mips_send_packet (s, get_ack)
      const char *s;
      int get_ack;
 {
-  unsigned int len;
+  /* unsigned */ int len;
   unsigned char *packet;
   register int cksum;
   int try;
@@ -657,7 +852,7 @@ mips_send_packet (s, get_ack)
          unsigned char hdr[HDR_LENGTH + 1];
          unsigned char trlr[TRLR_LENGTH + 1];
          int err;
-         int seq;
+         unsigned int seq;
 
          /* Get the packet header.  If we time out, resend the data
             packet.  */
@@ -671,8 +866,36 @@ mips_send_packet (s, get_ack)
             ignore it.  FIXME: If the acknowledgement is lost, this
             data packet may be the packet the remote sends after the
             acknowledgement.  */
-         if (HDR_IS_DATA (hdr))
+         if (HDR_IS_DATA (hdr)) {
+            int i;
+
+            /* Ignore any errors raised whilst attempting to ignore
+               packet. */
+
+            len = HDR_GET_LEN (hdr);
+
+            for (i = 0; i < len; i++)
+              {
+                int rch;
+
+                rch = mips_readchar (2);
+                if (rch == SYN)
+                  {
+                    ch = SYN;
+                    break;
+                  }
+                if (rch == SERIAL_TIMEOUT)
+                  break;
+                /* ignore the character */
+              }
+
+            if (i == len)
+              (void) mips_receive_trailer (trlr, &garbage, &ch, 2);
+
+            /* We don't bother checking the checksum, or providing an
+               ACK to the packet. */
            continue;
+          }
 
          /* If the length is not 0, this is a garbled packet.  */
          if (HDR_GET_LEN (hdr) != 0)
@@ -767,6 +990,15 @@ mips_receive_packet (buff, throw_error, timeout)
       /* An acknowledgement is probably a duplicate; ignore it.  */
       if (! HDR_IS_DATA (hdr))
        {
+          len = HDR_GET_LEN (hdr);
+          /* Check if the length is valid for an ACK, we may aswell
+             try and read the remainder of the packet: */
+          if (len == 0)
+            {
+              /* Ignore the error condition, since we are going to
+                 ignore the packet anyway. */
+              (void) mips_receive_trailer (trlr, &garbage, &ch, timeout);
+            }
          /* Don't use _filtered; we can't deal with a QUIT out of
             target_wait, and I think this might be called from there.  */
          if (remote_debug > 0)
@@ -774,19 +1006,7 @@ mips_receive_packet (buff, throw_error, timeout)
          continue;
        }
 
-      /* If this is the wrong sequence number, ignore it.  */
-      if (HDR_GET_SEQ (hdr) != mips_receive_seq)
-       {
-         /* Don't use _filtered; we can't deal with a QUIT out of
-            target_wait, and I think this might be called from there.  */
-         if (remote_debug > 0)
-           printf_unfiltered ("Ignoring sequence number %d (want %d)\n",
-                            HDR_GET_SEQ (hdr), mips_receive_seq);
-         continue;
-       }
-
       len = HDR_GET_LEN (hdr);
-
       for (i = 0; i < len; i++)
        {
          int rch;
@@ -834,8 +1054,19 @@ mips_receive_packet (buff, throw_error, timeout)
          continue;
        }
 
+      /* If this is the wrong sequence number, ignore it.  */
+      if (HDR_GET_SEQ (hdr) != mips_receive_seq)
+       {
+         /* Don't use _filtered; we can't deal with a QUIT out of
+            target_wait, and I think this might be called from there.  */
+         if (remote_debug > 0)
+           printf_unfiltered ("Ignoring sequence number %d (want %d)\n",
+                            HDR_GET_SEQ (hdr), mips_receive_seq);
+         continue;
+       }
+
       if (mips_cksum (hdr, buff, len) == TRLR_GET_CKSUM (trlr))
-       break;
+        break;
 
       if (remote_debug > 0)
        /* Don't use _filtered; we can't deal with a QUIT out of
@@ -942,11 +1173,11 @@ mips_receive_packet (buff, throw_error, timeout)
    occurs, it sets *PERR to 1 and sets errno according to what the
    target board reports.  */
 
-static int
+static CORE_ADDR 
 mips_request (cmd, addr, data, perr, timeout, buff)
      int cmd;
-     unsigned int addr;
-     unsigned int data;
+     CORE_ADDR addr;
+     CORE_ADDR data;
      int *perr;
      int timeout;
      char *buff;
@@ -965,7 +1196,7 @@ mips_request (cmd, addr, data, perr, timeout, buff)
     {
       if (mips_need_reply)
        fatal ("mips_request: Trying to send command before reply");
-      sprintf (buff, "0x0 %c 0x%x 0x%x", cmd, addr, data);
+      sprintf (buff, "0x0 %c 0x%s 0x%s", cmd, paddr_nz (addr), paddr_nz (data));
       mips_send_packet (buff, 1);
       mips_need_reply = 1;
     }
@@ -1010,13 +1241,103 @@ mips_initialize_cleanups (arg)
   mips_initializing = 0;
 }
 
+static void
+mips_exit_cleanups (arg)
+     PTR arg;
+{
+  mips_exiting = 0;
+}
+
+static void
+mips_send_command (cmd, prompt)
+     const char *cmd;
+     int prompt;
+{
+  SERIAL_WRITE (mips_desc, cmd, strlen(cmd));
+  mips_expect (cmd);
+  mips_expect ("\n");
+  if (prompt)
+    mips_expect (mips_monitor_prompt);
+}
+
+/* Enter remote (dbx) debug mode: */
+static void
+mips_enter_debug ()
+{
+  /* Reset the sequence numbers, ready for the new debug sequence: */
+  mips_send_seq = 0;
+  mips_receive_seq = 0;
+
+  if (mips_monitor != MON_IDT)
+    mips_send_command ("debug\r", 0);
+  else /* assume IDT monitor by default */
+    mips_send_command ("db tty0\r", 0);
+
+  SERIAL_WRITE (mips_desc, "\r", sizeof "\r" - 1);
+
+  /* We don't need to absorb any spurious characters here, since the
+     mips_receive_header will eat up a reasonable number of characters
+     whilst looking for the SYN, however this avoids the "garbage"
+     being displayed to the user. */
+  if (mips_monitor != MON_IDT)
+    mips_expect ("\r");
+  
+  {
+    char buff[DATA_MAXLEN + 1];
+    if (mips_receive_packet (buff, 1, 3) < 0)
+      mips_error ("Failed to initialize (didn't receive packet).");
+  }
+}
+
+/* Exit remote (dbx) debug mode, returning to the monitor prompt: */
+static int
+mips_exit_debug ()
+{
+  int err;
+  struct cleanup *old_cleanups = make_cleanup (mips_exit_cleanups, NULL);
+
+  mips_exiting = 1;
+
+  if (mips_monitor != MON_IDT)
+    {
+      /* The DDB (NEC) and MiniRISC (LSI) versions of PMON exit immediately,
+         so we do not get a reply to this command: */
+      mips_request ('x', (unsigned int) 0, (unsigned int) 0, NULL,
+               mips_receive_wait, NULL);
+      mips_need_reply = 0;
+      if (!mips_expect (" break!"))
+        return -1;
+    }
+  else
+    mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err,
+                  mips_receive_wait, NULL);
+
+  if (mips_monitor == MON_IDT && !mips_expect ("Exiting remote debug mode"))
+    return -1;
+    
+  if (mips_monitor == MON_DDB)
+    {
+      if (!mips_expect ("\n"))
+        return -1;
+    }
+  else
+    if (!mips_expect ("\r\n"))
+      return -1;
+
+  if (!mips_expect (mips_monitor_prompt))
+    return -1;
+
+  do_cleanups (old_cleanups);
+
+  return 0;
+}
+
 /* Initialize a new connection to the MIPS board, and make sure we are
    really connected.  */
 
 static void
 mips_initialize ()
 {
-  char buff[DATA_MAXLEN + 1];
   int err;
   struct cleanup *old_cleanups = make_cleanup (mips_initialize_cleanups, NULL);
   int j;
@@ -1034,19 +1355,23 @@ mips_initialize ()
   mips_wait_flag = 0;
   mips_initializing = 1;
 
-  mips_send_seq = 0;
-  mips_receive_seq = 0;
-
   /* At this point, the packit protocol isn't responding.  We'll try getting
      into the monitor, and restarting the protocol.  */
 
-  /* Force the system into the IDT monitor.  After this we *should* be at the
-     <IDT> prompt.  */
-
-  for (j = 1; j <= 4; j++)
+  /* Force the system into the monitor.  After this we *should* be at
+     the mips_monitor_prompt.  */
+  if (mips_monitor != MON_IDT)
+    j = 0; /* start by checking if we are already at the prompt */
+  else
+    j = 1; /* start by sending a break */
+  for (; j <= 4; j++)
     {
       switch (j)
        {
+        case 0:                 /* First, try sending a CR */
+          SERIAL_FLUSH_INPUT (mips_desc);
+         SERIAL_WRITE (mips_desc, "\r", 1);
+          break;
        case 1:                 /* First, try sending a break */
          SERIAL_SEND_BREAK (mips_desc);
          break;
@@ -1055,48 +1380,75 @@ mips_initialize ()
          break;
        case 3:                 /* Then, try escaping from download */
          {
-           int i;
-           char srec[10];
-
-           /* We are possibly in binary download mode, having aborted in the
-              middle of an S-record.  ^C won't work because of binary mode.
-              The only reliable way out is to send enough termination packets
-              (8 bytes) to fill up and then overflow the largest size S-record
-              (255 bytes in this case).  This amounts to 256/8 + 1 packets.
-              */
-
-           mips_make_srec (srec, '7', 0, NULL, 0);
-
-           for (i = 1; i <= 33; i++)
-             {
-               SERIAL_WRITE (mips_desc, srec, 8);
-
-               if (SERIAL_READCHAR (mips_desc, 0) >= 0)
-                 break;        /* Break immediatly if we get something from
+            if (mips_monitor != MON_IDT)
+              {
+                char tbuff[7];
+
+                /* We shouldn't need to send multiple termination
+                   sequences, since the target performs line (or
+                   block) reads, and then processes those
+                   packets. In-case we were downloading a large packet
+                   we flush the output buffer before inserting a
+                   termination sequence. */
+                SERIAL_FLUSH_OUTPUT (mips_desc);
+                sprintf (tbuff, "\r/E/E\r");
+                SERIAL_WRITE (mips_desc, tbuff, 6);
+              }
+            else
+              {
+                char srec[10];
+                int i;
+
+                /* We are possibly in binary download mode, having
+                   aborted in the middle of an S-record.  ^C won't
+                   work because of binary mode.  The only reliable way
+                   out is to send enough termination packets (8 bytes)
+                   to fill up and then overflow the largest size
+                   S-record (255 bytes in this case).  This amounts to
+                   256/8 + 1 packets.
+                   */
+
+                mips_make_srec (srec, '7', 0, NULL, 0);
+
+                for (i = 1; i <= 33; i++)
+                  {
+                    SERIAL_WRITE (mips_desc, srec, 8);
+
+                    if (SERIAL_READCHAR (mips_desc, 0) >= 0)
+                      break;   /* Break immediatly if we get something from
                                   the board. */
-             }
-           break;
-         case 4:
-           mips_error ("Failed to initialize.");
-         }
-
-         if (mips_expect (TARGET_MONITOR_PROMPT))
-           break;
+                  }
+              }
+          }
+         break;
+       case 4:
+         mips_error ("Failed to initialize.");
        }
 
-      SERIAL_WRITE (mips_desc, "db tty0\015", sizeof "db tty0\015" - 1);
-      mips_expect ("db tty0\015\012"); /* Eat the echo */
-
-      SERIAL_WRITE (mips_desc, "\015", sizeof "\015" - 1);
+      if (mips_expect (mips_monitor_prompt))
+       break;
+    }
 
-      if (mips_receive_packet (buff, 1, 3) < 0)
-       mips_error ("Failed to initialize (didn't receive packet).");
+  if (mips_monitor != MON_IDT)
+    {
+      /* Ensure the correct target state: */
+      if (mips_monitor != MON_LSI)
+       mips_send_command ("set regsize 64\r", -1);
+      mips_send_command ("set hostport tty0\r", -1);
+      mips_send_command ("set brkcmd \"\"\r", -1);
+      /* Delete all the current breakpoints: */
+      mips_send_command ("db *\r", -1);
+      /* NOTE: PMON does not have breakpoint support through the
+         "debug" mode, only at the monitor command-line. */
     }
 
-  if (common_breakpoint ('b', -1, 0, NULL)) /* Clear all breakpoints */
-    monitor_supports_breakpoints = 0; /* Failed, don't use it anymore */
-  else
+  mips_enter_debug ();
+
+  /* Clear all breakpoints: */
+  if (mips_monitor == MON_IDT && common_breakpoint ('b', -1, 0, NULL) == 0)
     monitor_supports_breakpoints = 1;
+  else
+    monitor_supports_breakpoints = 0;
 
   do_cleanups (old_cleanups);
 
@@ -1110,48 +1462,107 @@ mips_initialize ()
 }
 
 /* Open a connection to the remote board.  */
-
 static void
-mips_open (name, from_tty)
+common_open (ops, name, from_tty)
+     struct target_ops *ops;
      char *name;
      int from_tty;
 {
   char *ptype;
+  char *serial_port_name;
+  char *remote_name = 0;
+  char *local_name = 0;
+  char **argv;
 
   if (name == 0)
     error (
 "To open a MIPS remote debugging connection, you need to specify what serial\n\
-device is attached to the target board (e.g., /dev/ttya).");
+device is attached to the target board (e.g., /dev/ttya).\n"
+"If you want to use TFTP to download to the board, specify the name of a\n"
+"temporary file to be used by GDB for downloads as the second argument.\n"
+"This filename must be in the form host:filename, where host is the name\n"
+"of the host running the TFTP server, and the file must be readable by the\n"
+"world.  If the local name of the temporary file differs from the name as\n"
+"seen from the board via TFTP, specify that name as the third parameter.\n");
+
+  /* Parse the serial port name, the optional TFTP name, and the
+     optional local TFTP name.  */
+  if ((argv = buildargv (name)) == NULL)
+    nomem(0);
+  make_cleanup (freeargv, (char *) argv);
+
+  serial_port_name = strsave (argv[0]);
+  if (argv[1])                         /* remote TFTP name specified? */
+    {
+      remote_name = argv[1];
+      if (argv[2])                     /* local TFTP filename specified? */
+       local_name = argv[2];
+    }
 
   target_preopen (from_tty);
 
   if (mips_is_open)
-    unpush_target (&mips_ops);
+    unpush_target (current_ops);
 
-  mips_desc = SERIAL_OPEN (name);
+  /* Open and initialize the serial port.  */
+  mips_desc = SERIAL_OPEN (serial_port_name);
   if (mips_desc == (serial_t) NULL)
-    perror_with_name (name);
+    perror_with_name (serial_port_name);
 
   if (baud_rate != -1)
     {
       if (SERIAL_SETBAUDRATE (mips_desc, baud_rate))
         {
           SERIAL_CLOSE (mips_desc);
-          perror_with_name (name);
+          perror_with_name (serial_port_name);
         }
     }
 
   SERIAL_RAW (mips_desc);
 
+  /* Open and initialize the optional download port.  If it is in the form
+     hostname#portnumber, it's a UDP socket.  If it is in the form
+     hostname:filename, assume it's the TFTP filename that must be
+     passed to the DDB board to tell it where to get the load file.  */
+  if (remote_name)
+    {
+      if (strchr (remote_name, '#'))
+       {
+         udp_desc = SERIAL_OPEN (remote_name);
+         if (!udp_desc)
+           perror_with_name ("Unable to open UDP port");
+         udp_in_use = 1;
+       }
+      else
+       {
+         /* Save the remote and local names of the TFTP temp file.  If
+            the user didn't specify a local name, assume it's the same
+            as the part of the remote name after the "host:".  */
+         if (tftp_name)
+           free (tftp_name);
+         if (tftp_localname)
+           free (tftp_localname);
+         if (local_name == NULL)
+             if ((local_name = strchr (remote_name, ':')) != NULL)
+               local_name++;           /* skip over the colon */
+         if (local_name == NULL)
+           local_name = remote_name;   /* local name same as remote name */
+         tftp_name = strsave (remote_name);
+         tftp_localname = strsave (local_name);
+         tftp_in_use = 1;
+       }
+    }
+
+  current_ops = ops;
   mips_is_open = 1;
 
   mips_initialize ();
 
   if (from_tty)
-    printf_unfiltered ("Remote MIPS debugging using %s\n", name);
+    printf_unfiltered ("Remote MIPS debugging using %s\n", serial_port_name);
 
   /* Switch to using remote target now.  */
-  push_target (&mips_ops);
+  push_target (ops);
 
   /* FIXME: Should we call start_remote here?  */
 
@@ -1171,6 +1582,50 @@ device is attached to the target board (e.g., /dev/ttya).");
   set_current_frame (create_new_frame (read_fp (), stop_pc));
   select_frame (get_current_frame (), 0);
   print_stack_frame (selected_frame, -1, 1);
+  free (serial_port_name);
+}
+
+static void
+mips_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  mips_monitor = MON_IDT;
+  common_open (&mips_ops, name, from_tty);
+}
+
+static void
+pmon_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  /* The PMON monitor has a prompt different from the default
+     "TARGET_MONITOR_PROMPT": */
+  mips_monitor_prompt = "PMON> ";
+  mips_monitor = MON_PMON;
+  common_open (&pmon_ops, name, from_tty);
+}
+
+static void
+ddb_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  /* The PMON monitor has a prompt different from the default
+     "TARGET_MONITOR_PROMPT": */
+  mips_monitor_prompt = "NEC010>";
+  mips_monitor = MON_DDB;
+  common_open (&ddb_ops, name, from_tty);
+}
+
+static void
+lsi_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  mips_monitor_prompt = "PMON> ";
+  mips_monitor = MON_LSI;
+  common_open (&ddb_ops, name, from_tty);
 }
 
 /* Close a connection to the remote board.  */
@@ -1181,15 +1636,10 @@ mips_close (quitting)
 {
   if (mips_is_open)
     {
-      int err;
-
-      mips_is_open = 0;
-
       /* Get the board out of remote debugging mode.  */
-      mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err,
-                   mips_receive_wait, NULL);
+      (void) mips_exit_debug ();
 
-      SERIAL_CLOSE (mips_desc);
+      close_ports ();
     }
 }
 
@@ -1219,6 +1669,7 @@ mips_resume (pid, step, siggnal)
      int pid, step;
      enum target_signal siggnal;
 {
+  int err;
 
 /* start-sanitize-gm */
 #ifndef GENERAL_MAGIC
@@ -1229,10 +1680,12 @@ mips_resume (pid, step, siggnal)
 #endif /* GENERAL_MAGIC */
 /* end-sanitize-gm */
 
+  /* LSI PMON requires returns a reply packet "0x1 s 0x0 0x57f" after
+     a single step, so we wait for that.  */
   mips_request (step ? 's' : 'c',
                (unsigned int) 1,
                (unsigned int) siggnal,
-               (int *) NULL,
+               mips_monitor == MON_LSI && step ? &err : (int *) NULL,
                mips_receive_wait, NULL);
 }
 
@@ -1346,25 +1799,102 @@ mips_wait (pid, status)
   return 0;
 }
 
-/* We have to map between the register numbers used by gdb and the
-   register numbers used by the debugging protocol.  This function
-   assumes that we are using tm-mips.h.  */
-
-#define REGNO_OFFSET 96
-
 static int
-mips_map_regno (regno)
-     int regno;
+pmon_wait (pid, status)
+     int pid;
+     struct target_waitstatus *status;
 {
-  if (regno < 32)
-    return regno;
-  if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
-    return regno - FP0_REGNUM + 32;
-  switch (regno)
+  int rstatus;
+  int err;
+  char buff[DATA_MAXLEN];
+
+  interrupt_count = 0;
+  hit_watchpoint = 0;
+
+  /* If we have not sent a single step or continue command, then the
+     board is waiting for us to do something.  Return a status
+     indicating that it is stopped.  */
+  if (! mips_need_reply)
     {
-    case PC_REGNUM:
-      return REGNO_OFFSET + 0;
-    case CAUSE_REGNUM:
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TRAP;
+      return 0;
+    }
+
+  /* Sit, polling the serial until the target decides to talk to
+     us. NOTE: the timeout value we use is used not just for the
+     first character, but for all the characters. */
+  mips_wait_flag = 1;
+  rstatus = mips_request ('\000', (unsigned int) 0, (unsigned int) 0, &err, -1,
+                         buff);
+  mips_wait_flag = 0;
+  if (err)
+    mips_error ("Remote failure: %s", safe_strerror (errno));
+
+  /* NOTE: The following (sig) numbers are defined by PMON:
+       SPP_SIGTRAP     5       breakpoint
+        SPP_SIGINT      2
+        SPP_SIGSEGV     11
+        SPP_SIGBUS      10
+        SPP_SIGILL      4
+        SPP_SIGFPE      8
+        SPP_SIGTERM     15 */
+
+  /* On returning from a continue, the PMON monitor seems to start
+     echoing back the messages we send prior to sending back the
+     ACK. The code can cope with this, but to try and avoid the
+     unnecessary serial traffic, and "spurious" characters displayed
+     to the user, we cheat and reset the debug protocol. The problems
+     seems to be caused by a check on the number of arguments, and the
+     command length, within the monitor causing it to echo the command
+     as a bad packet. */
+  if (mips_monitor != MON_DDB && mips_monitor != MON_LSI)
+    {
+      mips_exit_debug ();
+      mips_enter_debug ();
+    }
+
+  /* Translate a MIPS waitstatus.  We use constants here rather than WTERMSIG
+     and so on, because the constants we want here are determined by the
+     MIPS protocol and have nothing to do with what host we are running on.  */
+  if ((rstatus & 0377) == 0)
+    {
+      status->kind = TARGET_WAITKIND_EXITED;
+      status->value.integer = (((rstatus) >> 8) & 0377);
+    }
+  else if ((rstatus & 0377) == 0177)
+    {
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = mips_signal_from_protocol (((rstatus) >> 8) & 0377);
+    }
+  else
+    {
+      status->kind = TARGET_WAITKIND_SIGNALLED;
+      status->value.sig = mips_signal_from_protocol (rstatus & 0177);
+    }
+
+  return 0;
+}
+
+/* We have to map between the register numbers used by gdb and the
+   register numbers used by the debugging protocol.  This function
+   assumes that we are using tm-mips.h.  */
+
+#define REGNO_OFFSET 96
+
+static int
+mips_map_regno (regno)
+     int regno;
+{
+  if (regno < 32)
+    return regno;
+  if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+    return regno - FP0_REGNUM + 32;
+  switch (regno)
+    {
+    case PC_REGNUM:
+      return REGNO_OFFSET + 0;
+    case CAUSE_REGNUM:
       return REGNO_OFFSET + 1;
     case HI_REGNUM:
       return REGNO_OFFSET + 2;
@@ -1402,11 +1932,26 @@ mips_fetch_registers (regno)
     val = 0;
   else
     {
-      val = mips_request ('r', (unsigned int) mips_map_regno (regno),
-                         (unsigned int) 0, &err, mips_receive_wait, NULL);
-      if (err)
-       mips_error ("Can't read register %d: %s", regno,
-                   safe_strerror (errno));
+      /* If PMON doesn't support this register, don't waste serial
+         bandwidth trying to read it.  */
+      int pmon_reg = mips_map_regno (regno);
+      if (regno != 0 && pmon_reg == 0)
+       val = 0;
+      else
+       {
+         /* Unfortunately the PMON version in the Vr4300 board has been
+            compiled without the 64bit register access commands. This
+            means we cannot get hold of the full register width. */
+         if (mips_monitor == MON_DDB)
+           val = (unsigned)mips_request ('t', (unsigned int) pmon_reg,
+                               (unsigned int) 0, &err, mips_receive_wait, NULL);
+         else
+           val = mips_request ('r', (unsigned int) pmon_reg,
+                               (unsigned int) 0, &err, mips_receive_wait, NULL);
+         if (err)
+           mips_error ("Can't read register %d: %s", regno,
+                       safe_strerror (errno));
+       }
     }
 
   {
@@ -1443,7 +1988,7 @@ mips_store_registers (regno)
     }
 
   mips_request ('R', (unsigned int) mips_map_regno (regno),
-               (unsigned int) read_register (regno),
+               read_register (regno),
                &err, mips_receive_wait, NULL);
   if (err)
     mips_error ("Can't write register %d: %s", regno, safe_strerror (errno));
@@ -1451,22 +1996,25 @@ mips_store_registers (regno)
 
 /* Fetch a word from the target board.  */
 
-static int 
+static unsigned int 
 mips_fetch_word (addr)
      CORE_ADDR addr;
 {
-  int val;
+  unsigned int val;
   int err;
 
-  val = mips_request ('d', (unsigned int) addr, (unsigned int) 0, &err,
+  /* FIXME! addr was cast to uint! */
+  val = mips_request ('d', addr, (unsigned int) 0, &err,
                      mips_receive_wait, NULL);
   if (err)
     {
       /* Data space failed; try instruction space.  */
-      val = mips_request ('i', (unsigned int) addr, (unsigned int) 0, &err,
+      /* FIXME! addr was cast to uint! */
+      val = mips_request ('i', addr, (unsigned int) 0, &err,
                          mips_receive_wait, NULL);
       if (err)
-       mips_error ("Can't read address 0x%x: %s", addr, safe_strerror (errno));
+        mips_error ("Can't read address 0x%s: %s",
+             paddr_nz (addr), safe_strerror (errno));
     }
   return val;
 }
@@ -1475,22 +2023,23 @@ mips_fetch_word (addr)
    success.  If OLD_CONTENTS is non-NULL, put the old contents of that
    memory location there.  */
 
+/* FIXME! make sure only 32-bit quantities get stored! */
 static int
 mips_store_word (addr, val, old_contents)
      CORE_ADDR addr;
-     int val;
+     unsigned int val;
      char *old_contents;
 {
   int err;
   unsigned int oldcontents;
 
-  oldcontents = mips_request ('D', (unsigned int) addr, (unsigned int) val,
+  oldcontents = mips_request ('D', addr, (unsigned int) val,
                              &err,
                              mips_receive_wait, NULL);
   if (err)
     {
       /* Data space failed; try instruction space.  */
-      oldcontents = mips_request ('I', (unsigned int) addr,
+      oldcontents = mips_request ('I', addr,
                                  (unsigned int) val, &err,
                                  mips_receive_wait, NULL);
       if (err)
@@ -1620,8 +2169,7 @@ Give up (and stop debugging it)? "))
             board (it almost surely won't work since we weren't able to talk to
             it).  */
          mips_wait_flag = 0;
-         mips_is_open = 0;
-         SERIAL_CLOSE (mips_desc);
+         close_ports();
 
          printf_unfiltered ("Ending remote MIPS debugging.\n");
          target_mourn_inferior ();
@@ -1695,7 +2243,8 @@ Can't pass arguments to remote MIPS board; arguments ignored.");
 static void
 mips_mourn_inferior ()
 {
-  unpush_target (&mips_ops);
+  if (current_ops != NULL)
+    unpush_target (current_ops);
   generic_mourn_inferior ();
 }
 \f
@@ -1721,8 +2270,6 @@ mips_insert_breakpoint (addr, contents_cache)
      CORE_ADDR addr;
      char *contents_cache;
 {
-  int status;
-
   if (monitor_supports_breakpoints)
     return common_breakpoint ('B', addr, 0x3, "f");
 
@@ -1740,6 +2287,129 @@ mips_remove_breakpoint (addr, contents_cache)
   return target_write_memory (addr, contents_cache, BREAK_INSN_SIZE);
 }
 
+#if 0 /* currently not used */
+/* PMON does not currently provide support for the debug mode 'b'
+   commands to manipulate breakpoints. However, if we wanted to use
+   the monitor breakpoints (rather than the GDB BREAK_INSN version)
+   then this code performs the work needed to leave debug mode,
+   set/clear the breakpoint, and then return to debug mode. */
+
+#define PMON_MAX_BP (33) /* 32 SW, 1 HW */
+static CORE_ADDR mips_pmon_bp_info[PMON_MAX_BP];
+/* NOTE: The code relies on this vector being zero-initialised by the system */
+
+static int
+pmon_insert_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  int status;
+
+  if (monitor_supports_breakpoints)
+    {
+      char tbuff[12]; /* space for breakpoint command */
+      int bpnum;
+      CORE_ADDR bpaddr;
+
+      /* PMON does not support debug level breakpoint set/remove: */
+      if (mips_exit_debug ())
+        mips_error ("Failed to exit debug mode");
+
+      sprintf (tbuff, "b %08x\r", addr);
+      mips_send_command (tbuff, 0);
+
+      mips_expect ("Bpt ");
+
+      if (!mips_getstring (tbuff, 2))
+        return 1;
+      tbuff[2] = '\0'; /* terminate the string */
+      if (sscanf (tbuff, "%d", &bpnum) != 1)
+        {
+          fprintf_unfiltered (stderr, "Invalid decimal breakpoint number from target: %s\n", tbuff);
+          return 1;
+        }
+
+      mips_expect (" = ");
+
+      /* Lead in the hex number we are expecting: */
+      tbuff[0] = '0';
+      tbuff[1] = 'x';
+
+      /* FIXME!! only 8 bytes!  need to expand for Bfd64; 
+         which targets return 64-bit addresses?  PMON returns only 32! */
+      if (!mips_getstring (&tbuff[2], 8))
+        return 1;
+      tbuff[10] = '\0'; /* terminate the string */
+
+      if (sscanf (tbuff, "0x%08x", &bpaddr) != 1)
+        {
+          fprintf_unfiltered (stderr, "Invalid hex address from target: %s\n", tbuff);
+          return 1;
+        }
+
+      if (bpnum >= PMON_MAX_BP)
+        {
+          fprintf_unfiltered (stderr, "Error: Returned breakpoint number %d outside acceptable range (0..%d)\n",
+                              bpnum, PMON_MAX_BP - 1);
+          return 1;
+        }
+
+      if (bpaddr != addr)
+        fprintf_unfiltered (stderr, "Warning: Breakpoint addresses do not match: 0x%x != 0x%x\n", addr, bpaddr);
+
+      mips_pmon_bp_info[bpnum] = bpaddr;
+
+      mips_expect ("\r\n");
+      mips_expect (mips_monitor_prompt);
+
+      mips_enter_debug ();
+
+      return 0;
+    }
+
+  return mips_store_word (addr, BREAK_INSN, contents_cache);
+}
+
+static int
+pmon_remove_breakpoint (addr, contents_cache)
+     CORE_ADDR addr;
+     char *contents_cache;
+{
+  if (monitor_supports_breakpoints)
+    {
+      int bpnum;
+      char tbuff[7]; /* enough for delete breakpoint command */
+
+      for (bpnum = 0; bpnum < PMON_MAX_BP; bpnum++)
+        if (mips_pmon_bp_info[bpnum] == addr)
+          break;
+
+      if (bpnum >= PMON_MAX_BP)
+        {
+          fprintf_unfiltered (stderr,
+           "pmon_remove_breakpoint: Failed to find breakpoint at address 0x%s\n",
+           paddr_nz (addr));
+          return 1;
+        }
+
+      if (mips_exit_debug ())
+        mips_error ("Failed to exit debug mode");
+
+      sprintf (tbuff, "db %02d\r", bpnum);
+
+      mips_send_command (tbuff, -1);
+      /* NOTE: If the breakpoint does not exist then a "Bpt <dd> not
+         set" message will be returned. */
+
+      mips_enter_debug ();
+
+      return 0;
+    }
+
+  return target_write_memory (addr, contents_cache, BREAK_INSN_SIZE);
+}
+#endif
+
 /* Compute a don't care mask for the region bounding ADDR and ADDR + LEN - 1.
    This is used for memory ref breakpoints.  */
 
@@ -1833,7 +2503,9 @@ remote_mips_stopped_by_watchpoint ()
 
    Where <CMD> is one of: `B' to set, or `b' to clear a breakpoint.  <ADDR> is
    the address of the breakpoint.  <MASK> is a don't care mask for addresses.
-   <FLAGS> is any combination of `r', `w', or `f' for read/write/or fetch.  */
+   <FLAGS> is any combination of `r', `w', or `f' for read/write/or fetch.
+
+   Return 0 if successful; otherwise 1.  */
 
 static int
 common_breakpoint (cmd, addr, mask, flags)
@@ -1848,14 +2520,17 @@ common_breakpoint (cmd, addr, mask, flags)
   int rpid, rerrflg, rresponse;
   int nfields;
 
+  addr = ADDR_BITS_REMOVE (addr);
   if (flags)
-    sprintf (buf, "0x0 %c 0x%x 0x%x %s", cmd, addr, mask, flags);
+    sprintf (buf, "0x0 %c 0x%s 0x%s %s", cmd, paddr_nz (addr), paddr_nz (mask),
+            flags);
   else
-    sprintf (buf, "0x0 %c 0x%x", cmd, addr);
+    sprintf (buf, "0x0 %c 0x%s", cmd, paddr_nz (addr));
 
   mips_send_packet (buf, 1);
 
   len = mips_receive_packet (buf, 1, mips_receive_wait);
+  buf[len] = '\0';
 
   nfields = sscanf (buf, "0x%x %c 0x%x 0x%x", &rpid, &rcmd, &rerrflg, &rresponse);
 
@@ -1865,9 +2540,13 @@ common_breakpoint (cmd, addr, mask, flags)
 
   if (rerrflg != 0)
     {
-      if (rresponse != EINVAL)
-       fprintf_unfiltered (stderr, "common_breakpoint (0x%x):  Got error: 0x%x\n",
-                           addr, rresponse);
+      /* Ddb returns "0x0 b 0x16 0x0\000", whereas
+         Cogent returns "0x0 b 0xffffffff 0x16\000": */
+      if (mips_monitor == MON_DDB)
+        rresponse = rerrflg;
+      if (rresponse != 22) /* invalid argument */
+       fprintf_unfiltered (stderr, "common_breakpoint (0x%s):  Got error: 0x%x\n",
+                           paddr_nz (addr), rresponse);
       return 1;
     }
 
@@ -1913,8 +2592,8 @@ mips_load_srec (args)
   bfd *abfd;
   asection *s;
   char *buffer, srec[1024];
-  int i;
-  int srec_frame = 200;
+  unsigned int i;
+  unsigned int srec_frame = 200;
   int reclen;
   static int hashmark = 1;
 
@@ -1932,20 +2611,17 @@ mips_load_srec (args)
       printf_filtered ("File is not an object file\n");
       return;
     }
-  
-#define LOAD_CMD "load -b -s tty0\015"
-
-  SERIAL_WRITE (mips_desc, LOAD_CMD, sizeof LOAD_CMD - 1);
 
-  mips_expect (LOAD_CMD);
-  mips_expect ("\012");
+/* This actually causes a download in the IDT binary format: */
+  mips_send_command (LOAD_CMD, 0);
 
   for (s = abfd->sections; s; s = s->next)
     {
       if (s->flags & SEC_LOAD)
        {
-         int numbytes;
+         unsigned int numbytes;
 
+         /* FIXME!  vma too small?? */
          printf_filtered ("%s\t: 0x%4x .. 0x%4x  ", s->name, s->vma,
                           s->vma + s->_raw_size);
          gdb_flush (gdb_stdout);
@@ -2041,19 +2717,22 @@ mips_make_srec (buf, type, memaddr, myaddr, len)
   /* Create the header for the srec. addr_size is the number of bytes in the address,
      and 1 is the number of bytes in the count.  */
 
+  /* FIXME!! bigger buf required for 64-bit! */
   buf[0] = 'S';
   buf[1] = type;
   buf[2] = len + 4 + 1;                /* len + 4 byte address + 1 byte checksum */
+  /* This assumes S3 style downloads (4byte addresses). There should
+     probably be a check, or the code changed to make it more
+     explicit. */
   buf[3] = memaddr >> 24;
   buf[4] = memaddr >> 16;
   buf[5] = memaddr >> 8;
   buf[6] = memaddr;
   memcpy (&buf[7], myaddr, len);
 
-/* Note that the checksum is calculated on the raw data, not the hexified
-   data.  It includes the length, address and the data portions of the
-   packet.  */
-
+  /* Note that the checksum is calculated on the raw data, not the
+     hexified data.  It includes the length, address and the data
+     portions of the packet.  */
   checksum = 0;
   buf += 2;                    /* Point at length byte */
   for (i = 0; i < len + 4 + 1; i++)
@@ -2064,6 +2743,448 @@ mips_make_srec (buf, type, memaddr, myaddr, len)
   return len + 8;
 }
 
+/* The following manifest controls whether we enable the simple flow
+   control support provided by the monitor. If enabled the code will
+   wait for an affirmative ACK between transmitting packets. */
+#define DOETXACK (1)
+
+/* The PMON fast-download uses an encoded packet format constructed of
+   3byte data packets (encoded as 4 printable ASCII characters), and
+   escape sequences (preceded by a '/'):
+
+       'K'     clear checksum
+       'C'     compare checksum (12bit value, not included in checksum calculation)
+       'S'     define symbol name (for addr) terminated with "," and padded to 4char boundary
+       'Z'     zero fill multiple of 3bytes
+       'B'     byte (12bit encoded value, of 8bit data)
+       'A'     address (36bit encoded value)
+       'E'     define entry as original address, and exit load
+
+   The packets are processed in 4 character chunks, so the escape
+   sequences that do not have any data (or variable length data)
+   should be padded to a 4 character boundary.  The decoder will give
+   an error if the complete message block size is not a multiple of
+   4bytes (size of record).
+
+   The encoding of numbers is done in 6bit fields.  The 6bit value is
+   used to index into this string to get the specific character
+   encoding for the value: */
+static char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,.";
+
+/* Convert the number of bits required into an encoded number, 6bits
+   at a time (range 0..63).  Keep a checksum if required (passed
+   pointer non-NULL). The function returns the number of encoded
+   characters written into the buffer. */
+static int
+pmon_makeb64 (v, p, n, chksum)
+     unsigned long v;
+     char *p;
+     int n;
+     int *chksum;
+{
+  int count = (n / 6);
+
+  if ((n % 12) != 0) {
+    fprintf_unfiltered(stderr,"Fast encoding bitcount must be a multiple of 12bits: %dbit%s\n",n,(n == 1)?"":"s");
+    return(0);
+  }
+  if (n > 36) {
+    fprintf_unfiltered(stderr,"Fast encoding cannot process more than 36bits at the moment: %dbits\n",n);
+    return(0);
+  }
+
+  /* Deal with the checksum: */
+  if (chksum != NULL) {
+    switch (n) {
+     case 36: *chksum += ((v >> 24) & 0xFFF);
+     case 24: *chksum += ((v >> 12) & 0xFFF);
+     case 12: *chksum += ((v >>  0) & 0xFFF);
+    }
+  }
+
+  do {
+    n -= 6;
+    *p++ = encoding[(v >> n) & 0x3F];
+  } while (n > 0);
+
+  return(count);
+}
+
+/* Shorthand function (that could be in-lined) to output the zero-fill
+   escape sequence into the data stream. */
+static int
+pmon_zeroset (recsize, buff, amount, chksum)
+     int recsize;
+     char **buff;
+     int *amount;
+     unsigned int *chksum;
+{
+  int count;
+
+  sprintf(*buff,"/Z");
+  count = pmon_makeb64 (*amount, (*buff + 2), 12, chksum);
+  *buff += (count + 2);
+  *amount = 0;
+  return(recsize + count + 2);
+}
+
+static int
+pmon_checkset (recsize, buff, value)
+     int recsize;
+     char **buff;
+     int *value;
+{
+  int count;
+
+  /* Add the checksum (without updating the value): */
+  sprintf (*buff, "/C");
+  count = pmon_makeb64 (*value, (*buff + 2), 12, NULL);
+  *buff += (count + 2);
+  sprintf (*buff, "\n");
+  *buff += 2; /* include zero terminator */
+  /* Forcing a checksum validation clears the sum: */
+  *value = 0;
+  return(recsize + count + 3);
+}
+
+/* Amount of padding we leave after at the end of the output buffer,
+   for the checksum and line termination characters: */
+#define CHECKSIZE (4 + 4 + 4 + 2)
+/* zero-fill, checksum, transfer end and line termination space. */
+
+/* The amount of binary data loaded from the object file in a single
+   operation: */
+#define BINCHUNK (1024)
+
+/* Maximum line of data accepted by the monitor: */
+#define MAXRECSIZE (550)
+/* NOTE: This constant depends on the monitor being used. This value
+   is for PMON 5.x on the Cogent Vr4300 board. */
+
+static void
+pmon_make_fastrec (outbuf, inbuf, inptr, inamount, recsize, csum, zerofill)
+     char **outbuf;
+     unsigned char *inbuf;
+     int *inptr;
+     int inamount;
+     int *recsize;
+     unsigned int *csum;
+     unsigned int *zerofill;
+{
+  int count = 0;
+  char *p = *outbuf;
+
+  /* This is a simple check to ensure that our data will fit within
+     the maximum allowable record size. Each record output is 4bytes
+     in length. We must allow space for a pending zero fill command,
+     the record, and a checksum record. */
+  while ((*recsize < (MAXRECSIZE - CHECKSIZE)) && ((inamount - *inptr) > 0)) {
+    /* Process the binary data: */
+    if ((inamount - *inptr) < 3) {
+      if (*zerofill != 0)
+       *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+      sprintf (p, "/B");
+      count = pmon_makeb64 (inbuf[*inptr], &p[2], 12, csum);
+      p += (2 + count);
+      *recsize += (2 + count);
+      (*inptr)++;
+    } else {
+      unsigned int value = ((inbuf[*inptr + 0] << 16) | (inbuf[*inptr + 1] << 8) | inbuf[*inptr + 2]);
+      /* Simple check for zero data. TODO: A better check would be
+         to check the last, and then the middle byte for being zero
+         (if the first byte is not). We could then check for
+         following runs of zeros, and if above a certain size it is
+         worth the 4 or 8 character hit of the byte insertions used
+         to pad to the start of the zeroes. NOTE: This also depends
+         on the alignment at the end of the zero run. */
+      if (value == 0x00000000) {
+        (*zerofill)++;
+        if (*zerofill == 0xFFF) /* 12bit counter */
+         *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+      }else {
+        if (*zerofill != 0)
+         *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+        count = pmon_makeb64 (value, p, 24, csum);
+        p += count;
+        *recsize += count;
+      }
+      *inptr += 3;
+    }
+  }
+
+  *outbuf = p;
+  return;
+}
+
+static int
+pmon_check_ack(mesg)
+     char *mesg;
+{
+#if defined(DOETXACK)
+  int c;
+
+  if (!tftp_in_use)
+    {
+      c = SERIAL_READCHAR (udp_in_use ? udp_desc : mips_desc, 2);
+      if ((c == SERIAL_TIMEOUT) || (c != 0x06))
+       {
+         fprintf_unfiltered (gdb_stderr,
+                             "Failed to receive valid ACK for %s\n", mesg);
+         return(-1); /* terminate the download */
+       }
+    }
+#endif /* DOETXACK */
+  return(0);
+}
+
+/* pmon_download - Send a sequence of characters to the PMON download port,
+   which is either a serial port or a UDP socket.  */
+
+static void
+pmon_start_download ()
+{
+  if (tftp_in_use)
+    {
+      /* Create the temporary download file.  */
+      if ((tftp_file = fopen (tftp_localname, "w")) == NULL)
+       perror_with_name (tftp_localname);
+    }
+  else
+    {
+      mips_send_command (udp_in_use ? LOAD_CMD_UDP : LOAD_CMD, 0);
+      mips_expect ("Downloading from ");
+      mips_expect (udp_in_use ? "udp" : "tty0");
+      mips_expect (", ^C to abort\r\n");
+    }
+}
+
+static int
+mips_expect_download (char *string)
+{
+  if (!mips_expect (string))
+    {
+      fprintf_unfiltered (gdb_stderr, "Load did not complete successfully.\n");
+      if (tftp_in_use)
+       remove (tftp_localname);        /* Remove temporary file */
+      return 0;
+    }
+  else
+    return 1;
+}
+
+static void
+pmon_end_download (final, bintotal)
+     int final;
+     int bintotal;
+{
+  char hexnumber[9]; /* includes '\0' space */
+
+  if (tftp_in_use)
+    {
+      static char *load_cmd_prefix = "load -b -s ";
+      char *cmd;
+      struct stat stbuf;
+
+      /* Close off the temporary file containing the load data.  */
+      fclose (tftp_file);
+      tftp_file = NULL;
+
+      /* Make the temporary file readable by the world.  */
+      if (stat (tftp_localname, &stbuf) == 0)
+       chmod (tftp_localname, stbuf.st_mode | S_IROTH);
+
+      /* Must reinitialize the board to prevent PMON from crashing.  */
+      mips_send_command ("initEther\r", -1);
+
+      /* Send the load command.  */
+      cmd = xmalloc (strlen (load_cmd_prefix) + strlen (tftp_name) + 2);
+      strcpy (cmd, load_cmd_prefix);
+      strcat (cmd, tftp_name);
+      strcat (cmd, "\r");
+      mips_send_command (cmd, 0);
+      free (cmd);
+      if (!mips_expect_download ("Downloading from "))
+       return;
+      if (!mips_expect_download (tftp_name))
+       return;
+      if (!mips_expect_download (", ^C to abort\r\n"))
+       return;
+    }
+
+  /* Wait for the stuff that PMON prints after the load has completed.
+     The timeout value for use in the tftp case (15 seconds) was picked
+     arbitrarily but might be too small for really large downloads. FIXME. */
+  if (mips_monitor == MON_LSI)
+    {
+      pmon_check_ack ("termination");
+      mips_expect_timeout ("Entry address is ", tftp_in_use ? 15 : 2);
+    }
+  else
+    mips_expect_timeout ("Entry Address  = ", tftp_in_use ? 15 : 2);
+
+  sprintf (hexnumber,"%x",final);
+  mips_expect (hexnumber);
+  mips_expect ("\r\n");
+  if (mips_monitor != MON_LSI)
+    pmon_check_ack ("termination");
+  mips_expect ("\r\ntotal = 0x");
+  sprintf (hexnumber,"%x",bintotal);
+  mips_expect (hexnumber);
+  if (!mips_expect_download (" bytes\r\n"))
+    return;
+
+  if (tftp_in_use)
+    remove (tftp_localname);   /* Remove temporary file */
+}
+
+static void
+pmon_download (buffer, length)
+     char *buffer;
+     int length;
+{
+  if (tftp_in_use)
+    fwrite (buffer, 1, length, tftp_file);
+  else
+    SERIAL_WRITE (udp_in_use ? udp_desc : mips_desc, buffer, length);
+}
+
+static void
+pmon_load_fast (file)
+     char *file;
+{
+  bfd *abfd;
+  asection *s;
+  unsigned char *binbuf;
+  char *buffer;
+  int reclen;
+  unsigned int csum = 0;
+  int hashmark = !tftp_in_use;
+  int bintotal = 0;
+  int final = 0;
+  int finished = 0;
+
+  buffer = (char *)xmalloc(MAXRECSIZE + 1);
+  binbuf = (unsigned char *)xmalloc(BINCHUNK);
+
+  abfd = bfd_openr(file,0);
+  if (!abfd)
+   {
+     printf_filtered ("Unable to open file %s\n",file);
+     return;
+   }
+
+  if (bfd_check_format(abfd,bfd_object) == 0)
+   {
+     printf_filtered("File is not an object file\n");
+     return;
+   }
+
+  /* Setup the required download state: */
+  mips_send_command ("set dlproto etxack\r", -1);
+  mips_send_command ("set dlecho off\r", -1);
+  /* NOTE: We get a "cannot set variable" message if the variable is
+     already defined to have the argument we give. The code doesn't
+     care, since it just scans to the next prompt anyway. */
+  /* Start the download: */
+  pmon_start_download();
+  
+  /* Zero the checksum */
+  sprintf(buffer,"/Kxx\n");
+  reclen = strlen(buffer);
+  pmon_download (buffer, reclen);
+  finished = pmon_check_ack("/Kxx");
+
+  for (s = abfd->sections; s && !finished; s = s->next)
+   if (s->flags & SEC_LOAD) /* only deal with loadable sections */
+    {
+      bintotal += s->_raw_size;
+      final = (s->vma + s->_raw_size);
+
+      printf_filtered ("%s\t: 0x%4x .. 0x%4x  ", s->name, (unsigned int)s->vma,
+                       (unsigned int)(s->vma + s->_raw_size));
+      gdb_flush (gdb_stdout);
+
+      /* Output the starting address */
+      sprintf(buffer,"/A");
+      reclen = pmon_makeb64(s->vma,&buffer[2],36,&csum);
+      buffer[2 + reclen] = '\n';
+      buffer[3 + reclen] = '\0';
+      reclen += 3; /* for the initial escape code and carriage return */
+      pmon_download (buffer, reclen);
+      finished = pmon_check_ack("/A");
+
+      if (!finished)
+       {
+         unsigned int binamount;
+         unsigned int zerofill = 0;
+         char *bp = buffer;
+         unsigned int i;
+
+         reclen = 0;
+
+         for (i = 0; ((i < s->_raw_size) && !finished); i += binamount) {
+           int binptr = 0;
+
+           binamount = min (BINCHUNK, s->_raw_size - i);
+
+           bfd_get_section_contents (abfd, s, binbuf, i, binamount);
+
+           /* This keeps a rolling checksum, until we decide to output
+              the line: */
+           for (; ((binamount - binptr) > 0);) {
+             pmon_make_fastrec (&bp, binbuf, &binptr, binamount, &reclen, &csum, &zerofill);
+             if (reclen >= (MAXRECSIZE - CHECKSIZE)) {
+               reclen = pmon_checkset (reclen, &bp, &csum);
+               pmon_download (buffer, reclen);
+               finished = pmon_check_ack("data record");
+               if (finished) {
+                 zerofill = 0; /* do not transmit pending zerofills */
+                 break;
+               }
+
+               if (hashmark) {
+                 putchar_unfiltered ('#');
+                 gdb_flush (gdb_stdout);
+               }
+
+               bp = buffer;
+               reclen = 0; /* buffer processed */
+             }
+           }
+         }
+
+         /* Ensure no out-standing zerofill requests: */
+         if (zerofill != 0)
+          reclen = pmon_zeroset (reclen, &bp, &zerofill, &csum);
+
+         /* and then flush the line: */
+         if (reclen > 0) {
+           reclen = pmon_checkset (reclen, &bp, &csum);
+           /* Currently pmon_checkset outputs the line terminator by
+              default, so we write out the buffer so far: */
+           pmon_download (buffer, reclen);
+           finished = pmon_check_ack("record remnant");
+         }
+       }
+
+      putchar_unfiltered ('\n');
+    }
+
+  /* Terminate the transfer. We know that we have an empty output
+     buffer at this point. */
+  sprintf (buffer, "/E/E\n"); /* include dummy padding characters */
+  reclen = strlen (buffer);
+  pmon_download (buffer, reclen);
+
+  if (finished) { /* Ignore the termination message: */
+    SERIAL_FLUSH_INPUT (udp_in_use ? udp_desc : mips_desc);
+  } else { /* Deal with termination message: */
+    pmon_end_download (final, bintotal);
+  }
+
+  return;
+}
+
 /* mips_load -- download a file. */
 
 static void
@@ -2071,24 +3192,25 @@ mips_load (file, from_tty)
     char *file;
     int  from_tty;
 {
-  int err;
-
   /* Get the board out of remote debugging mode.  */
-
-  mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err,
-               mips_receive_wait, NULL);
-
-  if (!mips_expect ("\015\012") || !mips_expect (TARGET_MONITOR_PROMPT))
+  if (mips_exit_debug ())
     error ("mips_load:  Couldn't get into monitor mode.");
 
-  mips_load_srec (file);
-
-  SERIAL_WRITE (mips_desc, "\015db tty0\015", sizeof "\015db tty0\015" - 1);
+  if (mips_monitor != MON_IDT)
+   pmon_load_fast (file);
+  else
+   mips_load_srec (file);
 
   mips_initialize ();
 
-/* Finally, make the PC point at the start address */
-
+  /* Finally, make the PC point at the start address */
+  if (mips_monitor == MON_DDB)
+    {
+      /* Work around problem where DDB monitor does not update the
+         PC after a load. The following ensures that the write_pc()
+         WILL update the PC value: */
+      register_valid[PC_REGNUM] = 0;
+    }
   if (exec_bfd)
     write_pc (bfd_get_start_address (exec_bfd));
 
@@ -2152,10 +3274,168 @@ HOST:PORT to access a board over a network",  /* to_doc */
   OPS_MAGIC                    /* to_magic */
 };
 \f
+/* An alternative target vector: */
+struct target_ops pmon_ops =
+{
+  "pmon",                      /* to_shortname */
+  "Remote MIPS debugging over serial line",    /* to_longname */
+  "\
+Debug a board using the PMON MIPS remote debugging protocol over a serial\n\
+line. The argument is the device it is connected to or, if it contains a\n\
+colon, HOST:PORT to access a board over a network",  /* to_doc */
+  pmon_open,                   /* to_open */
+  mips_close,                  /* to_close */
+  NULL,                                /* to_attach */
+  mips_detach,                 /* to_detach */
+  mips_resume,                 /* to_resume */
+  pmon_wait,                   /* to_wait */
+  mips_fetch_registers,                /* to_fetch_registers */
+  mips_store_registers,                /* to_store_registers */
+  mips_prepare_to_store,       /* to_prepare_to_store */
+  mips_xfer_memory,            /* to_xfer_memory */
+  mips_files_info,             /* to_files_info */
+  mips_insert_breakpoint,      /* to_insert_breakpoint */
+  mips_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 */
+  mips_kill,                   /* to_kill */
+  mips_load,                   /* to_load */
+  NULL,                                /* to_lookup_symbol */
+  mips_create_inferior,                /* to_create_inferior */
+  mips_mourn_inferior,         /* to_mourn_inferior */
+  NULL,                                /* to_can_run */
+  NULL,                                /* 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 */
+};
+\f
+/* Another alternative target vector. This is a PMON system, but with
+   a different monitor prompt, aswell as some other operational
+   differences: */
+struct target_ops ddb_ops =
+{
+  "ddb",                       /* to_shortname */
+  "Remote MIPS debugging over serial line",    /* to_longname */
+  "\
+Debug a board using the PMON MIPS remote debugging protocol over a serial\n\
+line. The first argument is the device it is connected to or, if it contains\n\
+a colon, HOST:PORT to access a board over a network.  The optional second\n\
+parameter is the temporary file in the form HOST:FILENAME to be used for\n\
+TFTP downloads to the board.  The optional third parameter is the local\n\
+of the TFTP temporary file, if it differs from the filename seen by the board",
+                               /* to_doc */
+  ddb_open,                    /* to_open */
+  mips_close,                  /* to_close */
+  NULL,                                /* to_attach */
+  mips_detach,                 /* to_detach */
+  mips_resume,                 /* to_resume */
+  pmon_wait,                   /* to_wait */
+  mips_fetch_registers,                /* to_fetch_registers */
+  mips_store_registers,                /* to_store_registers */
+  mips_prepare_to_store,       /* to_prepare_to_store */
+  mips_xfer_memory,            /* to_xfer_memory */
+  mips_files_info,             /* to_files_info */
+  mips_insert_breakpoint,      /* to_insert_breakpoint */
+  mips_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 */
+  mips_kill,                   /* to_kill */
+  mips_load,                   /* to_load */
+  NULL,                                /* to_lookup_symbol */
+  mips_create_inferior,                /* to_create_inferior */
+  mips_mourn_inferior,         /* to_mourn_inferior */
+  NULL,                                /* to_can_run */
+  NULL,                                /* 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 */
+};
+\f
+/* Another alternative target vector for LSI Logic MiniRISC boards.
+   This is a PMON system, but with some other operational differences.  */
+struct target_ops lsi_ops =
+{
+  "lsi",                       /* to_shortname */
+  "Remote MIPS debugging over serial line",    /* to_longname */
+  "\
+Debug a board using the PMON MIPS remote debugging protocol over a serial\n\
+line. The first argument is the device it is connected to or, if it contains\n\
+a colon, HOST:PORT to access a board over a network.  The optional second\n\
+parameter is the temporary file in the form HOST:FILENAME to be used for\n\
+TFTP downloads to the board.  The optional third parameter is the local\n\
+of the TFTP temporary file, if it differs from the filename seen by the board",
+                               /* to_doc */
+  lsi_open,                    /* to_open */
+  mips_close,                  /* to_close */
+  NULL,                                /* to_attach */
+  mips_detach,                 /* to_detach */
+  mips_resume,                 /* to_resume */
+  pmon_wait,                   /* to_wait */
+  mips_fetch_registers,                /* to_fetch_registers */
+  mips_store_registers,                /* to_store_registers */
+  mips_prepare_to_store,       /* to_prepare_to_store */
+  mips_xfer_memory,            /* to_xfer_memory */
+  mips_files_info,             /* to_files_info */
+  mips_insert_breakpoint,      /* to_insert_breakpoint */
+  mips_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 */
+  mips_kill,                   /* to_kill */
+  mips_load,                   /* to_load */
+  NULL,                                /* to_lookup_symbol */
+  mips_create_inferior,                /* to_create_inferior */
+  mips_mourn_inferior,         /* to_mourn_inferior */
+  NULL,                                /* to_can_run */
+  NULL,                                /* 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 */
+};
+\f
 void
 _initialize_remote_mips ()
 {
   add_target (&mips_ops);
+  add_target (&pmon_ops);
+  add_target (&ddb_ops);
+  add_target (&lsi_ops);
 
   add_show_from_set (
     add_set_cmd ("timeout", no_class, var_zinteger,
@@ -2171,4 +3451,14 @@ _initialize_remote_mips ()
 This is the number of seconds to wait for an acknowledgement to a packet\n\
 before resending the packet.", &setlist),
        &showlist);
+
+  add_show_from_set (
+    add_set_cmd ("syn-garbage-limit", no_class, var_zinteger,
+                (char *) &mips_syn_garbage,
+"Set the maximum number of characters to ignore when scanning for a SYN.\n\
+This is the maximum number of characters GDB will ignore when trying to\n\
+synchronize with the remote system.  A value of -1 means that there is no limit\n\
+(Note that these characters are printed out even though they are ignored.)",
+                &setlist),
+                    &showlist);
 }
This page took 0.052597 seconds and 4 git commands to generate.