1b725ae77Skettenis /* Target communications support for Macraigor Systems' On-Chip Debugging
2b725ae77Skettenis
3b725ae77Skettenis Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004 Free
4b725ae77Skettenis Software 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 #include "defs.h"
24b725ae77Skettenis #include "gdbcore.h"
25b725ae77Skettenis #include "gdb_string.h"
26b725ae77Skettenis #include <fcntl.h>
27b725ae77Skettenis #include "frame.h"
28b725ae77Skettenis #include "inferior.h"
29b725ae77Skettenis #include "bfd.h"
30b725ae77Skettenis #include "symfile.h"
31b725ae77Skettenis #include "target.h"
32b725ae77Skettenis #include "gdbcmd.h"
33b725ae77Skettenis #include "objfiles.h"
34b725ae77Skettenis #include "gdb-stabs.h"
35b725ae77Skettenis #include <sys/types.h>
36b725ae77Skettenis #include <signal.h>
37b725ae77Skettenis #include "serial.h"
38b725ae77Skettenis #include "ocd.h"
39b725ae77Skettenis #include "regcache.h"
40b725ae77Skettenis
41b725ae77Skettenis /* Prototypes for local functions */
42b725ae77Skettenis
43b725ae77Skettenis static int ocd_read_bytes (CORE_ADDR memaddr, char *myaddr, int len);
44b725ae77Skettenis
45b725ae77Skettenis static int ocd_start_remote (void *dummy);
46b725ae77Skettenis
47b725ae77Skettenis static int readchar (int timeout);
48b725ae77Skettenis
49b725ae77Skettenis static void ocd_interrupt (int signo);
50b725ae77Skettenis
51b725ae77Skettenis static void ocd_interrupt_twice (int signo);
52b725ae77Skettenis
53b725ae77Skettenis static void interrupt_query (void);
54b725ae77Skettenis
55b725ae77Skettenis static unsigned char *ocd_do_command (int cmd, int *statusp, int *lenp);
56b725ae77Skettenis
57b725ae77Skettenis static void ocd_put_packet (unsigned char *packet, int pktlen);
58b725ae77Skettenis
59b725ae77Skettenis static unsigned char *ocd_get_packet (int cmd, int *pktlen, int timeout);
60b725ae77Skettenis
61b725ae77Skettenis static struct target_ops *current_ops = NULL;
62b725ae77Skettenis
63b725ae77Skettenis static int last_run_status;
64b725ae77Skettenis
65b725ae77Skettenis /* Descriptor for I/O to remote machine. Initialize it to NULL so that
66b725ae77Skettenis ocd_open knows that we don't have a file open when the program
67b725ae77Skettenis starts. */
68b725ae77Skettenis static struct serial *ocd_desc = NULL;
69b725ae77Skettenis
70b725ae77Skettenis void
ocd_error(char * s,int error_code)71b725ae77Skettenis ocd_error (char *s, int error_code)
72b725ae77Skettenis {
73b725ae77Skettenis char buf[100];
74b725ae77Skettenis
75b725ae77Skettenis fputs_filtered (s, gdb_stderr);
76b725ae77Skettenis fputs_filtered (" ", gdb_stderr);
77b725ae77Skettenis
78b725ae77Skettenis switch (error_code)
79b725ae77Skettenis {
80b725ae77Skettenis case 0x1:
81b725ae77Skettenis s = "Unknown fault";
82b725ae77Skettenis break;
83b725ae77Skettenis case 0x2:
84b725ae77Skettenis s = "Power failed";
85b725ae77Skettenis break;
86b725ae77Skettenis case 0x3:
87b725ae77Skettenis s = "Cable disconnected";
88b725ae77Skettenis break;
89b725ae77Skettenis case 0x4:
90b725ae77Skettenis s = "Couldn't enter OCD mode";
91b725ae77Skettenis break;
92b725ae77Skettenis case 0x5:
93b725ae77Skettenis s = "Target stuck in reset";
94b725ae77Skettenis break;
95b725ae77Skettenis case 0x6:
96b725ae77Skettenis s = "OCD hasn't been initialized";
97b725ae77Skettenis break;
98b725ae77Skettenis case 0x7:
99b725ae77Skettenis s = "Write verify failed";
100b725ae77Skettenis break;
101b725ae77Skettenis case 0x8:
102b725ae77Skettenis s = "Reg buff error (during MPC5xx fp reg read/write)";
103b725ae77Skettenis break;
104b725ae77Skettenis case 0x9:
105b725ae77Skettenis s = "Invalid CPU register access attempt failed";
106b725ae77Skettenis break;
107b725ae77Skettenis case 0x11:
108b725ae77Skettenis s = "Bus error";
109b725ae77Skettenis break;
110b725ae77Skettenis case 0x12:
111b725ae77Skettenis s = "Checksum error";
112b725ae77Skettenis break;
113b725ae77Skettenis case 0x13:
114b725ae77Skettenis s = "Illegal command";
115b725ae77Skettenis break;
116b725ae77Skettenis case 0x14:
117b725ae77Skettenis s = "Parameter error";
118b725ae77Skettenis break;
119b725ae77Skettenis case 0x15:
120b725ae77Skettenis s = "Internal error";
121b725ae77Skettenis break;
122b725ae77Skettenis case 0x80:
123b725ae77Skettenis s = "Flash erase error";
124b725ae77Skettenis break;
125b725ae77Skettenis default:
126b725ae77Skettenis sprintf (buf, "Unknown error code %d", error_code);
127b725ae77Skettenis s = buf;
128b725ae77Skettenis }
129b725ae77Skettenis
130b725ae77Skettenis error ("%s", s);
131b725ae77Skettenis }
132b725ae77Skettenis
133b725ae77Skettenis /* Return nonzero if the thread TH is still alive on the remote system. */
134b725ae77Skettenis
135b725ae77Skettenis int
ocd_thread_alive(ptid_t th)136b725ae77Skettenis ocd_thread_alive (ptid_t th)
137b725ae77Skettenis {
138b725ae77Skettenis return 1;
139b725ae77Skettenis }
140b725ae77Skettenis
141b725ae77Skettenis /* Clean up connection to a remote debugger. */
142b725ae77Skettenis
143b725ae77Skettenis void
ocd_close(int quitting)144b725ae77Skettenis ocd_close (int quitting)
145b725ae77Skettenis {
146b725ae77Skettenis if (ocd_desc)
147b725ae77Skettenis serial_close (ocd_desc);
148b725ae77Skettenis ocd_desc = NULL;
149b725ae77Skettenis }
150b725ae77Skettenis
151b725ae77Skettenis /* Stub for catch_errors. */
152b725ae77Skettenis
153b725ae77Skettenis static int
ocd_start_remote(void * dummy)154b725ae77Skettenis ocd_start_remote (void *dummy)
155b725ae77Skettenis {
156b725ae77Skettenis unsigned char buf[10], *p;
157b725ae77Skettenis int pktlen;
158b725ae77Skettenis int status;
159b725ae77Skettenis int error_code;
160b725ae77Skettenis int speed;
161b725ae77Skettenis enum ocd_target_type target_type;
162b725ae77Skettenis
163b725ae77Skettenis target_type = *(enum ocd_target_type *) dummy;
164b725ae77Skettenis
165b725ae77Skettenis immediate_quit++; /* Allow user to interrupt it */
166b725ae77Skettenis
167b725ae77Skettenis serial_send_break (ocd_desc); /* Wake up the wiggler */
168b725ae77Skettenis
169b725ae77Skettenis speed = 80; /* Divide clock by 4000 */
170b725ae77Skettenis
171b725ae77Skettenis buf[0] = OCD_INIT;
172b725ae77Skettenis buf[1] = speed >> 8;
173b725ae77Skettenis buf[2] = speed & 0xff;
174b725ae77Skettenis buf[3] = target_type;
175b725ae77Skettenis ocd_put_packet (buf, 4); /* Init OCD params */
176b725ae77Skettenis p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
177b725ae77Skettenis
178b725ae77Skettenis if (pktlen < 2)
179b725ae77Skettenis error ("Truncated response packet from OCD device");
180b725ae77Skettenis
181b725ae77Skettenis status = p[1];
182b725ae77Skettenis error_code = p[2];
183b725ae77Skettenis
184b725ae77Skettenis if (error_code != 0)
185b725ae77Skettenis ocd_error ("OCD_INIT:", error_code);
186b725ae77Skettenis
187b725ae77Skettenis ocd_do_command (OCD_AYT, &status, &pktlen);
188b725ae77Skettenis
189b725ae77Skettenis p = ocd_do_command (OCD_GET_VERSION, &status, &pktlen);
190b725ae77Skettenis
191b725ae77Skettenis printf_unfiltered ("[Wiggler version %x.%x, capability 0x%x]\n",
192b725ae77Skettenis p[0], p[1], (p[2] << 16) | p[3]);
193b725ae77Skettenis
194b725ae77Skettenis /* If processor is still running, stop it. */
195b725ae77Skettenis
196b725ae77Skettenis if (!(status & OCD_FLAG_BDM))
197b725ae77Skettenis ocd_stop ();
198b725ae77Skettenis
199b725ae77Skettenis /* When using a target box, we want to asynchronously return status when
200b725ae77Skettenis target stops. The OCD_SET_CTL_FLAGS command is ignored by Wigglers.dll
201b725ae77Skettenis when using a parallel Wiggler */
202b725ae77Skettenis buf[0] = OCD_SET_CTL_FLAGS;
203b725ae77Skettenis buf[1] = 0;
204b725ae77Skettenis buf[2] = 1;
205b725ae77Skettenis ocd_put_packet (buf, 3);
206b725ae77Skettenis
207b725ae77Skettenis p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
208b725ae77Skettenis
209b725ae77Skettenis if (pktlen < 2)
210b725ae77Skettenis error ("Truncated response packet from OCD device");
211b725ae77Skettenis
212b725ae77Skettenis status = p[1];
213b725ae77Skettenis error_code = p[2];
214b725ae77Skettenis
215b725ae77Skettenis if (error_code != 0)
216b725ae77Skettenis ocd_error ("OCD_SET_CTL_FLAGS:", error_code);
217b725ae77Skettenis
218b725ae77Skettenis immediate_quit--;
219b725ae77Skettenis
220b725ae77Skettenis /* This is really the job of start_remote however, that makes an assumption
221b725ae77Skettenis that the target is about to print out a status message of some sort. That
222b725ae77Skettenis doesn't happen here (in fact, it may not be possible to get the monitor to
223b725ae77Skettenis send the appropriate packet). */
224b725ae77Skettenis
225b725ae77Skettenis flush_cached_frames ();
226b725ae77Skettenis registers_changed ();
227b725ae77Skettenis stop_pc = read_pc ();
228*11efff7fSkettenis print_stack_frame (get_selected_frame (), 0, SRC_AND_LOC);
229b725ae77Skettenis
230b725ae77Skettenis buf[0] = OCD_LOG_FILE;
231b725ae77Skettenis buf[1] = 3; /* close existing WIGGLERS.LOG */
232b725ae77Skettenis ocd_put_packet (buf, 2);
233b725ae77Skettenis p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
234b725ae77Skettenis
235b725ae77Skettenis buf[0] = OCD_LOG_FILE;
236b725ae77Skettenis buf[1] = 2; /* append to existing WIGGLERS.LOG */
237b725ae77Skettenis ocd_put_packet (buf, 2);
238b725ae77Skettenis p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
239b725ae77Skettenis
240b725ae77Skettenis return 1;
241b725ae77Skettenis }
242b725ae77Skettenis
243b725ae77Skettenis /* Open a connection to a remote debugger.
244b725ae77Skettenis NAME is the filename used for communication. */
245b725ae77Skettenis
246b725ae77Skettenis void
ocd_open(char * name,int from_tty,enum ocd_target_type target_type,struct target_ops * ops)247b725ae77Skettenis ocd_open (char *name, int from_tty, enum ocd_target_type target_type,
248b725ae77Skettenis struct target_ops *ops)
249b725ae77Skettenis {
250b725ae77Skettenis unsigned char buf[10], *p;
251b725ae77Skettenis int pktlen;
252b725ae77Skettenis
253b725ae77Skettenis if (name == 0)
254b725ae77Skettenis error ("To open an OCD connection, you need to specify the\n\
255b725ae77Skettenis device the OCD device is attached to (e.g. /dev/ttya).");
256b725ae77Skettenis
257b725ae77Skettenis target_preopen (from_tty);
258b725ae77Skettenis
259b725ae77Skettenis current_ops = ops;
260b725ae77Skettenis
261b725ae77Skettenis unpush_target (current_ops);
262b725ae77Skettenis
263b725ae77Skettenis ocd_desc = serial_open (name);
264b725ae77Skettenis if (!ocd_desc)
265b725ae77Skettenis perror_with_name (name);
266b725ae77Skettenis
267b725ae77Skettenis if (baud_rate != -1)
268b725ae77Skettenis {
269b725ae77Skettenis if (serial_setbaudrate (ocd_desc, baud_rate))
270b725ae77Skettenis {
271b725ae77Skettenis serial_close (ocd_desc);
272b725ae77Skettenis perror_with_name (name);
273b725ae77Skettenis }
274b725ae77Skettenis }
275b725ae77Skettenis
276b725ae77Skettenis serial_raw (ocd_desc);
277b725ae77Skettenis
278b725ae77Skettenis /* If there is something sitting in the buffer we might take it as a
279b725ae77Skettenis response to a command, which would be bad. */
280b725ae77Skettenis serial_flush_input (ocd_desc);
281b725ae77Skettenis
282b725ae77Skettenis if (from_tty)
283b725ae77Skettenis {
284b725ae77Skettenis puts_filtered ("Remote target wiggler connected to ");
285b725ae77Skettenis puts_filtered (name);
286b725ae77Skettenis puts_filtered ("\n");
287b725ae77Skettenis }
288b725ae77Skettenis push_target (current_ops); /* Switch to using remote target now */
289b725ae77Skettenis
290b725ae77Skettenis /* Without this, some commands which require an active target (such as kill)
291b725ae77Skettenis won't work. This variable serves (at least) double duty as both the pid
292b725ae77Skettenis of the target process (if it has such), and as a flag indicating that a
293b725ae77Skettenis target is active. These functions should be split out into seperate
294b725ae77Skettenis variables, especially since GDB will someday have a notion of debugging
295b725ae77Skettenis several processes. */
296b725ae77Skettenis
297b725ae77Skettenis inferior_ptid = pid_to_ptid (42000);
298b725ae77Skettenis /* Start the remote connection; if error (0), discard this target.
299b725ae77Skettenis In particular, if the user quits, be sure to discard it
300b725ae77Skettenis (we'd be in an inconsistent state otherwise). */
301b725ae77Skettenis if (!catch_errors (ocd_start_remote, &target_type,
302b725ae77Skettenis "Couldn't establish connection to remote target\n",
303b725ae77Skettenis RETURN_MASK_ALL))
304b725ae77Skettenis {
305b725ae77Skettenis pop_target ();
306b725ae77Skettenis error ("Failed to connect to OCD.");
307b725ae77Skettenis }
308b725ae77Skettenis }
309b725ae77Skettenis
310b725ae77Skettenis /* This takes a program previously attached to and detaches it. After
311b725ae77Skettenis this is done, GDB can be used to debug some other program. We
312b725ae77Skettenis better not have left any breakpoints in the target program or it'll
313b725ae77Skettenis die when it hits one. */
314b725ae77Skettenis
315b725ae77Skettenis void
ocd_detach(char * args,int from_tty)316b725ae77Skettenis ocd_detach (char *args, int from_tty)
317b725ae77Skettenis {
318b725ae77Skettenis if (args)
319b725ae77Skettenis error ("Argument given to \"detach\" when remotely debugging.");
320b725ae77Skettenis
321b725ae77Skettenis pop_target ();
322b725ae77Skettenis if (from_tty)
323b725ae77Skettenis puts_filtered ("Ending remote debugging.\n");
324b725ae77Skettenis }
325b725ae77Skettenis
326b725ae77Skettenis /* Tell the remote machine to resume. */
327b725ae77Skettenis
328b725ae77Skettenis void
ocd_resume(ptid_t ptid,int step,enum target_signal siggnal)329b725ae77Skettenis ocd_resume (ptid_t ptid, int step, enum target_signal siggnal)
330b725ae77Skettenis {
331b725ae77Skettenis int pktlen;
332b725ae77Skettenis
333b725ae77Skettenis if (step)
334b725ae77Skettenis ocd_do_command (OCD_STEP, &last_run_status, &pktlen);
335b725ae77Skettenis else
336b725ae77Skettenis ocd_do_command (OCD_RUN, &last_run_status, &pktlen);
337b725ae77Skettenis }
338b725ae77Skettenis
339b725ae77Skettenis void
ocd_stop(void)340b725ae77Skettenis ocd_stop (void)
341b725ae77Skettenis {
342b725ae77Skettenis int status;
343b725ae77Skettenis int pktlen;
344b725ae77Skettenis
345b725ae77Skettenis ocd_do_command (OCD_STOP, &status, &pktlen);
346b725ae77Skettenis
347b725ae77Skettenis if (!(status & OCD_FLAG_BDM))
348b725ae77Skettenis error ("Can't stop target via BDM");
349b725ae77Skettenis }
350b725ae77Skettenis
351b725ae77Skettenis static volatile int ocd_interrupt_flag;
352b725ae77Skettenis
353b725ae77Skettenis /* Send ^C to target to halt it. Target will respond, and send us a
354b725ae77Skettenis packet. */
355b725ae77Skettenis
356b725ae77Skettenis static void
ocd_interrupt(int signo)357b725ae77Skettenis ocd_interrupt (int signo)
358b725ae77Skettenis {
359b725ae77Skettenis /* If this doesn't work, try more severe steps. */
360b725ae77Skettenis signal (signo, ocd_interrupt_twice);
361b725ae77Skettenis
362b725ae77Skettenis if (remote_debug)
363b725ae77Skettenis printf_unfiltered ("ocd_interrupt called\n");
364b725ae77Skettenis
365b725ae77Skettenis {
366b725ae77Skettenis char buf[1];
367b725ae77Skettenis
368b725ae77Skettenis ocd_stop ();
369b725ae77Skettenis buf[0] = OCD_AYT;
370b725ae77Skettenis ocd_put_packet (buf, 1);
371b725ae77Skettenis ocd_interrupt_flag = 1;
372b725ae77Skettenis }
373b725ae77Skettenis }
374b725ae77Skettenis
375b725ae77Skettenis static void (*ofunc) ();
376b725ae77Skettenis
377b725ae77Skettenis /* The user typed ^C twice. */
378b725ae77Skettenis static void
ocd_interrupt_twice(int signo)379b725ae77Skettenis ocd_interrupt_twice (int signo)
380b725ae77Skettenis {
381b725ae77Skettenis signal (signo, ofunc);
382b725ae77Skettenis
383b725ae77Skettenis interrupt_query ();
384b725ae77Skettenis
385b725ae77Skettenis signal (signo, ocd_interrupt);
386b725ae77Skettenis }
387b725ae77Skettenis
388b725ae77Skettenis /* Ask the user what to do when an interrupt is received. */
389b725ae77Skettenis
390b725ae77Skettenis static void
interrupt_query(void)391b725ae77Skettenis interrupt_query (void)
392b725ae77Skettenis {
393b725ae77Skettenis target_terminal_ours ();
394b725ae77Skettenis
395b725ae77Skettenis if (query ("Interrupted while waiting for the program.\n\
396b725ae77Skettenis Give up (and stop debugging it)? "))
397b725ae77Skettenis {
398b725ae77Skettenis target_mourn_inferior ();
399b725ae77Skettenis throw_exception (RETURN_QUIT);
400b725ae77Skettenis }
401b725ae77Skettenis
402b725ae77Skettenis target_terminal_inferior ();
403b725ae77Skettenis }
404b725ae77Skettenis
405b725ae77Skettenis /* If nonzero, ignore the next kill. */
406b725ae77Skettenis static int kill_kludge;
407b725ae77Skettenis
408b725ae77Skettenis /* Wait until the remote machine stops, then return,
409b725ae77Skettenis storing status in STATUS just as `wait' would.
410b725ae77Skettenis Returns "pid" (though it's not clear what, if anything, that
411b725ae77Skettenis means in the case of this target). */
412b725ae77Skettenis
413b725ae77Skettenis int
ocd_wait(void)414b725ae77Skettenis ocd_wait (void)
415b725ae77Skettenis {
416b725ae77Skettenis unsigned char *p;
417b725ae77Skettenis int error_code;
418b725ae77Skettenis int pktlen;
419b725ae77Skettenis char buf[1];
420b725ae77Skettenis
421b725ae77Skettenis ocd_interrupt_flag = 0;
422b725ae77Skettenis
423b725ae77Skettenis /* Target might already be stopped by the time we get here. */
424b725ae77Skettenis /* If we aren't already stopped, we need to loop until we've dropped
425b725ae77Skettenis back into BDM mode */
426b725ae77Skettenis
427b725ae77Skettenis while (!(last_run_status & OCD_FLAG_BDM))
428b725ae77Skettenis {
429b725ae77Skettenis buf[0] = OCD_AYT;
430b725ae77Skettenis ocd_put_packet (buf, 1);
431b725ae77Skettenis p = ocd_get_packet (OCD_AYT, &pktlen, -1);
432b725ae77Skettenis
433b725ae77Skettenis ofunc = (void (*)()) signal (SIGINT, ocd_interrupt);
434b725ae77Skettenis signal (SIGINT, ofunc);
435b725ae77Skettenis
436b725ae77Skettenis if (pktlen < 2)
437b725ae77Skettenis error ("Truncated response packet from OCD device");
438b725ae77Skettenis
439b725ae77Skettenis last_run_status = p[1];
440b725ae77Skettenis error_code = p[2];
441b725ae77Skettenis
442b725ae77Skettenis if (error_code != 0)
443b725ae77Skettenis ocd_error ("target_wait:", error_code);
444b725ae77Skettenis
445b725ae77Skettenis if (last_run_status & OCD_FLAG_PWF)
446b725ae77Skettenis error ("OCD device lost VCC at BDM interface.");
447b725ae77Skettenis else if (last_run_status & OCD_FLAG_CABLE_DISC)
448b725ae77Skettenis error ("OCD device cable appears to have been disconnected.");
449b725ae77Skettenis }
450b725ae77Skettenis
451b725ae77Skettenis if (ocd_interrupt_flag)
452b725ae77Skettenis return 1;
453b725ae77Skettenis else
454b725ae77Skettenis return 0;
455b725ae77Skettenis }
456b725ae77Skettenis
457b725ae77Skettenis /* Read registers from the OCD device. Specify the starting and ending
458b725ae77Skettenis register number. Return the number of regs actually read in *NUMREGS.
459b725ae77Skettenis Returns a pointer to a static array containing the register contents. */
460b725ae77Skettenis
461b725ae77Skettenis unsigned char *
ocd_read_bdm_registers(int first_bdm_regno,int last_bdm_regno,int * reglen)462b725ae77Skettenis ocd_read_bdm_registers (int first_bdm_regno, int last_bdm_regno, int *reglen)
463b725ae77Skettenis {
464b725ae77Skettenis unsigned char buf[10];
465b725ae77Skettenis int i;
466b725ae77Skettenis unsigned char *p;
467b725ae77Skettenis unsigned char *regs;
468b725ae77Skettenis int error_code, status;
469b725ae77Skettenis int pktlen;
470b725ae77Skettenis
471b725ae77Skettenis buf[0] = OCD_READ_REGS;
472b725ae77Skettenis buf[1] = first_bdm_regno >> 8;
473b725ae77Skettenis buf[2] = first_bdm_regno & 0xff;
474b725ae77Skettenis buf[3] = last_bdm_regno >> 8;
475b725ae77Skettenis buf[4] = last_bdm_regno & 0xff;
476b725ae77Skettenis
477b725ae77Skettenis ocd_put_packet (buf, 5);
478b725ae77Skettenis p = ocd_get_packet (OCD_READ_REGS, &pktlen, remote_timeout);
479b725ae77Skettenis
480b725ae77Skettenis status = p[1];
481b725ae77Skettenis error_code = p[2];
482b725ae77Skettenis
483b725ae77Skettenis if (error_code != 0)
484b725ae77Skettenis ocd_error ("read_bdm_registers:", error_code);
485b725ae77Skettenis
486b725ae77Skettenis i = p[3];
487b725ae77Skettenis if (i == 0)
488b725ae77Skettenis i = 256;
489b725ae77Skettenis
490b725ae77Skettenis if (i > pktlen - 4
491b725ae77Skettenis || ((i & 3) != 0))
492b725ae77Skettenis error ("Register block size bad: %d", i);
493b725ae77Skettenis
494b725ae77Skettenis *reglen = i;
495b725ae77Skettenis
496b725ae77Skettenis regs = p + 4;
497b725ae77Skettenis
498b725ae77Skettenis return regs;
499b725ae77Skettenis }
500b725ae77Skettenis
501b725ae77Skettenis /* Read register BDM_REGNO and returns its value ala read_register() */
502b725ae77Skettenis
503b725ae77Skettenis CORE_ADDR
ocd_read_bdm_register(int bdm_regno)504b725ae77Skettenis ocd_read_bdm_register (int bdm_regno)
505b725ae77Skettenis {
506b725ae77Skettenis int reglen;
507b725ae77Skettenis unsigned char *p;
508b725ae77Skettenis CORE_ADDR regval;
509b725ae77Skettenis
510b725ae77Skettenis p = ocd_read_bdm_registers (bdm_regno, bdm_regno, ®len);
511b725ae77Skettenis regval = extract_unsigned_integer (p, reglen);
512b725ae77Skettenis
513b725ae77Skettenis return regval;
514b725ae77Skettenis }
515b725ae77Skettenis
516b725ae77Skettenis void
ocd_write_bdm_registers(int first_bdm_regno,unsigned char * regptr,int reglen)517b725ae77Skettenis ocd_write_bdm_registers (int first_bdm_regno, unsigned char *regptr, int reglen)
518b725ae77Skettenis {
519b725ae77Skettenis unsigned char *buf;
520b725ae77Skettenis unsigned char *p;
521b725ae77Skettenis int error_code, status;
522b725ae77Skettenis int pktlen;
523b725ae77Skettenis
524b725ae77Skettenis buf = alloca (4 + reglen);
525b725ae77Skettenis
526b725ae77Skettenis buf[0] = OCD_WRITE_REGS;
527b725ae77Skettenis buf[1] = first_bdm_regno >> 8;
528b725ae77Skettenis buf[2] = first_bdm_regno & 0xff;
529b725ae77Skettenis buf[3] = reglen;
530b725ae77Skettenis memcpy (buf + 4, regptr, reglen);
531b725ae77Skettenis
532b725ae77Skettenis ocd_put_packet (buf, 4 + reglen);
533b725ae77Skettenis p = ocd_get_packet (OCD_WRITE_REGS, &pktlen, remote_timeout);
534b725ae77Skettenis
535b725ae77Skettenis if (pktlen < 3)
536b725ae77Skettenis error ("Truncated response packet from OCD device");
537b725ae77Skettenis
538b725ae77Skettenis status = p[1];
539b725ae77Skettenis error_code = p[2];
540b725ae77Skettenis
541b725ae77Skettenis if (error_code != 0)
542b725ae77Skettenis ocd_error ("ocd_write_bdm_registers:", error_code);
543b725ae77Skettenis }
544b725ae77Skettenis
545b725ae77Skettenis void
ocd_write_bdm_register(int bdm_regno,CORE_ADDR reg)546b725ae77Skettenis ocd_write_bdm_register (int bdm_regno, CORE_ADDR reg)
547b725ae77Skettenis {
548b725ae77Skettenis unsigned char buf[4];
549b725ae77Skettenis
550b725ae77Skettenis store_unsigned_integer (buf, 4, reg);
551b725ae77Skettenis
552b725ae77Skettenis ocd_write_bdm_registers (bdm_regno, buf, 4);
553b725ae77Skettenis }
554b725ae77Skettenis
555b725ae77Skettenis void
ocd_prepare_to_store(void)556b725ae77Skettenis ocd_prepare_to_store (void)
557b725ae77Skettenis {
558b725ae77Skettenis }
559b725ae77Skettenis
560b725ae77Skettenis /* Write memory data directly to the remote machine.
561b725ae77Skettenis This does not inform the data cache; the data cache uses this.
562b725ae77Skettenis MEMADDR is the address in the remote memory space.
563b725ae77Skettenis MYADDR is the address of the buffer in our space.
564b725ae77Skettenis LEN is the number of bytes.
565b725ae77Skettenis
566b725ae77Skettenis Returns number of bytes transferred, or 0 for error. */
567b725ae77Skettenis
568b725ae77Skettenis static int write_mem_command = OCD_WRITE_MEM;
569b725ae77Skettenis
570b725ae77Skettenis int
ocd_write_bytes(CORE_ADDR memaddr,char * myaddr,int len)571b725ae77Skettenis ocd_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
572b725ae77Skettenis {
573b725ae77Skettenis char buf[256 + 10];
574b725ae77Skettenis unsigned char *p;
575b725ae77Skettenis int origlen;
576b725ae77Skettenis
577b725ae77Skettenis origlen = len;
578b725ae77Skettenis
579b725ae77Skettenis buf[0] = write_mem_command;
580b725ae77Skettenis buf[5] = 1; /* Write as bytes */
581b725ae77Skettenis buf[6] = 0; /* Don't verify */
582b725ae77Skettenis
583b725ae77Skettenis while (len > 0)
584b725ae77Skettenis {
585b725ae77Skettenis int numbytes;
586b725ae77Skettenis int pktlen;
587b725ae77Skettenis int status, error_code;
588b725ae77Skettenis
589b725ae77Skettenis numbytes = min (len, 256 - 8);
590b725ae77Skettenis
591b725ae77Skettenis buf[1] = memaddr >> 24;
592b725ae77Skettenis buf[2] = memaddr >> 16;
593b725ae77Skettenis buf[3] = memaddr >> 8;
594b725ae77Skettenis buf[4] = memaddr;
595b725ae77Skettenis
596b725ae77Skettenis buf[7] = numbytes;
597b725ae77Skettenis
598b725ae77Skettenis memcpy (&buf[8], myaddr, numbytes);
599b725ae77Skettenis ocd_put_packet (buf, 8 + numbytes);
600b725ae77Skettenis p = ocd_get_packet (OCD_WRITE_MEM, &pktlen, remote_timeout);
601b725ae77Skettenis if (pktlen < 3)
602b725ae77Skettenis error ("Truncated response packet from OCD device");
603b725ae77Skettenis
604b725ae77Skettenis status = p[1];
605b725ae77Skettenis error_code = p[2];
606b725ae77Skettenis
607b725ae77Skettenis if (error_code == 0x11) /* Got a bus error? */
608b725ae77Skettenis {
609b725ae77Skettenis CORE_ADDR error_address;
610b725ae77Skettenis
611b725ae77Skettenis error_address = p[3] << 24;
612b725ae77Skettenis error_address |= p[4] << 16;
613b725ae77Skettenis error_address |= p[5] << 8;
614b725ae77Skettenis error_address |= p[6];
615b725ae77Skettenis numbytes = error_address - memaddr;
616b725ae77Skettenis
617b725ae77Skettenis len -= numbytes;
618b725ae77Skettenis
619b725ae77Skettenis errno = EIO;
620b725ae77Skettenis
621b725ae77Skettenis break;
622b725ae77Skettenis }
623b725ae77Skettenis else if (error_code != 0)
624b725ae77Skettenis ocd_error ("ocd_write_bytes:", error_code);
625b725ae77Skettenis
626b725ae77Skettenis len -= numbytes;
627b725ae77Skettenis memaddr += numbytes;
628b725ae77Skettenis myaddr += numbytes;
629b725ae77Skettenis }
630b725ae77Skettenis
631b725ae77Skettenis return origlen - len;
632b725ae77Skettenis }
633b725ae77Skettenis
634b725ae77Skettenis /* Read memory data directly from the remote machine.
635b725ae77Skettenis This does not use the data cache; the data cache uses this.
636b725ae77Skettenis MEMADDR is the address in the remote memory space.
637b725ae77Skettenis MYADDR is the address of the buffer in our space.
638b725ae77Skettenis LEN is the number of bytes.
639b725ae77Skettenis
640b725ae77Skettenis Returns number of bytes transferred, or 0 for error. */
641b725ae77Skettenis
642b725ae77Skettenis static int
ocd_read_bytes(CORE_ADDR memaddr,char * myaddr,int len)643b725ae77Skettenis ocd_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
644b725ae77Skettenis {
645b725ae77Skettenis char buf[256 + 10];
646b725ae77Skettenis unsigned char *p;
647b725ae77Skettenis int origlen;
648b725ae77Skettenis
649b725ae77Skettenis origlen = len;
650b725ae77Skettenis
651b725ae77Skettenis buf[0] = OCD_READ_MEM;
652b725ae77Skettenis buf[5] = 1; /* Read as bytes */
653b725ae77Skettenis
654b725ae77Skettenis while (len > 0)
655b725ae77Skettenis {
656b725ae77Skettenis int numbytes;
657b725ae77Skettenis int pktlen;
658b725ae77Skettenis int status, error_code;
659b725ae77Skettenis
660b725ae77Skettenis numbytes = min (len, 256 - 7);
661b725ae77Skettenis
662b725ae77Skettenis buf[1] = memaddr >> 24;
663b725ae77Skettenis buf[2] = memaddr >> 16;
664b725ae77Skettenis buf[3] = memaddr >> 8;
665b725ae77Skettenis buf[4] = memaddr;
666b725ae77Skettenis
667b725ae77Skettenis buf[6] = numbytes;
668b725ae77Skettenis
669b725ae77Skettenis ocd_put_packet (buf, 7);
670b725ae77Skettenis p = ocd_get_packet (OCD_READ_MEM, &pktlen, remote_timeout);
671b725ae77Skettenis if (pktlen < 4)
672b725ae77Skettenis error ("Truncated response packet from OCD device");
673b725ae77Skettenis
674b725ae77Skettenis status = p[1];
675b725ae77Skettenis error_code = p[2];
676b725ae77Skettenis
677b725ae77Skettenis if (error_code == 0x11) /* Got a bus error? */
678b725ae77Skettenis {
679b725ae77Skettenis CORE_ADDR error_address;
680b725ae77Skettenis
681b725ae77Skettenis error_address = p[3] << 24;
682b725ae77Skettenis error_address |= p[4] << 16;
683b725ae77Skettenis error_address |= p[5] << 8;
684b725ae77Skettenis error_address |= p[6];
685b725ae77Skettenis numbytes = error_address - memaddr;
686b725ae77Skettenis
687b725ae77Skettenis len -= numbytes;
688b725ae77Skettenis
689b725ae77Skettenis errno = EIO;
690b725ae77Skettenis
691b725ae77Skettenis break;
692b725ae77Skettenis }
693b725ae77Skettenis else if (error_code != 0)
694b725ae77Skettenis ocd_error ("ocd_read_bytes:", error_code);
695b725ae77Skettenis
696b725ae77Skettenis memcpy (myaddr, &p[4], numbytes);
697b725ae77Skettenis
698b725ae77Skettenis len -= numbytes;
699b725ae77Skettenis memaddr += numbytes;
700b725ae77Skettenis myaddr += numbytes;
701b725ae77Skettenis }
702b725ae77Skettenis
703b725ae77Skettenis return origlen - len;
704b725ae77Skettenis }
705b725ae77Skettenis
706b725ae77Skettenis /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
707b725ae77Skettenis to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
708b725ae77Skettenis nonzero. Returns length of data written or read; 0 for error. TARGET
709b725ae77Skettenis is ignored. */
710b725ae77Skettenis
711b725ae77Skettenis int
ocd_xfer_memory(CORE_ADDR memaddr,char * myaddr,int len,int should_write,struct mem_attrib * attrib,struct target_ops * target)712b725ae77Skettenis ocd_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write,
713b725ae77Skettenis struct mem_attrib *attrib, struct target_ops *target)
714b725ae77Skettenis {
715b725ae77Skettenis int res;
716b725ae77Skettenis
717b725ae77Skettenis if (should_write)
718b725ae77Skettenis res = ocd_write_bytes (memaddr, myaddr, len);
719b725ae77Skettenis else
720b725ae77Skettenis res = ocd_read_bytes (memaddr, myaddr, len);
721b725ae77Skettenis
722b725ae77Skettenis return res;
723b725ae77Skettenis }
724b725ae77Skettenis
725b725ae77Skettenis void
ocd_files_info(struct target_ops * ignore)726b725ae77Skettenis ocd_files_info (struct target_ops *ignore)
727b725ae77Skettenis {
728b725ae77Skettenis puts_filtered ("Debugging a target over a serial line.\n");
729b725ae77Skettenis }
730b725ae77Skettenis
731b725ae77Skettenis /* Stuff for dealing with the packets which are part of this protocol.
732b725ae77Skettenis See comment at top of file for details. */
733b725ae77Skettenis
734b725ae77Skettenis /* Read a single character from the remote side, handling wierd errors. */
735b725ae77Skettenis
736b725ae77Skettenis static int
readchar(int timeout)737b725ae77Skettenis readchar (int timeout)
738b725ae77Skettenis {
739b725ae77Skettenis int ch;
740b725ae77Skettenis
741b725ae77Skettenis ch = serial_readchar (ocd_desc, timeout);
742b725ae77Skettenis
743b725ae77Skettenis switch (ch)
744b725ae77Skettenis {
745b725ae77Skettenis case SERIAL_EOF:
746b725ae77Skettenis error ("Remote connection closed");
747b725ae77Skettenis case SERIAL_ERROR:
748b725ae77Skettenis perror_with_name ("Remote communication error");
749b725ae77Skettenis case SERIAL_TIMEOUT:
750b725ae77Skettenis default:
751b725ae77Skettenis return ch;
752b725ae77Skettenis }
753b725ae77Skettenis }
754b725ae77Skettenis
755b725ae77Skettenis /* Send a packet to the OCD device. The packet framed by a SYN character,
756b725ae77Skettenis a byte count and a checksum. The byte count only counts the number of
757b725ae77Skettenis bytes between the count and the checksum. A count of zero actually
758b725ae77Skettenis means 256. Any SYNs within the packet (including the checksum and
759b725ae77Skettenis count) must be quoted. The quote character must be quoted as well.
760b725ae77Skettenis Quoting is done by replacing the character with the two-character sequence
761b725ae77Skettenis DLE, {char} | 0100. Note that the quoting mechanism has no effect on the
762b725ae77Skettenis byte count. */
763b725ae77Skettenis
764b725ae77Skettenis static void
ocd_put_packet(unsigned char * buf,int len)765b725ae77Skettenis ocd_put_packet (unsigned char *buf, int len)
766b725ae77Skettenis {
767b725ae77Skettenis unsigned char checksum;
768b725ae77Skettenis unsigned char c;
769b725ae77Skettenis unsigned char *packet, *packet_ptr;
770b725ae77Skettenis
771b725ae77Skettenis packet = alloca (len + 1 + 1); /* packet + SYN + checksum */
772b725ae77Skettenis packet_ptr = packet;
773b725ae77Skettenis
774b725ae77Skettenis checksum = 0;
775b725ae77Skettenis
776b725ae77Skettenis *packet_ptr++ = 0x55;
777b725ae77Skettenis
778b725ae77Skettenis while (len-- > 0)
779b725ae77Skettenis {
780b725ae77Skettenis c = *buf++;
781b725ae77Skettenis
782b725ae77Skettenis checksum += c;
783b725ae77Skettenis *packet_ptr++ = c;
784b725ae77Skettenis }
785b725ae77Skettenis
786b725ae77Skettenis *packet_ptr++ = -checksum;
787b725ae77Skettenis if (serial_write (ocd_desc, packet, packet_ptr - packet))
788b725ae77Skettenis perror_with_name ("output_packet: write failed");
789b725ae77Skettenis }
790b725ae77Skettenis
791b725ae77Skettenis /* Get a packet from the OCD device. Timeout is only enforced for the
792b725ae77Skettenis first byte of the packet. Subsequent bytes are expected to arrive in
793b725ae77Skettenis time <= remote_timeout. Returns a pointer to a static buffer containing
794b725ae77Skettenis the payload of the packet. *LENP contains the length of the packet.
795b725ae77Skettenis */
796b725ae77Skettenis
797b725ae77Skettenis static unsigned char *
ocd_get_packet(int cmd,int * lenp,int timeout)798b725ae77Skettenis ocd_get_packet (int cmd, int *lenp, int timeout)
799b725ae77Skettenis {
800b725ae77Skettenis int ch;
801b725ae77Skettenis int len;
802b725ae77Skettenis static unsigned char packet[512];
803b725ae77Skettenis unsigned char *packet_ptr;
804b725ae77Skettenis unsigned char checksum;
805b725ae77Skettenis
806b725ae77Skettenis ch = readchar (timeout);
807b725ae77Skettenis
808b725ae77Skettenis if (ch < 0)
809b725ae77Skettenis error ("ocd_get_packet (readchar): %d", ch);
810b725ae77Skettenis
811b725ae77Skettenis if (ch != 0x55)
812b725ae77Skettenis error ("ocd_get_packet (readchar): %d", ch);
813b725ae77Skettenis
814b725ae77Skettenis /* Found the start of a packet */
815b725ae77Skettenis
816b725ae77Skettenis packet_ptr = packet;
817b725ae77Skettenis checksum = 0;
818b725ae77Skettenis
819b725ae77Skettenis /* Read command char. That sort of tells us how long the packet is. */
820b725ae77Skettenis
821b725ae77Skettenis ch = readchar (timeout);
822b725ae77Skettenis
823b725ae77Skettenis if (ch < 0)
824b725ae77Skettenis error ("ocd_get_packet (readchar): %d", ch);
825b725ae77Skettenis
826b725ae77Skettenis *packet_ptr++ = ch;
827b725ae77Skettenis checksum += ch;
828b725ae77Skettenis
829b725ae77Skettenis /* Get status. */
830b725ae77Skettenis
831b725ae77Skettenis ch = readchar (timeout);
832b725ae77Skettenis
833b725ae77Skettenis if (ch < 0)
834b725ae77Skettenis error ("ocd_get_packet (readchar): %d", ch);
835b725ae77Skettenis *packet_ptr++ = ch;
836b725ae77Skettenis checksum += ch;
837b725ae77Skettenis
838b725ae77Skettenis /* Get error code. */
839b725ae77Skettenis
840b725ae77Skettenis ch = readchar (timeout);
841b725ae77Skettenis
842b725ae77Skettenis if (ch < 0)
843b725ae77Skettenis error ("ocd_get_packet (readchar): %d", ch);
844b725ae77Skettenis *packet_ptr++ = ch;
845b725ae77Skettenis checksum += ch;
846b725ae77Skettenis
847b725ae77Skettenis switch (ch) /* Figure out length of packet */
848b725ae77Skettenis {
849b725ae77Skettenis case 0x7: /* Write verify error? */
850b725ae77Skettenis len = 8; /* write address, value read back */
851b725ae77Skettenis break;
852b725ae77Skettenis case 0x11: /* Bus error? */
853b725ae77Skettenis /* write address, read flag */
854b725ae77Skettenis case 0x15: /* Internal error */
855b725ae77Skettenis len = 5; /* error code, vector */
856b725ae77Skettenis break;
857b725ae77Skettenis default: /* Error w/no params */
858b725ae77Skettenis len = 0;
859b725ae77Skettenis break;
860b725ae77Skettenis case 0x0: /* Normal result */
861b725ae77Skettenis switch (packet[0])
862b725ae77Skettenis {
863b725ae77Skettenis case OCD_AYT: /* Are You There? */
864b725ae77Skettenis case OCD_SET_BAUD_RATE: /* Set Baud Rate */
865b725ae77Skettenis case OCD_INIT: /* Initialize OCD device */
866b725ae77Skettenis case OCD_SET_SPEED: /* Set Speed */
867b725ae77Skettenis case OCD_SET_FUNC_CODE: /* Set Function Code */
868b725ae77Skettenis case OCD_SET_CTL_FLAGS: /* Set Control Flags */
869b725ae77Skettenis case OCD_SET_BUF_ADDR: /* Set Register Buffer Address */
870b725ae77Skettenis case OCD_RUN: /* Run Target from PC */
871b725ae77Skettenis case OCD_RUN_ADDR: /* Run Target from Specified Address */
872b725ae77Skettenis case OCD_STOP: /* Stop Target */
873b725ae77Skettenis case OCD_RESET_RUN: /* Reset Target and Run */
874b725ae77Skettenis case OCD_RESET: /* Reset Target and Halt */
875b725ae77Skettenis case OCD_STEP: /* Single Step */
876b725ae77Skettenis case OCD_WRITE_REGS: /* Write Register */
877b725ae77Skettenis case OCD_WRITE_MEM: /* Write Memory */
878b725ae77Skettenis case OCD_FILL_MEM: /* Fill Memory */
879b725ae77Skettenis case OCD_MOVE_MEM: /* Move Memory */
880b725ae77Skettenis case OCD_WRITE_INT_MEM: /* Write Internal Memory */
881b725ae77Skettenis case OCD_JUMP: /* Jump to Subroutine */
882b725ae77Skettenis case OCD_ERASE_FLASH: /* Erase flash memory */
883b725ae77Skettenis case OCD_PROGRAM_FLASH: /* Write flash memory */
884b725ae77Skettenis case OCD_EXIT_MON: /* Exit the flash programming monitor */
885b725ae77Skettenis case OCD_ENTER_MON: /* Enter the flash programming monitor */
886b725ae77Skettenis case OCD_LOG_FILE: /* Make Wigglers.dll save Wigglers.log */
887b725ae77Skettenis case OCD_SET_CONNECTION: /* Set type of connection in Wigglers.dll */
888b725ae77Skettenis len = 0;
889b725ae77Skettenis break;
890b725ae77Skettenis case OCD_GET_VERSION: /* Get Version */
891b725ae77Skettenis len = 10;
892b725ae77Skettenis break;
893b725ae77Skettenis case OCD_GET_STATUS_MASK: /* Get Status Mask */
894b725ae77Skettenis len = 1;
895b725ae77Skettenis break;
896b725ae77Skettenis case OCD_GET_CTRS: /* Get Error Counters */
897b725ae77Skettenis case OCD_READ_REGS: /* Read Register */
898b725ae77Skettenis case OCD_READ_MEM: /* Read Memory */
899b725ae77Skettenis case OCD_READ_INT_MEM: /* Read Internal Memory */
900b725ae77Skettenis len = 257;
901b725ae77Skettenis break;
902b725ae77Skettenis default:
903b725ae77Skettenis error ("ocd_get_packet: unknown packet type 0x%x\n", ch);
904b725ae77Skettenis }
905b725ae77Skettenis }
906b725ae77Skettenis
907b725ae77Skettenis if (len == 257) /* Byte stream? */
908b725ae77Skettenis { /* Yes, byte streams contain the length */
909b725ae77Skettenis ch = readchar (timeout);
910b725ae77Skettenis
911b725ae77Skettenis if (ch < 0)
912b725ae77Skettenis error ("ocd_get_packet (readchar): %d", ch);
913b725ae77Skettenis *packet_ptr++ = ch;
914b725ae77Skettenis checksum += ch;
915b725ae77Skettenis len = ch;
916b725ae77Skettenis if (len == 0)
917b725ae77Skettenis len = 256;
918b725ae77Skettenis }
919b725ae77Skettenis
920b725ae77Skettenis while (len-- >= 0) /* Do rest of packet and checksum */
921b725ae77Skettenis {
922b725ae77Skettenis ch = readchar (timeout);
923b725ae77Skettenis
924b725ae77Skettenis if (ch < 0)
925b725ae77Skettenis error ("ocd_get_packet (readchar): %d", ch);
926b725ae77Skettenis *packet_ptr++ = ch;
927b725ae77Skettenis checksum += ch;
928b725ae77Skettenis }
929b725ae77Skettenis
930b725ae77Skettenis if (checksum != 0)
931b725ae77Skettenis error ("ocd_get_packet: bad packet checksum");
932b725ae77Skettenis
933b725ae77Skettenis if (cmd != -1 && cmd != packet[0])
934b725ae77Skettenis error ("Response phase error. Got 0x%x, expected 0x%x", packet[0], cmd);
935b725ae77Skettenis
936b725ae77Skettenis *lenp = packet_ptr - packet - 1; /* Subtract checksum byte */
937b725ae77Skettenis return packet;
938b725ae77Skettenis }
939b725ae77Skettenis
940b725ae77Skettenis /* Execute a simple (one-byte) command. Returns a pointer to the data
941b725ae77Skettenis following the error code. */
942b725ae77Skettenis
943b725ae77Skettenis static unsigned char *
ocd_do_command(int cmd,int * statusp,int * lenp)944b725ae77Skettenis ocd_do_command (int cmd, int *statusp, int *lenp)
945b725ae77Skettenis {
946b725ae77Skettenis unsigned char buf[100], *p;
947b725ae77Skettenis int status, error_code;
948b725ae77Skettenis char errbuf[100];
949b725ae77Skettenis
950b725ae77Skettenis unsigned char logbuf[100];
951b725ae77Skettenis int logpktlen;
952b725ae77Skettenis
953b725ae77Skettenis buf[0] = cmd;
954b725ae77Skettenis ocd_put_packet (buf, 1); /* Send command */
955b725ae77Skettenis p = ocd_get_packet (*buf, lenp, remote_timeout);
956b725ae77Skettenis
957b725ae77Skettenis if (*lenp < 3)
958b725ae77Skettenis error ("Truncated response packet from OCD device");
959b725ae77Skettenis
960b725ae77Skettenis status = p[1];
961b725ae77Skettenis error_code = p[2];
962b725ae77Skettenis
963b725ae77Skettenis if (error_code != 0)
964b725ae77Skettenis {
965b725ae77Skettenis sprintf (errbuf, "ocd_do_command (0x%x):", cmd);
966b725ae77Skettenis ocd_error (errbuf, error_code);
967b725ae77Skettenis }
968b725ae77Skettenis
969b725ae77Skettenis if (status & OCD_FLAG_PWF)
970b725ae77Skettenis error ("OCD device can't detect VCC at BDM interface.");
971b725ae77Skettenis else if (status & OCD_FLAG_CABLE_DISC)
972b725ae77Skettenis error ("BDM cable appears to be disconnected.");
973b725ae77Skettenis
974b725ae77Skettenis *statusp = status;
975b725ae77Skettenis
976b725ae77Skettenis logbuf[0] = OCD_LOG_FILE;
977b725ae77Skettenis logbuf[1] = 3; /* close existing WIGGLERS.LOG */
978b725ae77Skettenis ocd_put_packet (logbuf, 2);
979b725ae77Skettenis ocd_get_packet (logbuf[0], &logpktlen, remote_timeout);
980b725ae77Skettenis
981b725ae77Skettenis logbuf[0] = OCD_LOG_FILE;
982b725ae77Skettenis logbuf[1] = 2; /* append to existing WIGGLERS.LOG */
983b725ae77Skettenis ocd_put_packet (logbuf, 2);
984b725ae77Skettenis ocd_get_packet (logbuf[0], &logpktlen, remote_timeout);
985b725ae77Skettenis
986b725ae77Skettenis return p + 3;
987b725ae77Skettenis }
988b725ae77Skettenis
989b725ae77Skettenis void
ocd_kill(void)990b725ae77Skettenis ocd_kill (void)
991b725ae77Skettenis {
992b725ae77Skettenis /* For some mysterious reason, wait_for_inferior calls kill instead of
993b725ae77Skettenis mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
994b725ae77Skettenis if (kill_kludge)
995b725ae77Skettenis {
996b725ae77Skettenis kill_kludge = 0;
997b725ae77Skettenis target_mourn_inferior ();
998b725ae77Skettenis return;
999b725ae77Skettenis }
1000b725ae77Skettenis
1001b725ae77Skettenis /* Don't wait for it to die. I'm not really sure it matters whether
1002b725ae77Skettenis we do or not. */
1003b725ae77Skettenis target_mourn_inferior ();
1004b725ae77Skettenis }
1005b725ae77Skettenis
1006b725ae77Skettenis void
ocd_mourn(void)1007b725ae77Skettenis ocd_mourn (void)
1008b725ae77Skettenis {
1009b725ae77Skettenis unpush_target (current_ops);
1010b725ae77Skettenis generic_mourn_inferior ();
1011b725ae77Skettenis }
1012b725ae77Skettenis
1013b725ae77Skettenis /* All we actually do is set the PC to the start address of exec_bfd, and start
1014b725ae77Skettenis the program at that point. */
1015b725ae77Skettenis
1016b725ae77Skettenis void
ocd_create_inferior(char * exec_file,char * args,char ** env,int from_tty)1017*11efff7fSkettenis ocd_create_inferior (char *exec_file, char *args, char **env, int from_tty)
1018b725ae77Skettenis {
1019b725ae77Skettenis if (args && (*args != '\000'))
1020b725ae77Skettenis error ("Args are not supported by BDM.");
1021b725ae77Skettenis
1022b725ae77Skettenis clear_proceed_status ();
1023b725ae77Skettenis proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
1024b725ae77Skettenis }
1025b725ae77Skettenis
1026b725ae77Skettenis void
ocd_load(char * args,int from_tty)1027b725ae77Skettenis ocd_load (char *args, int from_tty)
1028b725ae77Skettenis {
1029b725ae77Skettenis generic_load (args, from_tty);
1030b725ae77Skettenis
1031b725ae77Skettenis inferior_ptid = null_ptid;
1032b725ae77Skettenis
1033b725ae77Skettenis /* This is necessary because many things were based on the PC at the time that
1034b725ae77Skettenis we attached to the monitor, which is no longer valid now that we have loaded
1035b725ae77Skettenis new code (and just changed the PC). Another way to do this might be to call
1036b725ae77Skettenis normal_stop, except that the stack may not be valid, and things would get
1037b725ae77Skettenis horribly confused... */
1038b725ae77Skettenis
1039b725ae77Skettenis clear_symtab_users ();
1040b725ae77Skettenis }
1041b725ae77Skettenis
1042b725ae77Skettenis /* This should be defined for each target */
1043b725ae77Skettenis /* But we want to be able to compile this file for some configurations
1044b725ae77Skettenis not yet supported fully */
1045b725ae77Skettenis
1046b725ae77Skettenis #define BDM_BREAKPOINT {0x0,0x0,0x0,0x0} /* For ppc 8xx */
1047b725ae77Skettenis
1048b725ae77Skettenis /* BDM (at least on CPU32) uses a different breakpoint */
1049b725ae77Skettenis
1050b725ae77Skettenis int
ocd_insert_breakpoint(CORE_ADDR addr,char * contents_cache)1051b725ae77Skettenis ocd_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
1052b725ae77Skettenis {
1053b725ae77Skettenis static char break_insn[] = BDM_BREAKPOINT;
1054b725ae77Skettenis int val;
1055b725ae77Skettenis
1056b725ae77Skettenis val = target_read_memory (addr, contents_cache, sizeof (break_insn));
1057b725ae77Skettenis
1058b725ae77Skettenis if (val == 0)
1059b725ae77Skettenis val = target_write_memory (addr, break_insn, sizeof (break_insn));
1060b725ae77Skettenis
1061b725ae77Skettenis return val;
1062b725ae77Skettenis }
1063b725ae77Skettenis
1064b725ae77Skettenis int
ocd_remove_breakpoint(CORE_ADDR addr,char * contents_cache)1065b725ae77Skettenis ocd_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
1066b725ae77Skettenis {
1067b725ae77Skettenis static char break_insn[] = BDM_BREAKPOINT;
1068b725ae77Skettenis int val;
1069b725ae77Skettenis
1070b725ae77Skettenis val = target_write_memory (addr, contents_cache, sizeof (break_insn));
1071b725ae77Skettenis
1072b725ae77Skettenis return val;
1073b725ae77Skettenis }
1074b725ae77Skettenis
1075b725ae77Skettenis static void
bdm_command(char * args,int from_tty)1076b725ae77Skettenis bdm_command (char *args, int from_tty)
1077b725ae77Skettenis {
1078b725ae77Skettenis error ("bdm command must be followed by `reset'");
1079b725ae77Skettenis }
1080b725ae77Skettenis
1081b725ae77Skettenis static void
bdm_reset_command(char * args,int from_tty)1082b725ae77Skettenis bdm_reset_command (char *args, int from_tty)
1083b725ae77Skettenis {
1084b725ae77Skettenis int status, pktlen;
1085b725ae77Skettenis
1086b725ae77Skettenis if (!ocd_desc)
1087b725ae77Skettenis error ("Not connected to OCD device.");
1088b725ae77Skettenis
1089b725ae77Skettenis ocd_do_command (OCD_RESET, &status, &pktlen);
1090b725ae77Skettenis dcache_invalidate (target_dcache);
1091b725ae77Skettenis registers_changed ();
1092b725ae77Skettenis }
1093b725ae77Skettenis
1094b725ae77Skettenis static void
bdm_restart_command(char * args,int from_tty)1095b725ae77Skettenis bdm_restart_command (char *args, int from_tty)
1096b725ae77Skettenis {
1097b725ae77Skettenis int status, pktlen;
1098b725ae77Skettenis
1099b725ae77Skettenis if (!ocd_desc)
1100b725ae77Skettenis error ("Not connected to OCD device.");
1101b725ae77Skettenis
1102b725ae77Skettenis ocd_do_command (OCD_RESET_RUN, &status, &pktlen);
1103b725ae77Skettenis last_run_status = status;
1104b725ae77Skettenis clear_proceed_status ();
1105b725ae77Skettenis wait_for_inferior ();
1106b725ae77Skettenis normal_stop ();
1107b725ae77Skettenis }
1108b725ae77Skettenis
1109b725ae77Skettenis /* Temporary replacement for target_store_registers(). This prevents
1110b725ae77Skettenis generic_load from trying to set the PC. */
1111b725ae77Skettenis
1112b725ae77Skettenis static void
noop_store_registers(int regno)1113b725ae77Skettenis noop_store_registers (int regno)
1114b725ae77Skettenis {
1115b725ae77Skettenis }
1116b725ae77Skettenis
1117b725ae77Skettenis static void
bdm_update_flash_command(char * args,int from_tty)1118b725ae77Skettenis bdm_update_flash_command (char *args, int from_tty)
1119b725ae77Skettenis {
1120b725ae77Skettenis int status, pktlen;
1121b725ae77Skettenis struct cleanup *old_chain;
1122b725ae77Skettenis void (*store_registers_tmp) (int);
1123b725ae77Skettenis
1124b725ae77Skettenis if (!ocd_desc)
1125b725ae77Skettenis error ("Not connected to OCD device.");
1126b725ae77Skettenis
1127b725ae77Skettenis if (!args)
1128b725ae77Skettenis error ("Must specify file containing new OCD code.");
1129b725ae77Skettenis
1130b725ae77Skettenis /* old_chain = make_cleanup (flash_cleanup, 0); */
1131b725ae77Skettenis
1132b725ae77Skettenis ocd_do_command (OCD_ENTER_MON, &status, &pktlen);
1133b725ae77Skettenis
1134b725ae77Skettenis ocd_do_command (OCD_ERASE_FLASH, &status, &pktlen);
1135b725ae77Skettenis
1136b725ae77Skettenis write_mem_command = OCD_PROGRAM_FLASH;
1137b725ae77Skettenis store_registers_tmp = current_target.to_store_registers;
1138b725ae77Skettenis current_target.to_store_registers = noop_store_registers;
1139b725ae77Skettenis
1140b725ae77Skettenis generic_load (args, from_tty);
1141b725ae77Skettenis
1142b725ae77Skettenis current_target.to_store_registers = store_registers_tmp;
1143b725ae77Skettenis write_mem_command = OCD_WRITE_MEM;
1144b725ae77Skettenis
1145b725ae77Skettenis ocd_do_command (OCD_EXIT_MON, &status, &pktlen);
1146b725ae77Skettenis
1147b725ae77Skettenis /* discard_cleanups (old_chain); */
1148b725ae77Skettenis }
1149b725ae77Skettenis
1150b725ae77Skettenis extern initialize_file_ftype _initialize_remote_ocd; /* -Wmissing-prototypes */
1151b725ae77Skettenis
1152b725ae77Skettenis void
_initialize_remote_ocd(void)1153b725ae77Skettenis _initialize_remote_ocd (void)
1154b725ae77Skettenis {
1155b725ae77Skettenis extern struct cmd_list_element *cmdlist;
1156b725ae77Skettenis static struct cmd_list_element *ocd_cmd_list = NULL;
1157b725ae77Skettenis
1158*11efff7fSkettenis deprecated_add_show_from_set
1159*11efff7fSkettenis (add_set_cmd ("remotetimeout", no_class,
1160b725ae77Skettenis var_integer, (char *) &remote_timeout,
1161b725ae77Skettenis "Set timeout value for remote read.\n", &setlist),
1162b725ae77Skettenis &showlist);
1163b725ae77Skettenis
1164b725ae77Skettenis add_prefix_cmd ("ocd", class_obscure, bdm_command, "", &ocd_cmd_list, "ocd ",
1165b725ae77Skettenis 0, &cmdlist);
1166b725ae77Skettenis
1167b725ae77Skettenis add_cmd ("reset", class_obscure, bdm_reset_command, "", &ocd_cmd_list);
1168b725ae77Skettenis add_cmd ("restart", class_obscure, bdm_restart_command, "", &ocd_cmd_list);
1169b725ae77Skettenis add_cmd ("update-flash", class_obscure, bdm_update_flash_command, "", &ocd_cmd_list);
1170b725ae77Skettenis }
1171