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