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