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