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