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