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, ®len); 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