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