1130812Smarcel/* Remote target communications for serial-line targets using SDS' protocol. 2130812Smarcel 3130812Smarcel Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2004 Free Software 4130812Smarcel Foundation, Inc. 5130812Smarcel 6130812Smarcel This file is part of GDB. 7130812Smarcel 8130812Smarcel This program is free software; you can redistribute it and/or modify 9130812Smarcel it under the terms of the GNU General Public License as published by 10130812Smarcel the Free Software Foundation; either version 2 of the License, or 11130812Smarcel (at your option) any later version. 12130812Smarcel 13130812Smarcel This program is distributed in the hope that it will be useful, 14130812Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 15130812Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130812Smarcel GNU General Public License for more details. 17130812Smarcel 18130812Smarcel You should have received a copy of the GNU General Public License 19130812Smarcel along with this program; if not, write to the Free Software 20130812Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 21130812Smarcel Boston, MA 02111-1307, USA. */ 22130812Smarcel 23130812Smarcel/* This interface was written by studying the behavior of the SDS 24130812Smarcel monitor on an ADS 821/860 board, and by consulting the 25130812Smarcel documentation of the monitor that is available on Motorola's web 26130812Smarcel site. -sts 8/13/97 */ 27130812Smarcel 28130812Smarcel#include "defs.h" 29130812Smarcel#include "gdb_string.h" 30130812Smarcel#include <fcntl.h> 31130812Smarcel#include "frame.h" 32130812Smarcel#include "inferior.h" 33130812Smarcel#include "bfd.h" 34130812Smarcel#include "symfile.h" 35130812Smarcel#include "target.h" 36130812Smarcel#include "gdbcmd.h" 37130812Smarcel#include "objfiles.h" 38130812Smarcel#include "gdb-stabs.h" 39130812Smarcel#include "gdbthread.h" 40130812Smarcel#include "gdbcore.h" 41130812Smarcel#include "regcache.h" 42130812Smarcel 43130812Smarcel#ifdef USG 44130812Smarcel#include <sys/types.h> 45130812Smarcel#endif 46130812Smarcel 47130812Smarcel#include <signal.h> 48130812Smarcel#include "serial.h" 49130812Smarcel 50130812Smarcelextern void _initialize_remote_sds (void); 51130812Smarcel 52130812Smarcel/* Declarations of local functions. */ 53130812Smarcel 54130812Smarcelstatic int sds_write_bytes (CORE_ADDR, char *, int); 55130812Smarcel 56130812Smarcelstatic int sds_read_bytes (CORE_ADDR, char *, int); 57130812Smarcel 58130812Smarcelstatic void sds_files_info (struct target_ops *ignore); 59130812Smarcel 60130812Smarcelstatic int sds_xfer_memory (CORE_ADDR, char *, int, int, 61130812Smarcel struct mem_attrib *, struct target_ops *); 62130812Smarcel 63130812Smarcelstatic void sds_prepare_to_store (void); 64130812Smarcel 65130812Smarcelstatic void sds_fetch_registers (int); 66130812Smarcel 67130812Smarcelstatic void sds_resume (ptid_t, int, enum target_signal); 68130812Smarcel 69130812Smarcelstatic int sds_start_remote (void *); 70130812Smarcel 71130812Smarcelstatic void sds_open (char *, int); 72130812Smarcel 73130812Smarcelstatic void sds_close (int); 74130812Smarcel 75130812Smarcelstatic void sds_store_registers (int); 76130812Smarcel 77130812Smarcelstatic void sds_mourn (void); 78130812Smarcel 79130812Smarcelstatic void sds_create_inferior (char *, char *, char **); 80130812Smarcel 81130812Smarcelstatic void sds_load (char *, int); 82130812Smarcel 83130812Smarcelstatic int getmessage (unsigned char *, int); 84130812Smarcel 85130812Smarcelstatic int putmessage (unsigned char *, int); 86130812Smarcel 87130812Smarcelstatic int sds_send (unsigned char *, int); 88130812Smarcel 89130812Smarcelstatic int readchar (int); 90130812Smarcel 91130812Smarcelstatic ptid_t sds_wait (ptid_t, struct target_waitstatus *); 92130812Smarcel 93130812Smarcelstatic void sds_kill (void); 94130812Smarcel 95130812Smarcelstatic int fromhex (int); 96130812Smarcel 97130812Smarcelstatic void sds_detach (char *, int); 98130812Smarcel 99130812Smarcelstatic void sds_interrupt (int); 100130812Smarcel 101130812Smarcelstatic void sds_interrupt_twice (int); 102130812Smarcel 103130812Smarcelstatic void interrupt_query (void); 104130812Smarcel 105130812Smarcelstatic int read_frame (char *); 106130812Smarcel 107130812Smarcelstatic int sds_insert_breakpoint (CORE_ADDR, char *); 108130812Smarcel 109130812Smarcelstatic int sds_remove_breakpoint (CORE_ADDR, char *); 110130812Smarcel 111130812Smarcelstatic void init_sds_ops (void); 112130812Smarcel 113130812Smarcelstatic void sds_command (char *args, int from_tty); 114130812Smarcel 115130812Smarcel/* Define the target operations vector. */ 116130812Smarcel 117130812Smarcelstatic struct target_ops sds_ops; 118130812Smarcel 119130812Smarcel/* This was 5 seconds, which is a long time to sit and wait. 120130812Smarcel Unless this is going though some terminal server or multiplexer or 121130812Smarcel other form of hairy serial connection, I would think 2 seconds would 122130812Smarcel be plenty. */ 123130812Smarcel 124130812Smarcelstatic int sds_timeout = 2; 125130812Smarcel 126130812Smarcel/* Descriptor for I/O to remote machine. Initialize it to NULL so 127130812Smarcel that sds_open knows that we don't have a file open when the program 128130812Smarcel starts. */ 129130812Smarcel 130130812Smarcelstatic struct serial *sds_desc = NULL; 131130812Smarcel 132130812Smarcel/* This limit comes from the monitor. */ 133130812Smarcel 134130812Smarcel#define PBUFSIZ 250 135130812Smarcel 136130812Smarcel/* Maximum number of bytes to read/write at once. The value here 137130812Smarcel is chosen to fill up a packet (the headers account for the 32). */ 138130812Smarcel#define MAXBUFBYTES ((PBUFSIZ-32)/2) 139130812Smarcel 140130812Smarcelstatic int next_msg_id; 141130812Smarcel 142130812Smarcelstatic int just_started; 143130812Smarcel 144130812Smarcelstatic int message_pending; 145130812Smarcel 146130812Smarcel 147130812Smarcel/* Clean up connection to a remote debugger. */ 148130812Smarcel 149130812Smarcelstatic void 150130812Smarcelsds_close (int quitting) 151130812Smarcel{ 152130812Smarcel if (sds_desc) 153130812Smarcel serial_close (sds_desc); 154130812Smarcel sds_desc = NULL; 155130812Smarcel} 156130812Smarcel 157130812Smarcel/* Stub for catch_errors. */ 158130812Smarcel 159130812Smarcelstatic int 160130812Smarcelsds_start_remote (void *dummy) 161130812Smarcel{ 162130812Smarcel int c; 163130812Smarcel unsigned char buf[200]; 164130812Smarcel 165130812Smarcel immediate_quit++; /* Allow user to interrupt it */ 166130812Smarcel 167130812Smarcel /* Ack any packet which the remote side has already sent. */ 168130812Smarcel serial_write (sds_desc, "{#*\r\n", 5); 169130812Smarcel serial_write (sds_desc, "{#}\r\n", 5); 170130812Smarcel 171130812Smarcel while ((c = readchar (1)) >= 0) 172130812Smarcel printf_unfiltered ("%c", c); 173130812Smarcel printf_unfiltered ("\n"); 174130812Smarcel 175130812Smarcel next_msg_id = 251; 176130812Smarcel 177130812Smarcel buf[0] = 26; 178130812Smarcel sds_send (buf, 1); 179130812Smarcel 180130812Smarcel buf[0] = 0; 181130812Smarcel sds_send (buf, 1); 182130812Smarcel 183130812Smarcel immediate_quit--; 184130812Smarcel 185130812Smarcel start_remote (); /* Initialize gdb process mechanisms */ 186130812Smarcel return 1; 187130812Smarcel} 188130812Smarcel 189130812Smarcel/* Open a connection to a remote debugger. 190130812Smarcel NAME is the filename used for communication. */ 191130812Smarcel 192130812Smarcelstatic void 193130812Smarcelsds_open (char *name, int from_tty) 194130812Smarcel{ 195130812Smarcel if (name == 0) 196130812Smarcel error ("To open a remote debug connection, you need to specify what serial\n\ 197130812Smarceldevice is attached to the remote system (e.g. /dev/ttya)."); 198130812Smarcel 199130812Smarcel target_preopen (from_tty); 200130812Smarcel 201130812Smarcel unpush_target (&sds_ops); 202130812Smarcel 203130812Smarcel sds_desc = serial_open (name); 204130812Smarcel if (!sds_desc) 205130812Smarcel perror_with_name (name); 206130812Smarcel 207130812Smarcel if (baud_rate != -1) 208130812Smarcel { 209130812Smarcel if (serial_setbaudrate (sds_desc, baud_rate)) 210130812Smarcel { 211130812Smarcel serial_close (sds_desc); 212130812Smarcel perror_with_name (name); 213130812Smarcel } 214130812Smarcel } 215130812Smarcel 216130812Smarcel 217130812Smarcel serial_raw (sds_desc); 218130812Smarcel 219130812Smarcel /* If there is something sitting in the buffer we might take it as a 220130812Smarcel response to a command, which would be bad. */ 221130812Smarcel serial_flush_input (sds_desc); 222130812Smarcel 223130812Smarcel if (from_tty) 224130812Smarcel { 225130812Smarcel puts_filtered ("Remote debugging using "); 226130812Smarcel puts_filtered (name); 227130812Smarcel puts_filtered ("\n"); 228130812Smarcel } 229130812Smarcel push_target (&sds_ops); /* Switch to using remote target now */ 230130812Smarcel 231130812Smarcel just_started = 1; 232130812Smarcel 233130812Smarcel /* Start the remote connection; if error (0), discard this target. 234130812Smarcel In particular, if the user quits, be sure to discard it (we'd be 235130812Smarcel in an inconsistent state otherwise). */ 236130812Smarcel if (!catch_errors (sds_start_remote, NULL, 237130812Smarcel "Couldn't establish connection to remote target\n", 238130812Smarcel RETURN_MASK_ALL)) 239130812Smarcel pop_target (); 240130812Smarcel} 241130812Smarcel 242130812Smarcel/* This takes a program previously attached to and detaches it. After 243130812Smarcel this is done, GDB can be used to debug some other program. We 244130812Smarcel better not have left any breakpoints in the target program or it'll 245130812Smarcel die when it hits one. */ 246130812Smarcel 247130812Smarcelstatic void 248130812Smarcelsds_detach (char *args, int from_tty) 249130812Smarcel{ 250130812Smarcel char buf[PBUFSIZ]; 251130812Smarcel 252130812Smarcel if (args) 253130812Smarcel error ("Argument given to \"detach\" when remotely debugging."); 254130812Smarcel 255130812Smarcel#if 0 256130812Smarcel /* Tell the remote target to detach. */ 257130812Smarcel strcpy (buf, "D"); 258130812Smarcel sds_send (buf, 1); 259130812Smarcel#endif 260130812Smarcel 261130812Smarcel pop_target (); 262130812Smarcel if (from_tty) 263130812Smarcel puts_filtered ("Ending remote debugging.\n"); 264130812Smarcel} 265130812Smarcel 266130812Smarcel/* Convert hex digit A to a number. */ 267130812Smarcel 268130812Smarcelstatic int 269130812Smarcelfromhex (int a) 270130812Smarcel{ 271130812Smarcel if (a >= '0' && a <= '9') 272130812Smarcel return a - '0'; 273130812Smarcel else if (a >= 'a' && a <= 'f') 274130812Smarcel return a - 'a' + 10; 275130812Smarcel else 276130812Smarcel error ("Reply contains invalid hex digit %d", a); 277130812Smarcel} 278130812Smarcel 279130812Smarcelstatic int 280130812Smarceltob64 (unsigned char *inbuf, char *outbuf, int len) 281130812Smarcel{ 282130812Smarcel int i, sum; 283130812Smarcel char *p; 284130812Smarcel 285130812Smarcel if (len % 3 != 0) 286130812Smarcel error ("bad length"); 287130812Smarcel 288130812Smarcel p = outbuf; 289130812Smarcel for (i = 0; i < len; i += 3) 290130812Smarcel { 291130812Smarcel /* Collect the next three bytes into a number. */ 292130812Smarcel sum = ((long) *inbuf++) << 16; 293130812Smarcel sum |= ((long) *inbuf++) << 8; 294130812Smarcel sum |= ((long) *inbuf++); 295130812Smarcel 296130812Smarcel /* Spit out 4 6-bit encodings. */ 297130812Smarcel *p++ = ((sum >> 18) & 0x3f) + '0'; 298130812Smarcel *p++ = ((sum >> 12) & 0x3f) + '0'; 299130812Smarcel *p++ = ((sum >> 6) & 0x3f) + '0'; 300130812Smarcel *p++ = (sum & 0x3f) + '0'; 301130812Smarcel } 302130812Smarcel return (p - outbuf); 303130812Smarcel} 304130812Smarcel 305130812Smarcelstatic int 306130812Smarcelfromb64 (char *inbuf, char *outbuf, int len) 307130812Smarcel{ 308130812Smarcel int i, sum; 309130812Smarcel 310130812Smarcel if (len % 4 != 0) 311130812Smarcel error ("bad length"); 312130812Smarcel 313130812Smarcel for (i = 0; i < len; i += 4) 314130812Smarcel { 315130812Smarcel /* Collect 4 6-bit digits. */ 316130812Smarcel sum = (*inbuf++ - '0') << 18; 317130812Smarcel sum |= (*inbuf++ - '0') << 12; 318130812Smarcel sum |= (*inbuf++ - '0') << 6; 319130812Smarcel sum |= (*inbuf++ - '0'); 320130812Smarcel 321130812Smarcel /* Now take the resulting 24-bit number and get three bytes out 322130812Smarcel of it. */ 323130812Smarcel *outbuf++ = (sum >> 16) & 0xff; 324130812Smarcel *outbuf++ = (sum >> 8) & 0xff; 325130812Smarcel *outbuf++ = sum & 0xff; 326130812Smarcel } 327130812Smarcel 328130812Smarcel return (len / 4) * 3; 329130812Smarcel} 330130812Smarcel 331130812Smarcel 332130812Smarcel/* Tell the remote machine to resume. */ 333130812Smarcel 334130812Smarcelstatic enum target_signal last_sent_signal = TARGET_SIGNAL_0; 335130812Smarcelint last_sent_step; 336130812Smarcel 337130812Smarcelstatic void 338130812Smarcelsds_resume (ptid_t ptid, int step, enum target_signal siggnal) 339130812Smarcel{ 340130812Smarcel unsigned char buf[PBUFSIZ]; 341130812Smarcel 342130812Smarcel last_sent_signal = siggnal; 343130812Smarcel last_sent_step = step; 344130812Smarcel 345130812Smarcel buf[0] = (step ? 21 : 20); 346130812Smarcel buf[1] = 0; /* (should be signal?) */ 347130812Smarcel 348130812Smarcel sds_send (buf, 2); 349130812Smarcel} 350130812Smarcel 351130812Smarcel/* Send a message to target to halt it. Target will respond, and send 352130812Smarcel us a message pending notice. */ 353130812Smarcel 354130812Smarcelstatic void 355130812Smarcelsds_interrupt (int signo) 356130812Smarcel{ 357130812Smarcel unsigned char buf[PBUFSIZ]; 358130812Smarcel 359130812Smarcel /* If this doesn't work, try more severe steps. */ 360130812Smarcel signal (signo, sds_interrupt_twice); 361130812Smarcel 362130812Smarcel if (remote_debug) 363130812Smarcel fprintf_unfiltered (gdb_stdlog, "sds_interrupt called\n"); 364130812Smarcel 365130812Smarcel buf[0] = 25; 366130812Smarcel sds_send (buf, 1); 367130812Smarcel} 368130812Smarcel 369130812Smarcelstatic void (*ofunc) (); 370130812Smarcel 371130812Smarcel/* The user typed ^C twice. */ 372130812Smarcel 373130812Smarcelstatic void 374130812Smarcelsds_interrupt_twice (int signo) 375130812Smarcel{ 376130812Smarcel signal (signo, ofunc); 377130812Smarcel 378130812Smarcel interrupt_query (); 379130812Smarcel 380130812Smarcel signal (signo, sds_interrupt); 381130812Smarcel} 382130812Smarcel 383130812Smarcel/* Ask the user what to do when an interrupt is received. */ 384130812Smarcel 385130812Smarcelstatic void 386130812Smarcelinterrupt_query (void) 387130812Smarcel{ 388130812Smarcel target_terminal_ours (); 389130812Smarcel 390130812Smarcel if (query ("Interrupted while waiting for the program.\n\ 391130812SmarcelGive up (and stop debugging it)? ")) 392130812Smarcel { 393130812Smarcel target_mourn_inferior (); 394130812Smarcel throw_exception (RETURN_QUIT); 395130812Smarcel } 396130812Smarcel 397130812Smarcel target_terminal_inferior (); 398130812Smarcel} 399130812Smarcel 400130812Smarcel/* If nonzero, ignore the next kill. */ 401130812Smarcelint kill_kludge; 402130812Smarcel 403130812Smarcel/* Wait until the remote machine stops, then return, storing status in 404130812Smarcel STATUS just as `wait' would. Returns "pid" (though it's not clear 405130812Smarcel what, if anything, that means in the case of this target). */ 406130812Smarcel 407130812Smarcelstatic ptid_t 408130812Smarcelsds_wait (ptid_t ptid, struct target_waitstatus *status) 409130812Smarcel{ 410130812Smarcel unsigned char buf[PBUFSIZ]; 411130812Smarcel int retlen; 412130812Smarcel 413130812Smarcel status->kind = TARGET_WAITKIND_EXITED; 414130812Smarcel status->value.integer = 0; 415130812Smarcel 416130812Smarcel ofunc = (void (*)()) signal (SIGINT, sds_interrupt); 417130812Smarcel 418130812Smarcel signal (SIGINT, ofunc); 419130812Smarcel 420130812Smarcel if (just_started) 421130812Smarcel { 422130812Smarcel just_started = 0; 423130812Smarcel status->kind = TARGET_WAITKIND_STOPPED; 424130812Smarcel return inferior_ptid; 425130812Smarcel } 426130812Smarcel 427130812Smarcel while (1) 428130812Smarcel { 429130812Smarcel getmessage (buf, 1); 430130812Smarcel 431130812Smarcel if (message_pending) 432130812Smarcel { 433130812Smarcel buf[0] = 26; 434130812Smarcel retlen = sds_send (buf, 1); 435130812Smarcel if (remote_debug) 436130812Smarcel { 437130812Smarcel fprintf_unfiltered (gdb_stdlog, "Signals: %02x%02x %02x %02x\n", 438130812Smarcel buf[0], buf[1], 439130812Smarcel buf[2], buf[3]); 440130812Smarcel } 441130812Smarcel message_pending = 0; 442130812Smarcel status->kind = TARGET_WAITKIND_STOPPED; 443130812Smarcel status->value.sig = TARGET_SIGNAL_TRAP; 444130812Smarcel goto got_status; 445130812Smarcel } 446130812Smarcel } 447130812Smarcelgot_status: 448130812Smarcel return inferior_ptid; 449130812Smarcel} 450130812Smarcel 451130812Smarcelstatic unsigned char sprs[16]; 452130812Smarcel 453130812Smarcel/* Read the remote registers into the block REGS. */ 454130812Smarcel/* Currently we just read all the registers, so we don't use regno. */ 455130812Smarcel 456130812Smarcelstatic void 457130812Smarcelsds_fetch_registers (int regno) 458130812Smarcel{ 459130812Smarcel unsigned char buf[PBUFSIZ]; 460130812Smarcel int i, retlen; 461130812Smarcel char *regs = alloca (DEPRECATED_REGISTER_BYTES); 462130812Smarcel 463130812Smarcel /* Unimplemented registers read as all bits zero. */ 464130812Smarcel memset (regs, 0, DEPRECATED_REGISTER_BYTES); 465130812Smarcel 466130812Smarcel buf[0] = 18; 467130812Smarcel buf[1] = 1; 468130812Smarcel buf[2] = 0; 469130812Smarcel retlen = sds_send (buf, 3); 470130812Smarcel 471130812Smarcel for (i = 0; i < 4 * 6; ++i) 472130812Smarcel regs[i + 4 * 32 + 8 * 32] = buf[i]; 473130812Smarcel for (i = 0; i < 4 * 4; ++i) 474130812Smarcel sprs[i] = buf[i + 4 * 7]; 475130812Smarcel 476130812Smarcel buf[0] = 18; 477130812Smarcel buf[1] = 2; 478130812Smarcel buf[2] = 0; 479130812Smarcel retlen = sds_send (buf, 3); 480130812Smarcel 481130812Smarcel for (i = 0; i < retlen; i++) 482130812Smarcel regs[i] = buf[i]; 483130812Smarcel 484130812Smarcel /* (should warn about reply too short) */ 485130812Smarcel 486130812Smarcel for (i = 0; i < NUM_REGS; i++) 487130812Smarcel supply_register (i, ®s[DEPRECATED_REGISTER_BYTE (i)]); 488130812Smarcel} 489130812Smarcel 490130812Smarcel/* Prepare to store registers. Since we may send them all, we have to 491130812Smarcel read out the ones we don't want to change first. */ 492130812Smarcel 493130812Smarcelstatic void 494130812Smarcelsds_prepare_to_store (void) 495130812Smarcel{ 496130812Smarcel /* Make sure the entire registers array is valid. */ 497130812Smarcel deprecated_read_register_bytes (0, (char *) NULL, DEPRECATED_REGISTER_BYTES); 498130812Smarcel} 499130812Smarcel 500130812Smarcel/* Store register REGNO, or all registers if REGNO == -1, from the contents 501130812Smarcel of REGISTERS. FIXME: ignores errors. */ 502130812Smarcel 503130812Smarcelstatic void 504130812Smarcelsds_store_registers (int regno) 505130812Smarcel{ 506130812Smarcel unsigned char *p, buf[PBUFSIZ]; 507130812Smarcel int i; 508130812Smarcel 509130812Smarcel /* Store all the special-purpose registers. */ 510130812Smarcel p = buf; 511130812Smarcel *p++ = 19; 512130812Smarcel *p++ = 1; 513130812Smarcel *p++ = 0; 514130812Smarcel *p++ = 0; 515130812Smarcel for (i = 0; i < 4 * 6; i++) 516130812Smarcel *p++ = deprecated_registers[i + 4 * 32 + 8 * 32]; 517130812Smarcel for (i = 0; i < 4 * 1; i++) 518130812Smarcel *p++ = 0; 519130812Smarcel for (i = 0; i < 4 * 4; i++) 520130812Smarcel *p++ = sprs[i]; 521130812Smarcel 522130812Smarcel sds_send (buf, p - buf); 523130812Smarcel 524130812Smarcel /* Store all the general-purpose registers. */ 525130812Smarcel p = buf; 526130812Smarcel *p++ = 19; 527130812Smarcel *p++ = 2; 528130812Smarcel *p++ = 0; 529130812Smarcel *p++ = 0; 530130812Smarcel for (i = 0; i < 4 * 32; i++) 531130812Smarcel *p++ = deprecated_registers[i]; 532130812Smarcel 533130812Smarcel sds_send (buf, p - buf); 534130812Smarcel 535130812Smarcel} 536130812Smarcel 537130812Smarcel/* Write memory data directly to the remote machine. This does not 538130812Smarcel inform the data cache; the data cache uses this. MEMADDR is the 539130812Smarcel address in the remote memory space. MYADDR is the address of the 540130812Smarcel buffer in our space. LEN is the number of bytes. 541130812Smarcel 542130812Smarcel Returns number of bytes transferred, or 0 for error. */ 543130812Smarcel 544130812Smarcelstatic int 545130812Smarcelsds_write_bytes (CORE_ADDR memaddr, char *myaddr, int len) 546130812Smarcel{ 547130812Smarcel int max_buf_size; /* Max size of packet output buffer */ 548130812Smarcel int origlen; 549130812Smarcel unsigned char buf[PBUFSIZ]; 550130812Smarcel int todo; 551130812Smarcel int i; 552130812Smarcel 553130812Smarcel /* Chop the transfer down if necessary */ 554130812Smarcel 555130812Smarcel max_buf_size = 150; 556130812Smarcel 557130812Smarcel origlen = len; 558130812Smarcel while (len > 0) 559130812Smarcel { 560130812Smarcel todo = min (len, max_buf_size); 561130812Smarcel 562130812Smarcel buf[0] = 13; 563130812Smarcel buf[1] = 0; 564130812Smarcel buf[2] = (int) (memaddr >> 24) & 0xff; 565130812Smarcel buf[3] = (int) (memaddr >> 16) & 0xff; 566130812Smarcel buf[4] = (int) (memaddr >> 8) & 0xff; 567130812Smarcel buf[5] = (int) (memaddr) & 0xff; 568130812Smarcel buf[6] = 1; 569130812Smarcel buf[7] = 0; 570130812Smarcel 571130812Smarcel for (i = 0; i < todo; i++) 572130812Smarcel buf[i + 8] = myaddr[i]; 573130812Smarcel 574130812Smarcel sds_send (buf, 8 + todo); 575130812Smarcel 576130812Smarcel /* (should look at result) */ 577130812Smarcel 578130812Smarcel myaddr += todo; 579130812Smarcel memaddr += todo; 580130812Smarcel len -= todo; 581130812Smarcel } 582130812Smarcel return origlen; 583130812Smarcel} 584130812Smarcel 585130812Smarcel/* Read memory data directly from the remote machine. This does not 586130812Smarcel use the data cache; the data cache uses this. MEMADDR is the 587130812Smarcel address in the remote memory space. MYADDR is the address of the 588130812Smarcel buffer in our space. LEN is the number of bytes. 589130812Smarcel 590130812Smarcel Returns number of bytes transferred, or 0 for error. */ 591130812Smarcel 592130812Smarcelstatic int 593130812Smarcelsds_read_bytes (CORE_ADDR memaddr, char *myaddr, int len) 594130812Smarcel{ 595130812Smarcel int max_buf_size; /* Max size of packet output buffer */ 596130812Smarcel int origlen, retlen; 597130812Smarcel unsigned char buf[PBUFSIZ]; 598130812Smarcel int todo; 599130812Smarcel int i; 600130812Smarcel 601130812Smarcel /* Chop the transfer down if necessary */ 602130812Smarcel 603130812Smarcel max_buf_size = 150; 604130812Smarcel 605130812Smarcel origlen = len; 606130812Smarcel while (len > 0) 607130812Smarcel { 608130812Smarcel todo = min (len, max_buf_size); 609130812Smarcel 610130812Smarcel buf[0] = 12; 611130812Smarcel buf[1] = 0; 612130812Smarcel buf[2] = (int) (memaddr >> 24) & 0xff; 613130812Smarcel buf[3] = (int) (memaddr >> 16) & 0xff; 614130812Smarcel buf[4] = (int) (memaddr >> 8) & 0xff; 615130812Smarcel buf[5] = (int) (memaddr) & 0xff; 616130812Smarcel buf[6] = (int) (todo >> 8) & 0xff; 617130812Smarcel buf[7] = (int) (todo) & 0xff; 618130812Smarcel buf[8] = 1; 619130812Smarcel 620130812Smarcel retlen = sds_send (buf, 9); 621130812Smarcel 622130812Smarcel if (retlen - 2 != todo) 623130812Smarcel { 624130812Smarcel return 0; 625130812Smarcel } 626130812Smarcel 627130812Smarcel /* Reply describes memory byte by byte. */ 628130812Smarcel 629130812Smarcel for (i = 0; i < todo; i++) 630130812Smarcel myaddr[i] = buf[i + 2]; 631130812Smarcel 632130812Smarcel myaddr += todo; 633130812Smarcel memaddr += todo; 634130812Smarcel len -= todo; 635130812Smarcel } 636130812Smarcel 637130812Smarcel return origlen; 638130812Smarcel} 639130812Smarcel 640130812Smarcel/* Read or write LEN bytes from inferior memory at MEMADDR, 641130812Smarcel transferring to or from debugger address MYADDR. Write to inferior 642130812Smarcel if SHOULD_WRITE is nonzero. Returns length of data written or 643130812Smarcel read; 0 for error. TARGET is unused. */ 644130812Smarcel 645130812Smarcelstatic int 646130812Smarcelsds_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write, 647130812Smarcel struct mem_attrib *attrib, struct target_ops *target) 648130812Smarcel{ 649130812Smarcel int res; 650130812Smarcel 651130812Smarcel if (should_write) 652130812Smarcel res = sds_write_bytes (memaddr, myaddr, len); 653130812Smarcel else 654130812Smarcel res = sds_read_bytes (memaddr, myaddr, len); 655130812Smarcel 656130812Smarcel return res; 657130812Smarcel} 658130812Smarcel 659130812Smarcel 660130812Smarcelstatic void 661130812Smarcelsds_files_info (struct target_ops *ignore) 662130812Smarcel{ 663130812Smarcel puts_filtered ("Debugging over a serial connection, using SDS protocol.\n"); 664130812Smarcel} 665130812Smarcel 666130812Smarcel/* Stuff for dealing with the packets which are part of this protocol. 667130812Smarcel See comment at top of file for details. */ 668130812Smarcel 669130812Smarcel/* Read a single character from the remote end, masking it down to 7 bits. */ 670130812Smarcel 671130812Smarcelstatic int 672130812Smarcelreadchar (int timeout) 673130812Smarcel{ 674130812Smarcel int ch; 675130812Smarcel 676130812Smarcel ch = serial_readchar (sds_desc, timeout); 677130812Smarcel 678130812Smarcel if (remote_debug > 1 && ch >= 0) 679130812Smarcel fprintf_unfiltered (gdb_stdlog, "%c(%x)", ch, ch); 680130812Smarcel 681130812Smarcel switch (ch) 682130812Smarcel { 683130812Smarcel case SERIAL_EOF: 684130812Smarcel error ("Remote connection closed"); 685130812Smarcel case SERIAL_ERROR: 686130812Smarcel perror_with_name ("Remote communication error"); 687130812Smarcel case SERIAL_TIMEOUT: 688130812Smarcel return ch; 689130812Smarcel default: 690130812Smarcel return ch & 0x7f; 691130812Smarcel } 692130812Smarcel} 693130812Smarcel 694130812Smarcel/* An SDS-style checksum is a sum of the bytes modulo 253. (Presumably 695130812Smarcel because 253, 254, and 255 are special flags in the protocol.) */ 696130812Smarcel 697130812Smarcelstatic int 698130812Smarcelcompute_checksum (int csum, char *buf, int len) 699130812Smarcel{ 700130812Smarcel int i; 701130812Smarcel 702130812Smarcel for (i = 0; i < len; ++i) 703130812Smarcel csum += (unsigned char) buf[i]; 704130812Smarcel 705130812Smarcel csum %= 253; 706130812Smarcel return csum; 707130812Smarcel} 708130812Smarcel 709130812Smarcel/* Send the command in BUF to the remote machine, and read the reply 710130812Smarcel into BUF also. */ 711130812Smarcel 712130812Smarcelstatic int 713130812Smarcelsds_send (unsigned char *buf, int len) 714130812Smarcel{ 715130812Smarcel putmessage (buf, len); 716130812Smarcel 717130812Smarcel return getmessage (buf, 0); 718130812Smarcel} 719130812Smarcel 720130812Smarcel/* Send a message to the remote machine. */ 721130812Smarcel 722130812Smarcelstatic int 723130812Smarcelputmessage (unsigned char *buf, int len) 724130812Smarcel{ 725130812Smarcel int i, enclen; 726130812Smarcel unsigned char csum = 0; 727130812Smarcel char buf2[PBUFSIZ], buf3[PBUFSIZ]; 728130812Smarcel unsigned char header[3]; 729130812Smarcel char *p; 730130812Smarcel 731130812Smarcel /* Copy the packet into buffer BUF2, encapsulating it 732130812Smarcel and giving it a checksum. */ 733130812Smarcel 734130812Smarcel if (len > 170) /* Prosanity check */ 735130812Smarcel internal_error (__FILE__, __LINE__, "failed internal consistency check"); 736130812Smarcel 737130812Smarcel if (remote_debug) 738130812Smarcel { 739130812Smarcel fprintf_unfiltered (gdb_stdlog, "Message to send: \""); 740130812Smarcel for (i = 0; i < len; ++i) 741130812Smarcel fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]); 742130812Smarcel fprintf_unfiltered (gdb_stdlog, "\"\n"); 743130812Smarcel } 744130812Smarcel 745130812Smarcel p = buf2; 746130812Smarcel *p++ = '$'; 747130812Smarcel 748130812Smarcel if (len % 3 != 0) 749130812Smarcel { 750130812Smarcel buf[len] = '\0'; 751130812Smarcel buf[len + 1] = '\0'; 752130812Smarcel } 753130812Smarcel 754130812Smarcel header[1] = next_msg_id; 755130812Smarcel 756130812Smarcel header[2] = len; 757130812Smarcel 758130812Smarcel csum = compute_checksum (csum, buf, len); 759130812Smarcel csum = compute_checksum (csum, header + 1, 2); 760130812Smarcel 761130812Smarcel header[0] = csum; 762130812Smarcel 763130812Smarcel tob64 (header, p, 3); 764130812Smarcel p += 4; 765130812Smarcel enclen = tob64 (buf, buf3, ((len + 2) / 3) * 3); 766130812Smarcel 767130812Smarcel for (i = 0; i < enclen; ++i) 768130812Smarcel *p++ = buf3[i]; 769130812Smarcel *p++ = '\r'; 770130812Smarcel *p++ = '\n'; 771130812Smarcel 772130812Smarcel next_msg_id = (next_msg_id + 3) % 245; 773130812Smarcel 774130812Smarcel /* Send it over and over until we get a positive ack. */ 775130812Smarcel 776130812Smarcel while (1) 777130812Smarcel { 778130812Smarcel if (remote_debug) 779130812Smarcel { 780130812Smarcel *p = '\0'; 781130812Smarcel fprintf_unfiltered (gdb_stdlog, "Sending encoded: \"%s\"", buf2); 782130812Smarcel fprintf_unfiltered (gdb_stdlog, 783130812Smarcel " (Checksum %d, id %d, length %d)\n", 784130812Smarcel header[0], header[1], header[2]); 785130812Smarcel gdb_flush (gdb_stdlog); 786130812Smarcel } 787130812Smarcel if (serial_write (sds_desc, buf2, p - buf2)) 788130812Smarcel perror_with_name ("putmessage: write failed"); 789130812Smarcel 790130812Smarcel return 1; 791130812Smarcel } 792130812Smarcel} 793130812Smarcel 794130812Smarcel/* Come here after finding the start of the frame. Collect the rest 795130812Smarcel into BUF. Returns 0 on any error, 1 on success. */ 796130812Smarcel 797130812Smarcelstatic int 798130812Smarcelread_frame (char *buf) 799130812Smarcel{ 800130812Smarcel char *bp; 801130812Smarcel int c; 802130812Smarcel 803130812Smarcel bp = buf; 804130812Smarcel 805130812Smarcel while (1) 806130812Smarcel { 807130812Smarcel c = readchar (sds_timeout); 808130812Smarcel 809130812Smarcel switch (c) 810130812Smarcel { 811130812Smarcel case SERIAL_TIMEOUT: 812130812Smarcel if (remote_debug) 813130812Smarcel fputs_filtered ("Timeout in mid-message, retrying\n", gdb_stdlog); 814130812Smarcel return 0; 815130812Smarcel case '$': 816130812Smarcel if (remote_debug) 817130812Smarcel fputs_filtered ("Saw new packet start in middle of old one\n", 818130812Smarcel gdb_stdlog); 819130812Smarcel return 0; /* Start a new packet, count retries */ 820130812Smarcel case '\r': 821130812Smarcel break; 822130812Smarcel 823130812Smarcel case '\n': 824130812Smarcel { 825130812Smarcel *bp = '\000'; 826130812Smarcel if (remote_debug) 827130812Smarcel fprintf_unfiltered (gdb_stdlog, "Received encoded: \"%s\"\n", 828130812Smarcel buf); 829130812Smarcel return 1; 830130812Smarcel } 831130812Smarcel 832130812Smarcel default: 833130812Smarcel if (bp < buf + PBUFSIZ - 1) 834130812Smarcel { 835130812Smarcel *bp++ = c; 836130812Smarcel continue; 837130812Smarcel } 838130812Smarcel 839130812Smarcel *bp = '\0'; 840130812Smarcel puts_filtered ("Message too long: "); 841130812Smarcel puts_filtered (buf); 842130812Smarcel puts_filtered ("\n"); 843130812Smarcel 844130812Smarcel return 0; 845130812Smarcel } 846130812Smarcel } 847130812Smarcel} 848130812Smarcel 849130812Smarcel/* Read a packet from the remote machine, with error checking, 850130812Smarcel and store it in BUF. BUF is expected to be of size PBUFSIZ. 851130812Smarcel If FOREVER, wait forever rather than timing out; this is used 852130812Smarcel while the target is executing user code. */ 853130812Smarcel 854130812Smarcelstatic int 855130812Smarcelgetmessage (unsigned char *buf, int forever) 856130812Smarcel{ 857130812Smarcel int c, c2, c3; 858130812Smarcel int tries; 859130812Smarcel int timeout; 860130812Smarcel int val, i, len, csum; 861130812Smarcel unsigned char header[3]; 862130812Smarcel unsigned char inbuf[500]; 863130812Smarcel 864130812Smarcel strcpy (buf, "timeout"); 865130812Smarcel 866130812Smarcel if (forever) 867130812Smarcel { 868130812Smarcel timeout = watchdog > 0 ? watchdog : -1; 869130812Smarcel } 870130812Smarcel 871130812Smarcel else 872130812Smarcel timeout = sds_timeout; 873130812Smarcel 874130812Smarcel#define MAX_TRIES 3 875130812Smarcel 876130812Smarcel for (tries = 1; tries <= MAX_TRIES; tries++) 877130812Smarcel { 878130812Smarcel /* This can loop forever if the remote side sends us characters 879130812Smarcel continuously, but if it pauses, we'll get a zero from readchar 880130812Smarcel because of timeout. Then we'll count that as a retry. */ 881130812Smarcel 882130812Smarcel /* Note that we will only wait forever prior to the start of a packet. 883130812Smarcel After that, we expect characters to arrive at a brisk pace. They 884130812Smarcel should show up within sds_timeout intervals. */ 885130812Smarcel 886130812Smarcel do 887130812Smarcel { 888130812Smarcel c = readchar (timeout); 889130812Smarcel 890130812Smarcel if (c == SERIAL_TIMEOUT) 891130812Smarcel { 892130812Smarcel if (forever) /* Watchdog went off. Kill the target. */ 893130812Smarcel { 894130812Smarcel target_mourn_inferior (); 895130812Smarcel error ("Watchdog has expired. Target detached.\n"); 896130812Smarcel } 897130812Smarcel if (remote_debug) 898130812Smarcel fputs_filtered ("Timed out.\n", gdb_stdlog); 899130812Smarcel goto retry; 900130812Smarcel } 901130812Smarcel } 902130812Smarcel while (c != '$' && c != '{'); 903130812Smarcel 904130812Smarcel /* We might have seen a "trigraph", a sequence of three characters 905130812Smarcel that indicate various sorts of communication state. */ 906130812Smarcel 907130812Smarcel if (c == '{') 908130812Smarcel { 909130812Smarcel /* Read the other two chars of the trigraph. */ 910130812Smarcel c2 = readchar (timeout); 911130812Smarcel c3 = readchar (timeout); 912130812Smarcel if (remote_debug) 913130812Smarcel fprintf_unfiltered (gdb_stdlog, "Trigraph %c%c%c received\n", 914130812Smarcel c, c2, c3); 915130812Smarcel if (c3 == '+') 916130812Smarcel { 917130812Smarcel message_pending = 1; 918130812Smarcel return 0; /*???? */ 919130812Smarcel } 920130812Smarcel continue; 921130812Smarcel } 922130812Smarcel 923130812Smarcel val = read_frame (inbuf); 924130812Smarcel 925130812Smarcel if (val == 1) 926130812Smarcel { 927130812Smarcel fromb64 (inbuf, header, 4); 928130812Smarcel /* (should check out other bits) */ 929130812Smarcel fromb64 (inbuf + 4, buf, strlen (inbuf) - 4); 930130812Smarcel 931130812Smarcel len = header[2]; 932130812Smarcel 933130812Smarcel csum = 0; 934130812Smarcel csum = compute_checksum (csum, buf, len); 935130812Smarcel csum = compute_checksum (csum, header + 1, 2); 936130812Smarcel 937130812Smarcel if (csum != header[0]) 938130812Smarcel fprintf_unfiltered (gdb_stderr, 939130812Smarcel "Checksum mismatch: computed %d, received %d\n", 940130812Smarcel csum, header[0]); 941130812Smarcel 942130812Smarcel if (header[2] == 0xff) 943130812Smarcel fprintf_unfiltered (gdb_stderr, "Requesting resend...\n"); 944130812Smarcel 945130812Smarcel if (remote_debug) 946130812Smarcel { 947130812Smarcel fprintf_unfiltered (gdb_stdlog, 948130812Smarcel "... (Got checksum %d, id %d, length %d)\n", 949130812Smarcel header[0], header[1], header[2]); 950130812Smarcel fprintf_unfiltered (gdb_stdlog, "Message received: \""); 951130812Smarcel for (i = 0; i < len; ++i) 952130812Smarcel { 953130812Smarcel fprintf_unfiltered (gdb_stdlog, "%02x", (unsigned char) buf[i]); 954130812Smarcel } 955130812Smarcel fprintf_unfiltered (gdb_stdlog, "\"\n"); 956130812Smarcel } 957130812Smarcel 958130812Smarcel /* no ack required? */ 959130812Smarcel return len; 960130812Smarcel } 961130812Smarcel 962130812Smarcel /* Try the whole thing again. */ 963130812Smarcel retry: 964130812Smarcel /* need to do something here */ 965130812Smarcel ; 966130812Smarcel } 967130812Smarcel 968130812Smarcel /* We have tried hard enough, and just can't receive the packet. Give up. */ 969130812Smarcel 970130812Smarcel printf_unfiltered ("Ignoring packet error, continuing...\n"); 971130812Smarcel return 0; 972130812Smarcel} 973130812Smarcel 974130812Smarcelstatic void 975130812Smarcelsds_kill (void) 976130812Smarcel{ 977130812Smarcel /* Don't try to do anything to the target. */ 978130812Smarcel} 979130812Smarcel 980130812Smarcelstatic void 981130812Smarcelsds_mourn (void) 982130812Smarcel{ 983130812Smarcel unpush_target (&sds_ops); 984130812Smarcel generic_mourn_inferior (); 985130812Smarcel} 986130812Smarcel 987130812Smarcelstatic void 988130812Smarcelsds_create_inferior (char *exec_file, char *args, char **env) 989130812Smarcel{ 990130812Smarcel inferior_ptid = pid_to_ptid (42000); 991130812Smarcel 992130812Smarcel /* Clean up from the last time we were running. */ 993130812Smarcel clear_proceed_status (); 994130812Smarcel 995130812Smarcel /* Let the remote process run. */ 996130812Smarcel proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0); 997130812Smarcel} 998130812Smarcel 999130812Smarcelstatic void 1000130812Smarcelsds_load (char *filename, int from_tty) 1001130812Smarcel{ 1002130812Smarcel generic_load (filename, from_tty); 1003130812Smarcel 1004130812Smarcel inferior_ptid = null_ptid; 1005130812Smarcel} 1006130812Smarcel 1007130812Smarcel/* The SDS monitor has commands for breakpoint insertion, although it 1008130812Smarcel it doesn't actually manage the breakpoints, it just returns the 1009130812Smarcel replaced instruction back to the debugger. */ 1010130812Smarcel 1011130812Smarcelstatic int 1012130812Smarcelsds_insert_breakpoint (CORE_ADDR addr, char *contents_cache) 1013130812Smarcel{ 1014130812Smarcel int i, retlen; 1015130812Smarcel unsigned char *p, buf[PBUFSIZ]; 1016130812Smarcel 1017130812Smarcel p = buf; 1018130812Smarcel *p++ = 16; 1019130812Smarcel *p++ = 0; 1020130812Smarcel *p++ = (int) (addr >> 24) & 0xff; 1021130812Smarcel *p++ = (int) (addr >> 16) & 0xff; 1022130812Smarcel *p++ = (int) (addr >> 8) & 0xff; 1023130812Smarcel *p++ = (int) (addr) & 0xff; 1024130812Smarcel 1025130812Smarcel retlen = sds_send (buf, p - buf); 1026130812Smarcel 1027130812Smarcel for (i = 0; i < 4; ++i) 1028130812Smarcel contents_cache[i] = buf[i + 2]; 1029130812Smarcel 1030130812Smarcel return 0; 1031130812Smarcel} 1032130812Smarcel 1033130812Smarcelstatic int 1034130812Smarcelsds_remove_breakpoint (CORE_ADDR addr, char *contents_cache) 1035130812Smarcel{ 1036130812Smarcel int i, retlen; 1037130812Smarcel unsigned char *p, buf[PBUFSIZ]; 1038130812Smarcel 1039130812Smarcel p = buf; 1040130812Smarcel *p++ = 17; 1041130812Smarcel *p++ = 0; 1042130812Smarcel *p++ = (int) (addr >> 24) & 0xff; 1043130812Smarcel *p++ = (int) (addr >> 16) & 0xff; 1044130812Smarcel *p++ = (int) (addr >> 8) & 0xff; 1045130812Smarcel *p++ = (int) (addr) & 0xff; 1046130812Smarcel for (i = 0; i < 4; ++i) 1047130812Smarcel *p++ = contents_cache[i]; 1048130812Smarcel 1049130812Smarcel retlen = sds_send (buf, p - buf); 1050130812Smarcel 1051130812Smarcel return 0; 1052130812Smarcel} 1053130812Smarcel 1054130812Smarcelstatic void 1055130812Smarcelinit_sds_ops (void) 1056130812Smarcel{ 1057130812Smarcel sds_ops.to_shortname = "sds"; 1058130812Smarcel sds_ops.to_longname = "Remote serial target with SDS protocol"; 1059130812Smarcel sds_ops.to_doc = "Use a remote computer via a serial line; using the SDS protocol.\n\ 1060130812SmarcelSpecify the serial device it is connected to (e.g. /dev/ttya)."; 1061130812Smarcel sds_ops.to_open = sds_open; 1062130812Smarcel sds_ops.to_close = sds_close; 1063130812Smarcel sds_ops.to_detach = sds_detach; 1064130812Smarcel sds_ops.to_resume = sds_resume; 1065130812Smarcel sds_ops.to_wait = sds_wait; 1066130812Smarcel sds_ops.to_fetch_registers = sds_fetch_registers; 1067130812Smarcel sds_ops.to_store_registers = sds_store_registers; 1068130812Smarcel sds_ops.to_prepare_to_store = sds_prepare_to_store; 1069130812Smarcel sds_ops.to_xfer_memory = sds_xfer_memory; 1070130812Smarcel sds_ops.to_files_info = sds_files_info; 1071130812Smarcel sds_ops.to_insert_breakpoint = sds_insert_breakpoint; 1072130812Smarcel sds_ops.to_remove_breakpoint = sds_remove_breakpoint; 1073130812Smarcel sds_ops.to_kill = sds_kill; 1074130812Smarcel sds_ops.to_load = sds_load; 1075130812Smarcel sds_ops.to_create_inferior = sds_create_inferior; 1076130812Smarcel sds_ops.to_mourn_inferior = sds_mourn; 1077130812Smarcel sds_ops.to_stratum = process_stratum; 1078130812Smarcel sds_ops.to_has_all_memory = 1; 1079130812Smarcel sds_ops.to_has_memory = 1; 1080130812Smarcel sds_ops.to_has_stack = 1; 1081130812Smarcel sds_ops.to_has_registers = 1; 1082130812Smarcel sds_ops.to_has_execution = 1; 1083130812Smarcel sds_ops.to_magic = OPS_MAGIC; 1084130812Smarcel} 1085130812Smarcel 1086130812Smarcel/* Put a command string, in args, out to the monitor and display the 1087130812Smarcel reply message. */ 1088130812Smarcel 1089130812Smarcelstatic void 1090130812Smarcelsds_command (char *args, int from_tty) 1091130812Smarcel{ 1092130812Smarcel char *p; 1093130812Smarcel int i, len, retlen; 1094130812Smarcel unsigned char buf[1000]; 1095130812Smarcel 1096130812Smarcel /* Convert hexadecimal chars into a byte buffer. */ 1097130812Smarcel p = args; 1098130812Smarcel len = 0; 1099130812Smarcel while (*p != '\0') 1100130812Smarcel { 1101130812Smarcel buf[len++] = fromhex (p[0]) * 16 + fromhex (p[1]); 1102130812Smarcel if (p[1] == '\0') 1103130812Smarcel break; 1104130812Smarcel p += 2; 1105130812Smarcel } 1106130812Smarcel 1107130812Smarcel retlen = sds_send (buf, len); 1108130812Smarcel 1109130812Smarcel printf_filtered ("Reply is "); 1110130812Smarcel for (i = 0; i < retlen; ++i) 1111130812Smarcel { 1112130812Smarcel printf_filtered ("%02x", buf[i]); 1113130812Smarcel } 1114130812Smarcel printf_filtered ("\n"); 1115130812Smarcel} 1116130812Smarcel 1117130812Smarcelvoid 1118130812Smarcel_initialize_remote_sds (void) 1119130812Smarcel{ 1120130812Smarcel init_sds_ops (); 1121130812Smarcel add_target (&sds_ops); 1122130812Smarcel 1123130812Smarcel add_show_from_set (add_set_cmd ("sdstimeout", no_class, 1124130812Smarcel var_integer, (char *) &sds_timeout, 1125130812Smarcel "Set timeout value for sds read.\n", &setlist), 1126130812Smarcel &showlist); 1127130812Smarcel 1128130812Smarcel add_com ("sds", class_obscure, sds_command, 1129130812Smarcel "Send a command to the SDS monitor."); 1130130812Smarcel} 1131