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