146283Sdfr/* Target communications support for Macraigor Systems' On-Chip Debugging
246283Sdfr
3130803Smarcel   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004 Free
4130803Smarcel   Software Foundation, Inc.
546283Sdfr
698944Sobrien   This file is part of GDB.
746283Sdfr
898944Sobrien   This program is free software; you can redistribute it and/or modify
998944Sobrien   it under the terms of the GNU General Public License as published by
1098944Sobrien   the Free Software Foundation; either version 2 of the License, or
1198944Sobrien   (at your option) any later version.
1246283Sdfr
1398944Sobrien   This program is distributed in the hope that it will be useful,
1498944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1598944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1698944Sobrien   GNU General Public License for more details.
1746283Sdfr
1898944Sobrien   You should have received a copy of the GNU General Public License
1998944Sobrien   along with this program; if not, write to the Free Software
2098944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2198944Sobrien   Boston, MA 02111-1307, USA.  */
2298944Sobrien
2346283Sdfr#include "defs.h"
2446283Sdfr#include "gdbcore.h"
2546283Sdfr#include "gdb_string.h"
2646283Sdfr#include <fcntl.h>
2746283Sdfr#include "frame.h"
2846283Sdfr#include "inferior.h"
2946283Sdfr#include "bfd.h"
3046283Sdfr#include "symfile.h"
3146283Sdfr#include "target.h"
3246283Sdfr#include "gdbcmd.h"
3346283Sdfr#include "objfiles.h"
3446283Sdfr#include "gdb-stabs.h"
3546283Sdfr#include <sys/types.h>
3646283Sdfr#include <signal.h>
3746283Sdfr#include "serial.h"
3846283Sdfr#include "ocd.h"
3998944Sobrien#include "regcache.h"
4046283Sdfr
4146283Sdfr/* Prototypes for local functions */
4246283Sdfr
4398944Sobrienstatic int ocd_read_bytes (CORE_ADDR memaddr, char *myaddr, int len);
4446283Sdfr
45130803Smarcelstatic int ocd_start_remote (void *dummy);
4646283Sdfr
4798944Sobrienstatic int readchar (int timeout);
4846283Sdfr
4998944Sobrienstatic void ocd_interrupt (int signo);
5046283Sdfr
5198944Sobrienstatic void ocd_interrupt_twice (int signo);
5246283Sdfr
5398944Sobrienstatic void interrupt_query (void);
5446283Sdfr
5598944Sobrienstatic unsigned char *ocd_do_command (int cmd, int *statusp, int *lenp);
5646283Sdfr
5798944Sobrienstatic void ocd_put_packet (unsigned char *packet, int pktlen);
5846283Sdfr
5998944Sobrienstatic unsigned char *ocd_get_packet (int cmd, int *pktlen, int timeout);
6046283Sdfr
6146283Sdfrstatic struct target_ops *current_ops = NULL;
6246283Sdfr
6346283Sdfrstatic int last_run_status;
6446283Sdfr
6546283Sdfr/* Descriptor for I/O to remote machine.  Initialize it to NULL so that
6646283Sdfr   ocd_open knows that we don't have a file open when the program
6746283Sdfr   starts.  */
6898944Sobrienstatic struct serial *ocd_desc = NULL;
6946283Sdfr
7046283Sdfrvoid
7198944Sobrienocd_error (char *s, int error_code)
7246283Sdfr{
7346283Sdfr  char buf[100];
7446283Sdfr
7546283Sdfr  fputs_filtered (s, gdb_stderr);
7646283Sdfr  fputs_filtered (" ", gdb_stderr);
7746283Sdfr
7846283Sdfr  switch (error_code)
7946283Sdfr    {
8098944Sobrien    case 0x1:
8198944Sobrien      s = "Unknown fault";
8298944Sobrien      break;
8398944Sobrien    case 0x2:
8498944Sobrien      s = "Power failed";
8598944Sobrien      break;
8698944Sobrien    case 0x3:
8798944Sobrien      s = "Cable disconnected";
8898944Sobrien      break;
8998944Sobrien    case 0x4:
9098944Sobrien      s = "Couldn't enter OCD mode";
9198944Sobrien      break;
9298944Sobrien    case 0x5:
9398944Sobrien      s = "Target stuck in reset";
9498944Sobrien      break;
9598944Sobrien    case 0x6:
9698944Sobrien      s = "OCD hasn't been initialized";
9798944Sobrien      break;
9898944Sobrien    case 0x7:
9998944Sobrien      s = "Write verify failed";
10098944Sobrien      break;
10198944Sobrien    case 0x8:
10298944Sobrien      s = "Reg buff error (during MPC5xx fp reg read/write)";
10398944Sobrien      break;
10498944Sobrien    case 0x9:
10598944Sobrien      s = "Invalid CPU register access attempt failed";
10698944Sobrien      break;
10798944Sobrien    case 0x11:
10898944Sobrien      s = "Bus error";
10998944Sobrien      break;
11098944Sobrien    case 0x12:
11198944Sobrien      s = "Checksum error";
11298944Sobrien      break;
11398944Sobrien    case 0x13:
11498944Sobrien      s = "Illegal command";
11598944Sobrien      break;
11698944Sobrien    case 0x14:
11798944Sobrien      s = "Parameter error";
11898944Sobrien      break;
11998944Sobrien    case 0x15:
12098944Sobrien      s = "Internal error";
12198944Sobrien      break;
12298944Sobrien    case 0x80:
12398944Sobrien      s = "Flash erase error";
12498944Sobrien      break;
12546283Sdfr    default:
12646283Sdfr      sprintf (buf, "Unknown error code %d", error_code);
12746283Sdfr      s = buf;
12846283Sdfr    }
12946283Sdfr
130130803Smarcel  error ("%s", s);
13146283Sdfr}
13246283Sdfr
13346283Sdfr/*  Return nonzero if the thread TH is still alive on the remote system.  */
13446283Sdfr
13546283Sdfrint
13698944Sobrienocd_thread_alive (ptid_t th)
13746283Sdfr{
13846283Sdfr  return 1;
13946283Sdfr}
14046283Sdfr
14146283Sdfr/* Clean up connection to a remote debugger.  */
14246283Sdfr
14346283Sdfrvoid
14498944Sobrienocd_close (int quitting)
14546283Sdfr{
14646283Sdfr  if (ocd_desc)
14798944Sobrien    serial_close (ocd_desc);
14846283Sdfr  ocd_desc = NULL;
14946283Sdfr}
15046283Sdfr
15146283Sdfr/* Stub for catch_errors.  */
15246283Sdfr
15346283Sdfrstatic int
154130803Smarcelocd_start_remote (void *dummy)
15546283Sdfr{
15646283Sdfr  unsigned char buf[10], *p;
15746283Sdfr  int pktlen;
15846283Sdfr  int status;
15946283Sdfr  int error_code;
16046283Sdfr  int speed;
16146283Sdfr  enum ocd_target_type target_type;
16246283Sdfr
16398944Sobrien  target_type = *(enum ocd_target_type *) dummy;
16446283Sdfr
16598944Sobrien  immediate_quit++;		/* Allow user to interrupt it */
16646283Sdfr
16798944Sobrien  serial_send_break (ocd_desc);	/* Wake up the wiggler */
16846283Sdfr
16946283Sdfr  speed = 80;			/* Divide clock by 4000 */
17046283Sdfr
17146283Sdfr  buf[0] = OCD_INIT;
17246283Sdfr  buf[1] = speed >> 8;
17346283Sdfr  buf[2] = speed & 0xff;
17446283Sdfr  buf[3] = target_type;
17546283Sdfr  ocd_put_packet (buf, 4);	/* Init OCD params */
17646283Sdfr  p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
17746283Sdfr
17846283Sdfr  if (pktlen < 2)
17946283Sdfr    error ("Truncated response packet from OCD device");
18046283Sdfr
18146283Sdfr  status = p[1];
18246283Sdfr  error_code = p[2];
18346283Sdfr
18446283Sdfr  if (error_code != 0)
18546283Sdfr    ocd_error ("OCD_INIT:", error_code);
18646283Sdfr
18746283Sdfr  ocd_do_command (OCD_AYT, &status, &pktlen);
18846283Sdfr
18946283Sdfr  p = ocd_do_command (OCD_GET_VERSION, &status, &pktlen);
19046283Sdfr
19146283Sdfr  printf_unfiltered ("[Wiggler version %x.%x, capability 0x%x]\n",
19246283Sdfr		     p[0], p[1], (p[2] << 16) | p[3]);
19346283Sdfr
19446283Sdfr  /* If processor is still running, stop it.  */
19546283Sdfr
19646283Sdfr  if (!(status & OCD_FLAG_BDM))
19746283Sdfr    ocd_stop ();
19846283Sdfr
19946283Sdfr  /* When using a target box, we want to asynchronously return status when
20046283Sdfr     target stops.  The OCD_SET_CTL_FLAGS command is ignored by Wigglers.dll
20146283Sdfr     when using a parallel Wiggler */
20246283Sdfr  buf[0] = OCD_SET_CTL_FLAGS;
20346283Sdfr  buf[1] = 0;
20446283Sdfr  buf[2] = 1;
20546283Sdfr  ocd_put_packet (buf, 3);
20646283Sdfr
20746283Sdfr  p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
20846283Sdfr
20946283Sdfr  if (pktlen < 2)
21046283Sdfr    error ("Truncated response packet from OCD device");
21146283Sdfr
21246283Sdfr  status = p[1];
21346283Sdfr  error_code = p[2];
21446283Sdfr
21546283Sdfr  if (error_code != 0)
21646283Sdfr    ocd_error ("OCD_SET_CTL_FLAGS:", error_code);
21746283Sdfr
21898944Sobrien  immediate_quit--;
21946283Sdfr
22046283Sdfr/* This is really the job of start_remote however, that makes an assumption
22146283Sdfr   that the target is about to print out a status message of some sort.  That
22246283Sdfr   doesn't happen here (in fact, it may not be possible to get the monitor to
22346283Sdfr   send the appropriate packet).  */
22446283Sdfr
22546283Sdfr  flush_cached_frames ();
22646283Sdfr  registers_changed ();
22746283Sdfr  stop_pc = read_pc ();
228130803Smarcel  print_stack_frame (get_selected_frame (), -1, 1);
22946283Sdfr
23046283Sdfr  buf[0] = OCD_LOG_FILE;
23198944Sobrien  buf[1] = 3;			/* close existing WIGGLERS.LOG */
23246283Sdfr  ocd_put_packet (buf, 2);
23346283Sdfr  p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
23446283Sdfr
23546283Sdfr  buf[0] = OCD_LOG_FILE;
23698944Sobrien  buf[1] = 2;			/* append to existing WIGGLERS.LOG */
23746283Sdfr  ocd_put_packet (buf, 2);
23846283Sdfr  p = ocd_get_packet (buf[0], &pktlen, remote_timeout);
23946283Sdfr
24046283Sdfr  return 1;
24146283Sdfr}
24246283Sdfr
24346283Sdfr/* Open a connection to a remote debugger.
24446283Sdfr   NAME is the filename used for communication.  */
24546283Sdfr
24646283Sdfrvoid
24798944Sobrienocd_open (char *name, int from_tty, enum ocd_target_type target_type,
24898944Sobrien	  struct target_ops *ops)
24946283Sdfr{
25046283Sdfr  unsigned char buf[10], *p;
25146283Sdfr  int pktlen;
25246283Sdfr
25346283Sdfr  if (name == 0)
25446283Sdfr    error ("To open an OCD connection, you need to specify the\n\
25546283Sdfrdevice the OCD device is attached to (e.g. /dev/ttya).");
25646283Sdfr
25746283Sdfr  target_preopen (from_tty);
25846283Sdfr
25946283Sdfr  current_ops = ops;
26046283Sdfr
26146283Sdfr  unpush_target (current_ops);
26246283Sdfr
26398944Sobrien  ocd_desc = serial_open (name);
26498944Sobrien  if (!ocd_desc)
26598944Sobrien    perror_with_name (name);
26646283Sdfr
26746283Sdfr  if (baud_rate != -1)
26846283Sdfr    {
26998944Sobrien      if (serial_setbaudrate (ocd_desc, baud_rate))
27046283Sdfr	{
27198944Sobrien	  serial_close (ocd_desc);
27246283Sdfr	  perror_with_name (name);
27346283Sdfr	}
27446283Sdfr    }
27546283Sdfr
27698944Sobrien  serial_raw (ocd_desc);
27746283Sdfr
27846283Sdfr  /* If there is something sitting in the buffer we might take it as a
27946283Sdfr     response to a command, which would be bad.  */
28098944Sobrien  serial_flush_input (ocd_desc);
28146283Sdfr
28246283Sdfr  if (from_tty)
28346283Sdfr    {
28446283Sdfr      puts_filtered ("Remote target wiggler connected to ");
28546283Sdfr      puts_filtered (name);
28646283Sdfr      puts_filtered ("\n");
28746283Sdfr    }
28846283Sdfr  push_target (current_ops);	/* Switch to using remote target now */
28946283Sdfr
29046283Sdfr  /* Without this, some commands which require an active target (such as kill)
29146283Sdfr     won't work.  This variable serves (at least) double duty as both the pid
29246283Sdfr     of the target process (if it has such), and as a flag indicating that a
29346283Sdfr     target is active.  These functions should be split out into seperate
29446283Sdfr     variables, especially since GDB will someday have a notion of debugging
29546283Sdfr     several processes.  */
29646283Sdfr
29798944Sobrien  inferior_ptid = pid_to_ptid (42000);
29846283Sdfr  /* Start the remote connection; if error (0), discard this target.
29946283Sdfr     In particular, if the user quits, be sure to discard it
30046283Sdfr     (we'd be in an inconsistent state otherwise).  */
30146283Sdfr  if (!catch_errors (ocd_start_remote, &target_type,
30246283Sdfr		     "Couldn't establish connection to remote target\n",
30346283Sdfr		     RETURN_MASK_ALL))
30446283Sdfr    {
30598944Sobrien      pop_target ();
30646283Sdfr      error ("Failed to connect to OCD.");
30746283Sdfr    }
30846283Sdfr}
30946283Sdfr
31046283Sdfr/* This takes a program previously attached to and detaches it.  After
31146283Sdfr   this is done, GDB can be used to debug some other program.  We
31246283Sdfr   better not have left any breakpoints in the target program or it'll
31346283Sdfr   die when it hits one.  */
31446283Sdfr
31546283Sdfrvoid
31698944Sobrienocd_detach (char *args, int from_tty)
31746283Sdfr{
31846283Sdfr  if (args)
31946283Sdfr    error ("Argument given to \"detach\" when remotely debugging.");
32046283Sdfr
32146283Sdfr  pop_target ();
32246283Sdfr  if (from_tty)
32346283Sdfr    puts_filtered ("Ending remote debugging.\n");
32446283Sdfr}
32546283Sdfr
32646283Sdfr/* Tell the remote machine to resume.  */
32746283Sdfr
32846283Sdfrvoid
32998944Sobrienocd_resume (ptid_t ptid, int step, enum target_signal siggnal)
33046283Sdfr{
33146283Sdfr  int pktlen;
33246283Sdfr
33346283Sdfr  if (step)
33446283Sdfr    ocd_do_command (OCD_STEP, &last_run_status, &pktlen);
33546283Sdfr  else
33646283Sdfr    ocd_do_command (OCD_RUN, &last_run_status, &pktlen);
33746283Sdfr}
33846283Sdfr
33946283Sdfrvoid
34098944Sobrienocd_stop (void)
34146283Sdfr{
34246283Sdfr  int status;
34346283Sdfr  int pktlen;
34446283Sdfr
34546283Sdfr  ocd_do_command (OCD_STOP, &status, &pktlen);
34646283Sdfr
34746283Sdfr  if (!(status & OCD_FLAG_BDM))
34846283Sdfr    error ("Can't stop target via BDM");
34946283Sdfr}
35046283Sdfr
35146283Sdfrstatic volatile int ocd_interrupt_flag;
35246283Sdfr
35346283Sdfr/* Send ^C to target to halt it.  Target will respond, and send us a
35446283Sdfr   packet.  */
35546283Sdfr
35646283Sdfrstatic void
35798944Sobrienocd_interrupt (int signo)
35846283Sdfr{
35946283Sdfr  /* If this doesn't work, try more severe steps.  */
36046283Sdfr  signal (signo, ocd_interrupt_twice);
36198944Sobrien
36246283Sdfr  if (remote_debug)
36346283Sdfr    printf_unfiltered ("ocd_interrupt called\n");
36446283Sdfr
36546283Sdfr  {
36646283Sdfr    char buf[1];
36746283Sdfr
36846283Sdfr    ocd_stop ();
36946283Sdfr    buf[0] = OCD_AYT;
37046283Sdfr    ocd_put_packet (buf, 1);
37146283Sdfr    ocd_interrupt_flag = 1;
37246283Sdfr  }
37346283Sdfr}
37446283Sdfr
37598944Sobrienstatic void (*ofunc) ();
37646283Sdfr
37746283Sdfr/* The user typed ^C twice.  */
37846283Sdfrstatic void
37998944Sobrienocd_interrupt_twice (int signo)
38046283Sdfr{
38146283Sdfr  signal (signo, ofunc);
38298944Sobrien
38346283Sdfr  interrupt_query ();
38446283Sdfr
38546283Sdfr  signal (signo, ocd_interrupt);
38646283Sdfr}
38746283Sdfr
38846283Sdfr/* Ask the user what to do when an interrupt is received.  */
38946283Sdfr
39046283Sdfrstatic void
39198944Sobrieninterrupt_query (void)
39246283Sdfr{
39346283Sdfr  target_terminal_ours ();
39446283Sdfr
39546283Sdfr  if (query ("Interrupted while waiting for the program.\n\
39646283SdfrGive up (and stop debugging it)? "))
39746283Sdfr    {
39846283Sdfr      target_mourn_inferior ();
39998944Sobrien      throw_exception (RETURN_QUIT);
40046283Sdfr    }
40146283Sdfr
40246283Sdfr  target_terminal_inferior ();
40346283Sdfr}
40446283Sdfr
40546283Sdfr/* If nonzero, ignore the next kill.  */
40646283Sdfrstatic int kill_kludge;
40746283Sdfr
40846283Sdfr/* Wait until the remote machine stops, then return,
40946283Sdfr   storing status in STATUS just as `wait' would.
41046283Sdfr   Returns "pid" (though it's not clear what, if anything, that
41146283Sdfr   means in the case of this target).  */
41246283Sdfr
41346283Sdfrint
41498944Sobrienocd_wait (void)
41546283Sdfr{
41646283Sdfr  unsigned char *p;
41746283Sdfr  int error_code;
41846283Sdfr  int pktlen;
41946283Sdfr  char buf[1];
42046283Sdfr
42146283Sdfr  ocd_interrupt_flag = 0;
42246283Sdfr
42346283Sdfr  /* Target might already be stopped by the time we get here. */
42446283Sdfr  /* If we aren't already stopped, we need to loop until we've dropped
42546283Sdfr     back into BDM mode */
42646283Sdfr
42746283Sdfr  while (!(last_run_status & OCD_FLAG_BDM))
42846283Sdfr    {
42946283Sdfr      buf[0] = OCD_AYT;
43046283Sdfr      ocd_put_packet (buf, 1);
43146283Sdfr      p = ocd_get_packet (OCD_AYT, &pktlen, -1);
43246283Sdfr
43346283Sdfr      ofunc = (void (*)()) signal (SIGINT, ocd_interrupt);
43446283Sdfr      signal (SIGINT, ofunc);
43546283Sdfr
43646283Sdfr      if (pktlen < 2)
43746283Sdfr	error ("Truncated response packet from OCD device");
43846283Sdfr
43946283Sdfr      last_run_status = p[1];
44046283Sdfr      error_code = p[2];
44146283Sdfr
44246283Sdfr      if (error_code != 0)
44346283Sdfr	ocd_error ("target_wait:", error_code);
44446283Sdfr
44546283Sdfr      if (last_run_status & OCD_FLAG_PWF)
44646283Sdfr	error ("OCD device lost VCC at BDM interface.");
44746283Sdfr      else if (last_run_status & OCD_FLAG_CABLE_DISC)
44846283Sdfr	error ("OCD device cable appears to have been disconnected.");
44946283Sdfr    }
45046283Sdfr
45146283Sdfr  if (ocd_interrupt_flag)
45246283Sdfr    return 1;
45346283Sdfr  else
45446283Sdfr    return 0;
45546283Sdfr}
45646283Sdfr
45746283Sdfr/* Read registers from the OCD device.  Specify the starting and ending
45846283Sdfr   register number.  Return the number of regs actually read in *NUMREGS.
45946283Sdfr   Returns a pointer to a static array containing the register contents.  */
46046283Sdfr
46146283Sdfrunsigned char *
46298944Sobrienocd_read_bdm_registers (int first_bdm_regno, int last_bdm_regno, int *reglen)
46346283Sdfr{
46446283Sdfr  unsigned char buf[10];
46546283Sdfr  int i;
46646283Sdfr  unsigned char *p;
46746283Sdfr  unsigned char *regs;
46846283Sdfr  int error_code, status;
46946283Sdfr  int pktlen;
47046283Sdfr
47146283Sdfr  buf[0] = OCD_READ_REGS;
47246283Sdfr  buf[1] = first_bdm_regno >> 8;
47346283Sdfr  buf[2] = first_bdm_regno & 0xff;
47446283Sdfr  buf[3] = last_bdm_regno >> 8;
47546283Sdfr  buf[4] = last_bdm_regno & 0xff;
47646283Sdfr
47746283Sdfr  ocd_put_packet (buf, 5);
47846283Sdfr  p = ocd_get_packet (OCD_READ_REGS, &pktlen, remote_timeout);
47946283Sdfr
48046283Sdfr  status = p[1];
48146283Sdfr  error_code = p[2];
48246283Sdfr
48346283Sdfr  if (error_code != 0)
48446283Sdfr    ocd_error ("read_bdm_registers:", error_code);
48546283Sdfr
48646283Sdfr  i = p[3];
48746283Sdfr  if (i == 0)
48846283Sdfr    i = 256;
48946283Sdfr
49046283Sdfr  if (i > pktlen - 4
49146283Sdfr      || ((i & 3) != 0))
49246283Sdfr    error ("Register block size bad:  %d", i);
49346283Sdfr
49446283Sdfr  *reglen = i;
49546283Sdfr
49646283Sdfr  regs = p + 4;
49746283Sdfr
49846283Sdfr  return regs;
49946283Sdfr}
50046283Sdfr
50146283Sdfr/* Read register BDM_REGNO and returns its value ala read_register() */
50246283Sdfr
50346283SdfrCORE_ADDR
50498944Sobrienocd_read_bdm_register (int bdm_regno)
50546283Sdfr{
50646283Sdfr  int reglen;
50746283Sdfr  unsigned char *p;
50846283Sdfr  CORE_ADDR regval;
50946283Sdfr
51046283Sdfr  p = ocd_read_bdm_registers (bdm_regno, bdm_regno, &reglen);
51146283Sdfr  regval = extract_unsigned_integer (p, reglen);
51246283Sdfr
51346283Sdfr  return regval;
51446283Sdfr}
51546283Sdfr
51646283Sdfrvoid
51798944Sobrienocd_write_bdm_registers (int first_bdm_regno, unsigned char *regptr, int reglen)
51846283Sdfr{
51946283Sdfr  unsigned char *buf;
52046283Sdfr  unsigned char *p;
52146283Sdfr  int error_code, status;
52246283Sdfr  int pktlen;
52346283Sdfr
52446283Sdfr  buf = alloca (4 + reglen);
52546283Sdfr
52646283Sdfr  buf[0] = OCD_WRITE_REGS;
52746283Sdfr  buf[1] = first_bdm_regno >> 8;
52846283Sdfr  buf[2] = first_bdm_regno & 0xff;
52946283Sdfr  buf[3] = reglen;
53046283Sdfr  memcpy (buf + 4, regptr, reglen);
53146283Sdfr
53246283Sdfr  ocd_put_packet (buf, 4 + reglen);
53346283Sdfr  p = ocd_get_packet (OCD_WRITE_REGS, &pktlen, remote_timeout);
53446283Sdfr
53546283Sdfr  if (pktlen < 3)
53646283Sdfr    error ("Truncated response packet from OCD device");
53746283Sdfr
53846283Sdfr  status = p[1];
53946283Sdfr  error_code = p[2];
54046283Sdfr
54146283Sdfr  if (error_code != 0)
54246283Sdfr    ocd_error ("ocd_write_bdm_registers:", error_code);
54346283Sdfr}
54446283Sdfr
54546283Sdfrvoid
54698944Sobrienocd_write_bdm_register (int bdm_regno, CORE_ADDR reg)
54746283Sdfr{
54846283Sdfr  unsigned char buf[4];
54946283Sdfr
55046283Sdfr  store_unsigned_integer (buf, 4, reg);
55146283Sdfr
55246283Sdfr  ocd_write_bdm_registers (bdm_regno, buf, 4);
55346283Sdfr}
55446283Sdfr
55598944Sobrienvoid
55698944Sobrienocd_prepare_to_store (void)
55746283Sdfr{
55846283Sdfr}
55946283Sdfr
56046283Sdfr/* Write memory data directly to the remote machine.
56146283Sdfr   This does not inform the data cache; the data cache uses this.
56246283Sdfr   MEMADDR is the address in the remote memory space.
56346283Sdfr   MYADDR is the address of the buffer in our space.
56446283Sdfr   LEN is the number of bytes.
56546283Sdfr
56646283Sdfr   Returns number of bytes transferred, or 0 for error.  */
56746283Sdfr
56846283Sdfrstatic int write_mem_command = OCD_WRITE_MEM;
56946283Sdfr
57046283Sdfrint
57198944Sobrienocd_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
57246283Sdfr{
57346283Sdfr  char buf[256 + 10];
57446283Sdfr  unsigned char *p;
57546283Sdfr  int origlen;
57646283Sdfr
57746283Sdfr  origlen = len;
57846283Sdfr
57946283Sdfr  buf[0] = write_mem_command;
58046283Sdfr  buf[5] = 1;			/* Write as bytes */
58146283Sdfr  buf[6] = 0;			/* Don't verify */
58246283Sdfr
58346283Sdfr  while (len > 0)
58446283Sdfr    {
58546283Sdfr      int numbytes;
58646283Sdfr      int pktlen;
58746283Sdfr      int status, error_code;
58846283Sdfr
58946283Sdfr      numbytes = min (len, 256 - 8);
59046283Sdfr
59146283Sdfr      buf[1] = memaddr >> 24;
59246283Sdfr      buf[2] = memaddr >> 16;
59346283Sdfr      buf[3] = memaddr >> 8;
59446283Sdfr      buf[4] = memaddr;
59546283Sdfr
59646283Sdfr      buf[7] = numbytes;
59746283Sdfr
59846283Sdfr      memcpy (&buf[8], myaddr, numbytes);
59946283Sdfr      ocd_put_packet (buf, 8 + numbytes);
60046283Sdfr      p = ocd_get_packet (OCD_WRITE_MEM, &pktlen, remote_timeout);
60146283Sdfr      if (pktlen < 3)
60246283Sdfr	error ("Truncated response packet from OCD device");
60346283Sdfr
60446283Sdfr      status = p[1];
60546283Sdfr      error_code = p[2];
60646283Sdfr
60746283Sdfr      if (error_code == 0x11)	/* Got a bus error? */
60846283Sdfr	{
60946283Sdfr	  CORE_ADDR error_address;
61046283Sdfr
61146283Sdfr	  error_address = p[3] << 24;
61246283Sdfr	  error_address |= p[4] << 16;
61346283Sdfr	  error_address |= p[5] << 8;
61446283Sdfr	  error_address |= p[6];
61546283Sdfr	  numbytes = error_address - memaddr;
61646283Sdfr
61746283Sdfr	  len -= numbytes;
61846283Sdfr
61946283Sdfr	  errno = EIO;
62046283Sdfr
62146283Sdfr	  break;
62246283Sdfr	}
62346283Sdfr      else if (error_code != 0)
62446283Sdfr	ocd_error ("ocd_write_bytes:", error_code);
62546283Sdfr
62646283Sdfr      len -= numbytes;
62746283Sdfr      memaddr += numbytes;
62846283Sdfr      myaddr += numbytes;
62946283Sdfr    }
63046283Sdfr
63146283Sdfr  return origlen - len;
63246283Sdfr}
63346283Sdfr
63446283Sdfr/* Read memory data directly from the remote machine.
63546283Sdfr   This does not use the data cache; the data cache uses this.
63646283Sdfr   MEMADDR is the address in the remote memory space.
63746283Sdfr   MYADDR is the address of the buffer in our space.
63846283Sdfr   LEN is the number of bytes.
63946283Sdfr
64046283Sdfr   Returns number of bytes transferred, or 0 for error.  */
64146283Sdfr
64246283Sdfrstatic int
64398944Sobrienocd_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
64446283Sdfr{
64546283Sdfr  char buf[256 + 10];
64646283Sdfr  unsigned char *p;
64746283Sdfr  int origlen;
64846283Sdfr
64946283Sdfr  origlen = len;
65046283Sdfr
65146283Sdfr  buf[0] = OCD_READ_MEM;
65246283Sdfr  buf[5] = 1;			/* Read as bytes */
65346283Sdfr
65446283Sdfr  while (len > 0)
65546283Sdfr    {
65646283Sdfr      int numbytes;
65746283Sdfr      int pktlen;
65846283Sdfr      int status, error_code;
65946283Sdfr
66046283Sdfr      numbytes = min (len, 256 - 7);
66146283Sdfr
66246283Sdfr      buf[1] = memaddr >> 24;
66346283Sdfr      buf[2] = memaddr >> 16;
66446283Sdfr      buf[3] = memaddr >> 8;
66546283Sdfr      buf[4] = memaddr;
66646283Sdfr
66746283Sdfr      buf[6] = numbytes;
66846283Sdfr
66946283Sdfr      ocd_put_packet (buf, 7);
67046283Sdfr      p = ocd_get_packet (OCD_READ_MEM, &pktlen, remote_timeout);
67146283Sdfr      if (pktlen < 4)
67246283Sdfr	error ("Truncated response packet from OCD device");
67346283Sdfr
67446283Sdfr      status = p[1];
67546283Sdfr      error_code = p[2];
67646283Sdfr
67746283Sdfr      if (error_code == 0x11)	/* Got a bus error? */
67846283Sdfr	{
67946283Sdfr	  CORE_ADDR error_address;
68046283Sdfr
68146283Sdfr	  error_address = p[3] << 24;
68246283Sdfr	  error_address |= p[4] << 16;
68346283Sdfr	  error_address |= p[5] << 8;
68446283Sdfr	  error_address |= p[6];
68546283Sdfr	  numbytes = error_address - memaddr;
68646283Sdfr
68746283Sdfr	  len -= numbytes;
68846283Sdfr
68946283Sdfr	  errno = EIO;
69046283Sdfr
69146283Sdfr	  break;
69246283Sdfr	}
69346283Sdfr      else if (error_code != 0)
69446283Sdfr	ocd_error ("ocd_read_bytes:", error_code);
69546283Sdfr
69646283Sdfr      memcpy (myaddr, &p[4], numbytes);
69746283Sdfr
69846283Sdfr      len -= numbytes;
69946283Sdfr      memaddr += numbytes;
70046283Sdfr      myaddr += numbytes;
70146283Sdfr    }
70246283Sdfr
70346283Sdfr  return origlen - len;
70446283Sdfr}
70546283Sdfr
70646283Sdfr/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
70746283Sdfr   to or from debugger address MYADDR.  Write to inferior if SHOULD_WRITE is
70898944Sobrien   nonzero.  Returns length of data written or read; 0 for error.  TARGET
70998944Sobrien   is ignored.  */
71046283Sdfr
71146283Sdfrint
71298944Sobrienocd_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write,
71398944Sobrien		 struct mem_attrib *attrib, struct target_ops *target)
71446283Sdfr{
71598944Sobrien  int res;
71698944Sobrien
71798944Sobrien  if (should_write)
71898944Sobrien    res = ocd_write_bytes (memaddr, myaddr, len);
71998944Sobrien  else
72098944Sobrien    res = ocd_read_bytes (memaddr, myaddr, len);
72198944Sobrien
72298944Sobrien  return res;
72346283Sdfr}
72446283Sdfr
72546283Sdfrvoid
72698944Sobrienocd_files_info (struct target_ops *ignore)
72746283Sdfr{
72846283Sdfr  puts_filtered ("Debugging a target over a serial line.\n");
72946283Sdfr}
73046283Sdfr
73146283Sdfr/* Stuff for dealing with the packets which are part of this protocol.
73246283Sdfr   See comment at top of file for details.  */
73346283Sdfr
73446283Sdfr/* Read a single character from the remote side, handling wierd errors. */
73546283Sdfr
73646283Sdfrstatic int
73798944Sobrienreadchar (int timeout)
73846283Sdfr{
73946283Sdfr  int ch;
74046283Sdfr
74198944Sobrien  ch = serial_readchar (ocd_desc, timeout);
74246283Sdfr
74346283Sdfr  switch (ch)
74446283Sdfr    {
74546283Sdfr    case SERIAL_EOF:
74646283Sdfr      error ("Remote connection closed");
74746283Sdfr    case SERIAL_ERROR:
74846283Sdfr      perror_with_name ("Remote communication error");
74946283Sdfr    case SERIAL_TIMEOUT:
75046283Sdfr    default:
75146283Sdfr      return ch;
75246283Sdfr    }
75346283Sdfr}
75446283Sdfr
75546283Sdfr/* Send a packet to the OCD device.  The packet framed by a SYN character,
75646283Sdfr   a byte count and a checksum.  The byte count only counts the number of
75746283Sdfr   bytes between the count and the checksum.  A count of zero actually
75846283Sdfr   means 256.  Any SYNs within the packet (including the checksum and
75946283Sdfr   count) must be quoted.  The quote character must be quoted as well.
76046283Sdfr   Quoting is done by replacing the character with the two-character sequence
76146283Sdfr   DLE, {char} | 0100.  Note that the quoting mechanism has no effect on the
76246283Sdfr   byte count.  */
76346283Sdfr
76446283Sdfrstatic void
76598944Sobrienocd_put_packet (unsigned char *buf, int len)
76646283Sdfr{
76746283Sdfr  unsigned char checksum;
76846283Sdfr  unsigned char c;
76946283Sdfr  unsigned char *packet, *packet_ptr;
77046283Sdfr
77198944Sobrien  packet = alloca (len + 1 + 1);	/* packet + SYN + checksum */
77246283Sdfr  packet_ptr = packet;
77346283Sdfr
77446283Sdfr  checksum = 0;
77546283Sdfr
77646283Sdfr  *packet_ptr++ = 0x55;
77746283Sdfr
77846283Sdfr  while (len-- > 0)
77946283Sdfr    {
78046283Sdfr      c = *buf++;
78146283Sdfr
78246283Sdfr      checksum += c;
78346283Sdfr      *packet_ptr++ = c;
78446283Sdfr    }
78546283Sdfr
78646283Sdfr  *packet_ptr++ = -checksum;
78798944Sobrien  if (serial_write (ocd_desc, packet, packet_ptr - packet))
78846283Sdfr    perror_with_name ("output_packet: write failed");
78946283Sdfr}
79046283Sdfr
79146283Sdfr/* Get a packet from the OCD device.  Timeout is only enforced for the
79246283Sdfr   first byte of the packet.  Subsequent bytes are expected to arrive in
79346283Sdfr   time <= remote_timeout.  Returns a pointer to a static buffer containing
79446283Sdfr   the payload of the packet.  *LENP contains the length of the packet.
79598944Sobrien */
79646283Sdfr
79746283Sdfrstatic unsigned char *
79898944Sobrienocd_get_packet (int cmd, int *lenp, int timeout)
79946283Sdfr{
80046283Sdfr  int ch;
80146283Sdfr  int len;
80246283Sdfr  static unsigned char packet[512];
80346283Sdfr  unsigned char *packet_ptr;
80446283Sdfr  unsigned char checksum;
80546283Sdfr
80646283Sdfr  ch = readchar (timeout);
80746283Sdfr
80846283Sdfr  if (ch < 0)
80946283Sdfr    error ("ocd_get_packet (readchar): %d", ch);
81046283Sdfr
81146283Sdfr  if (ch != 0x55)
81246283Sdfr    error ("ocd_get_packet (readchar): %d", ch);
81346283Sdfr
81446283Sdfr/* Found the start of a packet */
81546283Sdfr
81646283Sdfr  packet_ptr = packet;
81746283Sdfr  checksum = 0;
81846283Sdfr
81946283Sdfr/* Read command char.  That sort of tells us how long the packet is. */
82046283Sdfr
82146283Sdfr  ch = readchar (timeout);
82246283Sdfr
82346283Sdfr  if (ch < 0)
82446283Sdfr    error ("ocd_get_packet (readchar): %d", ch);
82546283Sdfr
82646283Sdfr  *packet_ptr++ = ch;
82746283Sdfr  checksum += ch;
82846283Sdfr
82946283Sdfr/* Get status. */
83046283Sdfr
83146283Sdfr  ch = readchar (timeout);
83246283Sdfr
83346283Sdfr  if (ch < 0)
83446283Sdfr    error ("ocd_get_packet (readchar): %d", ch);
83546283Sdfr  *packet_ptr++ = ch;
83646283Sdfr  checksum += ch;
83746283Sdfr
83846283Sdfr/* Get error code. */
83946283Sdfr
84046283Sdfr  ch = readchar (timeout);
84146283Sdfr
84246283Sdfr  if (ch < 0)
84346283Sdfr    error ("ocd_get_packet (readchar): %d", ch);
84446283Sdfr  *packet_ptr++ = ch;
84546283Sdfr  checksum += ch;
84646283Sdfr
84746283Sdfr  switch (ch)			/* Figure out length of packet */
84846283Sdfr    {
84946283Sdfr    case 0x7:			/* Write verify error? */
85046283Sdfr      len = 8;			/* write address, value read back */
85146283Sdfr      break;
85246283Sdfr    case 0x11:			/* Bus error? */
85398944Sobrien      /* write address, read flag */
85446283Sdfr    case 0x15:			/* Internal error */
85546283Sdfr      len = 5;			/* error code, vector */
85646283Sdfr      break;
85746283Sdfr    default:			/* Error w/no params */
85846283Sdfr      len = 0;
85946283Sdfr      break;
86046283Sdfr    case 0x0:			/* Normal result */
86146283Sdfr      switch (packet[0])
86246283Sdfr	{
86398944Sobrien	case OCD_AYT:		/* Are You There? */
86498944Sobrien	case OCD_SET_BAUD_RATE:	/* Set Baud Rate */
86598944Sobrien	case OCD_INIT:		/* Initialize OCD device */
86646283Sdfr	case OCD_SET_SPEED:	/* Set Speed */
86798944Sobrien	case OCD_SET_FUNC_CODE:	/* Set Function Code */
86898944Sobrien	case OCD_SET_CTL_FLAGS:	/* Set Control Flags */
86998944Sobrien	case OCD_SET_BUF_ADDR:	/* Set Register Buffer Address */
87098944Sobrien	case OCD_RUN:		/* Run Target from PC  */
87146283Sdfr	case OCD_RUN_ADDR:	/* Run Target from Specified Address  */
87298944Sobrien	case OCD_STOP:		/* Stop Target */
87346283Sdfr	case OCD_RESET_RUN:	/* Reset Target and Run */
87446283Sdfr	case OCD_RESET:	/* Reset Target and Halt */
87598944Sobrien	case OCD_STEP:		/* Single Step */
87698944Sobrien	case OCD_WRITE_REGS:	/* Write Register */
87746283Sdfr	case OCD_WRITE_MEM:	/* Write Memory */
87846283Sdfr	case OCD_FILL_MEM:	/* Fill Memory */
87946283Sdfr	case OCD_MOVE_MEM:	/* Move Memory */
88098944Sobrien	case OCD_WRITE_INT_MEM:	/* Write Internal Memory */
88198944Sobrien	case OCD_JUMP:		/* Jump to Subroutine */
88298944Sobrien	case OCD_ERASE_FLASH:	/* Erase flash memory */
88398944Sobrien	case OCD_PROGRAM_FLASH:	/* Write flash memory */
88446283Sdfr	case OCD_EXIT_MON:	/* Exit the flash programming monitor  */
88546283Sdfr	case OCD_ENTER_MON:	/* Enter the flash programming monitor  */
88646283Sdfr	case OCD_LOG_FILE:	/* Make Wigglers.dll save Wigglers.log */
88798944Sobrien	case OCD_SET_CONNECTION:	/* Set type of connection in Wigglers.dll */
88846283Sdfr	  len = 0;
88946283Sdfr	  break;
89098944Sobrien	case OCD_GET_VERSION:	/* Get Version */
89146283Sdfr	  len = 10;
89246283Sdfr	  break;
89398944Sobrien	case OCD_GET_STATUS_MASK:	/* Get Status Mask */
89446283Sdfr	  len = 1;
89546283Sdfr	  break;
89646283Sdfr	case OCD_GET_CTRS:	/* Get Error Counters */
89746283Sdfr	case OCD_READ_REGS:	/* Read Register */
89846283Sdfr	case OCD_READ_MEM:	/* Read Memory */
89998944Sobrien	case OCD_READ_INT_MEM:	/* Read Internal Memory */
90046283Sdfr	  len = 257;
90146283Sdfr	  break;
90246283Sdfr	default:
90346283Sdfr	  error ("ocd_get_packet: unknown packet type 0x%x\n", ch);
90446283Sdfr	}
90546283Sdfr    }
90646283Sdfr
90746283Sdfr  if (len == 257)		/* Byte stream? */
90846283Sdfr    {				/* Yes, byte streams contain the length */
90946283Sdfr      ch = readchar (timeout);
91046283Sdfr
91146283Sdfr      if (ch < 0)
91246283Sdfr	error ("ocd_get_packet (readchar): %d", ch);
91346283Sdfr      *packet_ptr++ = ch;
91446283Sdfr      checksum += ch;
91546283Sdfr      len = ch;
91646283Sdfr      if (len == 0)
91746283Sdfr	len = 256;
91846283Sdfr    }
91946283Sdfr
92046283Sdfr  while (len-- >= 0)		/* Do rest of packet and checksum */
92146283Sdfr    {
92246283Sdfr      ch = readchar (timeout);
92346283Sdfr
92446283Sdfr      if (ch < 0)
92546283Sdfr	error ("ocd_get_packet (readchar): %d", ch);
92646283Sdfr      *packet_ptr++ = ch;
92746283Sdfr      checksum += ch;
92846283Sdfr    }
92946283Sdfr
93046283Sdfr  if (checksum != 0)
93146283Sdfr    error ("ocd_get_packet: bad packet checksum");
93246283Sdfr
93346283Sdfr  if (cmd != -1 && cmd != packet[0])
93446283Sdfr    error ("Response phase error.  Got 0x%x, expected 0x%x", packet[0], cmd);
93546283Sdfr
93698944Sobrien  *lenp = packet_ptr - packet - 1;	/* Subtract checksum byte */
93746283Sdfr  return packet;
93846283Sdfr}
93946283Sdfr
94046283Sdfr/* Execute a simple (one-byte) command.  Returns a pointer to the data
94146283Sdfr   following the error code.  */
94246283Sdfr
94346283Sdfrstatic unsigned char *
94498944Sobrienocd_do_command (int cmd, int *statusp, int *lenp)
94546283Sdfr{
94646283Sdfr  unsigned char buf[100], *p;
94746283Sdfr  int status, error_code;
94846283Sdfr  char errbuf[100];
94946283Sdfr
95046283Sdfr  unsigned char logbuf[100];
95146283Sdfr  int logpktlen;
95246283Sdfr
95346283Sdfr  buf[0] = cmd;
95498944Sobrien  ocd_put_packet (buf, 1);	/* Send command */
95546283Sdfr  p = ocd_get_packet (*buf, lenp, remote_timeout);
95646283Sdfr
95746283Sdfr  if (*lenp < 3)
95846283Sdfr    error ("Truncated response packet from OCD device");
95946283Sdfr
96046283Sdfr  status = p[1];
96146283Sdfr  error_code = p[2];
96246283Sdfr
96346283Sdfr  if (error_code != 0)
96446283Sdfr    {
96546283Sdfr      sprintf (errbuf, "ocd_do_command (0x%x):", cmd);
96646283Sdfr      ocd_error (errbuf, error_code);
96746283Sdfr    }
96846283Sdfr
96946283Sdfr  if (status & OCD_FLAG_PWF)
97046283Sdfr    error ("OCD device can't detect VCC at BDM interface.");
97146283Sdfr  else if (status & OCD_FLAG_CABLE_DISC)
97246283Sdfr    error ("BDM cable appears to be disconnected.");
97346283Sdfr
97446283Sdfr  *statusp = status;
97546283Sdfr
97646283Sdfr  logbuf[0] = OCD_LOG_FILE;
97798944Sobrien  logbuf[1] = 3;		/* close existing WIGGLERS.LOG */
97846283Sdfr  ocd_put_packet (logbuf, 2);
97946283Sdfr  ocd_get_packet (logbuf[0], &logpktlen, remote_timeout);
98046283Sdfr
98146283Sdfr  logbuf[0] = OCD_LOG_FILE;
98298944Sobrien  logbuf[1] = 2;		/* append to existing WIGGLERS.LOG */
98346283Sdfr  ocd_put_packet (logbuf, 2);
98446283Sdfr  ocd_get_packet (logbuf[0], &logpktlen, remote_timeout);
98546283Sdfr
98646283Sdfr  return p + 3;
98746283Sdfr}
98846283Sdfr
98946283Sdfrvoid
99098944Sobrienocd_kill (void)
99146283Sdfr{
99246283Sdfr  /* For some mysterious reason, wait_for_inferior calls kill instead of
99346283Sdfr     mourn after it gets TARGET_WAITKIND_SIGNALLED.  Work around it.  */
99446283Sdfr  if (kill_kludge)
99546283Sdfr    {
99646283Sdfr      kill_kludge = 0;
99746283Sdfr      target_mourn_inferior ();
99846283Sdfr      return;
99946283Sdfr    }
100046283Sdfr
100146283Sdfr  /* Don't wait for it to die.  I'm not really sure it matters whether
100246283Sdfr     we do or not.  */
100346283Sdfr  target_mourn_inferior ();
100446283Sdfr}
100546283Sdfr
100646283Sdfrvoid
100798944Sobrienocd_mourn (void)
100846283Sdfr{
100946283Sdfr  unpush_target (current_ops);
101046283Sdfr  generic_mourn_inferior ();
101146283Sdfr}
101246283Sdfr
101346283Sdfr/* All we actually do is set the PC to the start address of exec_bfd, and start
101446283Sdfr   the program at that point.  */
101546283Sdfr
101646283Sdfrvoid
101798944Sobrienocd_create_inferior (char *exec_file, char *args, char **env)
101846283Sdfr{
101946283Sdfr  if (args && (*args != '\000'))
102046283Sdfr    error ("Args are not supported by BDM.");
102146283Sdfr
102246283Sdfr  clear_proceed_status ();
102346283Sdfr  proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
102446283Sdfr}
102546283Sdfr
102646283Sdfrvoid
102798944Sobrienocd_load (char *args, int from_tty)
102846283Sdfr{
102946283Sdfr  generic_load (args, from_tty);
103046283Sdfr
103198944Sobrien  inferior_ptid = null_ptid;
103246283Sdfr
103346283Sdfr/* This is necessary because many things were based on the PC at the time that
103446283Sdfr   we attached to the monitor, which is no longer valid now that we have loaded
103546283Sdfr   new code (and just changed the PC).  Another way to do this might be to call
103646283Sdfr   normal_stop, except that the stack may not be valid, and things would get
103746283Sdfr   horribly confused... */
103846283Sdfr
103946283Sdfr  clear_symtab_users ();
104046283Sdfr}
104146283Sdfr
104246283Sdfr/* This should be defined for each target */
104346283Sdfr/* But we want to be able to compile this file for some configurations
104446283Sdfr   not yet supported fully */
104598944Sobrien
104698944Sobrien#define BDM_BREAKPOINT {0x0,0x0,0x0,0x0}	/* For ppc 8xx */
104746283Sdfr
104846283Sdfr/* BDM (at least on CPU32) uses a different breakpoint */
104946283Sdfr
105046283Sdfrint
105198944Sobrienocd_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
105246283Sdfr{
105346283Sdfr  static char break_insn[] = BDM_BREAKPOINT;
105446283Sdfr  int val;
105546283Sdfr
105646283Sdfr  val = target_read_memory (addr, contents_cache, sizeof (break_insn));
105746283Sdfr
105846283Sdfr  if (val == 0)
105946283Sdfr    val = target_write_memory (addr, break_insn, sizeof (break_insn));
106046283Sdfr
106146283Sdfr  return val;
106246283Sdfr}
106346283Sdfr
106446283Sdfrint
106598944Sobrienocd_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
106646283Sdfr{
106746283Sdfr  static char break_insn[] = BDM_BREAKPOINT;
106846283Sdfr  int val;
106946283Sdfr
107046283Sdfr  val = target_write_memory (addr, contents_cache, sizeof (break_insn));
107146283Sdfr
107246283Sdfr  return val;
107346283Sdfr}
107446283Sdfr
107546283Sdfrstatic void
107698944Sobrienbdm_command (char *args, int from_tty)
107746283Sdfr{
107846283Sdfr  error ("bdm command must be followed by `reset'");
107946283Sdfr}
108046283Sdfr
108146283Sdfrstatic void
108298944Sobrienbdm_reset_command (char *args, int from_tty)
108346283Sdfr{
108446283Sdfr  int status, pktlen;
108546283Sdfr
108646283Sdfr  if (!ocd_desc)
108746283Sdfr    error ("Not connected to OCD device.");
108846283Sdfr
108946283Sdfr  ocd_do_command (OCD_RESET, &status, &pktlen);
109098944Sobrien  dcache_invalidate (target_dcache);
109146283Sdfr  registers_changed ();
109246283Sdfr}
109346283Sdfr
109446283Sdfrstatic void
109598944Sobrienbdm_restart_command (char *args, int from_tty)
109646283Sdfr{
109746283Sdfr  int status, pktlen;
109846283Sdfr
109946283Sdfr  if (!ocd_desc)
110046283Sdfr    error ("Not connected to OCD device.");
110146283Sdfr
110246283Sdfr  ocd_do_command (OCD_RESET_RUN, &status, &pktlen);
110346283Sdfr  last_run_status = status;
110446283Sdfr  clear_proceed_status ();
110546283Sdfr  wait_for_inferior ();
110646283Sdfr  normal_stop ();
110746283Sdfr}
110846283Sdfr
110946283Sdfr/* Temporary replacement for target_store_registers().  This prevents
111046283Sdfr   generic_load from trying to set the PC.  */
111146283Sdfr
111246283Sdfrstatic void
111398944Sobriennoop_store_registers (int regno)
111446283Sdfr{
111546283Sdfr}
111646283Sdfr
111746283Sdfrstatic void
111898944Sobrienbdm_update_flash_command (char *args, int from_tty)
111946283Sdfr{
112046283Sdfr  int status, pktlen;
112198944Sobrien  struct cleanup *old_chain;
112298944Sobrien  void (*store_registers_tmp) (int);
112346283Sdfr
112446283Sdfr  if (!ocd_desc)
112546283Sdfr    error ("Not connected to OCD device.");
112646283Sdfr
112746283Sdfr  if (!args)
112846283Sdfr    error ("Must specify file containing new OCD code.");
112946283Sdfr
113098944Sobrien/*  old_chain = make_cleanup (flash_cleanup, 0); */
113146283Sdfr
113246283Sdfr  ocd_do_command (OCD_ENTER_MON, &status, &pktlen);
113346283Sdfr
113446283Sdfr  ocd_do_command (OCD_ERASE_FLASH, &status, &pktlen);
113546283Sdfr
113646283Sdfr  write_mem_command = OCD_PROGRAM_FLASH;
113746283Sdfr  store_registers_tmp = current_target.to_store_registers;
113846283Sdfr  current_target.to_store_registers = noop_store_registers;
113946283Sdfr
114046283Sdfr  generic_load (args, from_tty);
114146283Sdfr
114246283Sdfr  current_target.to_store_registers = store_registers_tmp;
114346283Sdfr  write_mem_command = OCD_WRITE_MEM;
114446283Sdfr
114546283Sdfr  ocd_do_command (OCD_EXIT_MON, &status, &pktlen);
114646283Sdfr
114798944Sobrien/*  discard_cleanups (old_chain); */
114846283Sdfr}
1149130803Smarcel
1150130803Smarcelextern initialize_file_ftype _initialize_remote_ocd; /* -Wmissing-prototypes */
115146283Sdfr
115246283Sdfrvoid
115398944Sobrien_initialize_remote_ocd (void)
115446283Sdfr{
115546283Sdfr  extern struct cmd_list_element *cmdlist;
115646283Sdfr  static struct cmd_list_element *ocd_cmd_list = NULL;
115746283Sdfr
115846283Sdfr  add_show_from_set (add_set_cmd ("remotetimeout", no_class,
115998944Sobrien				  var_integer, (char *) &remote_timeout,
116098944Sobrien			  "Set timeout value for remote read.\n", &setlist),
116146283Sdfr		     &showlist);
116246283Sdfr
116346283Sdfr  add_prefix_cmd ("ocd", class_obscure, bdm_command, "", &ocd_cmd_list, "ocd ",
116446283Sdfr		  0, &cmdlist);
116546283Sdfr
116646283Sdfr  add_cmd ("reset", class_obscure, bdm_reset_command, "", &ocd_cmd_list);
116746283Sdfr  add_cmd ("restart", class_obscure, bdm_restart_command, "", &ocd_cmd_list);
116846283Sdfr  add_cmd ("update-flash", class_obscure, bdm_update_flash_command, "", &ocd_cmd_list);
116946283Sdfr}
1170