xref: /openbsd/gnu/usr.bin/binutils/gdb/remote-sds.c (revision 11efff7f)
1b725ae77Skettenis /* Remote target communications for serial-line targets using SDS' protocol.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2004 Free Software
4b725ae77Skettenis    Foundation, Inc.
5b725ae77Skettenis 
6b725ae77Skettenis    This file is part of GDB.
7b725ae77Skettenis 
8b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
9b725ae77Skettenis    it under the terms of the GNU General Public License as published by
10b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
11b725ae77Skettenis    (at your option) any later version.
12b725ae77Skettenis 
13b725ae77Skettenis    This program is distributed in the hope that it will be useful,
14b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
15b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b725ae77Skettenis    GNU General Public License for more details.
17b725ae77Skettenis 
18b725ae77Skettenis    You should have received a copy of the GNU General Public License
19b725ae77Skettenis    along with this program; if not, write to the Free Software
20b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
22b725ae77Skettenis 
23b725ae77Skettenis /* This interface was written by studying the behavior of the SDS
24b725ae77Skettenis    monitor on an ADS 821/860 board, and by consulting the
25b725ae77Skettenis    documentation of the monitor that is available on Motorola's web
26b725ae77Skettenis    site.  -sts 8/13/97 */
27b725ae77Skettenis 
28b725ae77Skettenis #include "defs.h"
29b725ae77Skettenis #include "gdb_string.h"
30b725ae77Skettenis #include <fcntl.h>
31b725ae77Skettenis #include "frame.h"
32b725ae77Skettenis #include "inferior.h"
33b725ae77Skettenis #include "bfd.h"
34b725ae77Skettenis #include "symfile.h"
35b725ae77Skettenis #include "target.h"
36b725ae77Skettenis #include "gdbcmd.h"
37b725ae77Skettenis #include "objfiles.h"
38b725ae77Skettenis #include "gdb-stabs.h"
39b725ae77Skettenis #include "gdbthread.h"
40b725ae77Skettenis #include "gdbcore.h"
41b725ae77Skettenis #include "regcache.h"
42b725ae77Skettenis 
43b725ae77Skettenis #include <signal.h>
44b725ae77Skettenis #include "serial.h"
45b725ae77Skettenis 
46b725ae77Skettenis extern void _initialize_remote_sds (void);
47b725ae77Skettenis 
48b725ae77Skettenis /* Declarations of local functions. */
49b725ae77Skettenis 
50b725ae77Skettenis static int sds_write_bytes (CORE_ADDR, char *, int);
51b725ae77Skettenis 
52b725ae77Skettenis static int sds_read_bytes (CORE_ADDR, char *, int);
53b725ae77Skettenis 
54b725ae77Skettenis static void sds_files_info (struct target_ops *ignore);
55b725ae77Skettenis 
56b725ae77Skettenis static int sds_xfer_memory (CORE_ADDR, char *, int, int,
57b725ae77Skettenis 			    struct mem_attrib *, struct target_ops *);
58b725ae77Skettenis 
59b725ae77Skettenis static void sds_prepare_to_store (void);
60b725ae77Skettenis 
61b725ae77Skettenis static void sds_fetch_registers (int);
62b725ae77Skettenis 
63b725ae77Skettenis static void sds_resume (ptid_t, int, enum target_signal);
64b725ae77Skettenis 
65b725ae77Skettenis static int sds_start_remote (void *);
66b725ae77Skettenis 
67b725ae77Skettenis static void sds_open (char *, int);
68b725ae77Skettenis 
69b725ae77Skettenis static void sds_close (int);
70b725ae77Skettenis 
71b725ae77Skettenis static void sds_store_registers (int);
72b725ae77Skettenis 
73b725ae77Skettenis static void sds_mourn (void);
74b725ae77Skettenis 
75b725ae77Skettenis static void sds_load (char *, int);
76b725ae77Skettenis 
77b725ae77Skettenis static int getmessage (unsigned char *, int);
78b725ae77Skettenis 
79b725ae77Skettenis static int putmessage (unsigned char *, int);
80b725ae77Skettenis 
81b725ae77Skettenis static int sds_send (unsigned char *, int);
82b725ae77Skettenis 
83b725ae77Skettenis static int readchar (int);
84b725ae77Skettenis 
85b725ae77Skettenis static ptid_t sds_wait (ptid_t, struct target_waitstatus *);
86b725ae77Skettenis 
87b725ae77Skettenis static void sds_kill (void);
88b725ae77Skettenis 
89b725ae77Skettenis static int fromhex (int);
90b725ae77Skettenis 
91b725ae77Skettenis static void sds_detach (char *, int);
92b725ae77Skettenis 
93b725ae77Skettenis static void sds_interrupt (int);
94b725ae77Skettenis 
95b725ae77Skettenis static void sds_interrupt_twice (int);
96b725ae77Skettenis 
97b725ae77Skettenis static void interrupt_query (void);
98b725ae77Skettenis 
99b725ae77Skettenis static int read_frame (char *);
100b725ae77Skettenis 
101b725ae77Skettenis static int sds_insert_breakpoint (CORE_ADDR, char *);
102b725ae77Skettenis 
103b725ae77Skettenis static int sds_remove_breakpoint (CORE_ADDR, char *);
104b725ae77Skettenis 
105b725ae77Skettenis static void init_sds_ops (void);
106b725ae77Skettenis 
107b725ae77Skettenis static void sds_command (char *args, int from_tty);
108b725ae77Skettenis 
109b725ae77Skettenis /* Define the target operations vector. */
110b725ae77Skettenis 
111b725ae77Skettenis static struct target_ops sds_ops;
112b725ae77Skettenis 
113b725ae77Skettenis /* This was 5 seconds, which is a long time to sit and wait.
114b725ae77Skettenis    Unless this is going though some terminal server or multiplexer or
115b725ae77Skettenis    other form of hairy serial connection, I would think 2 seconds would
116b725ae77Skettenis    be plenty.  */
117b725ae77Skettenis 
118b725ae77Skettenis static int sds_timeout = 2;
119b725ae77Skettenis 
120b725ae77Skettenis /* Descriptor for I/O to remote machine.  Initialize it to NULL so
121b725ae77Skettenis    that sds_open knows that we don't have a file open when the program
122b725ae77Skettenis    starts.  */
123b725ae77Skettenis 
124b725ae77Skettenis static struct serial *sds_desc = NULL;
125b725ae77Skettenis 
126b725ae77Skettenis /* This limit comes from the monitor.  */
127b725ae77Skettenis 
128b725ae77Skettenis #define	PBUFSIZ	250
129b725ae77Skettenis 
130b725ae77Skettenis /* Maximum number of bytes to read/write at once.  The value here
131b725ae77Skettenis    is chosen to fill up a packet (the headers account for the 32).  */
132b725ae77Skettenis #define MAXBUFBYTES ((PBUFSIZ-32)/2)
133b725ae77Skettenis 
134b725ae77Skettenis static int next_msg_id;
135b725ae77Skettenis 
136b725ae77Skettenis static int just_started;
137b725ae77Skettenis 
138b725ae77Skettenis static int message_pending;
139b725ae77Skettenis 
140b725ae77Skettenis 
141b725ae77Skettenis /* Clean up connection to a remote debugger.  */
142b725ae77Skettenis 
143b725ae77Skettenis static void
sds_close(int quitting)144b725ae77Skettenis sds_close (int quitting)
145b725ae77Skettenis {
146b725ae77Skettenis   if (sds_desc)
147b725ae77Skettenis     serial_close (sds_desc);
148b725ae77Skettenis   sds_desc = NULL;
149b725ae77Skettenis }
150b725ae77Skettenis 
151b725ae77Skettenis /* Stub for catch_errors.  */
152b725ae77Skettenis 
153b725ae77Skettenis static int
sds_start_remote(void * dummy)154b725ae77Skettenis sds_start_remote (void *dummy)
155b725ae77Skettenis {
156b725ae77Skettenis   int c;
157b725ae77Skettenis   unsigned char buf[200];
158b725ae77Skettenis 
159b725ae77Skettenis   immediate_quit++;		/* Allow user to interrupt it */
160b725ae77Skettenis 
161b725ae77Skettenis   /* Ack any packet which the remote side has already sent.  */
162b725ae77Skettenis   serial_write (sds_desc, "{#*\r\n", 5);
163b725ae77Skettenis   serial_write (sds_desc, "{#}\r\n", 5);
164b725ae77Skettenis 
165b725ae77Skettenis   while ((c = readchar (1)) >= 0)
166b725ae77Skettenis     printf_unfiltered ("%c", c);
167b725ae77Skettenis   printf_unfiltered ("\n");
168b725ae77Skettenis 
169b725ae77Skettenis   next_msg_id = 251;
170b725ae77Skettenis 
171b725ae77Skettenis   buf[0] = 26;
172b725ae77Skettenis   sds_send (buf, 1);
173b725ae77Skettenis 
174b725ae77Skettenis   buf[0] = 0;
175b725ae77Skettenis   sds_send (buf, 1);
176b725ae77Skettenis 
177b725ae77Skettenis   immediate_quit--;
178b725ae77Skettenis 
179b725ae77Skettenis   start_remote ();		/* Initialize gdb process mechanisms */
180b725ae77Skettenis   return 1;
181b725ae77Skettenis }
182b725ae77Skettenis 
183b725ae77Skettenis /* Open a connection to a remote debugger.
184b725ae77Skettenis    NAME is the filename used for communication.  */
185b725ae77Skettenis 
186b725ae77Skettenis static void
sds_open(char * name,int from_tty)187b725ae77Skettenis sds_open (char *name, int from_tty)
188b725ae77Skettenis {
189b725ae77Skettenis   if (name == 0)
190b725ae77Skettenis     error ("To open a remote debug connection, you need to specify what serial\n\
191b725ae77Skettenis device is attached to the remote system (e.g. /dev/ttya).");
192b725ae77Skettenis 
193b725ae77Skettenis   target_preopen (from_tty);
194b725ae77Skettenis 
195b725ae77Skettenis   unpush_target (&sds_ops);
196b725ae77Skettenis 
197b725ae77Skettenis   sds_desc = serial_open (name);
198b725ae77Skettenis   if (!sds_desc)
199b725ae77Skettenis     perror_with_name (name);
200b725ae77Skettenis 
201b725ae77Skettenis   if (baud_rate != -1)
202b725ae77Skettenis     {
203b725ae77Skettenis       if (serial_setbaudrate (sds_desc, baud_rate))
204b725ae77Skettenis 	{
205b725ae77Skettenis 	  serial_close (sds_desc);
206b725ae77Skettenis 	  perror_with_name (name);
207b725ae77Skettenis 	}
208b725ae77Skettenis     }
209b725ae77Skettenis 
210b725ae77Skettenis 
211b725ae77Skettenis   serial_raw (sds_desc);
212b725ae77Skettenis 
213b725ae77Skettenis   /* If there is something sitting in the buffer we might take it as a
214b725ae77Skettenis      response to a command, which would be bad.  */
215b725ae77Skettenis   serial_flush_input (sds_desc);
216b725ae77Skettenis 
217b725ae77Skettenis   if (from_tty)
218b725ae77Skettenis     {
219b725ae77Skettenis       puts_filtered ("Remote debugging using ");
220b725ae77Skettenis       puts_filtered (name);
221b725ae77Skettenis       puts_filtered ("\n");
222b725ae77Skettenis     }
223b725ae77Skettenis   push_target (&sds_ops);	/* Switch to using remote target now */
224b725ae77Skettenis 
225b725ae77Skettenis   just_started = 1;
226b725ae77Skettenis 
227b725ae77Skettenis   /* Start the remote connection; if error (0), discard this target.
228b725ae77Skettenis      In particular, if the user quits, be sure to discard it (we'd be
229b725ae77Skettenis      in an inconsistent state otherwise).  */
230b725ae77Skettenis   if (!catch_errors (sds_start_remote, NULL,
231b725ae77Skettenis 		     "Couldn't establish connection to remote target\n",
232b725ae77Skettenis 		     RETURN_MASK_ALL))
233b725ae77Skettenis     pop_target ();
234b725ae77Skettenis }
235b725ae77Skettenis 
236b725ae77Skettenis /* This takes a program previously attached to and detaches it.  After
237b725ae77Skettenis    this is done, GDB can be used to debug some other program.  We
238b725ae77Skettenis    better not have left any breakpoints in the target program or it'll
239b725ae77Skettenis    die when it hits one.  */
240b725ae77Skettenis 
241b725ae77Skettenis static void
sds_detach(char * args,int from_tty)242b725ae77Skettenis sds_detach (char *args, int from_tty)
243b725ae77Skettenis {
244b725ae77Skettenis   char buf[PBUFSIZ];
245b725ae77Skettenis 
246b725ae77Skettenis   if (args)
247b725ae77Skettenis     error ("Argument given to \"detach\" when remotely debugging.");
248b725ae77Skettenis 
249b725ae77Skettenis #if 0
250b725ae77Skettenis   /* Tell the remote target to detach.  */
251b725ae77Skettenis   strcpy (buf, "D");
252b725ae77Skettenis   sds_send (buf, 1);
253b725ae77Skettenis #endif
254b725ae77Skettenis 
255b725ae77Skettenis   pop_target ();
256b725ae77Skettenis   if (from_tty)
257b725ae77Skettenis     puts_filtered ("Ending remote debugging.\n");
258b725ae77Skettenis }
259b725ae77Skettenis 
260b725ae77Skettenis /* Convert hex digit A to a number.  */
261b725ae77Skettenis 
262b725ae77Skettenis static int
fromhex(int a)263b725ae77Skettenis fromhex (int a)
264b725ae77Skettenis {
265b725ae77Skettenis   if (a >= '0' && a <= '9')
266b725ae77Skettenis     return a - '0';
267b725ae77Skettenis   else if (a >= 'a' && a <= 'f')
268b725ae77Skettenis     return a - 'a' + 10;
269b725ae77Skettenis   else
270b725ae77Skettenis     error ("Reply contains invalid hex digit %d", a);
271b725ae77Skettenis }
272b725ae77Skettenis 
273b725ae77Skettenis static int
tob64(unsigned char * inbuf,char * outbuf,int len)274b725ae77Skettenis tob64 (unsigned char *inbuf, char *outbuf, int len)
275b725ae77Skettenis {
276b725ae77Skettenis   int i, sum;
277b725ae77Skettenis   char *p;
278b725ae77Skettenis 
279b725ae77Skettenis   if (len % 3 != 0)
280b725ae77Skettenis     error ("bad length");
281b725ae77Skettenis 
282b725ae77Skettenis   p = outbuf;
283b725ae77Skettenis   for (i = 0; i < len; i += 3)
284b725ae77Skettenis     {
285b725ae77Skettenis       /* Collect the next three bytes into a number.  */
286b725ae77Skettenis       sum = ((long) *inbuf++) << 16;
287b725ae77Skettenis       sum |= ((long) *inbuf++) << 8;
288b725ae77Skettenis       sum |= ((long) *inbuf++);
289b725ae77Skettenis 
290b725ae77Skettenis       /* Spit out 4 6-bit encodings.  */
291b725ae77Skettenis       *p++ = ((sum >> 18) & 0x3f) + '0';
292b725ae77Skettenis       *p++ = ((sum >> 12) & 0x3f) + '0';
293b725ae77Skettenis       *p++ = ((sum >> 6) & 0x3f) + '0';
294b725ae77Skettenis       *p++ = (sum & 0x3f) + '0';
295b725ae77Skettenis     }
296b725ae77Skettenis   return (p - outbuf);
297b725ae77Skettenis }
298b725ae77Skettenis 
299b725ae77Skettenis static int
fromb64(char * inbuf,char * outbuf,int len)300b725ae77Skettenis fromb64 (char *inbuf, char *outbuf, int len)
301b725ae77Skettenis {
302b725ae77Skettenis   int i, sum;
303b725ae77Skettenis 
304b725ae77Skettenis   if (len % 4 != 0)
305b725ae77Skettenis     error ("bad length");
306b725ae77Skettenis 
307b725ae77Skettenis   for (i = 0; i < len; i += 4)
308b725ae77Skettenis     {
309b725ae77Skettenis       /* Collect 4 6-bit digits.  */
310b725ae77Skettenis       sum = (*inbuf++ - '0') << 18;
311b725ae77Skettenis       sum |= (*inbuf++ - '0') << 12;
312b725ae77Skettenis       sum |= (*inbuf++ - '0') << 6;
313b725ae77Skettenis       sum |= (*inbuf++ - '0');
314b725ae77Skettenis 
315b725ae77Skettenis       /* Now take the resulting 24-bit number and get three bytes out
316b725ae77Skettenis          of it.  */
317b725ae77Skettenis       *outbuf++ = (sum >> 16) & 0xff;
318b725ae77Skettenis       *outbuf++ = (sum >> 8) & 0xff;
319b725ae77Skettenis       *outbuf++ = sum & 0xff;
320b725ae77Skettenis     }
321b725ae77Skettenis 
322b725ae77Skettenis   return (len / 4) * 3;
323b725ae77Skettenis }
324b725ae77Skettenis 
325b725ae77Skettenis 
326b725ae77Skettenis /* Tell the remote machine to resume.  */
327b725ae77Skettenis 
328b725ae77Skettenis static enum target_signal last_sent_signal = TARGET_SIGNAL_0;
329b725ae77Skettenis int last_sent_step;
330b725ae77Skettenis 
331b725ae77Skettenis static void
sds_resume(ptid_t ptid,int step,enum target_signal siggnal)332b725ae77Skettenis sds_resume (ptid_t ptid, int step, enum target_signal siggnal)
333b725ae77Skettenis {
334b725ae77Skettenis   unsigned char buf[PBUFSIZ];
335b725ae77Skettenis 
336b725ae77Skettenis   last_sent_signal = siggnal;
337b725ae77Skettenis   last_sent_step = step;
338b725ae77Skettenis 
339b725ae77Skettenis   buf[0] = (step ? 21 : 20);
340b725ae77Skettenis   buf[1] = 0;			/* (should be signal?) */
341b725ae77Skettenis 
342b725ae77Skettenis   sds_send (buf, 2);
343b725ae77Skettenis }
344b725ae77Skettenis 
345b725ae77Skettenis /* Send a message to target to halt it.  Target will respond, and send
346b725ae77Skettenis    us a message pending notice.  */
347b725ae77Skettenis 
348b725ae77Skettenis static void
sds_interrupt(int signo)349b725ae77Skettenis sds_interrupt (int signo)
350b725ae77Skettenis {
351b725ae77Skettenis   unsigned char buf[PBUFSIZ];
352b725ae77Skettenis 
353b725ae77Skettenis   /* If this doesn't work, try more severe steps.  */
354b725ae77Skettenis   signal (signo, sds_interrupt_twice);
355b725ae77Skettenis 
356b725ae77Skettenis   if (remote_debug)
357b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog, "sds_interrupt called\n");
358b725ae77Skettenis 
359b725ae77Skettenis   buf[0] = 25;
360b725ae77Skettenis   sds_send (buf, 1);
361b725ae77Skettenis }
362b725ae77Skettenis 
363b725ae77Skettenis static void (*ofunc) ();
364b725ae77Skettenis 
365b725ae77Skettenis /* The user typed ^C twice.  */
366b725ae77Skettenis 
367b725ae77Skettenis static void
sds_interrupt_twice(int signo)368b725ae77Skettenis sds_interrupt_twice (int signo)
369b725ae77Skettenis {
370b725ae77Skettenis   signal (signo, ofunc);
371b725ae77Skettenis 
372b725ae77Skettenis   interrupt_query ();
373b725ae77Skettenis 
374b725ae77Skettenis   signal (signo, sds_interrupt);
375b725ae77Skettenis }
376b725ae77Skettenis 
377b725ae77Skettenis /* Ask the user what to do when an interrupt is received.  */
378b725ae77Skettenis 
379b725ae77Skettenis static void
interrupt_query(void)380b725ae77Skettenis interrupt_query (void)
381b725ae77Skettenis {
382b725ae77Skettenis   target_terminal_ours ();
383b725ae77Skettenis 
384b725ae77Skettenis   if (query ("Interrupted while waiting for the program.\n\
385b725ae77Skettenis Give up (and stop debugging it)? "))
386b725ae77Skettenis     {
387b725ae77Skettenis       target_mourn_inferior ();
388b725ae77Skettenis       throw_exception (RETURN_QUIT);
389b725ae77Skettenis     }
390b725ae77Skettenis 
391b725ae77Skettenis   target_terminal_inferior ();
392b725ae77Skettenis }
393b725ae77Skettenis 
394b725ae77Skettenis /* If nonzero, ignore the next kill.  */
395b725ae77Skettenis int kill_kludge;
396b725ae77Skettenis 
397b725ae77Skettenis /* Wait until the remote machine stops, then return, storing status in
398b725ae77Skettenis    STATUS just as `wait' would.  Returns "pid" (though it's not clear
399b725ae77Skettenis    what, if anything, that means in the case of this target).  */
400b725ae77Skettenis 
401b725ae77Skettenis static ptid_t
sds_wait(ptid_t ptid,struct target_waitstatus * status)402b725ae77Skettenis sds_wait (ptid_t ptid, struct target_waitstatus *status)
403b725ae77Skettenis {
404b725ae77Skettenis   unsigned char buf[PBUFSIZ];
405b725ae77Skettenis   int retlen;
406b725ae77Skettenis 
407b725ae77Skettenis   status->kind = TARGET_WAITKIND_EXITED;
408b725ae77Skettenis   status->value.integer = 0;
409b725ae77Skettenis 
410b725ae77Skettenis   ofunc = (void (*)()) signal (SIGINT, sds_interrupt);
411b725ae77Skettenis 
412b725ae77Skettenis   signal (SIGINT, ofunc);
413b725ae77Skettenis 
414b725ae77Skettenis   if (just_started)
415b725ae77Skettenis     {
416b725ae77Skettenis       just_started = 0;
417b725ae77Skettenis       status->kind = TARGET_WAITKIND_STOPPED;
418b725ae77Skettenis       return inferior_ptid;
419b725ae77Skettenis     }
420b725ae77Skettenis 
421b725ae77Skettenis   while (1)
422b725ae77Skettenis     {
423b725ae77Skettenis       getmessage (buf, 1);
424b725ae77Skettenis 
425b725ae77Skettenis       if (message_pending)
426b725ae77Skettenis 	{
427b725ae77Skettenis 	  buf[0] = 26;
428b725ae77Skettenis 	  retlen = sds_send (buf, 1);
429b725ae77Skettenis 	  if (remote_debug)
430b725ae77Skettenis 	    {
431b725ae77Skettenis 	      fprintf_unfiltered (gdb_stdlog, "Signals: %02x%02x %02x %02x\n",
432b725ae77Skettenis 				  buf[0], buf[1],
433b725ae77Skettenis 				  buf[2], buf[3]);
434b725ae77Skettenis 	    }
435b725ae77Skettenis 	  message_pending = 0;
436b725ae77Skettenis 	  status->kind = TARGET_WAITKIND_STOPPED;
437b725ae77Skettenis 	  status->value.sig = TARGET_SIGNAL_TRAP;
438b725ae77Skettenis 	  goto got_status;
439b725ae77Skettenis 	}
440b725ae77Skettenis     }
441b725ae77Skettenis got_status:
442b725ae77Skettenis   return inferior_ptid;
443b725ae77Skettenis }
444b725ae77Skettenis 
445b725ae77Skettenis static unsigned char sprs[16];
446b725ae77Skettenis 
447b725ae77Skettenis /* Read the remote registers into the block REGS.  */
448b725ae77Skettenis /* Currently we just read all the registers, so we don't use regno.  */
449b725ae77Skettenis 
450b725ae77Skettenis static void
sds_fetch_registers(int regno)451b725ae77Skettenis sds_fetch_registers (int regno)
452b725ae77Skettenis {
453b725ae77Skettenis   unsigned char buf[PBUFSIZ];
454b725ae77Skettenis   int i, retlen;
455*11efff7fSkettenis   char *regs = alloca (deprecated_register_bytes ());
456b725ae77Skettenis 
457b725ae77Skettenis   /* Unimplemented registers read as all bits zero.  */
458*11efff7fSkettenis   memset (regs, 0, deprecated_register_bytes ());
459b725ae77Skettenis 
460b725ae77Skettenis   buf[0] = 18;
461b725ae77Skettenis   buf[1] = 1;
462b725ae77Skettenis   buf[2] = 0;
463b725ae77Skettenis   retlen = sds_send (buf, 3);
464b725ae77Skettenis 
465b725ae77Skettenis   for (i = 0; i < 4 * 6; ++i)
466b725ae77Skettenis     regs[i + 4 * 32 + 8 * 32] = buf[i];
467b725ae77Skettenis   for (i = 0; i < 4 * 4; ++i)
468b725ae77Skettenis     sprs[i] = buf[i + 4 * 7];
469b725ae77Skettenis 
470b725ae77Skettenis   buf[0] = 18;
471b725ae77Skettenis   buf[1] = 2;
472b725ae77Skettenis   buf[2] = 0;
473b725ae77Skettenis   retlen = sds_send (buf, 3);
474b725ae77Skettenis 
475b725ae77Skettenis   for (i = 0; i < retlen; i++)
476b725ae77Skettenis     regs[i] = buf[i];
477b725ae77Skettenis 
478b725ae77Skettenis   /* (should warn about reply too short) */
479b725ae77Skettenis 
480b725ae77Skettenis   for (i = 0; i < NUM_REGS; i++)
481*11efff7fSkettenis     regcache_raw_supply (current_regcache, i,
482*11efff7fSkettenis 			 &regs[DEPRECATED_REGISTER_BYTE (i)]);
483b725ae77Skettenis }
484b725ae77Skettenis 
485b725ae77Skettenis /* Prepare to store registers.  Since we may send them all, we have to
486b725ae77Skettenis    read out the ones we don't want to change first.  */
487b725ae77Skettenis 
488b725ae77Skettenis static void
sds_prepare_to_store(void)489b725ae77Skettenis sds_prepare_to_store (void)
490b725ae77Skettenis {
491b725ae77Skettenis   /* Make sure the entire registers array is valid.  */
492*11efff7fSkettenis   deprecated_read_register_bytes (0, (char *) NULL, deprecated_register_bytes ());
493b725ae77Skettenis }
494b725ae77Skettenis 
495b725ae77Skettenis /* Store register REGNO, or all registers if REGNO == -1, from the contents
496b725ae77Skettenis    of REGISTERS.  FIXME: ignores errors.  */
497b725ae77Skettenis 
498b725ae77Skettenis static void
sds_store_registers(int regno)499b725ae77Skettenis sds_store_registers (int regno)
500b725ae77Skettenis {
501b725ae77Skettenis   unsigned char *p, buf[PBUFSIZ];
502b725ae77Skettenis   int i;
503b725ae77Skettenis 
504b725ae77Skettenis   /* Store all the special-purpose registers.  */
505b725ae77Skettenis   p = buf;
506b725ae77Skettenis   *p++ = 19;
507b725ae77Skettenis   *p++ = 1;
508b725ae77Skettenis   *p++ = 0;
509b725ae77Skettenis   *p++ = 0;
510b725ae77Skettenis   for (i = 0; i < 4 * 6; i++)
511b725ae77Skettenis     *p++ = deprecated_registers[i + 4 * 32 + 8 * 32];
512b725ae77Skettenis   for (i = 0; i < 4 * 1; i++)
513b725ae77Skettenis     *p++ = 0;
514b725ae77Skettenis   for (i = 0; i < 4 * 4; i++)
515b725ae77Skettenis     *p++ = sprs[i];
516b725ae77Skettenis 
517b725ae77Skettenis   sds_send (buf, p - buf);
518b725ae77Skettenis 
519b725ae77Skettenis   /* Store all the general-purpose registers.  */
520b725ae77Skettenis   p = buf;
521b725ae77Skettenis   *p++ = 19;
522b725ae77Skettenis   *p++ = 2;
523b725ae77Skettenis   *p++ = 0;
524b725ae77Skettenis   *p++ = 0;
525b725ae77Skettenis   for (i = 0; i < 4 * 32; i++)
526b725ae77Skettenis     *p++ = deprecated_registers[i];
527b725ae77Skettenis 
528b725ae77Skettenis   sds_send (buf, p - buf);
529b725ae77Skettenis 
530b725ae77Skettenis }
531b725ae77Skettenis 
532b725ae77Skettenis /* Write memory data directly to the remote machine.  This does not
533b725ae77Skettenis    inform the data cache; the data cache uses this.  MEMADDR is the
534b725ae77Skettenis    address in the remote memory space.  MYADDR is the address of the
535b725ae77Skettenis    buffer in our space.  LEN is the number of bytes.
536b725ae77Skettenis 
537b725ae77Skettenis    Returns number of bytes transferred, or 0 for error.  */
538b725ae77Skettenis 
539b725ae77Skettenis static int
sds_write_bytes(CORE_ADDR memaddr,char * myaddr,int len)540b725ae77Skettenis sds_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
541b725ae77Skettenis {
542b725ae77Skettenis   int max_buf_size;		/* Max size of packet output buffer */
543b725ae77Skettenis   int origlen;
544b725ae77Skettenis   unsigned char buf[PBUFSIZ];
545b725ae77Skettenis   int todo;
546b725ae77Skettenis   int i;
547b725ae77Skettenis 
548b725ae77Skettenis   /* Chop the transfer down if necessary */
549b725ae77Skettenis 
550b725ae77Skettenis   max_buf_size = 150;
551b725ae77Skettenis 
552b725ae77Skettenis   origlen = len;
553b725ae77Skettenis   while (len > 0)
554b725ae77Skettenis     {
555b725ae77Skettenis       todo = min (len, max_buf_size);
556b725ae77Skettenis 
557b725ae77Skettenis       buf[0] = 13;
558b725ae77Skettenis       buf[1] = 0;
559b725ae77Skettenis       buf[2] = (int) (memaddr >> 24) & 0xff;
560b725ae77Skettenis       buf[3] = (int) (memaddr >> 16) & 0xff;
561b725ae77Skettenis       buf[4] = (int) (memaddr >> 8) & 0xff;
562b725ae77Skettenis       buf[5] = (int) (memaddr) & 0xff;
563b725ae77Skettenis       buf[6] = 1;
564b725ae77Skettenis       buf[7] = 0;
565b725ae77Skettenis 
566b725ae77Skettenis       for (i = 0; i < todo; i++)
567b725ae77Skettenis 	buf[i + 8] = myaddr[i];
568b725ae77Skettenis 
569b725ae77Skettenis       sds_send (buf, 8 + todo);
570b725ae77Skettenis 
571b725ae77Skettenis       /* (should look at result) */
572b725ae77Skettenis 
573b725ae77Skettenis       myaddr += todo;
574b725ae77Skettenis       memaddr += todo;
575b725ae77Skettenis       len -= todo;
576b725ae77Skettenis     }
577b725ae77Skettenis   return origlen;
578b725ae77Skettenis }
579b725ae77Skettenis 
580b725ae77Skettenis /* Read memory data directly from the remote machine.  This does not
581b725ae77Skettenis    use the data cache; the data cache uses this.  MEMADDR is the
582b725ae77Skettenis    address in the remote memory space.  MYADDR is the address of the
583b725ae77Skettenis    buffer in our space.  LEN is the number of bytes.
584b725ae77Skettenis 
585b725ae77Skettenis    Returns number of bytes transferred, or 0 for error.  */
586b725ae77Skettenis 
587b725ae77Skettenis static int
sds_read_bytes(CORE_ADDR memaddr,char * myaddr,int len)588b725ae77Skettenis sds_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
589b725ae77Skettenis {
590b725ae77Skettenis   int max_buf_size;		/* Max size of packet output buffer */
591b725ae77Skettenis   int origlen, retlen;
592b725ae77Skettenis   unsigned char buf[PBUFSIZ];
593b725ae77Skettenis   int todo;
594b725ae77Skettenis   int i;
595b725ae77Skettenis 
596b725ae77Skettenis   /* Chop the transfer down if necessary */
597b725ae77Skettenis 
598b725ae77Skettenis   max_buf_size = 150;
599b725ae77Skettenis 
600b725ae77Skettenis   origlen = len;
601b725ae77Skettenis   while (len > 0)
602b725ae77Skettenis     {
603b725ae77Skettenis       todo = min (len, max_buf_size);
604b725ae77Skettenis 
605b725ae77Skettenis       buf[0] = 12;
606b725ae77Skettenis       buf[1] = 0;
607b725ae77Skettenis       buf[2] = (int) (memaddr >> 24) & 0xff;
608b725ae77Skettenis       buf[3] = (int) (memaddr >> 16) & 0xff;
609b725ae77Skettenis       buf[4] = (int) (memaddr >> 8) & 0xff;
610b725ae77Skettenis       buf[5] = (int) (memaddr) & 0xff;
611b725ae77Skettenis       buf[6] = (int) (todo >> 8) & 0xff;
612b725ae77Skettenis       buf[7] = (int) (todo) & 0xff;
613b725ae77Skettenis       buf[8] = 1;
614b725ae77Skettenis 
615b725ae77Skettenis       retlen = sds_send (buf, 9);
616b725ae77Skettenis 
617b725ae77Skettenis       if (retlen - 2 != todo)
618b725ae77Skettenis 	{
619b725ae77Skettenis 	  return 0;
620b725ae77Skettenis 	}
621b725ae77Skettenis 
622b725ae77Skettenis       /* Reply describes memory byte by byte. */
623b725ae77Skettenis 
624b725ae77Skettenis       for (i = 0; i < todo; i++)
625b725ae77Skettenis 	myaddr[i] = buf[i + 2];
626b725ae77Skettenis 
627b725ae77Skettenis       myaddr += todo;
628b725ae77Skettenis       memaddr += todo;
629b725ae77Skettenis       len -= todo;
630b725ae77Skettenis     }
631b725ae77Skettenis 
632b725ae77Skettenis   return origlen;
633b725ae77Skettenis }
634b725ae77Skettenis 
635b725ae77Skettenis /* Read or write LEN bytes from inferior memory at MEMADDR,
636b725ae77Skettenis    transferring to or from debugger address MYADDR.  Write to inferior
637b725ae77Skettenis    if SHOULD_WRITE is nonzero.  Returns length of data written or
638b725ae77Skettenis    read; 0 for error.  TARGET is unused.  */
639b725ae77Skettenis 
640b725ae77Skettenis static int
sds_xfer_memory(CORE_ADDR memaddr,char * myaddr,int len,int should_write,struct mem_attrib * attrib,struct target_ops * target)641b725ae77Skettenis sds_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write,
642b725ae77Skettenis 		 struct mem_attrib *attrib, struct target_ops *target)
643b725ae77Skettenis {
644b725ae77Skettenis   int res;
645b725ae77Skettenis 
646b725ae77Skettenis   if (should_write)
647b725ae77Skettenis     res = sds_write_bytes (memaddr, myaddr, len);
648b725ae77Skettenis   else
649b725ae77Skettenis     res = sds_read_bytes (memaddr, myaddr, len);
650b725ae77Skettenis 
651b725ae77Skettenis   return res;
652b725ae77Skettenis }
653b725ae77Skettenis 
654b725ae77Skettenis 
655b725ae77Skettenis static void
sds_files_info(struct target_ops * ignore)656b725ae77Skettenis sds_files_info (struct target_ops *ignore)
657b725ae77Skettenis {
658b725ae77Skettenis   puts_filtered ("Debugging over a serial connection, using SDS protocol.\n");
659b725ae77Skettenis }
660b725ae77Skettenis 
661b725ae77Skettenis /* Stuff for dealing with the packets which are part of this protocol.
662b725ae77Skettenis    See comment at top of file for details.  */
663b725ae77Skettenis 
664b725ae77Skettenis /* Read a single character from the remote end, masking it down to 7 bits. */
665b725ae77Skettenis 
666b725ae77Skettenis static int
readchar(int timeout)667b725ae77Skettenis readchar (int timeout)
668b725ae77Skettenis {
669b725ae77Skettenis   int ch;
670b725ae77Skettenis 
671b725ae77Skettenis   ch = serial_readchar (sds_desc, timeout);
672b725ae77Skettenis 
673b725ae77Skettenis   if (remote_debug > 1 && ch >= 0)
674b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog, "%c(%x)", ch, ch);
675b725ae77Skettenis 
676b725ae77Skettenis   switch (ch)
677b725ae77Skettenis     {
678b725ae77Skettenis     case SERIAL_EOF:
679b725ae77Skettenis       error ("Remote connection closed");
680b725ae77Skettenis     case SERIAL_ERROR:
681b725ae77Skettenis       perror_with_name ("Remote communication error");
682b725ae77Skettenis     case SERIAL_TIMEOUT:
683b725ae77Skettenis       return ch;
684b725ae77Skettenis     default:
685b725ae77Skettenis       return ch & 0x7f;
686b725ae77Skettenis     }
687b725ae77Skettenis }
688b725ae77Skettenis 
689b725ae77Skettenis /* An SDS-style checksum is a sum of the bytes modulo 253.  (Presumably
690b725ae77Skettenis    because 253, 254, and 255 are special flags in the protocol.)  */
691b725ae77Skettenis 
692b725ae77Skettenis static int
compute_checksum(int csum,char * buf,int len)693b725ae77Skettenis compute_checksum (int csum, char *buf, int len)
694b725ae77Skettenis {
695b725ae77Skettenis   int i;
696b725ae77Skettenis 
697b725ae77Skettenis   for (i = 0; i < len; ++i)
698b725ae77Skettenis     csum += (unsigned char) buf[i];
699b725ae77Skettenis 
700b725ae77Skettenis   csum %= 253;
701b725ae77Skettenis   return csum;
702b725ae77Skettenis }
703b725ae77Skettenis 
704b725ae77Skettenis /* Send the command in BUF to the remote machine, and read the reply
705b725ae77Skettenis    into BUF also.  */
706b725ae77Skettenis 
707b725ae77Skettenis static int
sds_send(unsigned char * buf,int len)708b725ae77Skettenis sds_send (unsigned char *buf, int len)
709b725ae77Skettenis {
710b725ae77Skettenis   putmessage (buf, len);
711b725ae77Skettenis 
712b725ae77Skettenis   return getmessage (buf, 0);
713b725ae77Skettenis }
714b725ae77Skettenis 
715b725ae77Skettenis /* Send a message to the remote machine.  */
716b725ae77Skettenis 
717b725ae77Skettenis static int
putmessage(unsigned char * buf,int len)718b725ae77Skettenis putmessage (unsigned char *buf, int len)
719b725ae77Skettenis {
720b725ae77Skettenis   int i, enclen;
721b725ae77Skettenis   unsigned char csum = 0;
722b725ae77Skettenis   char buf2[PBUFSIZ], buf3[PBUFSIZ];
723b725ae77Skettenis   unsigned char header[3];
724b725ae77Skettenis   char *p;
725b725ae77Skettenis 
726b725ae77Skettenis   /* Copy the packet into buffer BUF2, encapsulating it
727b725ae77Skettenis      and giving it a checksum.  */
728b725ae77Skettenis 
729b725ae77Skettenis   if (len > 170)		/* Prosanity check */
730b725ae77Skettenis     internal_error (__FILE__, __LINE__, "failed internal consistency check");
731b725ae77Skettenis 
732b725ae77Skettenis   if (remote_debug)
733b725ae77Skettenis     {
734b725ae77Skettenis       fprintf_unfiltered (gdb_stdlog, "Message to send: \"");
735b725ae77Skettenis       for (i = 0; i < len; ++i)
736b725ae77Skettenis 	fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
737b725ae77Skettenis       fprintf_unfiltered (gdb_stdlog, "\"\n");
738b725ae77Skettenis     }
739b725ae77Skettenis 
740b725ae77Skettenis   p = buf2;
741b725ae77Skettenis   *p++ = '$';
742b725ae77Skettenis 
743b725ae77Skettenis   if (len % 3 != 0)
744b725ae77Skettenis     {
745b725ae77Skettenis       buf[len] = '\0';
746b725ae77Skettenis       buf[len + 1] = '\0';
747b725ae77Skettenis     }
748b725ae77Skettenis 
749b725ae77Skettenis   header[1] = next_msg_id;
750b725ae77Skettenis 
751b725ae77Skettenis   header[2] = len;
752b725ae77Skettenis 
753b725ae77Skettenis   csum = compute_checksum (csum, buf, len);
754b725ae77Skettenis   csum = compute_checksum (csum, header + 1, 2);
755b725ae77Skettenis 
756b725ae77Skettenis   header[0] = csum;
757b725ae77Skettenis 
758b725ae77Skettenis   tob64 (header, p, 3);
759b725ae77Skettenis   p += 4;
760b725ae77Skettenis   enclen = tob64 (buf, buf3, ((len + 2) / 3) * 3);
761b725ae77Skettenis 
762b725ae77Skettenis   for (i = 0; i < enclen; ++i)
763b725ae77Skettenis     *p++ = buf3[i];
764b725ae77Skettenis   *p++ = '\r';
765b725ae77Skettenis   *p++ = '\n';
766b725ae77Skettenis 
767b725ae77Skettenis   next_msg_id = (next_msg_id + 3) % 245;
768b725ae77Skettenis 
769b725ae77Skettenis   /* Send it over and over until we get a positive ack.  */
770b725ae77Skettenis 
771b725ae77Skettenis   while (1)
772b725ae77Skettenis     {
773b725ae77Skettenis       if (remote_debug)
774b725ae77Skettenis 	{
775b725ae77Skettenis 	  *p = '\0';
776b725ae77Skettenis 	  fprintf_unfiltered (gdb_stdlog, "Sending encoded: \"%s\"", buf2);
777b725ae77Skettenis 	  fprintf_unfiltered (gdb_stdlog,
778b725ae77Skettenis 			      "  (Checksum %d, id %d, length %d)\n",
779b725ae77Skettenis 			      header[0], header[1], header[2]);
780b725ae77Skettenis 	  gdb_flush (gdb_stdlog);
781b725ae77Skettenis 	}
782b725ae77Skettenis       if (serial_write (sds_desc, buf2, p - buf2))
783b725ae77Skettenis 	perror_with_name ("putmessage: write failed");
784b725ae77Skettenis 
785b725ae77Skettenis       return 1;
786b725ae77Skettenis     }
787b725ae77Skettenis }
788b725ae77Skettenis 
789b725ae77Skettenis /* Come here after finding the start of the frame.  Collect the rest
790b725ae77Skettenis    into BUF.  Returns 0 on any error, 1 on success.  */
791b725ae77Skettenis 
792b725ae77Skettenis static int
read_frame(char * buf)793b725ae77Skettenis read_frame (char *buf)
794b725ae77Skettenis {
795b725ae77Skettenis   char *bp;
796b725ae77Skettenis   int c;
797b725ae77Skettenis 
798b725ae77Skettenis   bp = buf;
799b725ae77Skettenis 
800b725ae77Skettenis   while (1)
801b725ae77Skettenis     {
802b725ae77Skettenis       c = readchar (sds_timeout);
803b725ae77Skettenis 
804b725ae77Skettenis       switch (c)
805b725ae77Skettenis 	{
806b725ae77Skettenis 	case SERIAL_TIMEOUT:
807b725ae77Skettenis 	  if (remote_debug)
808b725ae77Skettenis 	    fputs_filtered ("Timeout in mid-message, retrying\n", gdb_stdlog);
809b725ae77Skettenis 	  return 0;
810b725ae77Skettenis 	case '$':
811b725ae77Skettenis 	  if (remote_debug)
812b725ae77Skettenis 	    fputs_filtered ("Saw new packet start in middle of old one\n",
813b725ae77Skettenis 			    gdb_stdlog);
814b725ae77Skettenis 	  return 0;		/* Start a new packet, count retries */
815b725ae77Skettenis 	case '\r':
816b725ae77Skettenis 	  break;
817b725ae77Skettenis 
818b725ae77Skettenis 	case '\n':
819b725ae77Skettenis 	  {
820b725ae77Skettenis 	    *bp = '\000';
821b725ae77Skettenis 	    if (remote_debug)
822b725ae77Skettenis 	      fprintf_unfiltered (gdb_stdlog, "Received encoded: \"%s\"\n",
823b725ae77Skettenis 				  buf);
824b725ae77Skettenis 	    return 1;
825b725ae77Skettenis 	  }
826b725ae77Skettenis 
827b725ae77Skettenis 	default:
828b725ae77Skettenis 	  if (bp < buf + PBUFSIZ - 1)
829b725ae77Skettenis 	    {
830b725ae77Skettenis 	      *bp++ = c;
831b725ae77Skettenis 	      continue;
832b725ae77Skettenis 	    }
833b725ae77Skettenis 
834b725ae77Skettenis 	  *bp = '\0';
835b725ae77Skettenis 	  puts_filtered ("Message too long: ");
836b725ae77Skettenis 	  puts_filtered (buf);
837b725ae77Skettenis 	  puts_filtered ("\n");
838b725ae77Skettenis 
839b725ae77Skettenis 	  return 0;
840b725ae77Skettenis 	}
841b725ae77Skettenis     }
842b725ae77Skettenis }
843b725ae77Skettenis 
844b725ae77Skettenis /* Read a packet from the remote machine, with error checking,
845b725ae77Skettenis    and store it in BUF.  BUF is expected to be of size PBUFSIZ.
846b725ae77Skettenis    If FOREVER, wait forever rather than timing out; this is used
847b725ae77Skettenis    while the target is executing user code.  */
848b725ae77Skettenis 
849b725ae77Skettenis static int
getmessage(unsigned char * buf,int forever)850b725ae77Skettenis getmessage (unsigned char *buf, int forever)
851b725ae77Skettenis {
852b725ae77Skettenis   int c, c2, c3;
853b725ae77Skettenis   int tries;
854b725ae77Skettenis   int timeout;
855b725ae77Skettenis   int val, i, len, csum;
856b725ae77Skettenis   unsigned char header[3];
857b725ae77Skettenis   unsigned char inbuf[500];
858b725ae77Skettenis 
859b725ae77Skettenis   strcpy (buf, "timeout");
860b725ae77Skettenis 
861b725ae77Skettenis   if (forever)
862b725ae77Skettenis     {
863b725ae77Skettenis       timeout = watchdog > 0 ? watchdog : -1;
864b725ae77Skettenis     }
865b725ae77Skettenis 
866b725ae77Skettenis   else
867b725ae77Skettenis     timeout = sds_timeout;
868b725ae77Skettenis 
869b725ae77Skettenis #define MAX_TRIES 3
870b725ae77Skettenis 
871b725ae77Skettenis   for (tries = 1; tries <= MAX_TRIES; tries++)
872b725ae77Skettenis     {
873b725ae77Skettenis       /* This can loop forever if the remote side sends us characters
874b725ae77Skettenis          continuously, but if it pauses, we'll get a zero from readchar
875b725ae77Skettenis          because of timeout.  Then we'll count that as a retry.  */
876b725ae77Skettenis 
877b725ae77Skettenis       /* Note that we will only wait forever prior to the start of a packet.
878b725ae77Skettenis          After that, we expect characters to arrive at a brisk pace.  They
879b725ae77Skettenis          should show up within sds_timeout intervals.  */
880b725ae77Skettenis 
881b725ae77Skettenis       do
882b725ae77Skettenis 	{
883b725ae77Skettenis 	  c = readchar (timeout);
884b725ae77Skettenis 
885b725ae77Skettenis 	  if (c == SERIAL_TIMEOUT)
886b725ae77Skettenis 	    {
887b725ae77Skettenis 	      if (forever)	/* Watchdog went off.  Kill the target. */
888b725ae77Skettenis 		{
889b725ae77Skettenis 		  target_mourn_inferior ();
890b725ae77Skettenis 		  error ("Watchdog has expired.  Target detached.\n");
891b725ae77Skettenis 		}
892b725ae77Skettenis 	      if (remote_debug)
893b725ae77Skettenis 		fputs_filtered ("Timed out.\n", gdb_stdlog);
894b725ae77Skettenis 	      goto retry;
895b725ae77Skettenis 	    }
896b725ae77Skettenis 	}
897b725ae77Skettenis       while (c != '$' && c != '{');
898b725ae77Skettenis 
899b725ae77Skettenis       /* We might have seen a "trigraph", a sequence of three characters
900b725ae77Skettenis          that indicate various sorts of communication state.  */
901b725ae77Skettenis 
902b725ae77Skettenis       if (c == '{')
903b725ae77Skettenis 	{
904b725ae77Skettenis 	  /* Read the other two chars of the trigraph. */
905b725ae77Skettenis 	  c2 = readchar (timeout);
906b725ae77Skettenis 	  c3 = readchar (timeout);
907b725ae77Skettenis 	  if (remote_debug)
908b725ae77Skettenis 	    fprintf_unfiltered (gdb_stdlog, "Trigraph %c%c%c received\n",
909b725ae77Skettenis 				c, c2, c3);
910b725ae77Skettenis 	  if (c3 == '+')
911b725ae77Skettenis 	    {
912b725ae77Skettenis 	      message_pending = 1;
913b725ae77Skettenis 	      return 0;		/*???? */
914b725ae77Skettenis 	    }
915b725ae77Skettenis 	  continue;
916b725ae77Skettenis 	}
917b725ae77Skettenis 
918b725ae77Skettenis       val = read_frame (inbuf);
919b725ae77Skettenis 
920b725ae77Skettenis       if (val == 1)
921b725ae77Skettenis 	{
922b725ae77Skettenis 	  fromb64 (inbuf, header, 4);
923b725ae77Skettenis 	  /* (should check out other bits) */
924b725ae77Skettenis 	  fromb64 (inbuf + 4, buf, strlen (inbuf) - 4);
925b725ae77Skettenis 
926b725ae77Skettenis 	  len = header[2];
927b725ae77Skettenis 
928b725ae77Skettenis 	  csum = 0;
929b725ae77Skettenis 	  csum = compute_checksum (csum, buf, len);
930b725ae77Skettenis 	  csum = compute_checksum (csum, header + 1, 2);
931b725ae77Skettenis 
932b725ae77Skettenis 	  if (csum != header[0])
933b725ae77Skettenis 	    fprintf_unfiltered (gdb_stderr,
934b725ae77Skettenis 			    "Checksum mismatch: computed %d, received %d\n",
935b725ae77Skettenis 				csum, header[0]);
936b725ae77Skettenis 
937b725ae77Skettenis 	  if (header[2] == 0xff)
938b725ae77Skettenis 	    fprintf_unfiltered (gdb_stderr, "Requesting resend...\n");
939b725ae77Skettenis 
940b725ae77Skettenis 	  if (remote_debug)
941b725ae77Skettenis 	    {
942b725ae77Skettenis 	      fprintf_unfiltered (gdb_stdlog,
943b725ae77Skettenis 				"... (Got checksum %d, id %d, length %d)\n",
944b725ae77Skettenis 				  header[0], header[1], header[2]);
945b725ae77Skettenis 	      fprintf_unfiltered (gdb_stdlog, "Message received: \"");
946b725ae77Skettenis 	      for (i = 0; i < len; ++i)
947b725ae77Skettenis 		{
948b725ae77Skettenis 		  fprintf_unfiltered (gdb_stdlog, "%02x", (unsigned char) buf[i]);
949b725ae77Skettenis 		}
950b725ae77Skettenis 	      fprintf_unfiltered (gdb_stdlog, "\"\n");
951b725ae77Skettenis 	    }
952b725ae77Skettenis 
953b725ae77Skettenis 	  /* no ack required? */
954b725ae77Skettenis 	  return len;
955b725ae77Skettenis 	}
956b725ae77Skettenis 
957b725ae77Skettenis       /* Try the whole thing again.  */
958b725ae77Skettenis     retry:
959b725ae77Skettenis       /* need to do something here */
960b725ae77Skettenis       ;
961b725ae77Skettenis     }
962b725ae77Skettenis 
963b725ae77Skettenis   /* We have tried hard enough, and just can't receive the packet.  Give up. */
964b725ae77Skettenis 
965b725ae77Skettenis   printf_unfiltered ("Ignoring packet error, continuing...\n");
966b725ae77Skettenis   return 0;
967b725ae77Skettenis }
968b725ae77Skettenis 
969b725ae77Skettenis static void
sds_kill(void)970b725ae77Skettenis sds_kill (void)
971b725ae77Skettenis {
972b725ae77Skettenis   /* Don't try to do anything to the target.  */
973b725ae77Skettenis }
974b725ae77Skettenis 
975b725ae77Skettenis static void
sds_mourn(void)976b725ae77Skettenis sds_mourn (void)
977b725ae77Skettenis {
978b725ae77Skettenis   unpush_target (&sds_ops);
979b725ae77Skettenis   generic_mourn_inferior ();
980b725ae77Skettenis }
981b725ae77Skettenis 
982b725ae77Skettenis static void
sds_create_inferior(char * exec_file,char * args,char ** env,int from_tty)983*11efff7fSkettenis sds_create_inferior (char *exec_file, char *args, char **env, int from_tty)
984b725ae77Skettenis {
985b725ae77Skettenis   inferior_ptid = pid_to_ptid (42000);
986b725ae77Skettenis 
987b725ae77Skettenis   /* Clean up from the last time we were running.  */
988b725ae77Skettenis   clear_proceed_status ();
989b725ae77Skettenis 
990b725ae77Skettenis   /* Let the remote process run.  */
991b725ae77Skettenis   proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
992b725ae77Skettenis }
993b725ae77Skettenis 
994b725ae77Skettenis static void
sds_load(char * filename,int from_tty)995b725ae77Skettenis sds_load (char *filename, int from_tty)
996b725ae77Skettenis {
997b725ae77Skettenis   generic_load (filename, from_tty);
998b725ae77Skettenis 
999b725ae77Skettenis   inferior_ptid = null_ptid;
1000b725ae77Skettenis }
1001b725ae77Skettenis 
1002b725ae77Skettenis /* The SDS monitor has commands for breakpoint insertion, although it
1003b725ae77Skettenis    it doesn't actually manage the breakpoints, it just returns the
1004b725ae77Skettenis    replaced instruction back to the debugger.  */
1005b725ae77Skettenis 
1006b725ae77Skettenis static int
sds_insert_breakpoint(CORE_ADDR addr,char * contents_cache)1007b725ae77Skettenis sds_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
1008b725ae77Skettenis {
1009b725ae77Skettenis   int i, retlen;
1010b725ae77Skettenis   unsigned char *p, buf[PBUFSIZ];
1011b725ae77Skettenis 
1012b725ae77Skettenis   p = buf;
1013b725ae77Skettenis   *p++ = 16;
1014b725ae77Skettenis   *p++ = 0;
1015b725ae77Skettenis   *p++ = (int) (addr >> 24) & 0xff;
1016b725ae77Skettenis   *p++ = (int) (addr >> 16) & 0xff;
1017b725ae77Skettenis   *p++ = (int) (addr >> 8) & 0xff;
1018b725ae77Skettenis   *p++ = (int) (addr) & 0xff;
1019b725ae77Skettenis 
1020b725ae77Skettenis   retlen = sds_send (buf, p - buf);
1021b725ae77Skettenis 
1022b725ae77Skettenis   for (i = 0; i < 4; ++i)
1023b725ae77Skettenis     contents_cache[i] = buf[i + 2];
1024b725ae77Skettenis 
1025b725ae77Skettenis   return 0;
1026b725ae77Skettenis }
1027b725ae77Skettenis 
1028b725ae77Skettenis static int
sds_remove_breakpoint(CORE_ADDR addr,char * contents_cache)1029b725ae77Skettenis sds_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
1030b725ae77Skettenis {
1031b725ae77Skettenis   int i, retlen;
1032b725ae77Skettenis   unsigned char *p, buf[PBUFSIZ];
1033b725ae77Skettenis 
1034b725ae77Skettenis   p = buf;
1035b725ae77Skettenis   *p++ = 17;
1036b725ae77Skettenis   *p++ = 0;
1037b725ae77Skettenis   *p++ = (int) (addr >> 24) & 0xff;
1038b725ae77Skettenis   *p++ = (int) (addr >> 16) & 0xff;
1039b725ae77Skettenis   *p++ = (int) (addr >> 8) & 0xff;
1040b725ae77Skettenis   *p++ = (int) (addr) & 0xff;
1041b725ae77Skettenis   for (i = 0; i < 4; ++i)
1042b725ae77Skettenis     *p++ = contents_cache[i];
1043b725ae77Skettenis 
1044b725ae77Skettenis   retlen = sds_send (buf, p - buf);
1045b725ae77Skettenis 
1046b725ae77Skettenis   return 0;
1047b725ae77Skettenis }
1048b725ae77Skettenis 
1049b725ae77Skettenis static void
init_sds_ops(void)1050b725ae77Skettenis init_sds_ops (void)
1051b725ae77Skettenis {
1052b725ae77Skettenis   sds_ops.to_shortname = "sds";
1053b725ae77Skettenis   sds_ops.to_longname = "Remote serial target with SDS protocol";
1054b725ae77Skettenis   sds_ops.to_doc = "Use a remote computer via a serial line; using the SDS protocol.\n\
1055b725ae77Skettenis Specify the serial device it is connected to (e.g. /dev/ttya).";
1056b725ae77Skettenis   sds_ops.to_open = sds_open;
1057b725ae77Skettenis   sds_ops.to_close = sds_close;
1058b725ae77Skettenis   sds_ops.to_detach = sds_detach;
1059b725ae77Skettenis   sds_ops.to_resume = sds_resume;
1060b725ae77Skettenis   sds_ops.to_wait = sds_wait;
1061b725ae77Skettenis   sds_ops.to_fetch_registers = sds_fetch_registers;
1062b725ae77Skettenis   sds_ops.to_store_registers = sds_store_registers;
1063b725ae77Skettenis   sds_ops.to_prepare_to_store = sds_prepare_to_store;
1064*11efff7fSkettenis   sds_ops.deprecated_xfer_memory = sds_xfer_memory;
1065b725ae77Skettenis   sds_ops.to_files_info = sds_files_info;
1066b725ae77Skettenis   sds_ops.to_insert_breakpoint = sds_insert_breakpoint;
1067b725ae77Skettenis   sds_ops.to_remove_breakpoint = sds_remove_breakpoint;
1068b725ae77Skettenis   sds_ops.to_kill = sds_kill;
1069b725ae77Skettenis   sds_ops.to_load = sds_load;
1070b725ae77Skettenis   sds_ops.to_create_inferior = sds_create_inferior;
1071b725ae77Skettenis   sds_ops.to_mourn_inferior = sds_mourn;
1072b725ae77Skettenis   sds_ops.to_stratum = process_stratum;
1073b725ae77Skettenis   sds_ops.to_has_all_memory = 1;
1074b725ae77Skettenis   sds_ops.to_has_memory = 1;
1075b725ae77Skettenis   sds_ops.to_has_stack = 1;
1076b725ae77Skettenis   sds_ops.to_has_registers = 1;
1077b725ae77Skettenis   sds_ops.to_has_execution = 1;
1078b725ae77Skettenis   sds_ops.to_magic = OPS_MAGIC;
1079b725ae77Skettenis }
1080b725ae77Skettenis 
1081b725ae77Skettenis /* Put a command string, in args, out to the monitor and display the
1082b725ae77Skettenis    reply message.  */
1083b725ae77Skettenis 
1084b725ae77Skettenis static void
sds_command(char * args,int from_tty)1085b725ae77Skettenis sds_command (char *args, int from_tty)
1086b725ae77Skettenis {
1087b725ae77Skettenis   char *p;
1088b725ae77Skettenis   int i, len, retlen;
1089b725ae77Skettenis   unsigned char buf[1000];
1090b725ae77Skettenis 
1091b725ae77Skettenis   /* Convert hexadecimal chars into a byte buffer.  */
1092b725ae77Skettenis   p = args;
1093b725ae77Skettenis   len = 0;
1094b725ae77Skettenis   while (*p != '\0')
1095b725ae77Skettenis     {
1096b725ae77Skettenis       buf[len++] = fromhex (p[0]) * 16 + fromhex (p[1]);
1097b725ae77Skettenis       if (p[1] == '\0')
1098b725ae77Skettenis 	break;
1099b725ae77Skettenis       p += 2;
1100b725ae77Skettenis     }
1101b725ae77Skettenis 
1102b725ae77Skettenis   retlen = sds_send (buf, len);
1103b725ae77Skettenis 
1104b725ae77Skettenis   printf_filtered ("Reply is ");
1105b725ae77Skettenis   for (i = 0; i < retlen; ++i)
1106b725ae77Skettenis     {
1107b725ae77Skettenis       printf_filtered ("%02x", buf[i]);
1108b725ae77Skettenis     }
1109b725ae77Skettenis   printf_filtered ("\n");
1110b725ae77Skettenis }
1111b725ae77Skettenis 
1112b725ae77Skettenis void
_initialize_remote_sds(void)1113b725ae77Skettenis _initialize_remote_sds (void)
1114b725ae77Skettenis {
1115b725ae77Skettenis   init_sds_ops ();
1116b725ae77Skettenis   add_target (&sds_ops);
1117b725ae77Skettenis 
1118*11efff7fSkettenis   deprecated_add_show_from_set
1119*11efff7fSkettenis     (add_set_cmd ("sdstimeout", no_class,
1120b725ae77Skettenis 		  var_integer, (char *) &sds_timeout,
1121b725ae77Skettenis 		  "Set timeout value for sds read.\n", &setlist),
1122b725ae77Skettenis      &showlist);
1123b725ae77Skettenis 
1124b725ae77Skettenis   add_com ("sds", class_obscure, sds_command,
1125b725ae77Skettenis 	   "Send a command to the SDS monitor.");
1126b725ae77Skettenis }
1127