OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [ocd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.