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