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 ®s[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