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