* remote.c: Make it work for embedded MIPS. Increase buffer
authorJohn Gilmore <gnu@cygnus>
Fri, 28 Feb 1992 03:26:45 +0000 (03:26 +0000)
committerJohn Gilmore <gnu@cygnus>
Fri, 28 Feb 1992 03:26:45 +0000 (03:26 +0000)
size, and use throughout.  Round buffer size up if too many regs.
Support baud rate setting and try for an 8-bit path.  If
interrupted while waiting for target, send a ^C down the wire.
Avoid single-byte reads.
* tm-mips.h:  Add more embedded-system registers to REGISTER_NAMES
and NUM_REGS.
* mips-xdep.h:  Avoid the embedded regs when on Unix.

gdb/ChangeLog
gdb/mips-xdep.c
gdb/remote.c
gdb/tm-mips.h

index 99b3ee4..e7e3f42 100644 (file)
@@ -1,5 +1,14 @@
 Thu Feb 27 11:48:47 1992  John Gilmore  (gnu at cygnus.com)
 
+       * remote.c:  Make it work for embedded MIPS.  Increase buffer
+       size, and use throughout.  Round buffer size up if too many regs.
+       Support baud rate setting and try for an 8-bit path.  If
+       interrupted while waiting for target, send a ^C down the wire.
+       Avoid single-byte reads.
+       * tm-mips.h:  Add more embedded-system registers to REGISTER_NAMES
+       and NUM_REGS.
+       * mips-xdep.h:  Avoid the embedded regs when on Unix.
+
        * mipsread.c:  Byte-swap the symbol table structures, using
        routines from ecoff.c, to read a symbol table written in any
        of the four possible byte orders.
index b7e669d..d1f6319 100644 (file)
@@ -1,5 +1,5 @@
 /* Low level MIPS interface to ptrace, for GDB when running under Unix.
-   Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+   Copyright 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
    Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
    and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
 
@@ -144,7 +144,8 @@ store_inferior_registers (regno)
        {
          if (regno == ZERO_REGNUM || regno == PS_REGNUM
              || regno == BADVADDR_REGNUM || regno == CAUSE_REGNUM
-             || regno == FCRIR_REGNUM || regno == FP_REGNUM)
+             || regno == FCRIR_REGNUM || regno == FP_REGNUM
+             || (regno >= FIRST_EMBED_REGNUM && regno <= LAST_EMBED_REGNUM))
            continue;
          regaddr = register_addr (regno, 1);
          errno = 0;
index 8215243..8562124 100644 (file)
@@ -1,21 +1,21 @@
-/* Memory-access and commands for inferior process, for GDB.
-   Copyright (C) 1988-1991 Free Software Foundation, Inc.
+/* Remote target communications for serial-line targets in custom GDB protocol
+   Copyright 1988, 1991, 1992 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
-GDB is free software; you can redistribute it and/or modify
+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 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* Remote communication protocol.
    All values are encoded in ascii hex digits.
@@ -70,7 +70,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <string.h>
 #include <fcntl.h>
 #include "defs.h"
-#include "param.h"
 #include "frame.h"
 #include "inferior.h"
 #include "target.h"
@@ -83,9 +82,62 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include <signal.h>
 
-extern void add_syms_addr_command ();
-extern struct value *call_function_by_hand();
-extern void start_remote ();
+/* Prototypes for local functions */
+
+static void
+remote_write_bytes PARAMS ((CORE_ADDR, char *, int));
+
+static void
+remote_read_bytes PARAMS ((CORE_ADDR, char *, int));
+
+static void
+remote_files_info PARAMS ((struct target_ops *));
+
+static int
+remote_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static void 
+remote_prepare_to_store PARAMS ((void));
+
+static void
+remote_fetch_registers PARAMS ((int));
+
+static void
+remote_resume PARAMS ((int, int));
+
+static void
+remote_open PARAMS ((char *, int));
+
+static void
+remote_close PARAMS ((int));
+
+static void
+remote_store_registers PARAMS ((int));
+
+static void
+getpkt PARAMS ((char *));
+
+static void
+putpkt PARAMS ((char *));
+
+static void
+remote_send PARAMS ((char *));
+
+static int
+readchar PARAMS ((void));
+
+static int
+remote_wait PARAMS ((WAITTYPE *));
+
+static int
+tohex PARAMS ((int));
+
+static int
+fromhex PARAMS ((int));
+
+static void
+remote_detach PARAMS ((char *, int));
+
 
 extern struct target_ops remote_ops;   /* Forward decl */
 
@@ -101,19 +153,17 @@ int icache;
    starts.  */
 int remote_desc = -1;
 
-#define        PBUFSIZ 400
+#define        PBUFSIZ 1024
 
 /* 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 ((PBUFSIZ-32)/2)
 
-static void remote_send ();
-static void putpkt ();
-static void getpkt ();
-#if 0
-static void dcache_flush ();
+/* Round up PBUFSIZ to hold all the registers, at least.  */
+#if REGISTER_BYTES > MAXBUFBYTES
+#undef PBUFSIZ
+#define        PBUFSIZ (REGISTER_BYTES * 2 + 32)
 #endif
-
 \f
 /* Called when SIGALRM signal sent due to alarm() timeout.  */
 #ifndef HAVE_TERMIO
@@ -127,17 +177,10 @@ remote_timer ()
 }
 #endif
 
-/* Initialize remote connection */
-
-void
-remote_start()
-{
-}
-
 /* Clean up connection to a remote debugger.  */
 
 /* ARGSUSED */
-void
+static void
 remote_close (quitting)
      int quitting;
 {
@@ -146,15 +189,58 @@ remote_close (quitting)
   remote_desc = -1;
 }
 
+/* Translate baud rates from integers to damn B_codes.  Unix should
+   have outgrown this crap years ago, but even POSIX wouldn't buck it.  */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+static struct {int rate, damn_b;} baudtab[] = {
+       {0, B0},
+       {50, B50},
+       {75, B75},
+       {110, B110},
+       {134, B134},
+       {150, B150},
+       {200, B200},
+       {300, B300},
+       {600, B600},
+       {1200, B1200},
+       {1800, B1800},
+       {2400, B2400},
+       {4800, B4800},
+       {9600, B9600},
+       {19200, B19200},
+       {38400, B38400},
+       {-1, -1},
+};
+
+static int
+damn_b (rate)
+     int rate;
+{
+  int i;
+
+  for (i = 0; baudtab[i].rate != -1; i++)
+    if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+  return B38400;       /* Random */
+}
+
 /* Open a connection to a remote debugger.
    NAME is the filename used for communication.  */
 
-void
+static void
 remote_open (name, from_tty)
      char *name;
      int from_tty;
 {
   TERMINAL sg;
+  int a_rate, b_rate;
+  int baudrate_set = 0;
 
   if (name == 0)
     error (
@@ -173,13 +259,32 @@ device is attached to the remote system (e.g. /dev/ttya).");
   if (remote_desc < 0)
     perror_with_name (name);
 
+  if (baud_rate)
+    {
+      if (1 != sscanf (baud_rate, "%d ", &a_rate))
+       {
+         b_rate = damn_b (a_rate);
+         baudrate_set = 1;
+       }
+    }
+
   ioctl (remote_desc, TIOCGETP, &sg);
 #ifdef HAVE_TERMIO
   sg.c_cc[VMIN] = 0;           /* read with timeout.  */
   sg.c_cc[VTIME] = timeout * 10;
   sg.c_lflag &= ~(ICANON | ECHO);
+  sg.c_cflag &= ~PARENB;       /* No parity */
+  sg.c_cflag |= CS8;           /* 8-bit path */
+  if (baudrate_set)
+    sg.c_cflag = (sb.c_cflag & ~CBAUD) | b_rate;
 #else
-  sg.sg_flags = RAW;
+  sg.sg_flags |= RAW | ANYP;
+  sg.sg_flags &= ~ECHO;
+  if (baudrate_set)
+    {
+      sg.sg_ispeed = b_rate;
+      sg.sg_ospeed = b_rate;
+    }
 #endif
   ioctl (remote_desc, TIOCSETP, &sg);
 
@@ -256,7 +361,7 @@ tohex (nib)
 \f
 /* Tell the remote machine to resume.  */
 
-void
+static void
 remote_resume (step, siggnal)
      int step, siggnal;
 {
@@ -274,19 +379,33 @@ remote_resume (step, siggnal)
   putpkt (buf);
 }
 
+/* Send ^C to target to halt it.  Target will respond, and send us a
+   packet.  */
+
+void remote_interrupt()
+{
+  write (remote_desc, "\003", 1);      /* Send a ^C */
+}
+
+
 /* Wait until the remote machine stops, then return,
    storing status in STATUS just as `wait' would.
    Returns "pid" (though it's not clear what, if anything, that
    means in the case of this target).  */
 
-int
+static int
 remote_wait (status)
      WAITTYPE *status;
 {
   unsigned char buf[PBUFSIZ];
-
+  void (*ofunc)();
+  
   WSETEXIT ((*status), 0);
-  getpkt (buf);
+
+  ofunc = signal (SIGINT, remote_interrupt);
+  getpkt ((char *) buf);
+  signal (SIGINT, ofunc);
+
   if (buf[0] == 'E')
     error ("Remote failure reply: %s", buf);
   if (buf[0] != 'S')
@@ -299,7 +418,7 @@ remote_wait (status)
 
 /* Currently we just read all the registers, so we don't use regno.  */
 /* ARGSUSED */
-void
+static void
 remote_fetch_registers (regno)
      int regno;
 {
@@ -330,7 +449,7 @@ remote_fetch_registers (regno)
 /* Prepare to store registers.  Since we send them all, we have to
    read out the ones we don't want to change first.  */
 
-void 
+static void 
 remote_prepare_to_store ()
 {
   remote_fetch_registers (-1);
@@ -340,7 +459,7 @@ remote_prepare_to_store ()
    FIXME, eventually just store one register if that's all that is needed.  */
 
 /* ARGSUSED */
-int
+static void
 remote_store_registers (regno)
      int regno;
 {
@@ -362,7 +481,6 @@ remote_store_registers (regno)
   *p = '\0';
 
   remote_send (buf);
-  return 0;
 }
 
 #if 0
@@ -405,7 +523,7 @@ remote_store_word (addr, word)
    MYADDR is the address of the buffer in our space.
    LEN is the number of bytes.  */
 
-void
+static void
 remote_write_bytes (memaddr, myaddr, len)
      CORE_ADDR memaddr;
      char *myaddr;
@@ -420,7 +538,7 @@ remote_write_bytes (memaddr, myaddr, len)
 
   sprintf (buf, "M%x,%x:", memaddr, len);
 
-  /* Command describes registers byte by byte,
+  /* We send target system values byte by byte, in increasing byte addresses,
      each byte encoded as two hex characters.  */
 
   p = buf + strlen (buf);
@@ -440,7 +558,7 @@ remote_write_bytes (memaddr, myaddr, len)
    MYADDR is the address of the buffer in our space.
    LEN is the number of bytes.  */
 
-void
+static void
 remote_read_bytes (memaddr, myaddr, len)
      CORE_ADDR memaddr;
      char *myaddr;
@@ -456,7 +574,7 @@ remote_read_bytes (memaddr, myaddr, len)
   sprintf (buf, "m%x,%x", memaddr, len);
   remote_send (buf);
 
-  /* Reply describes registers byte by byte,
+  /* Reply describes memory byte by byte,
      each byte encoded as two hex characters.  */
 
   p = buf;
@@ -473,12 +591,14 @@ remote_read_bytes (memaddr, myaddr, len)
    to or from debugger address MYADDR.  Write to inferior if SHOULD_WRITE is
    nonzero.  Returns length of data written or read; 0 for error.  */
 
-int
-remote_xfer_inferior_memory(memaddr, myaddr, len, should_write)
+/* ARGSUSED */
+static int
+remote_xfer_memory(memaddr, myaddr, len, should_write, target)
      CORE_ADDR memaddr;
      char *myaddr;
      int len;
      int should_write;
+     struct target_ops *target;                        /* ignored */
 {
   int origlen = len;
   int xfersize;
@@ -500,8 +620,9 @@ remote_xfer_inferior_memory(memaddr, myaddr, len, should_write)
   return origlen; /* no error possible */
 }
 
-void
-remote_files_info ()
+static void
+remote_files_info (target)
+struct target_ops *target;
 {
   printf ("remote files info missing here.  FIXME.\n");
 }
@@ -527,22 +648,35 @@ Receiver responds with:
 
 */
 
+/* Read a single character from the remote end.
+   (If supported, we actually read many characters and buffer them up.)  */
+
 static int
 readchar ()
 {
   char buf;
+  static int inbuf_index, inbuf_count;
+#define        INBUFSIZE       PBUFSIZ
+  static char inbuf[INBUFSIZE];
 
-  buf = '\0';
+  if (inbuf_index >= inbuf_count)
+    {
+      /* Time to do another read... */
+      inbuf_index = 0;
+      inbuf_count = 0;
+      inbuf[0] = 0;            /* Just in case */
 #ifdef HAVE_TERMIO
-  /* termio does the timeout for us.  */
-  read (remote_desc, &buf, 1);
+      /* termio does the timeout for us.  */
+      inbuf_count = read (remote_desc, inbuf, INBUFSIZE);
 #else
-  alarm (timeout);
-  read (remote_desc, &buf, 1);
-  alarm (0);
+      alarm (timeout);
+      inbuf_count = read (remote_desc, inbuf, INBUFSIZE);
+      alarm (0);
 #endif
+    }
 
-  return buf & 0x7f;
+  /* Just return the next character from the buffer.  */
+  return inbuf[inbuf_index++] & 0x7f;
 }
 
 /* Send the command in BUF to the remote machine,
@@ -570,7 +704,7 @@ putpkt (buf)
 {
   int i;
   unsigned char csum = 0;
-  char buf2[500];
+  char buf2[PBUFSIZ];
   int cnt = strlen (buf);
   char ch;
   char *p;
@@ -578,6 +712,9 @@ putpkt (buf)
   /* Copy the packet into buffer BUF2, encapsulating it
      and giving it a checksum.  */
 
+  if (cnt > sizeof(buf2) - 5)          /* Prosanity check */
+    abort();
+
   p = buf2;
   *p++ = '$';
 
@@ -827,24 +964,45 @@ dcache_init ()
 /* Define the target subroutine names */
 
 struct target_ops remote_ops = {
-       "remote", "Remote serial target in gdb-specific protocol",
-       "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
-Specify the serial device it is connected to (e.g. /dev/ttya).",
-       remote_open, remote_close,
-       0, remote_detach, remote_resume, remote_wait,  /* attach */
-       remote_fetch_registers, remote_store_registers,
-       remote_prepare_to_store, 0, 0, /* conv_from, conv_to */
-       remote_xfer_inferior_memory, remote_files_info,
-       0, 0, /* insert_breakpoint, remove_breakpoint, */
-       0, 0, 0, 0, 0,  /* Terminal crud */
-       0, /* kill */
-       0, add_syms_addr_command,  /* load */
-       call_function_by_hand,
-       0, /* lookup_symbol */
-       0, 0, /* create_inferior FIXME, mourn_inferior FIXME */
-       process_stratum, 0, /* next */
-       1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
-       OPS_MAGIC,              /* Always the last thing */
+  "remote",                    /* to_shortname */
+  "Remote serial target in gdb-specific protocol",     /* to_longname */
+  "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
+  remote_open,                 /* to_open */
+  remote_close,                        /* to_close */
+  NULL,                                /* to_attach */
+  remote_detach,               /* to_detach */
+  remote_resume,               /* to_resume */
+  remote_wait,                 /* to_wait */
+  remote_fetch_registers,      /* to_fetch_registers */
+  remote_store_registers,      /* to_store_registers */
+  remote_prepare_to_store,     /* to_prepare_to_store */
+  NULL,                                /* to_convert_to_virtual */
+  NULL,                                /* to_convert_from_virtual */
+  remote_xfer_memory,          /* to_xfer_memory */
+  remote_files_info,           /* to_files_info */
+  NULL,                                /* to_insert_breakpoint */
+  NULL,                                /* 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 */
+  NULL,                                /* to_kill */
+  NULL,                                /* to_load */
+  NULL,                                /* to_lookup_symbol */
+  NULL,                                /* to_create_inferior */
+  NULL,                                /* to_mourn_inferior */
+  process_stratum,             /* to_stratum */
+  NULL,                                /* to_next */
+  1,                           /* to_has_all_memory */
+  1,                           /* to_has_memory */
+  1,                           /* to_has_stack */
+  1,                           /* to_has_registers */
+  1,                           /* to_has_execution */
+  NULL,                                /* sections */
+  NULL,                                /* sections_end */
+  OPS_MAGIC                    /* to_magic */
 };
 
 void
index 8fe1993..44390ef 100644 (file)
@@ -95,7 +95,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* Number of machine registers */
 
-#define NUM_REGS 73
+#define NUM_REGS 80
 
 /* Initializer for an array of names of registers.
    There should be NUM_REGS strings in this initializer.  */
@@ -107,10 +107,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
        "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra", \
        "sr",   "lo",   "hi",   "bad",  "cause","pc",    \
        "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
-       "f8",   "f9",   "f10",   "f11",   "f12",   "f13",   "f14",   "f15", \
-       "f16",   "f17",   "f18",   "f19",   "f20",   "f21",   "f22",   "f23",\
-       "f24",   "f25",   "f26",   "f27",   "f28",   "f29",   "f30",   "f31",\
-       "fsr",   "fir", "fp" \
+       "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
+       "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
+       "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
+       "fsr",  "fir",  "fp",   "inx",  "rand", "tlblo","ctxt", "tlbhi",\
+       "epc",  "prid"\
     }
 
 /* Register numbers of various important registers.
@@ -134,6 +135,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define FCRCS_REGNUM 70         /* FP control/status */
 #define FCRIR_REGNUM 71         /* FP implementation/revision */
 #define FP_REGNUM 72           /* Pseudo register that contains true address of executing stack frame */
+#define        FIRST_EMBED_REGNUM 73   /* First supervisor register for embedded use */
+#define        LAST_EMBED_REGNUM 79    /* Last one */
 
 /* Define DO_REGISTERS_INFO() to do machine-specific formatting
    of register dumps. */