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