1130812Smarcel/* Remote target communications for serial-line targets using SDS' protocol.
2130812Smarcel
3130812Smarcel   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2004 Free Software
4130812Smarcel   Foundation, Inc.
5130812Smarcel
6130812Smarcel   This file is part of GDB.
7130812Smarcel
8130812Smarcel   This program is free software; you can redistribute it and/or modify
9130812Smarcel   it under the terms of the GNU General Public License as published by
10130812Smarcel   the Free Software Foundation; either version 2 of the License, or
11130812Smarcel   (at your option) any later version.
12130812Smarcel
13130812Smarcel   This program is distributed in the hope that it will be useful,
14130812Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
15130812Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16130812Smarcel   GNU General Public License for more details.
17130812Smarcel
18130812Smarcel   You should have received a copy of the GNU General Public License
19130812Smarcel   along with this program; if not, write to the Free Software
20130812Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
21130812Smarcel   Boston, MA 02111-1307, USA.  */
22130812Smarcel
23130812Smarcel/* This interface was written by studying the behavior of the SDS
24130812Smarcel   monitor on an ADS 821/860 board, and by consulting the
25130812Smarcel   documentation of the monitor that is available on Motorola's web
26130812Smarcel   site.  -sts 8/13/97 */
27130812Smarcel
28130812Smarcel#include "defs.h"
29130812Smarcel#include "gdb_string.h"
30130812Smarcel#include <fcntl.h>
31130812Smarcel#include "frame.h"
32130812Smarcel#include "inferior.h"
33130812Smarcel#include "bfd.h"
34130812Smarcel#include "symfile.h"
35130812Smarcel#include "target.h"
36130812Smarcel#include "gdbcmd.h"
37130812Smarcel#include "objfiles.h"
38130812Smarcel#include "gdb-stabs.h"
39130812Smarcel#include "gdbthread.h"
40130812Smarcel#include "gdbcore.h"
41130812Smarcel#include "regcache.h"
42130812Smarcel
43130812Smarcel#ifdef USG
44130812Smarcel#include <sys/types.h>
45130812Smarcel#endif
46130812Smarcel
47130812Smarcel#include <signal.h>
48130812Smarcel#include "serial.h"
49130812Smarcel
50130812Smarcelextern void _initialize_remote_sds (void);
51130812Smarcel
52130812Smarcel/* Declarations of local functions. */
53130812Smarcel
54130812Smarcelstatic int sds_write_bytes (CORE_ADDR, char *, int);
55130812Smarcel
56130812Smarcelstatic int sds_read_bytes (CORE_ADDR, char *, int);
57130812Smarcel
58130812Smarcelstatic void sds_files_info (struct target_ops *ignore);
59130812Smarcel
60130812Smarcelstatic int sds_xfer_memory (CORE_ADDR, char *, int, int,
61130812Smarcel			    struct mem_attrib *, struct target_ops *);
62130812Smarcel
63130812Smarcelstatic void sds_prepare_to_store (void);
64130812Smarcel
65130812Smarcelstatic void sds_fetch_registers (int);
66130812Smarcel
67130812Smarcelstatic void sds_resume (ptid_t, int, enum target_signal);
68130812Smarcel
69130812Smarcelstatic int sds_start_remote (void *);
70130812Smarcel
71130812Smarcelstatic void sds_open (char *, int);
72130812Smarcel
73130812Smarcelstatic void sds_close (int);
74130812Smarcel
75130812Smarcelstatic void sds_store_registers (int);
76130812Smarcel
77130812Smarcelstatic void sds_mourn (void);
78130812Smarcel
79130812Smarcelstatic void sds_create_inferior (char *, char *, char **);
80130812Smarcel
81130812Smarcelstatic void sds_load (char *, int);
82130812Smarcel
83130812Smarcelstatic int getmessage (unsigned char *, int);
84130812Smarcel
85130812Smarcelstatic int putmessage (unsigned char *, int);
86130812Smarcel
87130812Smarcelstatic int sds_send (unsigned char *, int);
88130812Smarcel
89130812Smarcelstatic int readchar (int);
90130812Smarcel
91130812Smarcelstatic ptid_t sds_wait (ptid_t, struct target_waitstatus *);
92130812Smarcel
93130812Smarcelstatic void sds_kill (void);
94130812Smarcel
95130812Smarcelstatic int fromhex (int);
96130812Smarcel
97130812Smarcelstatic void sds_detach (char *, int);
98130812Smarcel
99130812Smarcelstatic void sds_interrupt (int);
100130812Smarcel
101130812Smarcelstatic void sds_interrupt_twice (int);
102130812Smarcel
103130812Smarcelstatic void interrupt_query (void);
104130812Smarcel
105130812Smarcelstatic int read_frame (char *);
106130812Smarcel
107130812Smarcelstatic int sds_insert_breakpoint (CORE_ADDR, char *);
108130812Smarcel
109130812Smarcelstatic int sds_remove_breakpoint (CORE_ADDR, char *);
110130812Smarcel
111130812Smarcelstatic void init_sds_ops (void);
112130812Smarcel
113130812Smarcelstatic void sds_command (char *args, int from_tty);
114130812Smarcel
115130812Smarcel/* Define the target operations vector. */
116130812Smarcel
117130812Smarcelstatic struct target_ops sds_ops;
118130812Smarcel
119130812Smarcel/* This was 5 seconds, which is a long time to sit and wait.
120130812Smarcel   Unless this is going though some terminal server or multiplexer or
121130812Smarcel   other form of hairy serial connection, I would think 2 seconds would
122130812Smarcel   be plenty.  */
123130812Smarcel
124130812Smarcelstatic int sds_timeout = 2;
125130812Smarcel
126130812Smarcel/* Descriptor for I/O to remote machine.  Initialize it to NULL so
127130812Smarcel   that sds_open knows that we don't have a file open when the program
128130812Smarcel   starts.  */
129130812Smarcel
130130812Smarcelstatic struct serial *sds_desc = NULL;
131130812Smarcel
132130812Smarcel/* This limit comes from the monitor.  */
133130812Smarcel
134130812Smarcel#define	PBUFSIZ	250
135130812Smarcel
136130812Smarcel/* Maximum number of bytes to read/write at once.  The value here
137130812Smarcel   is chosen to fill up a packet (the headers account for the 32).  */
138130812Smarcel#define MAXBUFBYTES ((PBUFSIZ-32)/2)
139130812Smarcel
140130812Smarcelstatic int next_msg_id;
141130812Smarcel
142130812Smarcelstatic int just_started;
143130812Smarcel
144130812Smarcelstatic int message_pending;
145130812Smarcel
146130812Smarcel
147130812Smarcel/* Clean up connection to a remote debugger.  */
148130812Smarcel
149130812Smarcelstatic void
150130812Smarcelsds_close (int quitting)
151130812Smarcel{
152130812Smarcel  if (sds_desc)
153130812Smarcel    serial_close (sds_desc);
154130812Smarcel  sds_desc = NULL;
155130812Smarcel}
156130812Smarcel
157130812Smarcel/* Stub for catch_errors.  */
158130812Smarcel
159130812Smarcelstatic int
160130812Smarcelsds_start_remote (void *dummy)
161130812Smarcel{
162130812Smarcel  int c;
163130812Smarcel  unsigned char buf[200];
164130812Smarcel
165130812Smarcel  immediate_quit++;		/* Allow user to interrupt it */
166130812Smarcel
167130812Smarcel  /* Ack any packet which the remote side has already sent.  */
168130812Smarcel  serial_write (sds_desc, "{#*\r\n", 5);
169130812Smarcel  serial_write (sds_desc, "{#}\r\n", 5);
170130812Smarcel
171130812Smarcel  while ((c = readchar (1)) >= 0)
172130812Smarcel    printf_unfiltered ("%c", c);
173130812Smarcel  printf_unfiltered ("\n");
174130812Smarcel
175130812Smarcel  next_msg_id = 251;
176130812Smarcel
177130812Smarcel  buf[0] = 26;
178130812Smarcel  sds_send (buf, 1);
179130812Smarcel
180130812Smarcel  buf[0] = 0;
181130812Smarcel  sds_send (buf, 1);
182130812Smarcel
183130812Smarcel  immediate_quit--;
184130812Smarcel
185130812Smarcel  start_remote ();		/* Initialize gdb process mechanisms */
186130812Smarcel  return 1;
187130812Smarcel}
188130812Smarcel
189130812Smarcel/* Open a connection to a remote debugger.
190130812Smarcel   NAME is the filename used for communication.  */
191130812Smarcel
192130812Smarcelstatic void
193130812Smarcelsds_open (char *name, int from_tty)
194130812Smarcel{
195130812Smarcel  if (name == 0)
196130812Smarcel    error ("To open a remote debug connection, you need to specify what serial\n\
197130812Smarceldevice is attached to the remote system (e.g. /dev/ttya).");
198130812Smarcel
199130812Smarcel  target_preopen (from_tty);
200130812Smarcel
201130812Smarcel  unpush_target (&sds_ops);
202130812Smarcel
203130812Smarcel  sds_desc = serial_open (name);
204130812Smarcel  if (!sds_desc)
205130812Smarcel    perror_with_name (name);
206130812Smarcel
207130812Smarcel  if (baud_rate != -1)
208130812Smarcel    {
209130812Smarcel      if (serial_setbaudrate (sds_desc, baud_rate))
210130812Smarcel	{
211130812Smarcel	  serial_close (sds_desc);
212130812Smarcel	  perror_with_name (name);
213130812Smarcel	}
214130812Smarcel    }
215130812Smarcel
216130812Smarcel
217130812Smarcel  serial_raw (sds_desc);
218130812Smarcel
219130812Smarcel  /* If there is something sitting in the buffer we might take it as a
220130812Smarcel     response to a command, which would be bad.  */
221130812Smarcel  serial_flush_input (sds_desc);
222130812Smarcel
223130812Smarcel  if (from_tty)
224130812Smarcel    {
225130812Smarcel      puts_filtered ("Remote debugging using ");
226130812Smarcel      puts_filtered (name);
227130812Smarcel      puts_filtered ("\n");
228130812Smarcel    }
229130812Smarcel  push_target (&sds_ops);	/* Switch to using remote target now */
230130812Smarcel
231130812Smarcel  just_started = 1;
232130812Smarcel
233130812Smarcel  /* Start the remote connection; if error (0), discard this target.
234130812Smarcel     In particular, if the user quits, be sure to discard it (we'd be
235130812Smarcel     in an inconsistent state otherwise).  */
236130812Smarcel  if (!catch_errors (sds_start_remote, NULL,
237130812Smarcel		     "Couldn't establish connection to remote target\n",
238130812Smarcel		     RETURN_MASK_ALL))
239130812Smarcel    pop_target ();
240130812Smarcel}
241130812Smarcel
242130812Smarcel/* This takes a program previously attached to and detaches it.  After
243130812Smarcel   this is done, GDB can be used to debug some other program.  We
244130812Smarcel   better not have left any breakpoints in the target program or it'll
245130812Smarcel   die when it hits one.  */
246130812Smarcel
247130812Smarcelstatic void
248130812Smarcelsds_detach (char *args, int from_tty)
249130812Smarcel{
250130812Smarcel  char buf[PBUFSIZ];
251130812Smarcel
252130812Smarcel  if (args)
253130812Smarcel    error ("Argument given to \"detach\" when remotely debugging.");
254130812Smarcel
255130812Smarcel#if 0
256130812Smarcel  /* Tell the remote target to detach.  */
257130812Smarcel  strcpy (buf, "D");
258130812Smarcel  sds_send (buf, 1);
259130812Smarcel#endif
260130812Smarcel
261130812Smarcel  pop_target ();
262130812Smarcel  if (from_tty)
263130812Smarcel    puts_filtered ("Ending remote debugging.\n");
264130812Smarcel}
265130812Smarcel
266130812Smarcel/* Convert hex digit A to a number.  */
267130812Smarcel
268130812Smarcelstatic int
269130812Smarcelfromhex (int a)
270130812Smarcel{
271130812Smarcel  if (a >= '0' && a <= '9')
272130812Smarcel    return a - '0';
273130812Smarcel  else if (a >= 'a' && a <= 'f')
274130812Smarcel    return a - 'a' + 10;
275130812Smarcel  else
276130812Smarcel    error ("Reply contains invalid hex digit %d", a);
277130812Smarcel}
278130812Smarcel
279130812Smarcelstatic int
280130812Smarceltob64 (unsigned char *inbuf, char *outbuf, int len)
281130812Smarcel{
282130812Smarcel  int i, sum;
283130812Smarcel  char *p;
284130812Smarcel
285130812Smarcel  if (len % 3 != 0)
286130812Smarcel    error ("bad length");
287130812Smarcel
288130812Smarcel  p = outbuf;
289130812Smarcel  for (i = 0; i < len; i += 3)
290130812Smarcel    {
291130812Smarcel      /* Collect the next three bytes into a number.  */
292130812Smarcel      sum = ((long) *inbuf++) << 16;
293130812Smarcel      sum |= ((long) *inbuf++) << 8;
294130812Smarcel      sum |= ((long) *inbuf++);
295130812Smarcel
296130812Smarcel      /* Spit out 4 6-bit encodings.  */
297130812Smarcel      *p++ = ((sum >> 18) & 0x3f) + '0';
298130812Smarcel      *p++ = ((sum >> 12) & 0x3f) + '0';
299130812Smarcel      *p++ = ((sum >> 6) & 0x3f) + '0';
300130812Smarcel      *p++ = (sum & 0x3f) + '0';
301130812Smarcel    }
302130812Smarcel  return (p - outbuf);
303130812Smarcel}
304130812Smarcel
305130812Smarcelstatic int
306130812Smarcelfromb64 (char *inbuf, char *outbuf, int len)
307130812Smarcel{
308130812Smarcel  int i, sum;
309130812Smarcel
310130812Smarcel  if (len % 4 != 0)
311130812Smarcel    error ("bad length");
312130812Smarcel
313130812Smarcel  for (i = 0; i < len; i += 4)
314130812Smarcel    {
315130812Smarcel      /* Collect 4 6-bit digits.  */
316130812Smarcel      sum = (*inbuf++ - '0') << 18;
317130812Smarcel      sum |= (*inbuf++ - '0') << 12;
318130812Smarcel      sum |= (*inbuf++ - '0') << 6;
319130812Smarcel      sum |= (*inbuf++ - '0');
320130812Smarcel
321130812Smarcel      /* Now take the resulting 24-bit number and get three bytes out
322130812Smarcel         of it.  */
323130812Smarcel      *outbuf++ = (sum >> 16) & 0xff;
324130812Smarcel      *outbuf++ = (sum >> 8) & 0xff;
325130812Smarcel      *outbuf++ = sum & 0xff;
326130812Smarcel    }
327130812Smarcel
328130812Smarcel  return (len / 4) * 3;
329130812Smarcel}
330130812Smarcel
331130812Smarcel
332130812Smarcel/* Tell the remote machine to resume.  */
333130812Smarcel
334130812Smarcelstatic enum target_signal last_sent_signal = TARGET_SIGNAL_0;
335130812Smarcelint last_sent_step;
336130812Smarcel
337130812Smarcelstatic void
338130812Smarcelsds_resume (ptid_t ptid, int step, enum target_signal siggnal)
339130812Smarcel{
340130812Smarcel  unsigned char buf[PBUFSIZ];
341130812Smarcel
342130812Smarcel  last_sent_signal = siggnal;
343130812Smarcel  last_sent_step = step;
344130812Smarcel
345130812Smarcel  buf[0] = (step ? 21 : 20);
346130812Smarcel  buf[1] = 0;			/* (should be signal?) */
347130812Smarcel
348130812Smarcel  sds_send (buf, 2);
349130812Smarcel}
350130812Smarcel
351130812Smarcel/* Send a message to target to halt it.  Target will respond, and send
352130812Smarcel   us a message pending notice.  */
353130812Smarcel
354130812Smarcelstatic void
355130812Smarcelsds_interrupt (int signo)
356130812Smarcel{
357130812Smarcel  unsigned char buf[PBUFSIZ];
358130812Smarcel
359130812Smarcel  /* If this doesn't work, try more severe steps.  */
360130812Smarcel  signal (signo, sds_interrupt_twice);
361130812Smarcel
362130812Smarcel  if (remote_debug)
363130812Smarcel    fprintf_unfiltered (gdb_stdlog, "sds_interrupt called\n");
364130812Smarcel
365130812Smarcel  buf[0] = 25;
366130812Smarcel  sds_send (buf, 1);
367130812Smarcel}
368130812Smarcel
369130812Smarcelstatic void (*ofunc) ();
370130812Smarcel
371130812Smarcel/* The user typed ^C twice.  */
372130812Smarcel
373130812Smarcelstatic void
374130812Smarcelsds_interrupt_twice (int signo)
375130812Smarcel{
376130812Smarcel  signal (signo, ofunc);
377130812Smarcel
378130812Smarcel  interrupt_query ();
379130812Smarcel
380130812Smarcel  signal (signo, sds_interrupt);
381130812Smarcel}
382130812Smarcel
383130812Smarcel/* Ask the user what to do when an interrupt is received.  */
384130812Smarcel
385130812Smarcelstatic void
386130812Smarcelinterrupt_query (void)
387130812Smarcel{
388130812Smarcel  target_terminal_ours ();
389130812Smarcel
390130812Smarcel  if (query ("Interrupted while waiting for the program.\n\
391130812SmarcelGive up (and stop debugging it)? "))
392130812Smarcel    {
393130812Smarcel      target_mourn_inferior ();
394130812Smarcel      throw_exception (RETURN_QUIT);
395130812Smarcel    }
396130812Smarcel
397130812Smarcel  target_terminal_inferior ();
398130812Smarcel}
399130812Smarcel
400130812Smarcel/* If nonzero, ignore the next kill.  */
401130812Smarcelint kill_kludge;
402130812Smarcel
403130812Smarcel/* Wait until the remote machine stops, then return, storing status in
404130812Smarcel   STATUS just as `wait' would.  Returns "pid" (though it's not clear
405130812Smarcel   what, if anything, that means in the case of this target).  */
406130812Smarcel
407130812Smarcelstatic ptid_t
408130812Smarcelsds_wait (ptid_t ptid, struct target_waitstatus *status)
409130812Smarcel{
410130812Smarcel  unsigned char buf[PBUFSIZ];
411130812Smarcel  int retlen;
412130812Smarcel
413130812Smarcel  status->kind = TARGET_WAITKIND_EXITED;
414130812Smarcel  status->value.integer = 0;
415130812Smarcel
416130812Smarcel  ofunc = (void (*)()) signal (SIGINT, sds_interrupt);
417130812Smarcel
418130812Smarcel  signal (SIGINT, ofunc);
419130812Smarcel
420130812Smarcel  if (just_started)
421130812Smarcel    {
422130812Smarcel      just_started = 0;
423130812Smarcel      status->kind = TARGET_WAITKIND_STOPPED;
424130812Smarcel      return inferior_ptid;
425130812Smarcel    }
426130812Smarcel
427130812Smarcel  while (1)
428130812Smarcel    {
429130812Smarcel      getmessage (buf, 1);
430130812Smarcel
431130812Smarcel      if (message_pending)
432130812Smarcel	{
433130812Smarcel	  buf[0] = 26;
434130812Smarcel	  retlen = sds_send (buf, 1);
435130812Smarcel	  if (remote_debug)
436130812Smarcel	    {
437130812Smarcel	      fprintf_unfiltered (gdb_stdlog, "Signals: %02x%02x %02x %02x\n",
438130812Smarcel				  buf[0], buf[1],
439130812Smarcel				  buf[2], buf[3]);
440130812Smarcel	    }
441130812Smarcel	  message_pending = 0;
442130812Smarcel	  status->kind = TARGET_WAITKIND_STOPPED;
443130812Smarcel	  status->value.sig = TARGET_SIGNAL_TRAP;
444130812Smarcel	  goto got_status;
445130812Smarcel	}
446130812Smarcel    }
447130812Smarcelgot_status:
448130812Smarcel  return inferior_ptid;
449130812Smarcel}
450130812Smarcel
451130812Smarcelstatic unsigned char sprs[16];
452130812Smarcel
453130812Smarcel/* Read the remote registers into the block REGS.  */
454130812Smarcel/* Currently we just read all the registers, so we don't use regno.  */
455130812Smarcel
456130812Smarcelstatic void
457130812Smarcelsds_fetch_registers (int regno)
458130812Smarcel{
459130812Smarcel  unsigned char buf[PBUFSIZ];
460130812Smarcel  int i, retlen;
461130812Smarcel  char *regs = alloca (DEPRECATED_REGISTER_BYTES);
462130812Smarcel
463130812Smarcel  /* Unimplemented registers read as all bits zero.  */
464130812Smarcel  memset (regs, 0, DEPRECATED_REGISTER_BYTES);
465130812Smarcel
466130812Smarcel  buf[0] = 18;
467130812Smarcel  buf[1] = 1;
468130812Smarcel  buf[2] = 0;
469130812Smarcel  retlen = sds_send (buf, 3);
470130812Smarcel
471130812Smarcel  for (i = 0; i < 4 * 6; ++i)
472130812Smarcel    regs[i + 4 * 32 + 8 * 32] = buf[i];
473130812Smarcel  for (i = 0; i < 4 * 4; ++i)
474130812Smarcel    sprs[i] = buf[i + 4 * 7];
475130812Smarcel
476130812Smarcel  buf[0] = 18;
477130812Smarcel  buf[1] = 2;
478130812Smarcel  buf[2] = 0;
479130812Smarcel  retlen = sds_send (buf, 3);
480130812Smarcel
481130812Smarcel  for (i = 0; i < retlen; i++)
482130812Smarcel    regs[i] = buf[i];
483130812Smarcel
484130812Smarcel  /* (should warn about reply too short) */
485130812Smarcel
486130812Smarcel  for (i = 0; i < NUM_REGS; i++)
487130812Smarcel    supply_register (i, &regs[DEPRECATED_REGISTER_BYTE (i)]);
488130812Smarcel}
489130812Smarcel
490130812Smarcel/* Prepare to store registers.  Since we may send them all, we have to
491130812Smarcel   read out the ones we don't want to change first.  */
492130812Smarcel
493130812Smarcelstatic void
494130812Smarcelsds_prepare_to_store (void)
495130812Smarcel{
496130812Smarcel  /* Make sure the entire registers array is valid.  */
497130812Smarcel  deprecated_read_register_bytes (0, (char *) NULL, DEPRECATED_REGISTER_BYTES);
498130812Smarcel}
499130812Smarcel
500130812Smarcel/* Store register REGNO, or all registers if REGNO == -1, from the contents
501130812Smarcel   of REGISTERS.  FIXME: ignores errors.  */
502130812Smarcel
503130812Smarcelstatic void
504130812Smarcelsds_store_registers (int regno)
505130812Smarcel{
506130812Smarcel  unsigned char *p, buf[PBUFSIZ];
507130812Smarcel  int i;
508130812Smarcel
509130812Smarcel  /* Store all the special-purpose registers.  */
510130812Smarcel  p = buf;
511130812Smarcel  *p++ = 19;
512130812Smarcel  *p++ = 1;
513130812Smarcel  *p++ = 0;
514130812Smarcel  *p++ = 0;
515130812Smarcel  for (i = 0; i < 4 * 6; i++)
516130812Smarcel    *p++ = deprecated_registers[i + 4 * 32 + 8 * 32];
517130812Smarcel  for (i = 0; i < 4 * 1; i++)
518130812Smarcel    *p++ = 0;
519130812Smarcel  for (i = 0; i < 4 * 4; i++)
520130812Smarcel    *p++ = sprs[i];
521130812Smarcel
522130812Smarcel  sds_send (buf, p - buf);
523130812Smarcel
524130812Smarcel  /* Store all the general-purpose registers.  */
525130812Smarcel  p = buf;
526130812Smarcel  *p++ = 19;
527130812Smarcel  *p++ = 2;
528130812Smarcel  *p++ = 0;
529130812Smarcel  *p++ = 0;
530130812Smarcel  for (i = 0; i < 4 * 32; i++)
531130812Smarcel    *p++ = deprecated_registers[i];
532130812Smarcel
533130812Smarcel  sds_send (buf, p - buf);
534130812Smarcel
535130812Smarcel}
536130812Smarcel
537130812Smarcel/* Write memory data directly to the remote machine.  This does not
538130812Smarcel   inform the data cache; the data cache uses this.  MEMADDR is the
539130812Smarcel   address in the remote memory space.  MYADDR is the address of the
540130812Smarcel   buffer in our space.  LEN is the number of bytes.
541130812Smarcel
542130812Smarcel   Returns number of bytes transferred, or 0 for error.  */
543130812Smarcel
544130812Smarcelstatic int
545130812Smarcelsds_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
546130812Smarcel{
547130812Smarcel  int max_buf_size;		/* Max size of packet output buffer */
548130812Smarcel  int origlen;
549130812Smarcel  unsigned char buf[PBUFSIZ];
550130812Smarcel  int todo;
551130812Smarcel  int i;
552130812Smarcel
553130812Smarcel  /* Chop the transfer down if necessary */
554130812Smarcel
555130812Smarcel  max_buf_size = 150;
556130812Smarcel
557130812Smarcel  origlen = len;
558130812Smarcel  while (len > 0)
559130812Smarcel    {
560130812Smarcel      todo = min (len, max_buf_size);
561130812Smarcel
562130812Smarcel      buf[0] = 13;
563130812Smarcel      buf[1] = 0;
564130812Smarcel      buf[2] = (int) (memaddr >> 24) & 0xff;
565130812Smarcel      buf[3] = (int) (memaddr >> 16) & 0xff;
566130812Smarcel      buf[4] = (int) (memaddr >> 8) & 0xff;
567130812Smarcel      buf[5] = (int) (memaddr) & 0xff;
568130812Smarcel      buf[6] = 1;
569130812Smarcel      buf[7] = 0;
570130812Smarcel
571130812Smarcel      for (i = 0; i < todo; i++)
572130812Smarcel	buf[i + 8] = myaddr[i];
573130812Smarcel
574130812Smarcel      sds_send (buf, 8 + todo);
575130812Smarcel
576130812Smarcel      /* (should look at result) */
577130812Smarcel
578130812Smarcel      myaddr += todo;
579130812Smarcel      memaddr += todo;
580130812Smarcel      len -= todo;
581130812Smarcel    }
582130812Smarcel  return origlen;
583130812Smarcel}
584130812Smarcel
585130812Smarcel/* Read memory data directly from the remote machine.  This does not
586130812Smarcel   use the data cache; the data cache uses this.  MEMADDR is the
587130812Smarcel   address in the remote memory space.  MYADDR is the address of the
588130812Smarcel   buffer in our space.  LEN is the number of bytes.
589130812Smarcel
590130812Smarcel   Returns number of bytes transferred, or 0 for error.  */
591130812Smarcel
592130812Smarcelstatic int
593130812Smarcelsds_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
594130812Smarcel{
595130812Smarcel  int max_buf_size;		/* Max size of packet output buffer */
596130812Smarcel  int origlen, retlen;
597130812Smarcel  unsigned char buf[PBUFSIZ];
598130812Smarcel  int todo;
599130812Smarcel  int i;
600130812Smarcel
601130812Smarcel  /* Chop the transfer down if necessary */
602130812Smarcel
603130812Smarcel  max_buf_size = 150;
604130812Smarcel
605130812Smarcel  origlen = len;
606130812Smarcel  while (len > 0)
607130812Smarcel    {
608130812Smarcel      todo = min (len, max_buf_size);
609130812Smarcel
610130812Smarcel      buf[0] = 12;
611130812Smarcel      buf[1] = 0;
612130812Smarcel      buf[2] = (int) (memaddr >> 24) & 0xff;
613130812Smarcel      buf[3] = (int) (memaddr >> 16) & 0xff;
614130812Smarcel      buf[4] = (int) (memaddr >> 8) & 0xff;
615130812Smarcel      buf[5] = (int) (memaddr) & 0xff;
616130812Smarcel      buf[6] = (int) (todo >> 8) & 0xff;
617130812Smarcel      buf[7] = (int) (todo) & 0xff;
618130812Smarcel      buf[8] = 1;
619130812Smarcel
620130812Smarcel      retlen = sds_send (buf, 9);
621130812Smarcel
622130812Smarcel      if (retlen - 2 != todo)
623130812Smarcel	{
624130812Smarcel	  return 0;
625130812Smarcel	}
626130812Smarcel
627130812Smarcel      /* Reply describes memory byte by byte. */
628130812Smarcel
629130812Smarcel      for (i = 0; i < todo; i++)
630130812Smarcel	myaddr[i] = buf[i + 2];
631130812Smarcel
632130812Smarcel      myaddr += todo;
633130812Smarcel      memaddr += todo;
634130812Smarcel      len -= todo;
635130812Smarcel    }
636130812Smarcel
637130812Smarcel  return origlen;
638130812Smarcel}
639130812Smarcel
640130812Smarcel/* Read or write LEN bytes from inferior memory at MEMADDR,
641130812Smarcel   transferring to or from debugger address MYADDR.  Write to inferior
642130812Smarcel   if SHOULD_WRITE is nonzero.  Returns length of data written or
643130812Smarcel   read; 0 for error.  TARGET is unused.  */
644130812Smarcel
645130812Smarcelstatic int
646130812Smarcelsds_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write,
647130812Smarcel		 struct mem_attrib *attrib, struct target_ops *target)
648130812Smarcel{
649130812Smarcel  int res;
650130812Smarcel
651130812Smarcel  if (should_write)
652130812Smarcel    res = sds_write_bytes (memaddr, myaddr, len);
653130812Smarcel  else
654130812Smarcel    res = sds_read_bytes (memaddr, myaddr, len);
655130812Smarcel
656130812Smarcel  return res;
657130812Smarcel}
658130812Smarcel
659130812Smarcel
660130812Smarcelstatic void
661130812Smarcelsds_files_info (struct target_ops *ignore)
662130812Smarcel{
663130812Smarcel  puts_filtered ("Debugging over a serial connection, using SDS protocol.\n");
664130812Smarcel}
665130812Smarcel
666130812Smarcel/* Stuff for dealing with the packets which are part of this protocol.
667130812Smarcel   See comment at top of file for details.  */
668130812Smarcel
669130812Smarcel/* Read a single character from the remote end, masking it down to 7 bits. */
670130812Smarcel
671130812Smarcelstatic int
672130812Smarcelreadchar (int timeout)
673130812Smarcel{
674130812Smarcel  int ch;
675130812Smarcel
676130812Smarcel  ch = serial_readchar (sds_desc, timeout);
677130812Smarcel
678130812Smarcel  if (remote_debug > 1 && ch >= 0)
679130812Smarcel    fprintf_unfiltered (gdb_stdlog, "%c(%x)", ch, ch);
680130812Smarcel
681130812Smarcel  switch (ch)
682130812Smarcel    {
683130812Smarcel    case SERIAL_EOF:
684130812Smarcel      error ("Remote connection closed");
685130812Smarcel    case SERIAL_ERROR:
686130812Smarcel      perror_with_name ("Remote communication error");
687130812Smarcel    case SERIAL_TIMEOUT:
688130812Smarcel      return ch;
689130812Smarcel    default:
690130812Smarcel      return ch & 0x7f;
691130812Smarcel    }
692130812Smarcel}
693130812Smarcel
694130812Smarcel/* An SDS-style checksum is a sum of the bytes modulo 253.  (Presumably
695130812Smarcel   because 253, 254, and 255 are special flags in the protocol.)  */
696130812Smarcel
697130812Smarcelstatic int
698130812Smarcelcompute_checksum (int csum, char *buf, int len)
699130812Smarcel{
700130812Smarcel  int i;
701130812Smarcel
702130812Smarcel  for (i = 0; i < len; ++i)
703130812Smarcel    csum += (unsigned char) buf[i];
704130812Smarcel
705130812Smarcel  csum %= 253;
706130812Smarcel  return csum;
707130812Smarcel}
708130812Smarcel
709130812Smarcel/* Send the command in BUF to the remote machine, and read the reply
710130812Smarcel   into BUF also.  */
711130812Smarcel
712130812Smarcelstatic int
713130812Smarcelsds_send (unsigned char *buf, int len)
714130812Smarcel{
715130812Smarcel  putmessage (buf, len);
716130812Smarcel
717130812Smarcel  return getmessage (buf, 0);
718130812Smarcel}
719130812Smarcel
720130812Smarcel/* Send a message to the remote machine.  */
721130812Smarcel
722130812Smarcelstatic int
723130812Smarcelputmessage (unsigned char *buf, int len)
724130812Smarcel{
725130812Smarcel  int i, enclen;
726130812Smarcel  unsigned char csum = 0;
727130812Smarcel  char buf2[PBUFSIZ], buf3[PBUFSIZ];
728130812Smarcel  unsigned char header[3];
729130812Smarcel  char *p;
730130812Smarcel
731130812Smarcel  /* Copy the packet into buffer BUF2, encapsulating it
732130812Smarcel     and giving it a checksum.  */
733130812Smarcel
734130812Smarcel  if (len > 170)		/* Prosanity check */
735130812Smarcel    internal_error (__FILE__, __LINE__, "failed internal consistency check");
736130812Smarcel
737130812Smarcel  if (remote_debug)
738130812Smarcel    {
739130812Smarcel      fprintf_unfiltered (gdb_stdlog, "Message to send: \"");
740130812Smarcel      for (i = 0; i < len; ++i)
741130812Smarcel	fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
742130812Smarcel      fprintf_unfiltered (gdb_stdlog, "\"\n");
743130812Smarcel    }
744130812Smarcel
745130812Smarcel  p = buf2;
746130812Smarcel  *p++ = '$';
747130812Smarcel
748130812Smarcel  if (len % 3 != 0)
749130812Smarcel    {
750130812Smarcel      buf[len] = '\0';
751130812Smarcel      buf[len + 1] = '\0';
752130812Smarcel    }
753130812Smarcel
754130812Smarcel  header[1] = next_msg_id;
755130812Smarcel
756130812Smarcel  header[2] = len;
757130812Smarcel
758130812Smarcel  csum = compute_checksum (csum, buf, len);
759130812Smarcel  csum = compute_checksum (csum, header + 1, 2);
760130812Smarcel
761130812Smarcel  header[0] = csum;
762130812Smarcel
763130812Smarcel  tob64 (header, p, 3);
764130812Smarcel  p += 4;
765130812Smarcel  enclen = tob64 (buf, buf3, ((len + 2) / 3) * 3);
766130812Smarcel
767130812Smarcel  for (i = 0; i < enclen; ++i)
768130812Smarcel    *p++ = buf3[i];
769130812Smarcel  *p++ = '\r';
770130812Smarcel  *p++ = '\n';
771130812Smarcel
772130812Smarcel  next_msg_id = (next_msg_id + 3) % 245;
773130812Smarcel
774130812Smarcel  /* Send it over and over until we get a positive ack.  */
775130812Smarcel
776130812Smarcel  while (1)
777130812Smarcel    {
778130812Smarcel      if (remote_debug)
779130812Smarcel	{
780130812Smarcel	  *p = '\0';
781130812Smarcel	  fprintf_unfiltered (gdb_stdlog, "Sending encoded: \"%s\"", buf2);
782130812Smarcel	  fprintf_unfiltered (gdb_stdlog,
783130812Smarcel			      "  (Checksum %d, id %d, length %d)\n",
784130812Smarcel			      header[0], header[1], header[2]);
785130812Smarcel	  gdb_flush (gdb_stdlog);
786130812Smarcel	}
787130812Smarcel      if (serial_write (sds_desc, buf2, p - buf2))
788130812Smarcel	perror_with_name ("putmessage: write failed");
789130812Smarcel
790130812Smarcel      return 1;
791130812Smarcel    }
792130812Smarcel}
793130812Smarcel
794130812Smarcel/* Come here after finding the start of the frame.  Collect the rest
795130812Smarcel   into BUF.  Returns 0 on any error, 1 on success.  */
796130812Smarcel
797130812Smarcelstatic int
798130812Smarcelread_frame (char *buf)
799130812Smarcel{
800130812Smarcel  char *bp;
801130812Smarcel  int c;
802130812Smarcel
803130812Smarcel  bp = buf;
804130812Smarcel
805130812Smarcel  while (1)
806130812Smarcel    {
807130812Smarcel      c = readchar (sds_timeout);
808130812Smarcel
809130812Smarcel      switch (c)
810130812Smarcel	{
811130812Smarcel	case SERIAL_TIMEOUT:
812130812Smarcel	  if (remote_debug)
813130812Smarcel	    fputs_filtered ("Timeout in mid-message, retrying\n", gdb_stdlog);
814130812Smarcel	  return 0;
815130812Smarcel	case '$':
816130812Smarcel	  if (remote_debug)
817130812Smarcel	    fputs_filtered ("Saw new packet start in middle of old one\n",
818130812Smarcel			    gdb_stdlog);
819130812Smarcel	  return 0;		/* Start a new packet, count retries */
820130812Smarcel	case '\r':
821130812Smarcel	  break;
822130812Smarcel
823130812Smarcel	case '\n':
824130812Smarcel	  {
825130812Smarcel	    *bp = '\000';
826130812Smarcel	    if (remote_debug)
827130812Smarcel	      fprintf_unfiltered (gdb_stdlog, "Received encoded: \"%s\"\n",
828130812Smarcel				  buf);
829130812Smarcel	    return 1;
830130812Smarcel	  }
831130812Smarcel
832130812Smarcel	default:
833130812Smarcel	  if (bp < buf + PBUFSIZ - 1)
834130812Smarcel	    {
835130812Smarcel	      *bp++ = c;
836130812Smarcel	      continue;
837130812Smarcel	    }
838130812Smarcel
839130812Smarcel	  *bp = '\0';
840130812Smarcel	  puts_filtered ("Message too long: ");
841130812Smarcel	  puts_filtered (buf);
842130812Smarcel	  puts_filtered ("\n");
843130812Smarcel
844130812Smarcel	  return 0;
845130812Smarcel	}
846130812Smarcel    }
847130812Smarcel}
848130812Smarcel
849130812Smarcel/* Read a packet from the remote machine, with error checking,
850130812Smarcel   and store it in BUF.  BUF is expected to be of size PBUFSIZ.
851130812Smarcel   If FOREVER, wait forever rather than timing out; this is used
852130812Smarcel   while the target is executing user code.  */
853130812Smarcel
854130812Smarcelstatic int
855130812Smarcelgetmessage (unsigned char *buf, int forever)
856130812Smarcel{
857130812Smarcel  int c, c2, c3;
858130812Smarcel  int tries;
859130812Smarcel  int timeout;
860130812Smarcel  int val, i, len, csum;
861130812Smarcel  unsigned char header[3];
862130812Smarcel  unsigned char inbuf[500];
863130812Smarcel
864130812Smarcel  strcpy (buf, "timeout");
865130812Smarcel
866130812Smarcel  if (forever)
867130812Smarcel    {
868130812Smarcel      timeout = watchdog > 0 ? watchdog : -1;
869130812Smarcel    }
870130812Smarcel
871130812Smarcel  else
872130812Smarcel    timeout = sds_timeout;
873130812Smarcel
874130812Smarcel#define MAX_TRIES 3
875130812Smarcel
876130812Smarcel  for (tries = 1; tries <= MAX_TRIES; tries++)
877130812Smarcel    {
878130812Smarcel      /* This can loop forever if the remote side sends us characters
879130812Smarcel         continuously, but if it pauses, we'll get a zero from readchar
880130812Smarcel         because of timeout.  Then we'll count that as a retry.  */
881130812Smarcel
882130812Smarcel      /* Note that we will only wait forever prior to the start of a packet.
883130812Smarcel         After that, we expect characters to arrive at a brisk pace.  They
884130812Smarcel         should show up within sds_timeout intervals.  */
885130812Smarcel
886130812Smarcel      do
887130812Smarcel	{
888130812Smarcel	  c = readchar (timeout);
889130812Smarcel
890130812Smarcel	  if (c == SERIAL_TIMEOUT)
891130812Smarcel	    {
892130812Smarcel	      if (forever)	/* Watchdog went off.  Kill the target. */
893130812Smarcel		{
894130812Smarcel		  target_mourn_inferior ();
895130812Smarcel		  error ("Watchdog has expired.  Target detached.\n");
896130812Smarcel		}
897130812Smarcel	      if (remote_debug)
898130812Smarcel		fputs_filtered ("Timed out.\n", gdb_stdlog);
899130812Smarcel	      goto retry;
900130812Smarcel	    }
901130812Smarcel	}
902130812Smarcel      while (c != '$' && c != '{');
903130812Smarcel
904130812Smarcel      /* We might have seen a "trigraph", a sequence of three characters
905130812Smarcel         that indicate various sorts of communication state.  */
906130812Smarcel
907130812Smarcel      if (c == '{')
908130812Smarcel	{
909130812Smarcel	  /* Read the other two chars of the trigraph. */
910130812Smarcel	  c2 = readchar (timeout);
911130812Smarcel	  c3 = readchar (timeout);
912130812Smarcel	  if (remote_debug)
913130812Smarcel	    fprintf_unfiltered (gdb_stdlog, "Trigraph %c%c%c received\n",
914130812Smarcel				c, c2, c3);
915130812Smarcel	  if (c3 == '+')
916130812Smarcel	    {
917130812Smarcel	      message_pending = 1;
918130812Smarcel	      return 0;		/*???? */
919130812Smarcel	    }
920130812Smarcel	  continue;
921130812Smarcel	}
922130812Smarcel
923130812Smarcel      val = read_frame (inbuf);
924130812Smarcel
925130812Smarcel      if (val == 1)
926130812Smarcel	{
927130812Smarcel	  fromb64 (inbuf, header, 4);
928130812Smarcel	  /* (should check out other bits) */
929130812Smarcel	  fromb64 (inbuf + 4, buf, strlen (inbuf) - 4);
930130812Smarcel
931130812Smarcel	  len = header[2];
932130812Smarcel
933130812Smarcel	  csum = 0;
934130812Smarcel	  csum = compute_checksum (csum, buf, len);
935130812Smarcel	  csum = compute_checksum (csum, header + 1, 2);
936130812Smarcel
937130812Smarcel	  if (csum != header[0])
938130812Smarcel	    fprintf_unfiltered (gdb_stderr,
939130812Smarcel			    "Checksum mismatch: computed %d, received %d\n",
940130812Smarcel				csum, header[0]);
941130812Smarcel
942130812Smarcel	  if (header[2] == 0xff)
943130812Smarcel	    fprintf_unfiltered (gdb_stderr, "Requesting resend...\n");
944130812Smarcel
945130812Smarcel	  if (remote_debug)
946130812Smarcel	    {
947130812Smarcel	      fprintf_unfiltered (gdb_stdlog,
948130812Smarcel				"... (Got checksum %d, id %d, length %d)\n",
949130812Smarcel				  header[0], header[1], header[2]);
950130812Smarcel	      fprintf_unfiltered (gdb_stdlog, "Message received: \"");
951130812Smarcel	      for (i = 0; i < len; ++i)
952130812Smarcel		{
953130812Smarcel		  fprintf_unfiltered (gdb_stdlog, "%02x", (unsigned char) buf[i]);
954130812Smarcel		}
955130812Smarcel	      fprintf_unfiltered (gdb_stdlog, "\"\n");
956130812Smarcel	    }
957130812Smarcel
958130812Smarcel	  /* no ack required? */
959130812Smarcel	  return len;
960130812Smarcel	}
961130812Smarcel
962130812Smarcel      /* Try the whole thing again.  */
963130812Smarcel    retry:
964130812Smarcel      /* need to do something here */
965130812Smarcel      ;
966130812Smarcel    }
967130812Smarcel
968130812Smarcel  /* We have tried hard enough, and just can't receive the packet.  Give up. */
969130812Smarcel
970130812Smarcel  printf_unfiltered ("Ignoring packet error, continuing...\n");
971130812Smarcel  return 0;
972130812Smarcel}
973130812Smarcel
974130812Smarcelstatic void
975130812Smarcelsds_kill (void)
976130812Smarcel{
977130812Smarcel  /* Don't try to do anything to the target.  */
978130812Smarcel}
979130812Smarcel
980130812Smarcelstatic void
981130812Smarcelsds_mourn (void)
982130812Smarcel{
983130812Smarcel  unpush_target (&sds_ops);
984130812Smarcel  generic_mourn_inferior ();
985130812Smarcel}
986130812Smarcel
987130812Smarcelstatic void
988130812Smarcelsds_create_inferior (char *exec_file, char *args, char **env)
989130812Smarcel{
990130812Smarcel  inferior_ptid = pid_to_ptid (42000);
991130812Smarcel
992130812Smarcel  /* Clean up from the last time we were running.  */
993130812Smarcel  clear_proceed_status ();
994130812Smarcel
995130812Smarcel  /* Let the remote process run.  */
996130812Smarcel  proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
997130812Smarcel}
998130812Smarcel
999130812Smarcelstatic void
1000130812Smarcelsds_load (char *filename, int from_tty)
1001130812Smarcel{
1002130812Smarcel  generic_load (filename, from_tty);
1003130812Smarcel
1004130812Smarcel  inferior_ptid = null_ptid;
1005130812Smarcel}
1006130812Smarcel
1007130812Smarcel/* The SDS monitor has commands for breakpoint insertion, although it
1008130812Smarcel   it doesn't actually manage the breakpoints, it just returns the
1009130812Smarcel   replaced instruction back to the debugger.  */
1010130812Smarcel
1011130812Smarcelstatic int
1012130812Smarcelsds_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
1013130812Smarcel{
1014130812Smarcel  int i, retlen;
1015130812Smarcel  unsigned char *p, buf[PBUFSIZ];
1016130812Smarcel
1017130812Smarcel  p = buf;
1018130812Smarcel  *p++ = 16;
1019130812Smarcel  *p++ = 0;
1020130812Smarcel  *p++ = (int) (addr >> 24) & 0xff;
1021130812Smarcel  *p++ = (int) (addr >> 16) & 0xff;
1022130812Smarcel  *p++ = (int) (addr >> 8) & 0xff;
1023130812Smarcel  *p++ = (int) (addr) & 0xff;
1024130812Smarcel
1025130812Smarcel  retlen = sds_send (buf, p - buf);
1026130812Smarcel
1027130812Smarcel  for (i = 0; i < 4; ++i)
1028130812Smarcel    contents_cache[i] = buf[i + 2];
1029130812Smarcel
1030130812Smarcel  return 0;
1031130812Smarcel}
1032130812Smarcel
1033130812Smarcelstatic int
1034130812Smarcelsds_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
1035130812Smarcel{
1036130812Smarcel  int i, retlen;
1037130812Smarcel  unsigned char *p, buf[PBUFSIZ];
1038130812Smarcel
1039130812Smarcel  p = buf;
1040130812Smarcel  *p++ = 17;
1041130812Smarcel  *p++ = 0;
1042130812Smarcel  *p++ = (int) (addr >> 24) & 0xff;
1043130812Smarcel  *p++ = (int) (addr >> 16) & 0xff;
1044130812Smarcel  *p++ = (int) (addr >> 8) & 0xff;
1045130812Smarcel  *p++ = (int) (addr) & 0xff;
1046130812Smarcel  for (i = 0; i < 4; ++i)
1047130812Smarcel    *p++ = contents_cache[i];
1048130812Smarcel
1049130812Smarcel  retlen = sds_send (buf, p - buf);
1050130812Smarcel
1051130812Smarcel  return 0;
1052130812Smarcel}
1053130812Smarcel
1054130812Smarcelstatic void
1055130812Smarcelinit_sds_ops (void)
1056130812Smarcel{
1057130812Smarcel  sds_ops.to_shortname = "sds";
1058130812Smarcel  sds_ops.to_longname = "Remote serial target with SDS protocol";
1059130812Smarcel  sds_ops.to_doc = "Use a remote computer via a serial line; using the SDS protocol.\n\
1060130812SmarcelSpecify the serial device it is connected to (e.g. /dev/ttya).";
1061130812Smarcel  sds_ops.to_open = sds_open;
1062130812Smarcel  sds_ops.to_close = sds_close;
1063130812Smarcel  sds_ops.to_detach = sds_detach;
1064130812Smarcel  sds_ops.to_resume = sds_resume;
1065130812Smarcel  sds_ops.to_wait = sds_wait;
1066130812Smarcel  sds_ops.to_fetch_registers = sds_fetch_registers;
1067130812Smarcel  sds_ops.to_store_registers = sds_store_registers;
1068130812Smarcel  sds_ops.to_prepare_to_store = sds_prepare_to_store;
1069130812Smarcel  sds_ops.to_xfer_memory = sds_xfer_memory;
1070130812Smarcel  sds_ops.to_files_info = sds_files_info;
1071130812Smarcel  sds_ops.to_insert_breakpoint = sds_insert_breakpoint;
1072130812Smarcel  sds_ops.to_remove_breakpoint = sds_remove_breakpoint;
1073130812Smarcel  sds_ops.to_kill = sds_kill;
1074130812Smarcel  sds_ops.to_load = sds_load;
1075130812Smarcel  sds_ops.to_create_inferior = sds_create_inferior;
1076130812Smarcel  sds_ops.to_mourn_inferior = sds_mourn;
1077130812Smarcel  sds_ops.to_stratum = process_stratum;
1078130812Smarcel  sds_ops.to_has_all_memory = 1;
1079130812Smarcel  sds_ops.to_has_memory = 1;
1080130812Smarcel  sds_ops.to_has_stack = 1;
1081130812Smarcel  sds_ops.to_has_registers = 1;
1082130812Smarcel  sds_ops.to_has_execution = 1;
1083130812Smarcel  sds_ops.to_magic = OPS_MAGIC;
1084130812Smarcel}
1085130812Smarcel
1086130812Smarcel/* Put a command string, in args, out to the monitor and display the
1087130812Smarcel   reply message.  */
1088130812Smarcel
1089130812Smarcelstatic void
1090130812Smarcelsds_command (char *args, int from_tty)
1091130812Smarcel{
1092130812Smarcel  char *p;
1093130812Smarcel  int i, len, retlen;
1094130812Smarcel  unsigned char buf[1000];
1095130812Smarcel
1096130812Smarcel  /* Convert hexadecimal chars into a byte buffer.  */
1097130812Smarcel  p = args;
1098130812Smarcel  len = 0;
1099130812Smarcel  while (*p != '\0')
1100130812Smarcel    {
1101130812Smarcel      buf[len++] = fromhex (p[0]) * 16 + fromhex (p[1]);
1102130812Smarcel      if (p[1] == '\0')
1103130812Smarcel	break;
1104130812Smarcel      p += 2;
1105130812Smarcel    }
1106130812Smarcel
1107130812Smarcel  retlen = sds_send (buf, len);
1108130812Smarcel
1109130812Smarcel  printf_filtered ("Reply is ");
1110130812Smarcel  for (i = 0; i < retlen; ++i)
1111130812Smarcel    {
1112130812Smarcel      printf_filtered ("%02x", buf[i]);
1113130812Smarcel    }
1114130812Smarcel  printf_filtered ("\n");
1115130812Smarcel}
1116130812Smarcel
1117130812Smarcelvoid
1118130812Smarcel_initialize_remote_sds (void)
1119130812Smarcel{
1120130812Smarcel  init_sds_ops ();
1121130812Smarcel  add_target (&sds_ops);
1122130812Smarcel
1123130812Smarcel  add_show_from_set (add_set_cmd ("sdstimeout", no_class,
1124130812Smarcel				  var_integer, (char *) &sds_timeout,
1125130812Smarcel			     "Set timeout value for sds read.\n", &setlist),
1126130812Smarcel		     &showlist);
1127130812Smarcel
1128130812Smarcel  add_com ("sds", class_obscure, sds_command,
1129130812Smarcel	   "Send a command to the SDS monitor.");
1130130812Smarcel}
1131