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