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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [remote-nindy.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 104 markom
/* Memory-access and commands for remote NINDY process, for GDB.
2
   Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3
   Contributed by Intel Corporation.  Modified from remote.c by Chris Benenati.
4
 
5
   GDB is distributed in the hope that it will be useful, but WITHOUT ANY
6
   WARRANTY.  No author or distributor accepts responsibility to anyone
7
   for the consequences of using it or for whether it serves any
8
   particular purpose or works at all, unless he says so in writing.
9
   Refer to the GDB General Public License for full details.
10
 
11
   Everyone is granted permission to copy, modify and redistribute GDB,
12
   but only under the conditions described in the GDB General Public
13
   License.  A copy of this license is supposed to have been given to you
14
   along with GDB so you can know your rights and responsibilities.  It
15
   should be in a file named COPYING.  Among other things, the copyright
16
   notice and this notice must be preserved on all copies.
17
 
18
   In other words, go ahead and share GDB, but don't try to stop
19
   anyone else from sharing it farther.  Help stamp out software hoarding!
20
 */
21
 
22
/*
23
   Except for the data cache routines, this file bears little resemblence
24
   to remote.c.  A new (although similar) protocol has been specified, and
25
   portions of the code are entirely dependent on having an i80960 with a
26
   NINDY ROM monitor at the other end of the line.
27
 */
28
 
29
/*****************************************************************************
30
 *
31
 * REMOTE COMMUNICATION PROTOCOL BETWEEN GDB960 AND THE NINDY ROM MONITOR.
32
 *
33
 *
34
 * MODES OF OPERATION
35
 * ----- -- ---------
36
 *
37
 * As far as NINDY is concerned, GDB is always in one of two modes: command
38
 * mode or passthrough mode.
39
 *
40
 * In command mode (the default) pre-defined packets containing requests
41
 * are sent by GDB to NINDY.  NINDY never talks except in reponse to a request.
42
 *
43
 * Once the the user program is started, GDB enters passthrough mode, to give
44
 * the user program access to the terminal.  GDB remains in this mode until
45
 * NINDY indicates that the program has stopped.
46
 *
47
 *
48
 * PASSTHROUGH MODE
49
 * ----------- ----
50
 *
51
 * GDB writes all input received from the keyboard directly to NINDY, and writes
52
 * all characters received from NINDY directly to the monitor.
53
 *
54
 * Keyboard input is neither buffered nor echoed to the monitor.
55
 *
56
 * GDB remains in passthrough mode until NINDY sends a single ^P character,
57
 * to indicate that the user process has stopped.
58
 *
59
 * Note:
60
 *      GDB assumes NINDY performs a 'flushreg' when the user program stops.
61
 *
62
 *
63
 * COMMAND MODE
64
 * ------- ----
65
 *
66
 * All info (except for message ack and nak) is transferred between gdb
67
 * and the remote processor in messages of the following format:
68
 *
69
 *              <info>#<checksum>
70
 *
71
 * where
72
 *      #       is a literal character
73
 *
74
 *      <info>  ASCII information;  all numeric information is in the
75
 *              form of hex digits ('0'-'9' and lowercase 'a'-'f').
76
 *
77
 *      <checksum>
78
 *              is a pair of ASCII hex digits representing an 8-bit
79
 *              checksum formed by adding together each of the
80
 *              characters in <info>.
81
 *
82
 * The receiver of a message always sends a single character to the sender
83
 * to indicate that the checksum was good ('+') or bad ('-');  the sender
84
 * re-transmits the entire message over until a '+' is received.
85
 *
86
 * In response to a command NINDY always sends back either data or
87
 * a result code of the form "Xnn", where "nn" are hex digits and "X00"
88
 * means no errors.  (Exceptions: the "s" and "c" commands don't respond.)
89
 *
90
 * SEE THE HEADER OF THE FILE "gdb.c" IN THE NINDY MONITOR SOURCE CODE FOR A
91
 * FULL DESCRIPTION OF LEGAL COMMANDS.
92
 *
93
 * SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST
94
 * OF STOP CODES.
95
 *
96
 ***************************************************************************/
97
 
98
#include "defs.h"
99
#include <signal.h>
100
#include <sys/types.h>
101
#include <setjmp.h>
102
 
103
#include "frame.h"
104
#include "inferior.h"
105
#include "bfd.h"
106
#include "symfile.h"
107
#include "target.h"
108
#include "gdbcore.h"
109
#include "command.h"
110
#include "floatformat.h"
111
 
112
#include "gdb_wait.h"
113
#include <sys/file.h>
114
#include <ctype.h>
115
#include "serial.h"
116
#include "nindy-share/env.h"
117
#include "nindy-share/stop.h"
118
 
119
#include "dcache.h"
120
#include "remote-utils.h"
121
 
122
static DCACHE *nindy_dcache;
123
 
124
extern int unlink ();
125
extern char *getenv ();
126
extern char *mktemp ();
127
 
128
extern void generic_mourn_inferior ();
129
 
130
extern struct target_ops nindy_ops;
131
extern FILE *instream;
132
 
133
extern char ninStopWhy ();
134
extern int ninMemGet ();
135
extern int ninMemPut ();
136
 
137
int nindy_initial_brk;          /* nonzero if want to send an initial BREAK to nindy */
138
int nindy_old_protocol;         /* nonzero if want to use old protocol */
139
char *nindy_ttyname;            /* name of tty to talk to nindy on, or null */
140
 
141
#define DLE     '\020'          /* Character NINDY sends to indicate user program has
142
                                   * halted.  */
143
#define TRUE    1
144
#define FALSE   0
145
 
146
/* From nindy-share/nindy.c.  */
147
extern serial_t nindy_serial;
148
 
149
static int have_regs = 0;        /* 1 iff regs read since i960 last halted */
150
static int regs_changed = 0;     /* 1 iff regs were modified since last read */
151
 
152
extern char *exists ();
153
 
154
static void
155
nindy_fetch_registers PARAMS ((int));
156
 
157
static void
158
nindy_store_registers PARAMS ((int));
159
 
160
static char *savename;
161
 
162
static void
163
nindy_close (quitting)
164
     int quitting;
165
{
166
  if (nindy_serial != NULL)
167
    SERIAL_CLOSE (nindy_serial);
168
  nindy_serial = NULL;
169
 
170
  if (savename)
171
    free (savename);
172
  savename = 0;
173
}
174
 
175
/* Open a connection to a remote debugger.
176
   FIXME, there should be "set" commands for the options that are
177
   now specified with gdb command-line options (old_protocol,
178
   and initial_brk).  */
179
void
180
nindy_open (name, from_tty)
181
     char *name;                /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
182
     int from_tty;
183
{
184
  char baudrate[1024];
185
 
186
  if (!name)
187
    error_no_arg ("serial port device name");
188
 
189
  target_preopen (from_tty);
190
 
191
  nindy_close (0);
192
 
193
  have_regs = regs_changed = 0;
194
  nindy_dcache = dcache_init (ninMemGet, ninMemPut);
195
 
196
  /* Allow user to interrupt the following -- we could hang if there's
197
     no NINDY at the other end of the remote tty.  */
198
  immediate_quit++;
199
  /* If baud_rate is -1, then ninConnect will not recognize the baud rate
200
     and will deal with the situation in a (more or less) reasonable
201
     fashion.  */
202
  sprintf (baudrate, "%d", baud_rate);
203
  ninConnect (name, baudrate,
204
              nindy_initial_brk, !from_tty, nindy_old_protocol);
205
  immediate_quit--;
206
 
207
  if (nindy_serial == NULL)
208
    {
209
      perror_with_name (name);
210
    }
211
 
212
  savename = savestring (name, strlen (name));
213
  push_target (&nindy_ops);
214
 
215
  target_fetch_registers (-1);
216
 
217
  init_thread_list ();
218
  init_wait_for_inferior ();
219
  clear_proceed_status ();
220
  normal_stop ();
221
}
222
 
223
/* User-initiated quit of nindy operations.  */
224
 
225
static void
226
nindy_detach (name, from_tty)
227
     char *name;
228
     int from_tty;
229
{
230
  if (name)
231
    error ("Too many arguments");
232
  pop_target ();
233
}
234
 
235
static void
236
nindy_files_info ()
237
{
238
  /* FIXME: this lies about the baud rate if we autobauded.  */
239
  printf_unfiltered ("\tAttached to %s at %d bits per second%s%s.\n", savename,
240
                     baud_rate,
241
                     nindy_old_protocol ? " in old protocol" : "",
242
                     nindy_initial_brk ? " with initial break" : "");
243
}
244
 
245
/* Return the number of characters in the buffer before
246
   the first DLE character.  */
247
 
248
static
249
int
250
non_dle (buf, n)
251
     char *buf;                 /* Character buffer; NOT '\0'-terminated */
252
     int n;                     /* Number of characters in buffer */
253
{
254
  int i;
255
 
256
  for (i = 0; i < n; i++)
257
    {
258
      if (buf[i] == DLE)
259
        {
260
          break;
261
        }
262
    }
263
  return i;
264
}
265
 
266
/* Tell the remote machine to resume.  */
267
 
268
void
269
nindy_resume (pid, step, siggnal)
270
     int pid, step;
271
     enum target_signal siggnal;
272
{
273
  if (siggnal != TARGET_SIGNAL_0 && siggnal != stop_signal)
274
    warning ("Can't send signals to remote NINDY targets.");
275
 
276
  dcache_flush (nindy_dcache);
277
  if (regs_changed)
278
    {
279
      nindy_store_registers (-1);
280
      regs_changed = 0;
281
    }
282
  have_regs = 0;
283
  ninGo (step);
284
}
285
 
286
/* FIXME, we can probably use the normal terminal_inferior stuff here.
287
   We have to do terminal_inferior and then set up the passthrough
288
   settings initially.  Thereafter, terminal_ours and terminal_inferior
289
   will automatically swap the settings around for us.  */
290
 
291
struct clean_up_tty_args
292
{
293
  serial_ttystate state;
294
  serial_t serial;
295
};
296
static struct clean_up_tty_args tty_args;
297
 
298
static void
299
clean_up_tty (ptrarg)
300
     PTR ptrarg;
301
{
302
  struct clean_up_tty_args *args = (struct clean_up_tty_args *) ptrarg;
303
  SERIAL_SET_TTY_STATE (args->serial, args->state);
304
  free (args->state);
305
  warning ("\n\nYou may need to reset the 80960 and/or reload your program.\n");
306
}
307
 
308
/* Recover from ^Z or ^C while remote process is running */
309
static void (*old_ctrlc) ();
310
#ifdef SIGTSTP
311
static void (*old_ctrlz) ();
312
#endif
313
 
314
static void
315
clean_up_int ()
316
{
317
  SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
318
  free (tty_args.state);
319
 
320
  signal (SIGINT, old_ctrlc);
321
#ifdef SIGTSTP
322
  signal (SIGTSTP, old_ctrlz);
323
#endif
324
  error ("\n\nYou may need to reset the 80960 and/or reload your program.\n");
325
}
326
 
327
/* Wait until the remote machine stops. While waiting, operate in passthrough
328
 * mode; i.e., pass everything NINDY sends to gdb_stdout, and everything from
329
 * stdin to NINDY.
330
 *
331
 * Return to caller, storing status in 'status' just as `wait' would.
332
 */
333
 
334
static int
335
nindy_wait (pid, status)
336
     int pid;
337
     struct target_waitstatus *status;
338
{
339
  fd_set fds;
340
  int c;
341
  char buf[2];
342
  int i, n;
343
  unsigned char stop_exit;
344
  unsigned char stop_code;
345
  struct cleanup *old_cleanups;
346
  long ip_value, fp_value, sp_value;    /* Reg values from stop */
347
 
348
  status->kind = TARGET_WAITKIND_EXITED;
349
  status->value.integer = 0;
350
 
351
  /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
352
 
353
  /* Save current tty attributes, and restore them when done.  */
354
  tty_args.serial = SERIAL_FDOPEN (0);
355
  tty_args.state = SERIAL_GET_TTY_STATE (tty_args.serial);
356
  old_ctrlc = signal (SIGINT, clean_up_int);
357
#ifdef SIGTSTP
358
  old_ctrlz = signal (SIGTSTP, clean_up_int);
359
#endif
360
 
361
  old_cleanups = make_cleanup (clean_up_tty, &tty_args);
362
 
363
  /* Pass input from keyboard to NINDY as it arrives.  NINDY will interpret
364
     <CR> and perform echo.  */
365
  /* This used to set CBREAK and clear ECHO and CRMOD.  I hope this is close
366
     enough.  */
367
  SERIAL_RAW (tty_args.serial);
368
 
369
  while (1)
370
    {
371
      /* Input on remote */
372
      c = SERIAL_READCHAR (nindy_serial, -1);
373
      if (c == SERIAL_ERROR)
374
        {
375
          error ("Cannot read from serial line");
376
        }
377
      else if (c == 0x1b)       /* ESC */
378
        {
379
          c = SERIAL_READCHAR (nindy_serial, -1);
380
          c &= ~0x40;
381
        }
382
      else if (c != 0x10)       /* DLE */
383
        /* Write out any characters preceding DLE */
384
        {
385
          buf[0] = (char) c;
386
          write (1, buf, 1);
387
        }
388
      else
389
        {
390
          stop_exit = ninStopWhy (&stop_code,
391
                                  &ip_value, &fp_value, &sp_value);
392
          if (!stop_exit && (stop_code == STOP_SRQ))
393
            {
394
              immediate_quit++;
395
              ninSrq ();
396
              immediate_quit--;
397
            }
398
          else
399
            {
400
              /* Get out of loop */
401
              supply_register (IP_REGNUM,
402
                               (char *) &ip_value);
403
              supply_register (FP_REGNUM,
404
                               (char *) &fp_value);
405
              supply_register (SP_REGNUM,
406
                               (char *) &sp_value);
407
              break;
408
            }
409
        }
410
    }
411
 
412
  SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
413
  free (tty_args.state);
414
  discard_cleanups (old_cleanups);
415
 
416
  if (stop_exit)
417
    {
418
      status->kind = TARGET_WAITKIND_EXITED;
419
      status->value.integer = stop_code;
420
    }
421
  else
422
    {
423
      /* nindy has some special stop code need to be handled */
424
      if (stop_code == STOP_GDB_BPT)
425
        stop_code = TRACE_STEP;
426
      status->kind = TARGET_WAITKIND_STOPPED;
427
      status->value.sig = i960_fault_to_signal (stop_code);
428
    }
429
  return inferior_pid;
430
}
431
 
432
/* Read the remote registers into the block REGS.  */
433
 
434
/* This is the block that ninRegsGet and ninRegsPut handles.  */
435
struct nindy_regs
436
{
437
  char local_regs[16 * 4];
438
  char global_regs[16 * 4];
439
  char pcw_acw[2 * 4];
440
  char ip[4];
441
  char tcw[4];
442
  char fp_as_double[4 * 8];
443
};
444
 
445
static void
446
nindy_fetch_registers (regno)
447
     int regno;
448
{
449
  struct nindy_regs nindy_regs;
450
  int regnum;
451
 
452
  immediate_quit++;
453
  ninRegsGet ((char *) &nindy_regs);
454
  immediate_quit--;
455
 
456
  memcpy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16 * 4);
457
  memcpy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16 * 4);
458
  memcpy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2 * 4);
459
  memcpy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1 * 4);
460
  memcpy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1 * 4);
461
  memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], nindy_regs.fp_as_double, 4 * 8);
462
 
463
  registers_fetched ();
464
}
465
 
466
static void
467
nindy_prepare_to_store ()
468
{
469
  /* Fetch all regs if they aren't already here.  */
470
  read_register_bytes (0, NULL, REGISTER_BYTES);
471
}
472
 
473
static void
474
nindy_store_registers (regno)
475
     int regno;
476
{
477
  struct nindy_regs nindy_regs;
478
  int regnum;
479
 
480
  memcpy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16 * 4);
481
  memcpy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16 * 4);
482
  memcpy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2 * 4);
483
  memcpy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1 * 4);
484
  memcpy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1 * 4);
485
  memcpy (nindy_regs.fp_as_double, &registers[REGISTER_BYTE (FP0_REGNUM)], 8 * 4);
486
 
487
  immediate_quit++;
488
  ninRegsPut ((char *) &nindy_regs);
489
  immediate_quit--;
490
}
491
 
492
/* Read a word from remote address ADDR and return it.
493
 * This goes through the data cache.
494
 */
495
int
496
nindy_fetch_word (addr)
497
     CORE_ADDR addr;
498
{
499
  return dcache_fetch (nindy_dcache, addr);
500
}
501
 
502
/* Write a word WORD into remote address ADDR.
503
   This goes through the data cache.  */
504
 
505
void
506
nindy_store_word (addr, word)
507
     CORE_ADDR addr;
508
     int word;
509
{
510
  dcache_poke (nindy_dcache, addr, word);
511
}
512
 
513
/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
514
   to debugger memory starting at MYADDR.   Copy to inferior if
515
   WRITE is nonzero.  Returns the length copied.
516
 
517
   This is stolen almost directly from infptrace.c's child_xfer_memory,
518
   which also deals with a word-oriented memory interface.  Sometime,
519
   FIXME, rewrite this to not use the word-oriented routines.  */
520
 
521
int
522
nindy_xfer_inferior_memory (memaddr, myaddr, len, should_write, target)
523
     CORE_ADDR memaddr;
524
     char *myaddr;
525
     int len;
526
     int should_write;
527
     struct target_ops *target; /* ignored */
528
{
529
  register int i;
530
  /* Round starting address down to longword boundary.  */
531
  register CORE_ADDR addr = memaddr & -sizeof (int);
532
  /* Round ending address up; get number of longwords that makes.  */
533
  register int count
534
  = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
535
  /* Allocate buffer of that many longwords.  */
536
  register int *buffer = (int *) alloca (count * sizeof (int));
537
 
538
  if (should_write)
539
    {
540
      /* Fill start and end extra bytes of buffer with existing memory data.  */
541
 
542
      if (addr != memaddr || len < (int) sizeof (int))
543
        {
544
          /* Need part of initial word -- fetch it.  */
545
          buffer[0] = nindy_fetch_word (addr);
546
        }
547
 
548
      if (count > 1)            /* FIXME, avoid if even boundary */
549
        {
550
          buffer[count - 1]
551
            = nindy_fetch_word (addr + (count - 1) * sizeof (int));
552
        }
553
 
554
      /* Copy data to be written over corresponding part of buffer */
555
 
556
      memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
557
 
558
      /* Write the entire buffer.  */
559
 
560
      for (i = 0; i < count; i++, addr += sizeof (int))
561
        {
562
          errno = 0;
563
          nindy_store_word (addr, buffer[i]);
564
          if (errno)
565
            return 0;
566
        }
567
    }
568
  else
569
    {
570
      /* Read all the longwords */
571
      for (i = 0; i < count; i++, addr += sizeof (int))
572
        {
573
          errno = 0;
574
          buffer[i] = nindy_fetch_word (addr);
575
          if (errno)
576
            return 0;
577
          QUIT;
578
        }
579
 
580
      /* Copy appropriate bytes out of the buffer.  */
581
      memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
582
    }
583
  return len;
584
}
585
 
586
static void
587
nindy_create_inferior (execfile, args, env)
588
     char *execfile;
589
     char *args;
590
     char **env;
591
{
592
  int entry_pt;
593
  int pid;
594
 
595
  if (args && *args)
596
    error ("Can't pass arguments to remote NINDY process");
597
 
598
  if (execfile == 0 || exec_bfd == 0)
599
    error ("No executable file specified");
600
 
601
  entry_pt = (int) bfd_get_start_address (exec_bfd);
602
 
603
  pid = 42;
604
 
605
  /* The "process" (board) is already stopped awaiting our commands, and
606
     the program is already downloaded.  We just set its PC and go.  */
607
 
608
  inferior_pid = pid;           /* Needed for wait_for_inferior below */
609
 
610
  clear_proceed_status ();
611
 
612
  /* Tell wait_for_inferior that we've started a new process.  */
613
  init_wait_for_inferior ();
614
 
615
  /* Set up the "saved terminal modes" of the inferior
616
     based on what modes we are starting it with.  */
617
  target_terminal_init ();
618
 
619
  /* Install inferior's terminal modes.  */
620
  target_terminal_inferior ();
621
 
622
  /* insert_step_breakpoint ();  FIXME, do we need this?  */
623
  /* Let 'er rip... */
624
  proceed ((CORE_ADDR) entry_pt, TARGET_SIGNAL_DEFAULT, 0);
625
}
626
 
627
static void
628
reset_command (args, from_tty)
629
     char *args;
630
     int from_tty;
631
{
632
  if (nindy_serial == NULL)
633
    {
634
      error ("No target system to reset -- use 'target nindy' command.");
635
    }
636
  if (query ("Really reset the target system?", 0, 0))
637
    {
638
      SERIAL_SEND_BREAK (nindy_serial);
639
      tty_flush (nindy_serial);
640
    }
641
}
642
 
643
void
644
nindy_kill (args, from_tty)
645
     char *args;
646
     int from_tty;
647
{
648
  return;                       /* Ignore attempts to kill target system */
649
}
650
 
651
/* Clean up when a program exits.
652
 
653
   The program actually lives on in the remote processor's RAM, and may be
654
   run again without a download.  Don't leave it full of breakpoint
655
   instructions.  */
656
 
657
void
658
nindy_mourn_inferior ()
659
{
660
  remove_breakpoints ();
661
  unpush_target (&nindy_ops);
662
  generic_mourn_inferior ();    /* Do all the proper things now */
663
}
664
 
665
/* Pass the args the way catch_errors wants them.  */
666
static int
667
nindy_open_stub (arg)
668
     char *arg;
669
{
670
  nindy_open (arg, 1);
671
  return 1;
672
}
673
 
674
static void
675
nindy_load (filename, from_tty)
676
     char *filename;
677
     int from_tty;
678
{
679
  asection *s;
680
  /* Can't do unix style forking on a VMS system, so we'll use bfd to do
681
     all the work for us
682
   */
683
 
684
  bfd *file = bfd_openr (filename, 0);
685
  if (!file)
686
    {
687
      perror_with_name (filename);
688
      return;
689
    }
690
 
691
  if (!bfd_check_format (file, bfd_object))
692
    {
693
      error ("can't prove it's an object file\n");
694
      return;
695
    }
696
 
697
  for (s = file->sections; s; s = s->next)
698
    {
699
      if (s->flags & SEC_LOAD)
700
        {
701
          char *buffer = xmalloc (s->_raw_size);
702
          bfd_get_section_contents (file, s, buffer, 0, s->_raw_size);
703
          printf ("Loading section %s, size %x vma %x\n",
704
                  s->name,
705
                  s->_raw_size,
706
                  s->vma);
707
          ninMemPut (s->vma, buffer, s->_raw_size);
708
          free (buffer);
709
        }
710
    }
711
  bfd_close (file);
712
}
713
 
714
static int
715
load_stub (arg)
716
     char *arg;
717
{
718
  target_load (arg, 1);
719
  return 1;
720
}
721
 
722
/* This routine is run as a hook, just before the main command loop is
723
   entered.  If gdb is configured for the i960, but has not had its
724
   nindy target specified yet, this will loop prompting the user to do so.
725
 
726
   Unlike the loop provided by Intel, we actually let the user get out
727
   of this with a RETURN.  This is useful when e.g. simply examining
728
   an i960 object file on the host system.  */
729
 
730
void
731
nindy_before_main_loop ()
732
{
733
  char ttyname[100];
734
  char *p, *p2;
735
 
736
  while (target_stack->target_ops != &nindy_ops)        /* What is this crap??? */
737
    {                           /* remote tty not specified yet */
738
      if (instream == stdin)
739
        {
740
          printf_unfiltered ("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit:  ");
741
          gdb_flush (gdb_stdout);
742
        }
743
      fgets (ttyname, sizeof (ttyname) - 1, stdin);
744
 
745
      /* Strip leading and trailing whitespace */
746
      for (p = ttyname; isspace (*p); p++)
747
        {
748
          ;
749
        }
750
      if (*p == '\0')
751
        {
752
          return;               /* User just hit spaces or return, wants out */
753
        }
754
      for (p2 = p; !isspace (*p2) && (*p2 != '\0'); p2++)
755
        {
756
          ;
757
        }
758
      *p2 = '\0';
759
      if (STREQ ("quit", p))
760
        {
761
          exit (1);
762
        }
763
 
764
      if (catch_errors (nindy_open_stub, p, "", RETURN_MASK_ALL))
765
        {
766
          /* Now that we have a tty open for talking to the remote machine,
767
             download the executable file if one was specified.  */
768
          if (exec_bfd)
769
            {
770
              catch_errors (load_stub, bfd_get_filename (exec_bfd), "",
771
                            RETURN_MASK_ALL);
772
            }
773
        }
774
    }
775
}
776
 
777
/* Define the target subroutine names */
778
 
779
struct target_ops nindy_ops;
780
 
781
static void
782
init_nindy_ops (void)
783
{
784
  nindy_ops.to_shortname = "nindy";
785
  "Remote serial target in i960 NINDY-specific protocol",
786
    nindy_ops.to_longname = "Use a remote i960 system running NINDY connected by a serial line.\n\
787
Specify the name of the device the serial line is connected to.\n\
788
The speed (baud rate), whether to use the old NINDY protocol,\n\
789
and whether to send a break on startup, are controlled by options\n\
790
specified when you started GDB.";
791
  nindy_ops.to_doc = "";
792
  nindy_ops.to_open = nindy_open;
793
  nindy_ops.to_close = nindy_close;
794
  nindy_ops.to_attach = 0;
795
  nindy_ops.to_post_attach = NULL;
796
  nindy_ops.to_require_attach = NULL;
797
  nindy_ops.to_detach = nindy_detach;
798
  nindy_ops.to_require_detach = NULL;
799
  nindy_ops.to_resume = nindy_resume;
800
  nindy_ops.to_wait = nindy_wait;
801
  nindy_ops.to_post_wait = NULL;
802
  nindy_ops.to_fetch_registers = nindy_fetch_registers;
803
  nindy_ops.to_store_registers = nindy_store_registers;
804
  nindy_ops.to_prepare_to_store = nindy_prepare_to_store;
805
  nindy_ops.to_xfer_memory = nindy_xfer_inferior_memory;
806
  nindy_ops.to_files_info = nindy_files_info;
807
  nindy_ops.to_insert_breakpoint = memory_insert_breakpoint;
808
  nindy_ops.to_remove_breakpoint = memory_remove_breakpoint;
809
  nindy_ops.to_terminal_init = 0;
810
  nindy_ops.to_terminal_inferior = 0;
811
  nindy_ops.to_terminal_ours_for_output = 0;
812
  nindy_ops.to_terminal_ours = 0;
813
  nindy_ops.to_terminal_info = 0;        /* Terminal crud */
814
  nindy_ops.to_kill = nindy_kill;
815
  nindy_ops.to_load = nindy_load;
816
  nindy_ops.to_lookup_symbol = 0;        /* lookup_symbol */
817
  nindy_ops.to_create_inferior = nindy_create_inferior;
818
  nindy_ops.to_post_startup_inferior = NULL;
819
  nindy_ops.to_acknowledge_created_inferior = NULL;
820
  nindy_ops.to_clone_and_follow_inferior = NULL;
821
  nindy_ops.to_post_follow_inferior_by_clone = NULL;
822
  nindy_ops.to_insert_fork_catchpoint = NULL;
823
  nindy_ops.to_remove_fork_catchpoint = NULL;
824
  nindy_ops.to_insert_vfork_catchpoint = NULL;
825
  nindy_ops.to_remove_vfork_catchpoint = NULL;
826
  nindy_ops.to_has_forked = NULL;
827
  nindy_ops.to_has_vforked = NULL;
828
  nindy_ops.to_can_follow_vfork_prior_to_exec = NULL;
829
  nindy_ops.to_post_follow_vfork = NULL;
830
  nindy_ops.to_insert_exec_catchpoint = NULL;
831
  nindy_ops.to_remove_exec_catchpoint = NULL;
832
  nindy_ops.to_has_execd = NULL;
833
  nindy_ops.to_reported_exec_events_per_exec_call = NULL;
834
  nindy_ops.to_has_exited = NULL;
835
  nindy_ops.to_mourn_inferior = nindy_mourn_inferior;
836
  nindy_ops.to_can_run = 0;      /* can_run */
837
  nindy_ops.to_notice_signals = 0;       /* notice_signals */
838
  nindy_ops.to_thread_alive = 0; /* to_thread_alive */
839
  nindy_ops.to_stop = 0; /* to_stop */
840
  nindy_ops.to_pid_to_exec_file = NULL;
841
  nindy_ops.to_core_file_to_sym_file = NULL;
842
  nindy_ops.to_stratum = process_stratum;
843
  nindy_ops.DONT_USE = 0;        /* next */
844
  nindy_ops.to_has_all_memory = 1;
845
  nindy_ops.to_has_memory = 1;
846
  nindy_ops.to_has_stack = 1;
847
  nindy_ops.to_has_registers = 1;
848
  nindy_ops.to_has_execution = 1;       /* all mem, mem, stack, regs, exec */
849
  nindy_ops.to_sections = 0;
850
  nindy_ops.to_sections_end = 0; /* Section pointers */
851
  nindy_ops.to_magic = OPS_MAGIC;       /* Always the last thing */
852
}
853
 
854
void
855
_initialize_nindy ()
856
{
857
  init_nindy_ops ();
858
  add_target (&nindy_ops);
859
  add_com ("reset", class_obscure, reset_command,
860
           "Send a 'break' to the remote target system.\n\
861
Only useful if the target has been equipped with a circuit\n\
862
to perform a hard reset when a break is detected.");
863
}

powered by: WebSVN 2.1.0

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