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