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