aboutsummaryrefslogtreecommitdiff
path: root/gdb/remote-mips.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1993-02-22 23:43:03 +0000
committerIan Lance Taylor <ian@airs.com>1993-02-22 23:43:03 +0000
commitc2a0f1cb8ee2a29429b51b286afafdedbccdbbd3 (patch)
tree8546a7ddc5cd128fe3ec31ce16edc2081392b30b /gdb/remote-mips.c
parent20f10b59ffd028b021937cc04280b7ca1e54ee7a (diff)
downloadgdb-c2a0f1cb8ee2a29429b51b286afafdedbccdbbd3.zip
gdb-c2a0f1cb8ee2a29429b51b286afafdedbccdbbd3.tar.gz
gdb-c2a0f1cb8ee2a29429b51b286afafdedbccdbbd3.tar.bz2
* remote-mips.c: New file; implements MIPS remote debugging
protocol. * config/idt.mt: New file; uses remote-mips.c * configure.in (mips-idt-ecoff): New target; uses idt.mt. * mips-tdep.c (mips_fpu): New variable; controls use of MIPS floating point coprocessor. (mips_push_dummy_frame): If not mips_fpu, don't save floating point registers. (mips_pop_frame): If not mips_fpu, don't restore floating point registers. (_initialize_mips_tdep): New function; let the user reset mips_fpu variable. * tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): If not mips_fpu, don't use fp0 as floating point return register. (FIX_CALL_DUMMY): If not mips_fpu, don't save floating point registers. Also added remote-mips.c to .Sanitize file.
Diffstat (limited to 'gdb/remote-mips.c')
-rw-r--r--gdb/remote-mips.c194
1 files changed, 166 insertions, 28 deletions
diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c
index 6c559f1..73a653c 100644
--- a/gdb/remote-mips.c
+++ b/gdb/remote-mips.c
@@ -48,7 +48,7 @@ static int mips_cksum PARAMS ((const unsigned char *hdr,
int len));
static void
-mips_send_packet PARAMS ((const char *s));
+mips_send_packet PARAMS ((const char *s, int get_ack));
static int
mips_receive_packet PARAMS ((char *buff));
@@ -58,6 +58,9 @@ mips_request PARAMS ((char cmd, unsigned int addr, unsigned int data,
int *perr));
static void
+mips_initialize PARAMS ((void));
+
+static void
mips_open PARAMS ((char *name, int from_tty));
static void
@@ -246,6 +249,9 @@ extern struct target_ops mips_ops;
/* Set to 1 if the target is open. */
static int mips_is_open;
+/* Set to 1 while the connection is being initialized. */
+static int mips_initializing;
+
/* The next sequence number to send. */
static int mips_send_seq;
@@ -263,7 +269,7 @@ static int mips_send_retries = 10;
static int mips_syn_garbage = 1050;
/* The time to wait for a packet, in seconds. */
-static int mips_receive_wait = 30;
+static int mips_receive_wait = 5;
/* Set if we have sent a packet to the board but have not yet received
a reply. */
@@ -273,13 +279,25 @@ static int mips_need_reply = 0;
static int mips_debug = 0;
/* Read a character from the remote, aborting on error. Returns -2 on
- timeout (since that's what serial_readchar returns). */
+ timeout (since that's what serial_readchar returns). FIXME: If we
+ see the string "<IDT>" 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 hack, put in because I can't find
+ any way for a program running on the remote board to terminate
+ without also ending remote debugging mode. I assume users won't
+ have any trouble with this; for one thing, the IDT documentation
+ generally assumes that the remote debugging port is not the console
+ port. This is, however, very convenient for DejaGnu when you only
+ have one connected serial port. */
static int
mips_readchar (timeout)
int timeout;
{
int ch;
+ static int state = 0;
+ static char nextstate[5] = { '<', 'I', 'D', 'T', '>' };
ch = serial_readchar (timeout);
if (ch == EOF)
@@ -293,6 +311,34 @@ mips_readchar (timeout)
else
printf_filtered ("Timed out in read\n");
}
+
+ /* If we have seen <IDT> 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 == -2 || ch == '@')
+ && state == 5
+ && ! mips_initializing)
+ {
+ if (mips_debug > 0)
+ printf_filtered ("Reinitializing MIPS debugging mode\n");
+ serial_write ("\rdb tty0\r", sizeof "\rdb tty0\r" - 1);
+ sleep (1);
+
+ mips_need_reply = 0;
+ mips_initialize ();
+
+ state = 0;
+
+ error ("Remote board reset");
+ }
+
+ if (ch == nextstate[state])
+ ++state;
+ else
+ state = 0;
+
return ch;
}
@@ -327,7 +373,11 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
what the program is outputting, if the debugging is
being done on the console port. FIXME: Perhaps this
should be filtered? */
- putchar (ch);
+ if (! mips_initializing || mips_debug > 0)
+ {
+ putchar (ch);
+ fflush (stdout);
+ }
++*pgarbage;
if (*pgarbage > mips_syn_garbage)
@@ -416,8 +466,9 @@ mips_cksum (hdr, data, len)
/* Send a packet containing the given ASCII string. */
static void
-mips_send_packet (s)
+mips_send_packet (s, get_ack)
const char *s;
+ int get_ack;
{
unsigned int len;
unsigned char *packet;
@@ -446,6 +497,9 @@ mips_send_packet (s)
the sequence number we expect in the acknowledgement. */
mips_send_seq = (mips_send_seq + 1) % SEQ_MODULOS;
+ if (! get_ack)
+ return;
+
/* We can only have one outstanding data packet, so we just wait for
the acknowledgement here. Keep retransmitting the packet until
we get one, or until we've tried too many times. */
@@ -728,7 +782,7 @@ mips_request (cmd, addr, data, perr)
if (mips_need_reply)
fatal ("mips_request: Trying to send command before reply");
sprintf (buff, "0x0 %c 0x%x 0x%x", cmd, addr, data);
- mips_send_packet (buff);
+ mips_send_packet (buff, 1);
mips_need_reply = 1;
}
@@ -766,6 +820,64 @@ mips_request (cmd, addr, data, perr)
return rresponse;
}
+/* Initialize a new connection to the MIPS board, and make sure we are
+ really connected. */
+
+static void
+mips_initialize ()
+{
+ char cr;
+ int hold_wait;
+ int tries;
+ char buff[DATA_MAXLEN + 1];
+ int err;
+
+ if (mips_initializing)
+ return;
+
+ mips_initializing = 1;
+
+ mips_send_seq = 0;
+ mips_receive_seq = 0;
+
+ /* The board seems to want to send us a packet. I don't know what
+ it means. The packet seems to be triggered by a carriage return
+ character, although perhaps any character would do. */
+ cr = '\r';
+ serial_write (&cr, 1);
+
+ hold_wait = mips_receive_wait;
+ mips_receive_wait = 3;
+
+ tries = 0;
+ while (catch_errors (mips_receive_packet, buff, (char *) NULL) == 0)
+ {
+ char cc;
+
+ if (tries > 0)
+ error ("Could not connect to target");
+ ++tries;
+
+ /* We did not receive the packet we expected; try resetting the
+ board and trying again. */
+ printf_filtered ("Failed to initialize; trying to reset board\n");
+ cc = '\003';
+ serial_write (&cc, 1);
+ sleep (2);
+ serial_write ("\rdb tty0\r", sizeof "\rdb tty0\r" - 1);
+ sleep (1);
+ cr = '\r';
+ serial_write (&cr, 1);
+ }
+
+ mips_receive_wait = hold_wait;
+ mips_initializing = 0;
+
+ /* If this doesn't call error, we have connected; we don't care if
+ the request itself succeeds or fails. */
+ mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err);
+}
+
/* Open a connection to the remote board. */
static void
@@ -773,10 +885,6 @@ mips_open (name, from_tty)
char *name;
int from_tty;
{
- int err;
- char cr;
- char buff[DATA_MAXLEN + 1];
-
if (name == 0)
error (
"To open a MIPS remote debugging connection, you need to specify what serial\n\
@@ -785,28 +893,20 @@ device is attached to the target board (e.g., /dev/ttya).");
target_preopen (from_tty);
if (mips_is_open)
- mips_close (0);
+ unpush_target (&mips_ops);
if (serial_open (name) == 0)
perror_with_name (name);
mips_is_open = 1;
- /* The board seems to want to send us a packet. I don't know what
- it means. */
- cr = '\r';
- serial_write (&cr, 1);
- mips_receive_packet (buff);
-
- /* If this doesn't call error, we have connected; we don't care if
- the request itself succeeds or fails. */
- mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err);
+ mips_initialize ();
if (from_tty)
printf ("Remote MIPS debugging using %s\n", name);
push_target (&mips_ops); /* Switch to using remote target now */
- start_remote (); /* Initialize gdb process mechanisms */
+ /* FIXME: Should we call start_remote here? */
}
/* Close a connection to the remote board. */
@@ -817,11 +917,14 @@ 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,
- (int *) NULL);
+ mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err);
+
serial_close ();
- mips_is_open = 0;
}
}
@@ -852,7 +955,7 @@ mips_resume (step, siggnal)
siggnal);
mips_request (step ? 's' : 'c',
- (unsigned int) read_register (PC_REGNUM),
+ (unsigned int) 1,
(unsigned int) 0,
(int *) NULL);
}
@@ -1099,6 +1202,28 @@ mips_files_info (ignore)
printf ("Debugging a MIPS board over a serial line.\n");
}
+/* Kill the process running on the board. This will actually only
+ work if we are doing remote debugging over the console input. I
+ think that if IDT/sim had the remote debug interrupt enabled on the
+ right port, we could interrupt the process with a break signal. */
+
+static void
+mips_kill ()
+{
+#if 0
+ if (mips_is_open)
+ {
+ char cc;
+
+ /* Send a ^C. */
+ cc = '\003';
+ serial_write (&cc, 1);
+ sleep (1);
+ target_mourn_inferior ();
+ }
+#endif
+}
+
/* Load an executable onto the board. */
static void
@@ -1109,6 +1234,7 @@ mips_load (args, from_tty)
bfd *abfd;
asection *s;
int err;
+ CORE_ADDR text;
abfd = bfd_openr (args, 0);
if (abfd == (bfd *) NULL)
@@ -1117,6 +1243,7 @@ mips_load (args, from_tty)
if (bfd_check_format (abfd, bfd_object) == 0)
error ("%s: Not an object file", args);
+ text = UINT_MAX;
for (s = abfd->sections; s != (asection *) NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0)
@@ -1140,6 +1267,10 @@ mips_load (args, from_tty)
mips_xfer_memory (vma, buffer, size, 1, &mips_ops);
do_cleanups (old_chain);
+
+ if ((bfd_get_section_flags (abfd, s) & SEC_CODE) != 0
+ && vma < text)
+ text = vma;
}
}
}
@@ -1152,7 +1283,13 @@ mips_load (args, from_tty)
bfd_close (abfd);
- /* FIXME: Should we call symbol_file_add here? */
+ /* FIXME: Should we call symbol_file_add here? The local variable
+ text exists just for this call. Making the call seems to confuse
+ gdb if more than one file is loaded in. Perhaps passing MAINLINE
+ as 1 would fix this, but it's not clear that that is correct
+ either since it is possible to load several files onto the board.
+
+ symbol_file_add (args, from_tty, text, 0, 0, 0); */
}
/* Start running on the target board. */
@@ -1165,7 +1302,6 @@ mips_create_inferior (execfile, args, env)
{
CORE_ADDR entry_pt;
- /* FIXME: Actually, we probably could pass arguments. */
if (args && *args)
error ("Can't pass arguments to remote MIPS board.");
@@ -1176,6 +1312,8 @@ mips_create_inferior (execfile, args, env)
init_wait_for_inferior ();
+ /* FIXME: Should we set inferior_pid here? */
+
proceed (entry_pt, -1, 0);
}
@@ -1213,7 +1351,7 @@ Specify the serial device it is connected to (e.g., /dev/ttya).", /* to_doc */
NULL, /* to_terminal_ours_for_output */
NULL, /* to_terminal_ours */
NULL, /* to_terminal_info */
- NULL, /* to_kill */
+ mips_kill, /* to_kill */
mips_load, /* to_load */
NULL, /* to_lookup_symbol */
mips_create_inferior, /* to_create_inferior */